X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;f=runtime%2Forg.argeo.slc.repo%2Fsrc%2Fmain%2Fjava%2Forg%2Fargeo%2Fslc%2Frepo%2Fosgi%2FArchiveWrapper.java;h=768cbbde392ea03ddd80dd19f91de2d9e4538390;hb=399702cec859f48ec171c30d268c55eb632d472a;hp=0adfe883f6d95ee7036dfa138c7d6da73d3061a9;hpb=50070c24a1b27dda7ac6669871caf008726d372d;p=gpl%2Fargeo-slc.git diff --git a/runtime/org.argeo.slc.repo/src/main/java/org/argeo/slc/repo/osgi/ArchiveWrapper.java b/runtime/org.argeo.slc.repo/src/main/java/org/argeo/slc/repo/osgi/ArchiveWrapper.java index 0adfe883f..768cbbde3 100644 --- a/runtime/org.argeo.slc.repo/src/main/java/org/argeo/slc/repo/osgi/ArchiveWrapper.java +++ b/runtime/org.argeo.slc.repo/src/main/java/org/argeo/slc/repo/osgi/ArchiveWrapper.java @@ -2,6 +2,7 @@ package org.argeo.slc.repo.osgi; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; +import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; @@ -9,23 +10,29 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeSet; +import java.util.jar.JarInputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; +import java.util.zip.ZipOutputStream; import javax.jcr.Node; import javax.jcr.Property; import javax.jcr.RepositoryException; import javax.jcr.Session; +import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.argeo.jcr.JcrUtils; +import org.argeo.slc.CategorizedNameVersion; +import org.argeo.slc.DefaultNameVersion; import org.argeo.slc.ModuleSet; import org.argeo.slc.NameVersion; import org.argeo.slc.SlcException; import org.argeo.slc.aether.ArtifactIdComparator; import org.argeo.slc.build.Distribution; +import org.argeo.slc.build.License; import org.argeo.slc.repo.OsgiFactory; import org.argeo.slc.repo.RepoUtils; import org.sonatype.aether.artifact.Artifact; @@ -33,6 +40,8 @@ import org.sonatype.aether.util.artifact.DefaultArtifact; import org.springframework.util.AntPathMatcher; import org.springframework.util.PathMatcher; +import aQute.lib.osgi.Jar; + /** * Download a software distribution and generates the related OSGi bundles from * the jars, or import them directly if they are already OSGi bundles and don't @@ -43,12 +52,15 @@ public class ArchiveWrapper implements Runnable, ModuleSet, Distribution { private OsgiFactory osgiFactory; private String version; + private License license; private String uri; - // jars to wrap as OSGi bundles + /** Jars to wrap as OSGi bundles */ private Map wrappers = new HashMap(); + private SourcesProvider sourcesProvider; + // pattern of OSGi bundles to import private PathMatcher pathMatcher = new AntPathMatcher(); private Map includes = new HashMap(); @@ -57,11 +69,13 @@ public class ArchiveWrapper implements Runnable, ModuleSet, Distribution { private Boolean mavenGroupIndexes = false; public void init() { - if (version != null) - for (BndWrapper wrapper : wrappers.values()) { - if (wrapper.getVersion() == null) - wrapper.setVersion(version); - } + for (BndWrapper wrapper : wrappers.values()) { + wrapper.setFactory(this); + if (version != null && wrapper.getVersion() == null) + wrapper.setVersion(version); + if (license != null && wrapper.getLicense() == null) + wrapper.setLicense(license); + } } public void destroy() { @@ -73,7 +87,57 @@ public class ArchiveWrapper implements Runnable, ModuleSet, Distribution { } public Iterator nameVersions() { - return wrappers.values().iterator(); + if (wrappers.size() > 0) + return wrappers.values().iterator(); + else + return osgiNameVersions(); + } + + @SuppressWarnings("resource") + protected Iterator osgiNameVersions() { + List nvs = new ArrayList(); + + Session distSession = null; + ZipInputStream zin = null; + try { + distSession = osgiFactory.openDistSession(); + + Node distNode = osgiFactory.getDist(distSession, uri); + zin = new ZipInputStream(distNode.getNode(Node.JCR_CONTENT) + .getProperty(Property.JCR_DATA).getBinary().getStream()); + + ZipEntry zentry = null; + entries: while ((zentry = zin.getNextEntry()) != null) { + String name = zentry.getName(); + // log.debug(name); + for (String exclude : excludes) + if (pathMatcher.match(exclude, name)) + continue entries; + + for (String include : includes.keySet()) { + if (pathMatcher.match(include, name)) { + String groupId = includes.get(include); + JarInputStream jis = new JarInputStream(zin); + NameVersion nv = RepoUtils.readNameVersion(jis + .getManifest()); + if (nv != null) { + if (nv.getName().endsWith(".source")) + continue entries; + CategorizedNameVersion cnv = new OsgiCategorizedNV( + groupId, nv.getName(), nv.getVersion(), + this); + nvs.add(cnv); + } + } + } + } + return nvs.iterator(); + } catch (Exception e) { + throw new SlcException("Cannot wrap distribution " + uri, e); + } finally { + IOUtils.closeQuietly(zin); + JcrUtils.logoutQuietly(distSession); + } } public void run() { @@ -93,6 +157,7 @@ public class ArchiveWrapper implements Runnable, ModuleSet, Distribution { if (log.isDebugEnabled()) log.debug("Wrapping " + uri); + boolean nothingWasDone = true; Node distNode = osgiFactory.getDist(distSession, uri); zin = new ZipInputStream(distNode.getNode(Node.JCR_CONTENT) @@ -101,12 +166,48 @@ public class ArchiveWrapper implements Runnable, ModuleSet, Distribution { ZipEntry zentry = null; entries: while ((zentry = zin.getNextEntry()) != null) { String name = zentry.getName(); + + // sources autodetect + String baseName = FilenameUtils.getBaseName(name); + if (baseName.endsWith("-sources")) { + String bundle = baseName.substring(0, baseName.length() + - "-sources".length()); + // log.debug(name + "," + baseName + ", " + bundle); + String bundlePath = FilenameUtils.getPath(name) + bundle + + ".jar"; + if (wrappers.containsKey(bundlePath)) { + BndWrapper wrapper = wrappers.get(bundlePath); + NameVersion bundleNv = new DefaultNameVersion( + wrapper.getName(), wrapper.getVersion()); + byte[] pdeSource = RepoUtils.packageAsPdeSource(zin, + bundleNv); + Artifact sourcesArtifact = new DefaultArtifact( + wrapper.getCategory(), wrapper.getName() + + ".source", "jar", + wrapper.getVersion()); + Node pdeSourceNode = RepoUtils.copyBytesAsArtifact( + javaSession.getRootNode(), sourcesArtifact, + pdeSource); + osgiFactory.indexNode(pdeSourceNode); + pdeSourceNode.getSession().save(); + if (log.isDebugEnabled()) + log.debug("Added sources " + sourcesArtifact + + " for bundle " + wrapper.getArtifact() + + "from " + name + " in binary archive."); + } + + } + // else if (baseName.endsWith(".source")) { + // } + + // binaries if (wrappers.containsKey(name)) { BndWrapper wrapper = (BndWrapper) wrappers.get(name); // we must copy since the stream is closed by BND - byte[] sourceJarBytes = IOUtils.toByteArray(zin); + byte[] origJarBytes = IOUtils.toByteArray(zin); Artifact artifact = wrapZipEntry(javaSession, zentry, - sourceJarBytes, wrapper); + origJarBytes, wrapper); + nothingWasDone = false; addArtifactToIndex(binaries, wrapper.getGroupId(), artifact); } else { for (String wrapperKey : wrappers.keySet()) @@ -115,9 +216,10 @@ public class ArchiveWrapper implements Runnable, ModuleSet, Distribution { BndWrapper wrapper = (BndWrapper) wrappers .get(wrapperKey); // we must copy since the stream is closed by BND - byte[] sourceJarBytes = IOUtils.toByteArray(zin); + byte[] origJarBytes = IOUtils.toByteArray(zin); Artifact artifact = wrapZipEntry(javaSession, - zentry, sourceJarBytes, wrapper); + zentry, origJarBytes, wrapper); + nothingWasDone = false; addArtifactToIndex(binaries, wrapper.getGroupId(), artifact); continue entries; @@ -134,9 +236,14 @@ public class ArchiveWrapper implements Runnable, ModuleSet, Distribution { for (String include : includes.keySet()) { if (pathMatcher.match(include, name)) { String groupId = includes.get(include); - byte[] sourceJarBytes = IOUtils.toByteArray(zin); + byte[] origJarBytes = IOUtils.toByteArray(zin); Artifact artifact = importZipEntry(javaSession, - zentry, sourceJarBytes, groupId); + zentry, origJarBytes, groupId); + if (artifact == null) { + log.warn("Skipped non identified " + zentry); + continue entries; + } + nothingWasDone = false; if (artifact.getArtifactId().endsWith(".source")) addArtifactToIndex(sources, groupId, artifact); else @@ -156,6 +263,10 @@ public class ArchiveWrapper implements Runnable, ModuleSet, Distribution { } } + if (nothingWasDone) + throw new SlcException("Nothing was done"); + + // FIXME Fail if not all wrappers matched } catch (Exception e) { throw new SlcException("Cannot wrap distribution " + uri, e); } finally { @@ -166,14 +277,14 @@ public class ArchiveWrapper implements Runnable, ModuleSet, Distribution { } protected Artifact wrapZipEntry(Session javaSession, ZipEntry zentry, - byte[] sourceJarBytes, BndWrapper wrapper) - throws RepositoryException { + byte[] origJarBytes, BndWrapper wrapper) throws RepositoryException { ByteArrayOutputStream out = null; ByteArrayInputStream in = null; Node newJarNode; + Jar jar = null; try { out = new ByteArrayOutputStream((int) zentry.getSize()); - in = new ByteArrayInputStream(sourceJarBytes); + in = new ByteArrayInputStream(origJarBytes); wrapper.wrapJar(in, out); Artifact artifact = wrapper.getArtifact(); @@ -184,29 +295,82 @@ public class ArchiveWrapper implements Runnable, ModuleSet, Distribution { if (log.isDebugEnabled()) log.debug("Wrapped jar " + zentry.getName() + " to " + newJarNode.getPath()); + + if (sourcesProvider != null) + addSource(javaSession, artifact, out.toByteArray()); + return artifact; } finally { IOUtils.closeQuietly(in); IOUtils.closeQuietly(out); + if (jar != null) + jar.close(); + } + } + + protected void addSource(Session javaSession, Artifact artifact, + byte[] binaryJarBytes) { + InputStream in = null; + ByteArrayOutputStream out = null; + Jar jar = null; + try { + in = new ByteArrayInputStream(binaryJarBytes); + jar = new Jar(null, in); + List packages = jar.getPackages(); + + out = new ByteArrayOutputStream(); + sourcesProvider.writeSources(packages, new ZipOutputStream(out)); + + IOUtils.closeQuietly(in); + in = new ByteArrayInputStream(out.toByteArray()); + byte[] sourcesJar = RepoUtils.packageAsPdeSource( + in, + new DefaultNameVersion(artifact.getArtifactId(), artifact + .getVersion())); + Artifact sourcesArtifact = new DefaultArtifact( + artifact.getGroupId(), + artifact.getArtifactId() + ".source", "jar", + artifact.getVersion()); + Node sourcesJarNode = RepoUtils.copyBytesAsArtifact( + javaSession.getRootNode(), sourcesArtifact, sourcesJar); + sourcesJarNode.getSession().save(); + + if (log.isDebugEnabled()) + log.debug("Added sources " + sourcesArtifact + " for bundle " + + artifact + "from source provider " + sourcesProvider); + } catch (Exception e) { + throw new SlcException("Cannot get sources for " + artifact, e); + } finally { + IOUtils.closeQuietly(in); + IOUtils.closeQuietly(out); + if (jar != null) + jar.close(); } } protected Artifact importZipEntry(Session javaSession, ZipEntry zentry, - byte[] sourceJarBytes, String groupId) throws RepositoryException { + byte[] binaryJarBytes, String groupId) throws RepositoryException { ByteArrayInputStream in = null; Node newJarNode; try { - in = new ByteArrayInputStream(sourceJarBytes); + in = new ByteArrayInputStream(binaryJarBytes); NameVersion nameVersion = RepoUtils.readNameVersion(in); + if (nameVersion == null) { + return null; + } Artifact artifact = new DefaultArtifact(groupId, nameVersion.getName(), "jar", nameVersion.getVersion()); newJarNode = RepoUtils.copyBytesAsArtifact( - javaSession.getRootNode(), artifact, sourceJarBytes); + javaSession.getRootNode(), artifact, binaryJarBytes); osgiFactory.indexNode(newJarNode); newJarNode.getSession().save(); if (log.isDebugEnabled()) log.debug("Imported OSGi bundle " + zentry.getName() + " to " + newJarNode.getPath()); + + if (sourcesProvider != null) + addSource(javaSession, artifact, binaryJarBytes); + return artifact; } finally { IOUtils.closeQuietly(in); @@ -237,6 +401,10 @@ public class ArchiveWrapper implements Runnable, ModuleSet, Distribution { this.version = version; } + public void setLicense(License license) { + this.license = license; + } + public void setPathMatcher(PathMatcher pathMatcher) { this.pathMatcher = pathMatcher; } @@ -253,4 +421,8 @@ public class ArchiveWrapper implements Runnable, ModuleSet, Distribution { this.mavenGroupIndexes = mavenGroupIndexes; } + public void setSourcesProvider(SourcesProvider sourcesProvider) { + this.sourcesProvider = sourcesProvider; + } + }