Generalize ArchiveWrapper and deprecates ImportBundlesZip
authorMathieu Baudier <mbaudier@argeo.org>
Tue, 17 Sep 2013 08:20:35 +0000 (08:20 +0000)
committerMathieu Baudier <mbaudier@argeo.org>
Tue, 17 Sep 2013 08:20:35 +0000 (08:20 +0000)
git-svn-id: https://svn.argeo.org/slc/trunk@6486 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

runtime/org.argeo.slc.repo/src/main/java/org/argeo/slc/repo/RepoConstants.java
runtime/org.argeo.slc.repo/src/main/java/org/argeo/slc/repo/RepoUtils.java
runtime/org.argeo.slc.repo/src/main/java/org/argeo/slc/repo/osgi/ArchiveWrapper.java
runtime/org.argeo.slc.repo/src/main/java/org/argeo/slc/repo/osgi/BndWrapper.java
runtime/org.argeo.slc.repo/src/main/java/org/argeo/slc/repo/osgi/ImportBundlesZip.java
runtime/org.argeo.slc.repo/src/main/java/org/argeo/slc/repo/osgi/NormalizeGroup.java

index 9ec9c43e985de0bb643cf2efdf2ee0a60663cadc..7a81e71022449471e55a4f62801fa28cc8248508 100644 (file)
@@ -28,4 +28,7 @@ public interface RepoConstants {
                        + "/slc:distributions";
        public final static String REPOSITORIES_BASE_PATH = REPO_BASEPATH
                        + "/slc:repositories";
+       public final static String BINARIES_ARTIFACT_ID = "binaries";
+       public final static String SOURCES_ARTIFACT_ID = "sources";
+       public final static String SDK_ARTIFACT_ID = "sdk";
 }
index f00c910a423e3bec98d244d8add164bf55813801..5f798c1444cc8af171af7469af7873e101c2ee90 100644 (file)
@@ -23,7 +23,9 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.Enumeration;
 import java.util.Iterator;
+import java.util.Set;
 import java.util.StringTokenizer;
+import java.util.TreeSet;
 import java.util.jar.Attributes;
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
@@ -40,6 +42,7 @@ import javax.jcr.PropertyIterator;
 import javax.jcr.Repository;
 import javax.jcr.RepositoryException;
 import javax.jcr.RepositoryFactory;
+import javax.jcr.Session;
 import javax.jcr.SimpleCredentials;
 import javax.jcr.nodetype.NodeType;
 
@@ -51,9 +54,10 @@ import org.argeo.jcr.ArgeoJcrUtils;
 import org.argeo.jcr.ArgeoNames;
 import org.argeo.jcr.ArgeoTypes;
 import org.argeo.jcr.JcrUtils;
-import org.argeo.slc.BasicNameVersion;
+import org.argeo.slc.DefaultNameVersion;
 import org.argeo.slc.NameVersion;
 import org.argeo.slc.SlcException;
+import org.argeo.slc.aether.ArtifactIdComparator;
 import org.argeo.slc.jcr.SlcNames;
 import org.argeo.slc.jcr.SlcTypes;
 import org.argeo.slc.repo.maven.MavenConventionsUtils;
