1 package org
.argeo
.slc
.repo
.osgi
;
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
;
12 import java
.util
.TreeSet
;
13 import java
.util
.zip
.ZipEntry
;
14 import java
.util
.zip
.ZipInputStream
;
15 import java
.util
.zip
.ZipOutputStream
;
17 import javax
.jcr
.Node
;
18 import javax
.jcr
.Property
;
19 import javax
.jcr
.RepositoryException
;
20 import javax
.jcr
.Session
;
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
;
41 import aQute
.lib
.osgi
.Jar
;
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.
48 public class ArchiveWrapper
implements Runnable
, ModuleSet
, Distribution
{
49 private final static Log log
= LogFactory
.getLog(ArchiveWrapper
.class);
51 private OsgiFactory osgiFactory
;
52 private String version
;
53 private License license
;
57 /** Jars to wrap as OSGi bundles */
58 private Map
<String
, BndWrapper
> wrappers
= new HashMap
<String
, BndWrapper
>();
60 private SourcesProvider sourcesProvider
;
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
>();
67 private Boolean mavenGroupIndexes
= false;
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
);
79 public void destroy() {
83 public String
getDistributionId() {
87 public Iterator
<?
extends NameVersion
> nameVersions() {
88 return wrappers
.values().iterator();
92 if (mavenGroupIndexes
&& (version
== null))
93 throw new SlcException(
94 "'mavenGroupIndexes' requires 'version' to be set");
96 Map
<String
, Set
<Artifact
>> binaries
= new HashMap
<String
, Set
<Artifact
>>();
97 Map
<String
, Set
<Artifact
>> sources
= new HashMap
<String
, Set
<Artifact
>>();
99 Session distSession
= null;
100 Session javaSession
= null;
101 ZipInputStream zin
= null;
103 javaSession
= osgiFactory
.openJavaSession();
104 distSession
= osgiFactory
.openDistSession();
106 if (log
.isDebugEnabled())
107 log
.debug("Wrapping " + uri
);
109 Node distNode
= osgiFactory
.getDist(distSession
, uri
);
110 zin
= new ZipInputStream(distNode
.getNode(Node
.JCR_CONTENT
)
111 .getProperty(Property
.JCR_DATA
).getBinary().getStream());
113 ZipEntry zentry
= null;
114 entries
: while ((zentry
= zin
.getNextEntry()) != null) {
115 String name
= zentry
.getName();
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
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
,
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();
139 } else if (baseName
.endsWith(".source")) {
140 // TODO Eclipse source already available
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
);
152 for (String wrapperKey
: wrappers
.keySet())
153 if (pathMatcher
.match(wrapperKey
, name
)) {
154 // first matched is taken
155 BndWrapper wrapper
= (BndWrapper
) wrappers
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(),
165 if (log
.isTraceEnabled())
166 log
.trace(name
+ " not matched by "
170 for (String exclude
: excludes
)
171 if (pathMatcher
.match(exclude
, name
))
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
);
183 addArtifactToIndex(binaries
, groupId
, artifact
);
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
)
199 // FIXME Fail if not all wrappers matched
200 } catch (Exception e
) {
201 throw new SlcException("Cannot wrap distribution " + uri
, e
);
203 IOUtils
.closeQuietly(zin
);
204 JcrUtils
.logoutQuietly(distSession
);
205 JcrUtils
.logoutQuietly(javaSession
);
209 protected Artifact
wrapZipEntry(Session javaSession
, ZipEntry zentry
,
210 byte[] sourceJarBytes
, BndWrapper wrapper
)
211 throws RepositoryException
{
212 ByteArrayOutputStream out
= null;
213 ByteArrayInputStream in
= null;
217 out
= new ByteArrayOutputStream((int) zentry
.getSize());
218 in
= new ByteArrayInputStream(sourceJarBytes
);
219 wrapper
.wrapJar(in
, out
);
221 Artifact artifact
= wrapper
.getArtifact();
222 newJarNode
= RepoUtils
.copyBytesAsArtifact(
223 javaSession
.getRootNode(), artifact
, out
.toByteArray());
224 osgiFactory
.indexNode(newJarNode
);
225 newJarNode
.getSession().save();
226 if (log
.isDebugEnabled())
227 log
.debug("Wrapped jar " + zentry
.getName() + " to "
228 + newJarNode
.getPath());
231 if (sourcesProvider
!= null) {
232 IOUtils
.closeQuietly(in
);
233 in
= new ByteArrayInputStream(out
.toByteArray());
234 jar
= new Jar(null, in
);
235 List
<String
> packages
= jar
.getPackages();
237 IOUtils
.closeQuietly(out
);
238 out
= new ByteArrayOutputStream();
240 .writeSources(packages
, new ZipOutputStream(out
));
242 IOUtils
.closeQuietly(in
);
243 in
= new ByteArrayInputStream(out
.toByteArray());
244 byte[] sourcesJar
= RepoUtils
.packageAsPdeSource(in
,
245 new DefaultNameVersion(wrapper
));
246 Artifact sourcesArtifact
= new DefaultArtifact(
247 artifact
.getGroupId(), artifact
.getArtifactId()
248 + ".source", "jar", artifact
.getVersion());
249 Node sourcesJarNode
= RepoUtils
.copyBytesAsArtifact(
250 javaSession
.getRootNode(), sourcesArtifact
, sourcesJar
);
251 sourcesJarNode
.getSession().save();
253 if (log
.isDebugEnabled())
254 log
.debug("Added sources " + sourcesArtifact
255 + " for bundle " + artifact
);
259 } catch (IOException e
) {
260 throw new SlcException("Cannot open jar", e
);
262 IOUtils
.closeQuietly(in
);
263 IOUtils
.closeQuietly(out
);
269 protected Artifact
importZipEntry(Session javaSession
, ZipEntry zentry
,
270 byte[] sourceJarBytes
, String groupId
) throws RepositoryException
{
271 ByteArrayInputStream in
= null;
274 in
= new ByteArrayInputStream(sourceJarBytes
);
275 NameVersion nameVersion
= RepoUtils
.readNameVersion(in
);
276 Artifact artifact
= new DefaultArtifact(groupId
,
277 nameVersion
.getName(), "jar", nameVersion
.getVersion());
278 newJarNode
= RepoUtils
.copyBytesAsArtifact(
279 javaSession
.getRootNode(), artifact
, sourceJarBytes
);
280 osgiFactory
.indexNode(newJarNode
);
281 newJarNode
.getSession().save();
282 if (log
.isDebugEnabled())
283 log
.debug("Imported OSGi bundle " + zentry
.getName() + " to "
284 + newJarNode
.getPath());
287 IOUtils
.closeQuietly(in
);
291 private void addArtifactToIndex(Map
<String
, Set
<Artifact
>> index
,
292 String groupId
, Artifact artifact
) {
293 if (!index
.containsKey(groupId
))
295 new TreeSet
<Artifact
>(new ArtifactIdComparator()));
296 index
.get(groupId
).add(artifact
);
299 public void setUri(String uri
) {
303 public void setWrappers(Map
<String
, BndWrapper
> wrappers
) {
304 this.wrappers
= wrappers
;
307 public void setOsgiFactory(OsgiFactory osgiFactory
) {
308 this.osgiFactory
= osgiFactory
;
311 public void setVersion(String version
) {
312 this.version
= version
;
315 public void setLicense(License license
) {
316 this.license
= license
;
319 public void setPathMatcher(PathMatcher pathMatcher
) {
320 this.pathMatcher
= pathMatcher
;
323 public void setIncludes(Map
<String
, String
> includes
) {
324 this.includes
= includes
;
327 public void setExcludes(List
<String
> excludes
) {
328 this.excludes
= excludes
;
331 public void setMavenGroupIndexes(Boolean mavenGroupIndexes
) {
332 this.mavenGroupIndexes
= mavenGroupIndexes
;
335 public void setSourcesProvider(SourcesProvider sourcesProvider
) {
336 this.sourcesProvider
= sourcesProvider
;