1 package org
.argeo
.slc
.build
;
3 import java
.io
.FileNotFoundException
;
4 import java
.io
.IOException
;
5 import java
.io
.InputStream
;
6 import java
.io
.OutputStream
;
7 import java
.lang
.System
.Logger
;
8 import java
.lang
.System
.Logger
.Level
;
10 import java
.nio
.file
.FileSystem
;
11 import java
.nio
.file
.FileSystems
;
12 import java
.nio
.file
.FileVisitResult
;
13 import java
.nio
.file
.Files
;
14 import java
.nio
.file
.Path
;
15 import java
.nio
.file
.PathMatcher
;
16 import java
.nio
.file
.Paths
;
17 import java
.nio
.file
.SimpleFileVisitor
;
18 import java
.nio
.file
.attribute
.BasicFileAttributes
;
19 import java
.util
.ArrayList
;
20 import java
.util
.HashMap
;
21 import java
.util
.List
;
23 import java
.util
.Properties
;
24 import java
.util
.jar
.Attributes
;
25 import java
.util
.jar
.JarEntry
;
26 import java
.util
.jar
.JarInputStream
;
27 import java
.util
.jar
.Manifest
;
29 import org
.argeo
.slc
.DefaultNameVersion
;
30 import org
.argeo
.slc
.ManifestConstants
;
31 import org
.argeo
.slc
.NameVersion
;
33 public class A2Factory
{
34 private final static Logger logger
= System
.getLogger(A2Factory
.class.getName());
36 private Path originBase
;
37 private Path factoryBase
;
39 /** key is URI prefix, value list of base URLs */
40 private Map
<String
, List
<String
>> mirrors
= new HashMap
<String
, List
<String
>>();
42 public A2Factory(Path originBase
, Path factoryBase
) {
44 this.originBase
= originBase
;
45 this.factoryBase
= factoryBase
;
47 // TODO make it configurable
48 List
<String
> eclipseMirrors
= new ArrayList
<>();
49 eclipseMirrors
.add("https://archive.eclipse.org/");
51 mirrors
.put("http://www.eclipse.org/downloads", eclipseMirrors
);
54 public void processEclipseArchive(Path duDir
) {
56 String category
= duDir
.getParent().getFileName().toString();
57 Path targetCategoryBase
= factoryBase
.resolve(category
);
58 Files
.createDirectories(targetCategoryBase
);
59 Files
.createDirectories(originBase
);
61 Path commonBnd
= duDir
.resolve("common.bnd");
62 Properties commonProps
= new Properties();
63 try (InputStream in
= Files
.newInputStream(commonBnd
)) {
66 Properties includes
= new Properties();
67 try (InputStream in
= Files
.newInputStream(duDir
.resolve("includes.properties"))) {
70 String url
= commonProps
.getProperty(ManifestConstants
.SLC_ORIGIN_URI
.toString());
71 Path downloaded
= tryDownload(url
, originBase
);
73 FileSystem zipFs
= FileSystems
.newFileSystem(downloaded
, null);
75 List
<PathMatcher
> pathMatchers
= new ArrayList
<>();
76 for (Object pattern
: includes
.keySet()) {
77 PathMatcher pathMatcher
= zipFs
.getPathMatcher("glob:/" + pattern
);
78 pathMatchers
.add(pathMatcher
);
81 Files
.walkFileTree(zipFs
.getRootDirectories().iterator().next(), new SimpleFileVisitor
<Path
>() {
84 public FileVisitResult
visitFile(Path file
, BasicFileAttributes attrs
) throws IOException
{
85 pathMatchers
: for (PathMatcher pathMatcher
: pathMatchers
) {
86 if (pathMatcher
.matches(file
)) {
87 // Path target = targetBase.resolve(file.getFileName().toString());
88 // if (!Files.exists(target)) {
89 // Files.copy(file, target);
90 // logger.log(Level.DEBUG, () -> "Copied " + target + " from " + downloaded);
92 // logger.log(Level.DEBUG, () -> target + " already exists.");
95 if (file
.getFileName().toString().contains(".source_")) {
96 processEclipseSourceJar(file
, targetCategoryBase
);
97 logger
.log(Level
.DEBUG
, () -> "Processed source " + file
);
100 processBundleJar(file
, targetCategoryBase
);
101 logger
.log(Level
.DEBUG
, () -> "Processed " + file
);
103 continue pathMatchers
;
106 return super.visitFile(file
, attrs
);
109 } catch (IOException e
) {
110 throw new RuntimeException("Cannot process " + duDir
, e
);
115 protected void processBundleJar(Path file
, Path targetBase
) throws IOException
{
116 NameVersion nameVersion
;
117 Path targetBundleDir
;
118 try (JarInputStream jarIn
= new JarInputStream(Files
.newInputStream(file
), false)) {
119 Manifest manifest
= jarIn
.getManifest();
120 nameVersion
= nameVersionFromManifest(manifest
);
121 targetBundleDir
= targetBase
.resolve(nameVersion
.getName() + "." + nameVersion
.getBranch());
123 // TODO make it less dangerous?
124 if (Files
.exists(targetBundleDir
)) {
125 deleteDirectory(targetBundleDir
);
130 entries
: while ((entry
= jarIn
.getNextJarEntry()) != null) {
131 if (entry
.isDirectory())
133 Path target
= targetBundleDir
.resolve(entry
.getName());
134 Files
.createDirectories(target
.getParent());
135 Files
.copy(jarIn
, target
);
136 logger
.log(Level
.TRACE
, () -> "Copied " + target
);
140 Path manifestPath
= targetBundleDir
.resolve("META-INF/MANIFEST.MF");
141 Files
.createDirectories(manifestPath
.getParent());
142 try (OutputStream out
= Files
.newOutputStream(manifestPath
)) {
149 protected void processEclipseSourceJar(Path file
, Path targetBase
) throws IOException
{
150 // NameVersion nameVersion;
151 Path targetBundleDir
;
152 try (JarInputStream jarIn
= new JarInputStream(Files
.newInputStream(file
), false)) {
153 Manifest manifest
= jarIn
.getManifest();
154 // nameVersion = nameVersionFromManifest(manifest);
156 String
[] relatedBundle
= manifest
.getMainAttributes().getValue("Eclipse-SourceBundle").split(";");
157 String version
= relatedBundle
[1].substring("version=\"".length());
158 version
= version
.substring(0, version
.length() - 1);
159 NameVersion nameVersion
= new DefaultNameVersion(relatedBundle
[0], version
);
160 targetBundleDir
= targetBase
.resolve(nameVersion
.getName() + "." + nameVersion
.getBranch());
162 Path targetSourceDir
= targetBundleDir
.resolve("OSGI-OPT/src");
164 // TODO make it less dangerous?
165 if (Files
.exists(targetSourceDir
)) {
166 deleteDirectory(targetSourceDir
);
168 Files
.createDirectories(targetSourceDir
);
173 entries
: while ((entry
= jarIn
.getNextJarEntry()) != null) {
174 if (entry
.isDirectory())
176 if (entry
.getName().startsWith("META-INF"))// skip META-INF entries
178 Path target
= targetSourceDir
.resolve(entry
.getName());
179 Files
.createDirectories(target
.getParent());
180 Files
.copy(jarIn
, target
);
181 logger
.log(Level
.TRACE
, () -> "Copied source " + target
);
185 // Path manifestPath = targetBundleDir.resolve("META-INF/MANIFEST.MF");
186 // Files.createDirectories(manifestPath.getParent());
187 // try (OutputStream out = Files.newOutputStream(manifestPath)) {
188 // manifest.write(out);
194 static void deleteDirectory(Path path
) throws IOException
{
195 if (!Files
.exists(path
))
197 Files
.walkFileTree(path
, new SimpleFileVisitor
<Path
>() {
199 public FileVisitResult
postVisitDirectory(Path directory
, IOException e
) throws IOException
{
202 Files
.delete(directory
);
203 return FileVisitResult
.CONTINUE
;
207 public FileVisitResult
visitFile(Path file
, BasicFileAttributes attrs
) throws IOException
{
209 return FileVisitResult
.CONTINUE
;
214 protected NameVersion
nameVersionFromManifest(Manifest manifest
) {
215 Attributes attrs
= manifest
.getMainAttributes();
217 String symbolicName
= attrs
.getValue(ManifestConstants
.BUNDLE_SYMBOLICNAME
.toString());
218 // make sure there is no directive
219 symbolicName
= symbolicName
.split(";")[0];
221 String version
= attrs
.getValue(ManifestConstants
.BUNDLE_VERSION
.toString());
222 return new DefaultNameVersion(symbolicName
, version
);
225 protected Path
tryDownload(String uri
, Path dir
) throws IOException
{
227 List
<String
> urlBases
= null;
228 String uriPrefix
= null;
229 uriPrefixes
: for (String uriPref
: mirrors
.keySet()) {
230 if (uri
.startsWith(uriPref
)) {
231 if (mirrors
.get(uriPref
).size() > 0) {
232 urlBases
= mirrors
.get(uriPref
);
238 if (urlBases
== null)
240 return download(uri
, dir
, null);
241 } catch (FileNotFoundException e
) {
242 throw new FileNotFoundException("Cannot find " + uri
);
246 for (String urlBase
: urlBases
) {
247 String relativePath
= uri
.substring(uriPrefix
.length());
248 String url
= urlBase
+ relativePath
;
250 return download(url
, dir
, null);
251 } catch (FileNotFoundException e
) {
252 logger
.log(Level
.WARNING
, "Cannot download " + url
+ ", trying another mirror");
255 throw new FileNotFoundException("Cannot find " + uri
);
258 // protected String simplifyName(URL u) {
259 // String name = u.getPath().substring(u.getPath().lastIndexOf('/') + 1);
263 public Path
download(String url
, Path dir
, String name
) throws IOException
{
266 URL u
= new URL(url
);
268 name
= u
.getPath().substring(u
.getPath().lastIndexOf('/') + 1);
271 dest
= dir
.resolve(name
);
272 if (Files
.exists(dest
)) {
273 logger
.log(Level
.DEBUG
, () -> "File " + dest
+ " already exists for " + url
+ ", not downloading again.");
277 try (InputStream in
= u
.openStream()) {
278 Files
.copy(in
, dest
);
283 public static void main(String
[] args
) {
284 Path originBase
= Paths
.get("../output/origin").toAbsolutePath();
285 Path factoryBase
= Paths
.get("../output/a2").toAbsolutePath();
286 A2Factory factory
= new A2Factory(originBase
, factoryBase
);
288 Path descriptorsBase
= Paths
.get("../tp").toAbsolutePath();
290 factory
.processEclipseArchive(
291 descriptorsBase
.resolve("org.argeo.tp.eclipse.equinox").resolve("eclipse-equinox"));
292 factory
.processEclipseArchive(descriptorsBase
.resolve("org.argeo.tp.eclipse.rap").resolve("eclipse-rap"));
293 factory
.processEclipseArchive(descriptorsBase
.resolve("org.argeo.tp.eclipse.rcp").resolve("eclipse-rcp"));