@@ -269,7 +273,7 @@ public class RepoUtils implements ArgeoNames, SlcNames {
 
        /** Read the OSGi {@link NameVersion} */
        public static NameVersion readNameVersion(Manifest manifest) {
-               BasicNameVersion nameVersion = new BasicNameVersion();
+               DefaultNameVersion nameVersion = new DefaultNameVersion();
                nameVersion.setName(manifest.getMainAttributes().getValue(
                                Constants.BUNDLE_SYMBOLICNAME));
 
@@ -413,6 +417,61 @@ public class RepoUtils implements ArgeoNames, SlcNames {
                }
        }
 
+       /**
+        * Write group indexes: 'binaries' lists all bundles and their versions,
+        * 'sources' list theire sources, and 'sdk' aggregates both.
+        */
+       public static void writeGroupIndexes(Session session,
+                       String artifactBasePath, String groupId, String version,
+                       Set<Artifact> binaries, Set<Artifact> sources) {
+               try {
+                       Set<Artifact> indexes = new TreeSet<Artifact>(
+                                       new ArtifactIdComparator());
+                       Artifact binariesArtifact = writeIndex(session, artifactBasePath,
+                                       groupId, RepoConstants.BINARIES_ARTIFACT_ID, version,
+                                       binaries);
+                       indexes.add(binariesArtifact);
+                       if (sources != null) {
+                               Artifact sourcesArtifact = writeIndex(session,
+                                               artifactBasePath, groupId,
+                                               RepoConstants.SOURCES_ARTIFACT_ID, version, sources);
+                               indexes.add(sourcesArtifact);
+                       }
+                       // sdk
+                       writeIndex(session, artifactBasePath, groupId,
+                                       RepoConstants.SDK_ARTIFACT_ID, version, indexes);
+                       session.save();
+               } catch (RepositoryException e) {
+                       throw new SlcException("Cannot write indexes for group " + groupId,
+                                       e);
+               }
+       }
+
+       /** Write a group index. */
+       private static Artifact writeIndex(Session session,
+                       String artifactBasePath, String groupId, String artifactId,
+                       String version, Set<Artifact> artifacts) throws RepositoryException {
+               Artifact artifact = new DefaultArtifact(groupId, artifactId, "pom",
+                               version);
+               String pom = MavenConventionsUtils.artifactsAsDependencyPom(artifact,
+                               artifacts, null);
+               Node node = RepoUtils.copyBytesAsArtifact(
+                               session.getNode(artifactBasePath), artifact, pom.getBytes());
+               addMavenChecksums(node);
+               return artifact;
+       }
+
+       /** Add files containing the SHA-1 and MD5 checksums. */
+       public static void addMavenChecksums(Node node) throws RepositoryException {
+               // TODO optimize
+               String sha = JcrUtils.checksumFile(node, "SHA-1");
+               JcrUtils.copyBytesAsFile(node.getParent(), node.getName() + ".sha1",
+                               sha.getBytes());
+               String md5 = JcrUtils.checksumFile(node, "MD5");
+               JcrUtils.copyBytesAsFile(node.getParent(), node.getName() + ".md5",
+                               md5.getBytes());
+       }
+
        /**
         * Custom copy since the one in commons does not fit the needs when copying
         * a workspace completely.
index 843951843c927cf6348c3e04379f4f87d947cedf..8d1cee58d4859750b4cd51fb408d7d6b2cd189ba 100644 (file)
@@ -2,42 +2,65 @@ 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.List;
 import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipInputStream;
 
 import javax.jcr.Node;
 import javax.jcr.Property;
+import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 
 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.NameVersion;
 import org.argeo.slc.SlcException;
+import org.argeo.slc.aether.ArtifactIdComparator;
 import org.argeo.slc.repo.OsgiFactory;
 import org.argeo.slc.repo.RepoUtils;
 import org.sonatype.aether.artifact.Artifact;
-
-/** Download a software distribution and generates the related OSGi bundles. */
+import org.sonatype.aether.util.artifact.DefaultArtifact;
+import org.springframework.util.AntPathMatcher;
+import org.springframework.util.PathMatcher;
+
+/**
+ * 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
+ * need further modification.
+ */
 public class ArchiveWrapper implements Runnable {
        private final static Log log = LogFactory.getLog(ArchiveWrapper.class);
 
        private OsgiFactory osgiFactory;
-
        private String version;
-       // private String groupId;
-
+       
        private String uri;
-
+       private List<String> fallbackUris = new ArrayList<String>();
+       
+       // jars to wrap as OSGi bundles
        private Map<String, BndWrapper> wrappers = new HashMap<String, BndWrapper>();
 
+       // pattern of OSGi bundles to import
+       private PathMatcher pathMatcher = new AntPathMatcher();
+       private Map<String, String> includes = new HashMap<String, String>();
+       private List<String> excludes = new ArrayList<String>();
+
+       private Boolean mavenGroupIndexes = false;
+
        public void init() {
-               for (BndWrapper wrapper : wrappers.values()) {
-                       if (wrapper.getVersion() == null)
-                               wrapper.setVersion(version);
-               }
+               if (version != null)
+                       for (BndWrapper wrapper : wrappers.values()) {
+                               if (wrapper.getVersion() == null)
+                                       wrapper.setVersion(version);
+                       }
        }
 
        public void destroy() {
@@ -45,6 +68,12 @@ public class ArchiveWrapper implements Runnable {
        }
 
        public void run() {
+               if (mavenGroupIndexes && (version == null))
+                       throw new SlcException(
+                                       "'mavenGroupIndexes' requires 'version' to be set");
+
+               Map<String, Set<Artifact>> binaries = new HashMap<String, Set<Artifact>>();
+               Map<String, Set<Artifact>> sources = new HashMap<String, Set<Artifact>>();
 
                Session distSession = null;
                Session javaSession = null;
@@ -61,40 +90,45 @@ public class ArchiveWrapper implements Runnable {
                                        .getProperty(Property.JCR_DATA).getBinary().getStream());
 
                        ZipEntry zentry = null;
-                       ByteArrayOutputStream out = null;
-                       ByteArrayInputStream in = null;
-                       while ((zentry = zin.getNextEntry()) != null) {
-                               try {
-                                       String name = zentry.getName();
-                                       // if (log.isDebugEnabled())
-                                       // log.debug("Scanning " + name);
-                                       if (wrappers.containsKey(name)) {
-
-                                               BndWrapper wrapper = (BndWrapper) wrappers.get(name);
-                                               // if (wrapper.getVersion() == null)
-                                               // wrapper.setVersion(version);// FIXME stateful?
-
-                                               out = new ByteArrayOutputStream((int) zentry.getSize());
-                                               // we must copy since the stream is closed by BND
-                                               byte[] sourceJarBytes = IOUtils.toByteArray(zin);
-                                               in = new ByteArrayInputStream(sourceJarBytes);
-                                               wrapper.wrapJar(in, out);
-
-                                               Artifact newArtifact = wrapper.getArtifact();
-                                               Node newJarNode = RepoUtils.copyBytesAsArtifact(
-                                                               javaSession.getRootNode(), newArtifact,
-                                                               out.toByteArray());
-                                               osgiFactory.indexNode(newJarNode);
-                                               newJarNode.getSession().save();
-                                               if (log.isDebugEnabled())
-                                                       log.debug("Wrapped " + name + " to "
-                                                                       + newJarNode.getPath());
+                       entries: while ((zentry = zin.getNextEntry()) != null) {
+                               String name = zentry.getName();
+                               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);
+                                       Artifact artifact = wrapZipEntry(javaSession, zentry,
+                                                       sourceJarBytes, wrapper);
+                                       addArtifactToIndex(binaries, wrapper.getGroupId(), artifact);
+                               } else {
+                                       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);
+                                                       byte[] sourceJarBytes = IOUtils.toByteArray(zin);
+                                                       Artifact artifact = importZipEntry(javaSession,
+                                                                       zentry, sourceJarBytes, groupId);
+                                                       if (artifact.getArtifactId().endsWith(".source"))
+                                                               addArtifactToIndex(sources, groupId, artifact);
+                                                       else
+                                                               addArtifactToIndex(binaries, groupId, artifact);
+                                               }
                                        }
-                               } finally {
-                                       IOUtils.closeQuietly(out);
-                                       IOUtils.closeQuietly(in);
                                }
                        }
+
+                       // indexes
+                       if (mavenGroupIndexes && version != null) {
+                               for (String groupId : binaries.keySet()) {
+                                       RepoUtils.writeGroupIndexes(javaSession, "/", groupId,
+                                                       version, binaries.get(groupId),
+                                                       sources.containsKey(groupId) ? sources.get(groupId)
+                                                                       : null);
+                               }
+                       }
+
                } catch (Exception e) {
                        throw new SlcException("Cannot wrap distribution " + uri, e);
                } finally {
@@ -104,15 +138,61 @@ public class ArchiveWrapper implements Runnable {
                }
        }
 
-       // public List<ArtifactDistribution> provides() {
-       // List<ArtifactDistribution> res = new ArrayList<ArtifactDistribution>();
-       // for (BndWrapper bndWrapper : wrappers.values()) {
-       // ArtifactDistribution ad = new ArtifactDistribution(groupId + ":"
-       // + bndWrapper.getName() + ":" + bndWrapper.getVersion());
-       // res.add(ad);
-       // }
-       // return res;
-       // }
+       protected Artifact wrapZipEntry(Session javaSession, ZipEntry zentry,
+                       byte[] sourceJarBytes, BndWrapper wrapper)
+                       throws RepositoryException {
+               ByteArrayOutputStream out = null;
+               ByteArrayInputStream in = null;
+               Node newJarNode;
+               try {
+                       out = new ByteArrayOutputStream((int) zentry.getSize());
+                       in = new ByteArrayInputStream(sourceJarBytes);
+                       wrapper.wrapJar(in, out);
+
+                       Artifact artifact = wrapper.getArtifact();
+                       newJarNode = RepoUtils.copyBytesAsArtifact(
+                                       javaSession.getRootNode(), artifact, out.toByteArray());
+                       osgiFactory.indexNode(newJarNode);
+                       newJarNode.getSession().save();
+                       if (log.isDebugEnabled())
+                               log.debug("Wrapped jar " + zentry.getName() + " to "
+                                               + newJarNode.getPath());
+                       return artifact;
+               } finally {
+                       IOUtils.closeQuietly(in);
+                       IOUtils.closeQuietly(out);
+               }
+       }
+
+       protected Artifact importZipEntry(Session javaSession, ZipEntry zentry,
+                       byte[] sourceJarBytes, String groupId) throws RepositoryException {
+               ByteArrayInputStream in = null;
+               Node newJarNode;
+               try {
+                       in = new ByteArrayInputStream(sourceJarBytes);
+                       NameVersion nameVersion = RepoUtils.readNameVersion(in);
+                       Artifact artifact = new DefaultArtifact(groupId,
+                                       nameVersion.getName(), "jar", nameVersion.getVersion());
+                       newJarNode = RepoUtils.copyBytesAsArtifact(
+                                       javaSession.getRootNode(), artifact, sourceJarBytes);
+                       osgiFactory.indexNode(newJarNode);
+                       newJarNode.getSession().save();
+                       if (log.isDebugEnabled())
+                               log.debug("Imported OSGi bundle " + zentry.getName() + " to "
+                                               + newJarNode.getPath());
+                       return artifact;
+               } finally {
+                       IOUtils.closeQuietly(in);
+               }
+       }
+
+       private void addArtifactToIndex(Map<String, Set<Artifact>> index,
+                       String groupId, Artifact artifact) {
+               if (!index.containsKey(groupId))
+                       index.put(groupId,
+                                       new TreeSet<Artifact>(new ArtifactIdComparator()));
+               index.get(groupId).add(artifact);
+       }
 
        public void setUri(String uri) {
                this.uri = uri;
@@ -130,4 +210,20 @@ public class ArchiveWrapper implements Runnable {
                this.version = version;
        }
 
+       public void setPathMatcher(PathMatcher pathMatcher) {
+               this.pathMatcher = pathMatcher;
+       }
+
+       public void setIncludes(Map<String, String> includes) {
+               this.includes = includes;
+       }
+
+       public void setExcludes(List<String> excludes) {
+               this.excludes = excludes;
+       }
+
+       public void setMavenGroupIndexes(Boolean mavenGroupIndexes) {
+               this.mavenGroupIndexes = mavenGroupIndexes;
+       }
+
 }
index f03a4d74bad0220f0e4a7837d6301b0a18ae261c..00679e2c6247aae4130d33d56372836b0f06df17 100644 (file)
@@ -22,7 +22,7 @@ import aQute.lib.osgi.Builder;
 import aQute.lib.osgi.Constants;
 import aQute.lib.osgi.Jar;
 
-/** Utilities around the BND library, which manipulates OSI meta-data. */
+/** Utilities around the BND library, which manipulates OSGi metadata. */
 public class BndWrapper implements Constants, NameVersion, BeanNameAware {
        private final static Log log = LogFactory.getLog(BndWrapper.class);
 
index 7d25cef8cb77e0a3feb51aa06ae59a50ebc1b42c..80574f8f66d8f27053a81717f8036317c3737674 100644 (file)
@@ -43,7 +43,10 @@ import org.sonatype.aether.util.artifact.DefaultArtifact;
 /**
  * Import all bundles in a zip file (typically an Eclipse distribution) into the
  * workspace.
+ * 
+ * @deprecated Use {@link ArchiveWrapper} instead.
  */
+@Deprecated
 public class ImportBundlesZip implements Runnable {
        private final static Log log = LogFactory.getLog(ImportBundlesZip.class);
        private Repository repository;
@@ -100,8 +103,8 @@ public class ImportBundlesZip implements Runnable {
                                        continue entries;
                                }
 
-                               String bundleName = RepoUtils.extractBundleNameFromSourceName(nv
-                                               .getName());
+                               String bundleName = RepoUtils
+                                               .extractBundleNameFromSourceName(nv.getName());
                                // skip excluded bundles and their sources
                                if (excludedBundles.contains(bundleName))
                                        continue entries;
index bc228285a0b88ad633a93c8a6993cf20075895a1..58f832c0aa69920354660b2ca736458bea28703b 100644 (file)
@@ -38,6 +38,7 @@ import org.argeo.slc.aether.ArtifactIdComparator;
 import org.argeo.slc.jcr.SlcNames;
 import org.argeo.slc.jcr.SlcTypes;
 import org.argeo.slc.repo.ArtifactIndexer;
+import org.argeo.slc.repo.RepoConstants;
 import org.argeo.slc.repo.RepoUtils;
 import org.argeo.slc.repo.maven.MavenConventionsUtils;
 import org.osgi.framework.Constants;
@@ -50,10 +51,6 @@ import org.sonatype.aether.util.artifact.DefaultArtifact;
  * group of OSGi bundles.
  */
 public class NormalizeGroup implements Runnable, SlcNames {
-       public final static String BINARIES_ARTIFACT_ID = "binaries";
-       public final static String SOURCES_ARTIFACT_ID = "sources";
-       public final static String SDK_ARTIFACT_ID = "sdk";
-
        private final static Log log = LogFactory.getLog(NormalizeGroup.class);
 
        private Repository repository;
@@ -190,13 +187,13 @@ public class NormalizeGroup implements Runnable, SlcNames {
                // indexes
                Set<Artifact> indexes = new TreeSet<Artifact>(
                                new ArtifactIdComparator());
-               Artifact indexArtifact = writeIndex(session, BINARIES_ARTIFACT_ID,
+               Artifact indexArtifact = writeIndex(session, RepoConstants.BINARIES_ARTIFACT_ID,
                                binaries);
                indexes.add(indexArtifact);
-               indexArtifact = writeIndex(session, SOURCES_ARTIFACT_ID, sources);
+               indexArtifact = writeIndex(session, RepoConstants.SOURCES_ARTIFACT_ID, sources);
                indexes.add(indexArtifact);
                // sdk
-               writeIndex(session, SDK_ARTIFACT_ID, indexes);
+               writeIndex(session, RepoConstants.SDK_ARTIFACT_ID, indexes);
                if (monitor != null)
                        monitor.worked(1);
        }
@@ -405,8 +402,8 @@ public class NormalizeGroup implements Runnable, SlcNames {
                p.append("<dependency>\n");
                p.append("\t<groupId>").append(groupId).append("</groupId>\n");
                p.append("\t<artifactId>")
-                               .append(ownSymbolicName.endsWith(".source") ? SOURCES_ARTIFACT_ID
-                                               : BINARIES_ARTIFACT_ID).append("</artifactId>\n");
+                               .append(ownSymbolicName.endsWith(".source") ? RepoConstants.SOURCES_ARTIFACT_ID
+                                               : RepoConstants.BINARIES_ARTIFACT_ID).append("</artifactId>\n");
                p.append("\t<version>").append(version).append("</version>\n");
                p.append("\t<type>pom</type>\n");
                p.append("\t<scope>import</scope>\n");