]> git.argeo.org Git - gpl/argeo-slc.git/blob - runtime/org.argeo.slc.repo/src/main/java/org/argeo/slc/repo/osgi/ArchiveWrapper.java
Manage archives sources
[gpl/argeo-slc.git] / runtime / org.argeo.slc.repo / src / main / java / org / argeo / slc / repo / osgi / ArchiveWrapper.java
1 package org.argeo.slc.repo.osgi;
2
3 import java.io.ByteArrayInputStream;
4 import java.io.ByteArrayOutputStream;
5 import java.io.IOException;
6 import java.util.ArrayList;
7 import java.util.HashMap;
8 import java.util.Iterator;
9 import java.util.List;
10 import java.util.Map;
11 import java.util.Set;
12 import java.util.TreeSet;
13 import java.util.zip.ZipEntry;
14 import java.util.zip.ZipInputStream;
15 import java.util.zip.ZipOutputStream;
16
17 import javax.jcr.Node;
18 import javax.jcr.Property;
19 import javax.jcr.RepositoryException;
20 import javax.jcr.Session;
21
22 import org.apache.commons.io.FilenameUtils;
23 import org.apache.commons.io.IOUtils;
24 import org.apache.commons.logging.Log;
25 import org.apache.commons.logging.LogFactory;
26 import org.argeo.jcr.JcrUtils;
27 import org.argeo.slc.DefaultNameVersion;
28 import org.argeo.slc.ModuleSet;
29 import org.argeo.slc.NameVersion;
30 import org.argeo.slc.SlcException;
31 import org.argeo.slc.aether.ArtifactIdComparator;
32 import org.argeo.slc.build.Distribution;
33 import org.argeo.slc.build.License;
34 import org.argeo.slc.repo.OsgiFactory;
35 import org.argeo.slc.repo.RepoUtils;
36 import org.sonatype.aether.artifact.Artifact;
37 import org.sonatype.aether.util.artifact.DefaultArtifact;
38 import org.springframework.util.AntPathMatcher;
39 import org.springframework.util.PathMatcher;
40
41 import aQute.lib.osgi.Jar;
42
43 /**
44 * Download a software distribution and generates the related OSGi bundles from
45 * the jars, or import them directly if they are already OSGi bundles and don't
46 * need further modification.
47 */
48 public class ArchiveWrapper implements Runnable, ModuleSet, Distribution {
49 private final static Log log = LogFactory.getLog(ArchiveWrapper.class);
50
51 private OsgiFactory osgiFactory;
52 private String version;
53 private License license;
54
55 private String uri;
56
57 /** Jars to wrap as OSGi bundles */
58 private Map<String, BndWrapper> wrappers = new HashMap<String, BndWrapper>();
59
60 private SourcesProvider sourcesProvider;
61
62 // pattern of OSGi bundles to import
63 private PathMatcher pathMatcher = new AntPathMatcher();
64 private Map<String, String> includes = new HashMap<String, String>();
65 private List<String> excludes = new ArrayList<String>();
66
67 private Boolean mavenGroupIndexes = false;
68
69 public void init() {
70 for (BndWrapper wrapper : wrappers.values()) {
71 wrapper.setFactory(this);
72 if (version != null && wrapper.getVersion() == null)
73 wrapper.setVersion(version);
74 if (license != null && wrapper.getLicense() == null)
75 wrapper.setLicense(license);
76 }
77 }
78
79 public void destroy() {
80
81 }
82
83 public String getDistributionId() {
84 return uri;
85 }
86
87 public Iterator<? extends NameVersion> nameVersions() {
88 return wrappers.values().iterator();
89 }
90
91 public void run() {
92 if (mavenGroupIndexes && (version == null))
93 throw new SlcException(
94 "'mavenGroupIndexes' requires 'version' to be set");
95
96 Map<String, Set<Artifact>> binaries = new HashMap<String, Set<Artifact>>();
97 Map<String, Set<Artifact>> sources = new HashMap<String, Set<Artifact>>();
98
99 Session distSession = null;
100 Session javaSession = null;
101 ZipInputStream zin = null;
102 try {
103 javaSession = osgiFactory.openJavaSession();
104 distSession = osgiFactory.openDistSession();
105
106 if (log.isDebugEnabled())
107 log.debug("Wrapping " + uri);
108
109 Node distNode = osgiFactory.getDist(distSession, uri);
110 zin = new ZipInputStream(distNode.getNode(Node.JCR_CONTENT)
111 .getProperty(Property.JCR_DATA).getBinary().getStream());
112
113 ZipEntry zentry = null;
114 entries: while ((zentry = zin.getNextEntry()) != null) {
115 String name = zentry.getName();
116
117 // sources autodetect
118 String baseName = FilenameUtils.getBaseName(name);
119 if (baseName.endsWith("-sources")) {
120 String bundle = baseName.substring(0, baseName.length()
121 - "-sources".length());
122 log.debug(name + "," + baseName + ", " + bundle);
123 String bundlePath = FilenameUtils.getPath(name) + bundle
124 + ".jar";
125 if (wrappers.containsKey(bundlePath)) {
126 BndWrapper wrapper = wrappers.get(bundlePath);
127 NameVersion bundleNv = new DefaultNameVersion(
128 wrapper.getName(), wrapper.getVersion());
129 byte[] pdeSource = RepoUtils.packageAsPdeSource(zin,
130 bundleNv);
131 Node pdeSourceNode = RepoUtils.copyBytesAsArtifact(
132 javaSession.getRootNode(),
133 new DefaultArtifact(wrapper.getCategory(),
134 wrapper.getName() + ".source", "jar",
135 wrapper.getVersion()), pdeSource);
136 osgiFactory.indexNode(pdeSourceNode);
137 pdeSourceNode.getSession().save();
138 }
139 } else if (baseName.endsWith(".source")) {
140 // TODO Eclipse source already available
141 }
142
143 // binaries
144 if (wrappers.containsKey(name)) {
145 BndWrapper wrapper = (BndWrapper) wrappers.get(name);
146 // we must copy since the stream is closed by BND
147 byte[] sourceJarBytes = IOUtils.toByteArray(zin);
148 Artifact artifact = wrapZipEntry(javaSession, zentry,
149 sourceJarBytes, wrapper);
150 addArtifactToIndex(binaries, wrapper.getGroupId(), artifact);
151 } else {
152 for (String wrapperKey : wrappers.keySet())
153 if (pathMatcher.match(wrapperKey, name)) {
154 // first matched is taken
155 BndWrapper wrapper = (BndWrapper) wrappers
156 .get(wrapperKey);
157 // we must copy since the stream is closed by BND
158 byte[] sourceJarBytes = IOUtils.toByteArray(zin);
159 Artifact artifact = wrapZipEntry(javaSession,
160 zentry, sourceJarBytes, wrapper);
161 addArtifactToIndex(binaries, wrapper.getGroupId(),
162 artifact);
163 continue entries;
164 } else {
165 if (log.isTraceEnabled())
166 log.trace(name + " not matched by "
167 + wrapperKey);
168 }
169
170 for (String exclude : excludes)
171 if (pathMatcher.match(exclude, name))
172 continue entries;
173
174 for (String include : includes.keySet()) {
175 if (pathMatcher.match(include, name)) {
176 String groupId = includes.get(include);
177 byte[] sourceJarBytes = IOUtils.toByteArray(zin);
178 Artifact artifact = importZipEntry(javaSession,
179 zentry, sourceJarBytes, groupId);
180 if (artifact.getArtifactId().endsWith(".source"))
181 addArtifactToIndex(sources, groupId, artifact);
182 else
183 addArtifactToIndex(binaries, groupId, artifact);
184 }
185 }
186 }
187 }
188
189 // indexes
190 if (mavenGroupIndexes && version != null) {
191 for (String groupId : binaries.keySet()) {
192 RepoUtils.writeGroupIndexes(javaSession, "/", groupId,
193 version, binaries.get(groupId),
194 sources.containsKey(groupId) ? sources.get(groupId)
195 : null);
196 }
197 }
198
199 } catch (Exception e) {
200 throw new SlcException("Cannot wrap distribution " + uri, e);
201 } finally {
202 IOUtils.closeQuietly(zin);
203 JcrUtils.logoutQuietly(distSession);
204 JcrUtils.logoutQuietly(javaSession);
205 }
206 }
207
208 protected Artifact wrapZipEntry(Session javaSession, ZipEntry zentry,
209 byte[] sourceJarBytes, BndWrapper wrapper)
210 throws RepositoryException {
211 ByteArrayOutputStream out = null;
212 ByteArrayInputStream in = null;
213 Node newJarNode;
214 Jar jar = null;
215 try {
216 out = new ByteArrayOutputStream((int) zentry.getSize());
217 in = new ByteArrayInputStream(sourceJarBytes);
218 wrapper.wrapJar(in, out);
219
220 Artifact artifact = wrapper.getArtifact();
221 newJarNode = RepoUtils.copyBytesAsArtifact(
222 javaSession.getRootNode(), artifact, out.toByteArray());
223 osgiFactory.indexNode(newJarNode);
224 newJarNode.getSession().save();
225 if (log.isDebugEnabled())
226 log.debug("Wrapped jar " + zentry.getName() + " to "
227 + newJarNode.getPath());
228
229 // sources
230 if (sourcesProvider != null) {
231 IOUtils.closeQuietly(in);
232 in = new ByteArrayInputStream(out.toByteArray());
233 jar = new Jar(null, in);
234 List<String> packages = jar.getPackages();
235
236 IOUtils.closeQuietly(out);
237 out = new ByteArrayOutputStream();
238 sourcesProvider
239 .writeSources(packages, new ZipOutputStream(out));
240
241 IOUtils.closeQuietly(in);
242 in = new ByteArrayInputStream(out.toByteArray());
243 byte[] sourcesJar = RepoUtils.packageAsPdeSource(in,
244 new DefaultNameVersion(wrapper));
245 Artifact sourcesArtifact = new DefaultArtifact(
246 artifact.getGroupId(), artifact.getArtifactId()
247 + ".source", "jar", artifact.getVersion());
248 Node sourcesJarNode = RepoUtils.copyBytesAsArtifact(
249 javaSession.getRootNode(), sourcesArtifact, sourcesJar);
250 sourcesJarNode.getSession().save();
251
252 if (log.isDebugEnabled())
253 log.debug("Added sources " + sourcesArtifact
254 + " for bundle " + artifact);
255 }
256
257 return artifact;
258 } catch (IOException e) {
259 throw new SlcException("Cannot open jar", e);
260 } finally {
261 IOUtils.closeQuietly(in);
262 IOUtils.closeQuietly(out);
263 if (jar != null)
264 jar.close();
265 }
266 }
267
268 protected Artifact importZipEntry(Session javaSession, ZipEntry zentry,
269 byte[] sourceJarBytes, String groupId) throws RepositoryException {
270 ByteArrayInputStream in = null;
271 Node newJarNode;
272 try {
273 in = new ByteArrayInputStream(sourceJarBytes);
274 NameVersion nameVersion = RepoUtils.readNameVersion(in);
275 Artifact artifact = new DefaultArtifact(groupId,
276 nameVersion.getName(), "jar", nameVersion.getVersion());
277 newJarNode = RepoUtils.copyBytesAsArtifact(
278 javaSession.getRootNode(), artifact, sourceJarBytes);
279 osgiFactory.indexNode(newJarNode);
280 newJarNode.getSession().save();
281 if (log.isDebugEnabled())
282 log.debug("Imported OSGi bundle " + zentry.getName() + " to "
283 + newJarNode.getPath());
284 return artifact;
285 } finally {
286 IOUtils.closeQuietly(in);
287 }
288 }
289
290 private void addArtifactToIndex(Map<String, Set<Artifact>> index,
291 String groupId, Artifact artifact) {
292 if (!index.containsKey(groupId))
293 index.put(groupId,
294 new TreeSet<Artifact>(new ArtifactIdComparator()));
295 index.get(groupId).add(artifact);
296 }
297
298 public void setUri(String uri) {
299 this.uri = uri;
300 }
301
302 public void setWrappers(Map<String, BndWrapper> wrappers) {
303 this.wrappers = wrappers;
304 }
305
306 public void setOsgiFactory(OsgiFactory osgiFactory) {
307 this.osgiFactory = osgiFactory;
308 }
309
310 public void setVersion(String version) {
311 this.version = version;
312 }
313
314 public void setLicense(License license) {
315 this.license = license;
316 }
317
318 public void setPathMatcher(PathMatcher pathMatcher) {
319 this.pathMatcher = pathMatcher;
320 }
321
322 public void setIncludes(Map<String, String> includes) {
323 this.includes = includes;
324 }
325
326 public void setExcludes(List<String> excludes) {
327 this.excludes = excludes;
328 }
329
330 public void setMavenGroupIndexes(Boolean mavenGroupIndexes) {
331 this.mavenGroupIndexes = mavenGroupIndexes;
332 }
333
334 public void setSourcesProvider(SourcesProvider sourcesProvider) {
335 this.sourcesProvider = sourcesProvider;
336 }
337
338 }