]> git.argeo.org Git - gpl/argeo-slc.git/blob - org.argeo.slc.build/src/org/argeo/slc/build/A2Factory.java
d8a80d0b299c89bd4ea2833dcbf7cf06c4e8aa43
[gpl/argeo-slc.git] / org.argeo.slc.build / src / org / argeo / slc / build / A2Factory.java
1 package org.argeo.slc.build;
2
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;
9 import java.net.URL;
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;
22 import java.util.Map;
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;
28
29 import org.argeo.slc.DefaultNameVersion;
30 import org.argeo.slc.ManifestConstants;
31 import org.argeo.slc.NameVersion;
32
33 public class A2Factory {
34 private final static Logger logger = System.getLogger(A2Factory.class.getName());
35
36 private Path originBase;
37 private Path factoryBase;
38
39 /** key is URI prefix, value list of base URLs */
40 private Map<String, List<String>> mirrors = new HashMap<String, List<String>>();
41
42 public A2Factory(Path originBase, Path factoryBase) {
43 super();
44 this.originBase = originBase;
45 this.factoryBase = factoryBase;
46
47 // TODO make it configurable
48 List<String> eclipseMirrors = new ArrayList<>();
49 eclipseMirrors.add("https://archive.eclipse.org/");
50
51 mirrors.put("http://www.eclipse.org/downloads", eclipseMirrors);
52 }
53
54 public void processEclipseArchive(Path duDir) {
55 try {
56 String category = duDir.getParent().getFileName().toString();
57 Path targetCategoryBase = factoryBase.resolve(category);
58 Files.createDirectories(targetCategoryBase);
59 Files.createDirectories(originBase);
60
61 Path commonBnd = duDir.resolve("common.bnd");
62 Properties commonProps = new Properties();
63 try (InputStream in = Files.newInputStream(commonBnd)) {
64 commonProps.load(in);
65 }
66 Properties includes = new Properties();
67 try (InputStream in = Files.newInputStream(duDir.resolve("includes.properties"))) {
68 includes.load(in);
69 }
70 String url = commonProps.getProperty(ManifestConstants.SLC_ORIGIN_URI.toString());
71 Path downloaded = tryDownload(url, originBase);
72
73 FileSystem zipFs = FileSystems.newFileSystem(downloaded, null);
74
75 List<PathMatcher> pathMatchers = new ArrayList<>();
76 for (Object pattern : includes.keySet()) {
77 PathMatcher pathMatcher = zipFs.getPathMatcher("glob:/" + pattern);
78 pathMatchers.add(pathMatcher);
79 }
80
81 Files.walkFileTree(zipFs.getRootDirectories().iterator().next(), new SimpleFileVisitor<Path>() {
82
83 @Override
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);
91 // } else {
92 // logger.log(Level.DEBUG, () -> target + " already exists.");
93 //
94 // }
95 if (file.getFileName().toString().contains(".source_")) {
96 processEclipseSourceJar(file, targetCategoryBase);
97 logger.log(Level.DEBUG, () -> "Processed source " + file);
98
99 } else {
100 processBundleJar(file, targetCategoryBase);
101 logger.log(Level.DEBUG, () -> "Processed " + file);
102 }
103 continue pathMatchers;
104 }
105 }
106 return super.visitFile(file, attrs);
107 }
108 });
109 } catch (IOException e) {
110 throw new RuntimeException("Cannot process " + duDir, e);
111 }
112
113 }
114
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());
122
123 // TODO make it less dangerous?
124 if (Files.exists(targetBundleDir)) {
125 deleteDirectory(targetBundleDir);
126 }
127
128 // copy entries
129 JarEntry entry;
130 entries: while ((entry = jarIn.getNextJarEntry()) != null) {
131 if (entry.isDirectory())
132 continue entries;
133 Path target = targetBundleDir.resolve(entry.getName());
134 Files.createDirectories(target.getParent());
135 Files.copy(jarIn, target);
136 logger.log(Level.TRACE, () -> "Copied " + target);
137 }
138
139 // copy MANIFEST
140 Path manifestPath = targetBundleDir.resolve("META-INF/MANIFEST.MF");
141 Files.createDirectories(manifestPath.getParent());
142 try (OutputStream out = Files.newOutputStream(manifestPath)) {
143 manifest.write(out);
144 }
145 }
146
147 }
148
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);
155
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());
161
162 Path targetSourceDir = targetBundleDir.resolve("OSGI-OPT/src");
163
164 // TODO make it less dangerous?
165 if (Files.exists(targetSourceDir)) {
166 deleteDirectory(targetSourceDir);
167 } else {
168 Files.createDirectories(targetSourceDir);
169 }
170
171 // copy entries
172 JarEntry entry;
173 entries: while ((entry = jarIn.getNextJarEntry()) != null) {
174 if (entry.isDirectory())
175 continue entries;
176 if (entry.getName().startsWith("META-INF"))// skip META-INF entries
177 continue 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);
182 }
183
184 // copy MANIFEST
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);
189 // }
190 }
191
192 }
193
194 static void deleteDirectory(Path path) throws IOException {
195 if (!Files.exists(path))
196 return;
197 Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
198 @Override
199 public FileVisitResult postVisitDirectory(Path directory, IOException e) throws IOException {
200 if (e != null)
201 throw e;
202 Files.delete(directory);
203 return FileVisitResult.CONTINUE;
204 }
205
206 @Override
207 public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
208 Files.delete(file);
209 return FileVisitResult.CONTINUE;
210 }
211 });
212 }
213
214 protected NameVersion nameVersionFromManifest(Manifest manifest) {
215 Attributes attrs = manifest.getMainAttributes();
216 // symbolic name
217 String symbolicName = attrs.getValue(ManifestConstants.BUNDLE_SYMBOLICNAME.toString());
218 // make sure there is no directive
219 symbolicName = symbolicName.split(";")[0];
220
221 String version = attrs.getValue(ManifestConstants.BUNDLE_VERSION.toString());
222 return new DefaultNameVersion(symbolicName, version);
223 }
224
225 protected Path tryDownload(String uri, Path dir) throws IOException {
226 // find mirror
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);
233 uriPrefix = uriPref;
234 break uriPrefixes;
235 }
236 }
237 }
238 if (urlBases == null)
239 try {
240 return download(uri, dir, null);
241 } catch (FileNotFoundException e) {
242 throw new FileNotFoundException("Cannot find " + uri);
243 }
244
245 // try to download
246 for (String urlBase : urlBases) {
247 String relativePath = uri.substring(uriPrefix.length());
248 String url = urlBase + relativePath;
249 try {
250 return download(url, dir, null);
251 } catch (FileNotFoundException e) {
252 logger.log(Level.WARNING, "Cannot download " + url + ", trying another mirror");
253 }
254 }
255 throw new FileNotFoundException("Cannot find " + uri);
256 }
257
258 // protected String simplifyName(URL u) {
259 // String name = u.getPath().substring(u.getPath().lastIndexOf('/') + 1);
260 //
261 // }
262
263 public Path download(String url, Path dir, String name) throws IOException {
264
265 Path dest;
266 URL u = new URL(url);
267 if (name == null) {
268 name = u.getPath().substring(u.getPath().lastIndexOf('/') + 1);
269 }
270
271 dest = dir.resolve(name);
272 if (Files.exists(dest)) {
273 logger.log(Level.DEBUG, () -> "File " + dest + " already exists for " + url + ", not downloading again.");
274 return dest;
275 }
276
277 try (InputStream in = u.openStream()) {
278 Files.copy(in, dest);
279 }
280 return dest;
281 }
282
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);
287
288 Path descriptorsBase = Paths.get("../tp").toAbsolutePath();
289
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"));
294 }
295 }