First working version of modular distribution creation while running the ProcessDistr...
authorBruno Sinou <bsinou@argeo.org>
Thu, 12 Jun 2014 20:58:49 +0000 (20:58 +0000)
committerBruno Sinou <bsinou@argeo.org>
Thu, 12 Jun 2014 20:58:49 +0000 (20:58 +0000)
git-svn-id: https://svn.argeo.org/slc/trunk@7055 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

runtime/org.argeo.slc.repo/src/main/java/org/argeo/slc/repo/ModularDistributionFactory.java [new file with mode: 0644]
runtime/org.argeo.slc.repo/src/main/java/org/argeo/slc/repo/ModularDistributionIndexer.java
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/ArgeoOsgiDistributionImpl.java
runtime/org.argeo.slc.repo/src/main/java/org/argeo/slc/repo/osgi/ProcessDistribution.java

diff --git a/runtime/org.argeo.slc.repo/src/main/java/org/argeo/slc/repo/ModularDistributionFactory.java b/runtime/org.argeo.slc.repo/src/main/java/org/argeo/slc/repo/ModularDistributionFactory.java
new file mode 100644 (file)
index 0000000..db22db6
--- /dev/null
@@ -0,0 +1,550 @@
+package org.argeo.slc.repo;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Iterator;
+import java.util.jar.Attributes;
+import java.util.jar.JarEntry;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.nodetype.NodeType;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.argeo.jcr.JcrUtils;
+import org.argeo.slc.CategorizedNameVersion;
+import org.argeo.slc.NameVersion;
+import org.argeo.slc.SlcException;
+import org.argeo.slc.jcr.SlcNames;
+import org.argeo.slc.jcr.SlcTypes;
+import org.osgi.framework.Constants;
+import org.sonatype.aether.artifact.Artifact;
+import org.sonatype.aether.util.artifact.DefaultArtifact;
+
+/**
+ * Creates a jar bundle from an ArgeoOsgiDistribution. This jar is then
+ * persisted and indexed in a java repository.
+ * 
+ * It does the following <list><li>Creates a Manifest</li><li>Creates files
+ * indexes (csv, feature.xml ...)</li><li>Populate the corresponding jar</li><li>
+ * Save it in the repository</li><li>Index the node and creates corresponding
+ * sha1 and md5 files</li> </list>
+ * 
+ */
+public class ModularDistributionFactory implements Runnable {
+
+       private Session javaSession;
+       private ArgeoOsgiDistribution osgiDistribution;
+       private String modularDistributionSeparator = ",";
+       private String artifactBasePath = RepoConstants.DEFAULT_ARTIFACTS_BASE_PATH;
+       private String artifactType = "jar";
+
+       // Constants
+       private final static String CSV_FILE_NAME = "modularDistribution.csv";
+       private final static String FEATURE_FILE_NAME = "feature.xml";
+       public static int BUFFER_SIZE = 10240;
+
+       /** Convenience constructor with minimal configuration */
+       public ModularDistributionFactory(Session javaSession,
+                       ArgeoOsgiDistribution osgiDistribution) {
+               this.javaSession = javaSession;
+               this.osgiDistribution = osgiDistribution;
+       }
+
+       @Override
+       public void run() {
+               internalCreateDistribution();
+       }
+
+       private void internalCreateDistribution() {
+               byte[] distFile = null;
+               try {
+                       if (artifactType == "jar")
+                               distFile = generateJarFile();
+                       else if (artifactType == "pom")
+                               distFile = generatePomFile();
+                       else
+                               throw new SlcException(
+                                               "Unimplemented distribution azrtiofact type "
+                                                               + artifactType + " for "
+                                                               + osgiDistribution.toString());
+
+                       // Save in java repository
+                       Artifact osgiArtifact = new DefaultArtifact(
+                                       osgiDistribution.getCategory(), osgiDistribution.getName(),
+                                       artifactType, osgiDistribution.getVersion());
+
+                       Node distNode = RepoUtils.copyBytesAsArtifact(
+                                       javaSession.getNode(artifactBasePath), osgiArtifact,
+                                       distFile);
+
+                       // index
+                       indexDistribution(distNode);
+
+                       // Really ?
+                       javaSession.save();
+               } catch (RepositoryException e) {
+                       throw new SlcException(
+                                       "JCR error while persisting modular distribution in JCR "
+                                                       + osgiDistribution.toString(), e);
+               }
+       }
+
+       private byte[] generateJarFile() {
+               ByteArrayOutputStream byteOut = null;
+               JarOutputStream jarOut = null;
+               try {
+                       byteOut = new ByteArrayOutputStream();
+                       jarOut = new JarOutputStream(byteOut, createManifest());
+                       // Create various indexes
+                       addToJar(createCsvDescriptor(), CSV_FILE_NAME, jarOut);
+                       return byteOut.toByteArray();
+               } catch (IOException e) {
+                       throw new SlcException(
+                                       "IO error while generating modular distribution "
+                                                       + osgiDistribution.toString(), e);
+               } finally {
+                       IOUtils.closeQuietly(byteOut);
+                       IOUtils.closeQuietly(jarOut);
+               }
+       }
+
+       private void indexDistribution(Node distNode) throws RepositoryException {
+               distNode.addMixin(SlcTypes.SLC_MODULAR_DISTRIBUTION);
+               distNode.addMixin(SlcTypes.SLC_CATEGORIZED_NAME_VERSION);
+               distNode.setProperty(SlcNames.SLC_CATEGORY,
+                               osgiDistribution.getCategory());
+               distNode.setProperty(SlcNames.SLC_NAME, osgiDistribution.getName());
+               distNode.setProperty(SlcNames.SLC_VERSION,
+                               osgiDistribution.getVersion());
+
+               Node modules = JcrUtils.mkdirs(distNode, SlcNames.SLC_MODULES,
+                               NodeType.NT_UNSTRUCTURED);
+
+               for (Iterator<? extends NameVersion> it = osgiDistribution
+                               .nameVersions(); it.hasNext();)
+                       addModule(modules, it.next());
+       }
+
+       private Manifest createManifest() {
+               Manifest manifest = new Manifest();
+
+               // TODO make this configurable
+               manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION,
+                               "1.0");
+               addManifestAttribute(manifest,
+                               Constants.BUNDLE_REQUIREDEXECUTIONENVIRONMENT, "JavaSE-1.6");
+               addManifestAttribute(manifest, Constants.BUNDLE_VENDOR, "Argeo");
+               addManifestAttribute(manifest, Constants.BUNDLE_MANIFESTVERSION, "2");
+               addManifestAttribute(manifest, "Bundle-License",
+                               "http://www.apache.org/licenses/LICENSE-2.0.txt");
+
+               // TODO define a user friendly name
+               addManifestAttribute(manifest, Constants.BUNDLE_NAME,
+                               osgiDistribution.getName());
+
+               // Categorized name version
+               addManifestAttribute(manifest, RepoConstants.SLC_GROUP_ID,
+                               osgiDistribution.getCategory());
+               addManifestAttribute(manifest, Constants.BUNDLE_SYMBOLICNAME,
+                               osgiDistribution.getName());
+               addManifestAttribute(manifest, Constants.BUNDLE_VERSION,
+                               osgiDistribution.getVersion());
+
+               return manifest;
+       }
+
+       private void addManifestAttribute(Manifest manifest, String name,
+                       String value) {
+               manifest.getMainAttributes().put(new Attributes.Name(name), value);
+       }
+
+       private byte[] createCsvDescriptor() {
+               Writer writer = null;
+               try {
+                       // FIXME remove use of tmp file.
+                       File tmpFile = File.createTempFile("modularDistribution", "csv");
+                       tmpFile.deleteOnExit();
+                       writer = new FileWriter(tmpFile);
+                       // Populate the file
+                       for (Iterator<? extends NameVersion> it = osgiDistribution
+                                       .nameVersions(); it.hasNext();)
+                               writer.write(getCsvLine(it.next()));
+                       writer.flush();
+                       return FileUtils.readFileToByteArray(tmpFile);
+               } catch (Exception e) {
+                       throw new SlcException(
+                                       "unable to create csv distribution file for "
+                                                       + osgiDistribution.toString(), e);
+               } finally {
+                       IOUtils.closeQuietly(writer);
+               }
+       }
+
+       private byte[] createFeatureDescriptor() {
+               // Directly retrieved from Argeo maven plugin
+               // Does not work due to the lack of org.codehaus.plexus/plexus-archiver
+               // third party dependency
+
+               throw new SlcException("Unimplemented method");
+
+               // // protected void writeFeatureDescriptor() throws
+               // MojoExecutionException {
+               // File featureDesc = File.createTempFile("feature", "xml");
+               // featureDesc.deleteOnExit();
+               //
+               // Writer writer = null;
+               // try {
+               // writer = new FileWriter(featureDesc);
+               // PrettyPrintXMLWriter xmlWriter = new PrettyPrintXMLWriter(writer);
+               // xmlWriter.startElement("feature");
+               // xmlWriter.addAttribute("id", project.getArtifactId());
+               // xmlWriter.addAttribute("label", project.getName());
+               //
+               // // Version
+               // String projectVersion = project.getVersion();
+               // int indexSnapshot = projectVersion.indexOf("-SNAPSHOT");
+               // if (indexSnapshot > -1)
+               // projectVersion = projectVersion.substring(0, indexSnapshot);
+               // projectVersion = projectVersion + ".qualifier";
+               //
+               // // project.
+               // xmlWriter.addAttribute("version", projectVersion);
+               //
+               // Organization organization = project.getOrganization();
+               // if (organization != null && organization.getName() != null)
+               // xmlWriter.addAttribute("provider-name", organization.getName());
+               //
+               // if (project.getDescription() != null || project.getUrl() != null) {
+               // xmlWriter.startElement("description");
+               // if (project.getUrl() != null)
+               // xmlWriter.addAttribute("url", project.getUrl());
+               // if (project.getDescription() != null)
+               // xmlWriter.writeText(project.getDescription());
+               // xmlWriter.endElement();// description
+               // }
+               //
+               // if (feature != null && feature.getCopyright() != null
+               // || (organization != null && organization.getUrl() != null)) {
+               // xmlWriter.startElement("copyright");
+               // if (organization != null && organization.getUrl() != null)
+               // xmlWriter.addAttribute("url", organization.getUrl());
+               // if (feature.getCopyright() != null)
+               // xmlWriter.writeText(feature.getCopyright());
+               // xmlWriter.endElement();// copyright
+               // }
+               //
+               // if (feature != null && feature.getUpdateSite() != null) {
+               // xmlWriter.startElement("url");
+               // xmlWriter.startElement("update");
+               // xmlWriter.addAttribute("url", feature.getUpdateSite());
+               // xmlWriter.endElement();// update
+               // xmlWriter.endElement();// url
+               // }
+               //
+               // List licenses = project.getLicenses();
+               // if (licenses.size() > 0) {
+               // // take the first one
+               // License license = (License) licenses.get(0);
+               // xmlWriter.startElement("license");
+               //
+               // if (license.getUrl() != null)
+               // xmlWriter.addAttribute("url", license.getUrl());
+               // if (license.getComments() != null)
+               // xmlWriter.writeText(license.getComments());
+               // else if (license.getName() != null)
+               // xmlWriter.writeText(license.getName());
+               // xmlWriter.endElement();// license
+               // }
+               //
+               // // deploymentRepository.pathOf(null);
+               // if (jarDirectory == null) {
+               // Set dependencies = mavenDependencyManager
+               // .getTransitiveProjectDependencies(project, remoteRepos,
+               // local);
+               // // // protected void writeFeatureDescriptor() throws
+               // MojoExecutionException {
+               // File featureDesc = File.createTempFile("feature", "xml");
+               // featureDesc.deleteOnExit();
+               //
+               // Writer writer = null;
+               // try {
+               // writer = new FileWriter(featureDesc);
+               // PrettyPrintXMLWriter xmlWriter = new PrettyPrintXMLWriter(writer);
+               // xmlWriter.startElement("feature");
+               // xmlWriter.addAttribute("id", project.getArtifactId());
+               // xmlWriter.addAttribute("label", project.getName());
+               //
+               // // Version
+               // String projectVersion = project.getVersion();
+               // int indexSnapshot = projectVersion.indexOf("-SNAPSHOT");
+               // if (indexSnapshot > -1)
+               // projectVersion = projectVersion.substring(0, indexSnapshot);
+               // projectVersion = projectVersion + ".qualifier";
+               //
+               // // project.
+               // xmlWriter.addAttribute("version", projectVersion);
+               //
+               // Organization organization = project.getOrganization();
+               // if (organization != null && organization.getName() != null)
+               // xmlWriter.addAttribute("provider-name", organization.getName());
+               //
+               // if (project.getDescription() != null || project.getUrl() != null) {
+               // xmlWriter.startElement("description");
+               // if (project.getUrl() != null)
+               // xmlWriter.addAttribute("url", project.getUrl());
+               // if (project.getDescription() != null)
+               // xmlWriter.writeText(project.getDescription());
+               // xmlWriter.endElement();// description
+               // }
+               //
+               // if (feature != null && feature.getCopyright() != null
+               // || (organization != null && organization.getUrl() != null)) {
+               // xmlWriter.startElement("copyright");
+               // if (organization != null && organization.getUrl() != null)
+               // xmlWriter.addAttribute("url", organization.getUrl());
+               // if (feature.getCopyright() != null)
+               // xmlWriter.writeText(feature.getCopyright());
+               // xmlWriter.endElement();// copyright
+               // }
+               //
+               // if (feature != null && feature.getUpdateSite() != null) {
+               // xmlWriter.startElement("url");
+               // xmlWriter.startElement("update");
+               // xmlWriter.addAttribute("url", feature.getUpdateSite());
+               // xmlWriter.endElement();// update
+               // xmlWriter.endElement();// url
+               // }
+               //
+               // List licenses = project.getLicenses();
+               // if (licenses.size() > 0) {
+               // // take the first one
+               // License license = (License) licenses.get(0);
+               // xmlWriter.startElement("license");
+               //
+               // if (license.getUrl() != null)
+               // xmlWriter.addAttribute("url", license.getUrl());
+               // if (license.getComments() != null)
+               // xmlWriter.writeText(license.getComments());
+               // else if (license.getName() != null)
+               // xmlWriter.writeText(license.getName());
+               // xmlWriter.endElement();// license
+               // }
+               //
+               // // deploymentRepository.pathOf(null);
+               // if (jarDirectory == null) {
+               // Set dependencies = mavenDependencyManager
+               // .getTransitiveProjectDependencies(project, remoteRepos,
+               // local);
+               // for (Iterator it = dependencies.iterator(); it.hasNext();) {
+               // Artifact artifact = (Artifact) it.next();
+               // writeFeaturePlugin(xmlWriter, artifact.getFile());
+               // }
+               // } else {
+               // // TODO: filter jars
+               // File[] jars = jarDirectory.listFiles();
+               // if (jars == null)
+               // throw new MojoExecutionException("No jar found in "
+               // + jarDirectory);
+               // for (int i = 0; i < jars.length; i++) {
+               // writeFeaturePlugin(xmlWriter, jars[i]);
+               // }
+               // }
+               //
+               // xmlWriter.endElement();// feature
+               //
+               // if (getLog().isDebugEnabled())
+               // getLog().debug("Wrote Eclipse feature descriptor.");
+               // } catch (Exception e) {
+               // throw new MojoExecutionException("Cannot write feature descriptor",
+               // e);
+               // } finally {
+               // IOUtil.close(writer);
+               // }for (Iterator it = dependencies.iterator(); it.hasNext();) {
+               // Artifact artifact = (Artifact) it.next();
+               // writeFeaturePlugin(xmlWriter, artifact.getFile());
+               // }
+               // } else {
+               // // TODO: filter jars
+               // File[] jars = jarDirectory.listFiles();
+               // if (jars == null)
+               // throw new MojoExecutionException("No jar found in "
+               // + jarDirectory);
+               // for (int i = 0; i < jars.length; i++) {
+               // writeFeaturePlugin(xmlWriter, jars[i]);
+               // }
+               // }
+               //
+               // xmlWriter.endElement();// feature
+               //
+               // if (getLog().isDebugEnabled())
+               // getLog().debug("Wrote Eclipse feature descriptor.");
+               // } catch (Exception e) {
+               // throw new MojoExecutionException("Cannot write feature descriptor",
+               // e);
+               // } finally {
+               // IOUtil.close(writer);
+               // }
+       }
+
+       /** Create an Aether like distribution artifact */
+       private byte[] generatePomFile() {
+               StringBuilder b = new StringBuilder();
+               // XML header
+               b.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+               b.append("<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd\">\n");
+               b.append("<modelVersion>4.0.0</modelVersion>");
+
+               // Artifact
+               b.append("<groupId>").append(osgiDistribution.getCategory())
+                               .append("</groupId>\n");
+               b.append("<artifactId>").append(osgiDistribution.getName())
+                               .append("</artifactId>\n");
+               b.append("<version>").append(osgiDistribution.getVersion())
+                               .append("</version>\n");
+               b.append("<packaging>pom</packaging>\n");
+               // p.append("<name>").append("Bundle Name").append("</name>\n");
+               // p.append("<description>").append("Bundle Description").append("</description>\n");
+
+               // Dependencies
+               b.append("<dependencies>\n");
+               for (Iterator<? extends NameVersion> it = osgiDistribution
+                               .nameVersions(); it.hasNext();) {
+                       NameVersion nameVersion = it.next();
+                       if (!(nameVersion instanceof CategorizedNameVersion))
+                               throw new SlcException("Unsupported type "
+                                               + nameVersion.getClass());
+                       CategorizedNameVersion nv = (CategorizedNameVersion) nameVersion;
+                       b.append(getDependencySnippet(nv, false));
+               }
+               b.append("</dependencies>\n");
+
+               // Dependency management
+               b.append("<dependencyManagement>\n");
+               b.append("<dependencies>\n");
+
+               for (Iterator<? extends NameVersion> it = osgiDistribution
+                               .nameVersions(); it.hasNext();)
+                       b.append(getDependencySnippet((CategorizedNameVersion) it.next(),
+                                       true));
+               b.append("</dependencies>\n");
+               b.append("</dependencyManagement>\n");
+
+               b.append("</project>\n");
+               return b.toString().getBytes();
+       }
+
+       private String getDependencySnippet(CategorizedNameVersion cnv,
+                       boolean includeVersion) { // , String type, String scope
+               StringBuilder b = new StringBuilder();
+               b.append("<dependency>\n");
+               b.append("\t<groupId>").append(cnv.getCategory())
+                               .append("</groupId>\n");
+               b.append("\t<artifactId>").append(cnv.getName())
+                               .append("</artifactId>\n");
+               if (includeVersion)
+                       b.append("\t<version>").append(cnv.getVersion())
+                                       .append("</version>\n");
+               // if (type!= null)
+               // p.append("\t<type>").append(type).append("</type>\n");
+               // if (type!= null)
+               // p.append("\t<scope>").append(scope).append("</scope>\n");
+               b.append("</dependency>\n");
+               return b.toString();
+       }
+
+       // Helpers
+       private Node addModule(Node modules, NameVersion nameVersion)
+                       throws RepositoryException {
+               CategorizedNameVersion cnv = (CategorizedNameVersion) nameVersion;
+               Node moduleCoord = null;
+               // TODO solve the same name issue
+               // if (modules.hasNode(cnv.getName()))
+               // moduleCoord = modules.getNode(cnv.getName());
+               // else {
+               moduleCoord = modules.addNode(cnv.getName(),
+                               SlcTypes.SLC_MODULE_COORDINATES);
+               moduleCoord.setProperty(SlcNames.SLC_CATEGORY, cnv.getCategory());
+               moduleCoord.setProperty(SlcNames.SLC_NAME, cnv.getName());
+               moduleCoord.setProperty(SlcNames.SLC_VERSION, cnv.getVersion());
+               // }
+               return moduleCoord;
+       }
+
+       private void addToJar(byte[] content, String name, JarOutputStream target)
+                       throws IOException {
+               ByteArrayInputStream in = null;
+               try {
+                       target.putNextEntry(new JarEntry(name));
+                       in = new ByteArrayInputStream(content);
+                       byte[] buffer = new byte[1024];
+                       while (true) {
+                               int count = in.read(buffer);
+                               if (count == -1)
+                                       break;
+                               target.write(buffer, 0, count);
+                       }
+                       target.closeEntry();
+               } finally {
+                       IOUtils.closeQuietly(in);
+               }
+       }
+
+       private String getCsvLine(NameVersion nameVersion)
+                       throws RepositoryException {
+               if (!(nameVersion instanceof CategorizedNameVersion))
+                       throw new SlcException("Unsupported type " + nameVersion.getClass());
+               CategorizedNameVersion cnv = (CategorizedNameVersion) nameVersion;
+               StringBuilder builder = new StringBuilder();
+
+               builder.append(cnv.getName());
+               builder.append(modularDistributionSeparator);
+               builder.append(nameVersion.getVersion());
+               builder.append(modularDistributionSeparator);
+               builder.append(cnv.getCategory().replace('.', '/'));
+               // MavenConventionsUtils.groupPath("", cnv.getCategory());
+               builder.append('/');
+               builder.append(cnv.getName());
+               builder.append('/');
+               builder.append(cnv.getVersion());
+               builder.append('/');
+               builder.append(cnv.getName());
+               builder.append('-');
+               builder.append(cnv.getVersion());
+               builder.append('.');
+               // TODO make this dynamic
+               builder.append("jar");
+               builder.append("\n");
+
+               return builder.toString();
+       }
+
+       public void setJavaSession(Session javaSession) {
+               this.javaSession = javaSession;
+       }
+
+       public void setOsgiDistribution(ArgeoOsgiDistribution osgiDistribution) {
+               this.osgiDistribution = osgiDistribution;
+       }
+
+       public void setModularDistributionSeparator(
+                       String modularDistributionSeparator) {
+               this.modularDistributionSeparator = modularDistributionSeparator;
+       }
+
+       public void setArtifactBasePath(String artifactBasePath) {
+               this.artifactBasePath = artifactBasePath;
+       }
+
+       public void setArtifactType(String artifactType) {
+               this.artifactType = artifactType;
+       }
+}
\ No newline at end of file
index 59c6b31f37b775cd6f9416acd0dff203135efe2a..3070b9b757ef909038c8345c17de2c9795d2ac16 100644 (file)
@@ -5,12 +5,10 @@ import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.Comparator;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Properties;
-import java.util.Set;
 import java.util.StringTokenizer;
-import java.util.TreeSet;
 import java.util.jar.JarEntry;
 import java.util.jar.JarInputStream;
 import java.util.jar.Manifest;
@@ -18,6 +16,7 @@ import java.util.jar.Manifest;
 import javax.jcr.Binary;
 import javax.jcr.Node;
 import javax.jcr.Property;
+import javax.jcr.RepositoryException;
 import javax.jcr.nodetype.NodeType;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
@@ -29,9 +28,10 @@ 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.NameVersion;
 import org.argeo.slc.SlcException;
 import org.argeo.slc.aether.AetherUtils;
-import org.argeo.slc.aether.ArtifactIdComparator;
+import org.argeo.slc.build.Distribution;
 import org.argeo.slc.jcr.SlcNames;
 import org.argeo.slc.jcr.SlcTypes;
 import org.osgi.framework.Constants;
@@ -68,19 +68,13 @@ public class ModularDistributionIndexer implements NodeIndexer, SlcNames {
        }
 
        private Manifest manifest;
-       // private String symbolicName;
-       // private String version;
-       // private List<Artifact> artifacts;
 
-       private Comparator<Artifact> artifactComparator = new ArtifactIdComparator();
-
-       // private Set<Artifact> artifacts = new
-       // TreeSet<Artifact>(artifactComparator);
+       // private Comparator<Artifact> artifactComparator = new
+       // ArtifactIdComparator();
 
        public Boolean support(String path) {
                if (FilenameUtils.getExtension(path).equals("jar"))
                        return true;
-
                if (FilenameUtils.getExtension(path).equals("pom")
                                && BINARIES_ARTIFACTS_NAME.contains(FilenameUtils.getName(path)
                                                .split("-")[0]))
@@ -89,7 +83,6 @@ public class ModularDistributionIndexer implements NodeIndexer, SlcNames {
        }
 
        public void index(Node fileNode) {
-               // JarInputStream jarIn = null;
                Binary fileBinary = null;
                try {
 
@@ -100,57 +93,27 @@ public class ModularDistributionIndexer implements NodeIndexer, SlcNames {
                        if (!fileNode.isNodeType(NodeType.NT_FILE))
                                return;
 
-                       // Session jcrSession = fileNode.getSession();
                        Node contentNode = fileNode.getNode(Node.JCR_CONTENT);
                        fileBinary = contentNode.getProperty(Property.JCR_DATA).getBinary();
 
-                       Set<Artifact> artifacts = new TreeSet<Artifact>(artifactComparator);
-
-                       MyCategorizedNameVersion currCatNV = null;
-
+                       MyModularDistribution currDist = null;
                        if (FilenameUtils.getExtension(fileNode.getPath()).equals("jar"))
-                               currCatNV = listModulesFromCsvIndex(artifacts, fileNode,
-                                               fileBinary);
+                               currDist = listModulesFromCsvIndex(fileNode, fileBinary);
                        else if (FilenameUtils.getExtension(fileNode.getPath()).equals(
                                        "pom"))
-                               currCatNV = listModulesFromPomIndex(artifacts, fileNode,
-                                               fileBinary);
+                               currDist = listModulesFromPomIndex(fileNode, fileBinary);
 
-                       if (artifacts.isEmpty())
-                               return; // no modules found
+                       if (fileNode.isNodeType(SlcTypes.SLC_MODULAR_DISTRIBUTION)
+                                       || currDist == null || !currDist.nameVersions().hasNext())
+                               return; // already indexed or no modules found
                        else {
-                               Node modules;
-                               if (fileNode.isNodeType(SlcTypes.SLC_MODULAR_DISTRIBUTION)) {
-                                       modules = fileNode.getNode(SlcNames.SLC_MODULES);
-                               } else {
-                                       fileNode.addMixin(SlcTypes.SLC_MODULAR_DISTRIBUTION);
-                                       fileNode.addMixin(SlcTypes.SLC_CATEGORIZED_NAME_VERSION);
-                                       if (currCatNV.getCategory() != null)
-                                               fileNode.setProperty(SLC_CATEGORY,
-                                                               currCatNV.getCategory());
-                                       fileNode.setProperty(SLC_NAME, currCatNV.getName());
-                                       fileNode.setProperty(SLC_VERSION, currCatNV.getVersion());
-                                       modules = JcrUtils.mkdirs(fileNode, SlcNames.SLC_MODULES,
-                                                       NodeType.NT_UNSTRUCTURED);
-                               }
-
-                               for (Artifact artifact : artifacts) {
-                                       // TODO clean this once an overwrite policy has been
-                                       // decided.
-                                       if (!modules.hasNode(artifact.getArtifactId())) {
-                                               Node moduleCoord = modules.addNode(
-                                                               artifact.getArtifactId(),
-                                                               SlcTypes.SLC_MODULE_COORDINATES);
-                                               moduleCoord.setProperty(SlcNames.SLC_NAME,
-                                                               artifact.getArtifactId());
-                                               moduleCoord.setProperty(SlcNames.SLC_VERSION,
-                                                               artifact.getVersion());
-                                               String groupId = artifact.getGroupId();
-                                               if (groupId != null && !"".equals(groupId.trim()))
-                                                       moduleCoord.setProperty(SlcNames.SLC_CATEGORY,
-                                                                       artifact.getGroupId());
-                                       }
-                               }
+                               fileNode.addMixin(SlcTypes.SLC_MODULAR_DISTRIBUTION);
+                               fileNode.addMixin(SlcTypes.SLC_CATEGORIZED_NAME_VERSION);
+                               if (currDist.getCategory() != null)
+                                       fileNode.setProperty(SLC_CATEGORY, currDist.getCategory());
+                               fileNode.setProperty(SLC_NAME, currDist.getName());
+                               fileNode.setProperty(SLC_VERSION, currDist.getVersion());
+                               indexDistribution(currDist, fileNode);
                        }
 
                        if (log.isTraceEnabled())
@@ -161,26 +124,58 @@ public class ModularDistributionIndexer implements NodeIndexer, SlcNames {
                }
        }
 
-       protected MyCategorizedNameVersion listModulesFromCsvIndex(
-                       Set<Artifact> artifacts, Node fileNode, Binary fileBinary) {
+       private void indexDistribution(ArgeoOsgiDistribution osgiDist, Node distNode)
+                       throws RepositoryException {
+               distNode.addMixin(SlcTypes.SLC_MODULAR_DISTRIBUTION);
+               distNode.addMixin(SlcTypes.SLC_CATEGORIZED_NAME_VERSION);
+               distNode.setProperty(SlcNames.SLC_CATEGORY, osgiDist.getCategory());
+               distNode.setProperty(SlcNames.SLC_NAME, osgiDist.getName());
+               distNode.setProperty(SlcNames.SLC_VERSION, osgiDist.getVersion());
+               Node modules = JcrUtils.mkdirs(distNode, SlcNames.SLC_MODULES,
+                               NodeType.NT_UNSTRUCTURED);
+
+               for (Iterator<? extends NameVersion> it = osgiDist.nameVersions(); it
+                               .hasNext();)
+                       addModule(modules, it.next());
+       }
+
+       // Helpers
+       private Node addModule(Node modules, NameVersion nameVersion)
+                       throws RepositoryException {
+               CategorizedNameVersion cnv = (CategorizedNameVersion) nameVersion;
+               Node moduleCoord = null;
+               moduleCoord = modules.addNode(cnv.getName(),
+                               SlcTypes.SLC_MODULE_COORDINATES);
+               moduleCoord.setProperty(SlcNames.SLC_CATEGORY, cnv.getCategory());
+               moduleCoord.setProperty(SlcNames.SLC_NAME, cnv.getName());
+               moduleCoord.setProperty(SlcNames.SLC_VERSION, cnv.getVersion());
+               return moduleCoord;
+       }
+
+       private MyModularDistribution listModulesFromCsvIndex(Node fileNode,
+                       Binary fileBinary) {
                JarInputStream jarIn = null;
                BufferedReader reader = null;
                try {
                        jarIn = new JarInputStream(fileBinary.getStream());
 
+                       List<CategorizedNameVersion> modules = new ArrayList<CategorizedNameVersion>();
+
                        // meta data
                        manifest = jarIn.getManifest();
                        if (manifest == null) {
                                log.error(fileNode + " has no MANIFEST");
                                return null;
                        }
-                       String symbolicName = manifest.getMainAttributes().getValue(
+                       String category = manifest.getMainAttributes().getValue(
+                                       RepoConstants.SLC_GROUP_ID);
+                       String name = manifest.getMainAttributes().getValue(
                                        Constants.BUNDLE_SYMBOLICNAME);
                        String version = manifest.getMainAttributes().getValue(
                                        Constants.BUNDLE_VERSION);
-                       String category = manifest.getMainAttributes().getValue(
-                                       "SLC-GroupId");
 
+                       Artifact distribution = new DefaultArtifact(category, name, "pom",
+                                       version);
                        // Retrieve the index file
                        JarEntry indexEntry;
                        while ((indexEntry = jarIn.getNextJarEntry()) != null) {
@@ -193,8 +188,7 @@ public class ModularDistributionIndexer implements NodeIndexer, SlcNames {
                                } catch (SecurityException se) {
                                        log.error("Invalid signature file digest "
                                                        + "for Manifest main attributes: " + entryName
-                                                       + " while looking for an index in bundle "
-                                                       + symbolicName);
+                                                       + " while looking for an index in bundle " + name);
                                }
                        }
                        if (indexEntry == null)
@@ -208,13 +202,13 @@ public class ModularDistributionIndexer implements NodeIndexer, SlcNames {
                                st.nextToken(); // moduleName
                                st.nextToken(); // moduleVersion
                                String relativeUrl = st.nextToken();
-                               artifacts.add(AetherUtils.convertPathToArtifact(relativeUrl,
-                                               null));
-                               // if (log.isTraceEnabled())
-                               // log.trace("Processed dependency: " + line);
+                               Artifact currModule = AetherUtils.convertPathToArtifact(
+                                               relativeUrl, null);
+                               modules.add(new MyCategorizedNameVersion(currModule
+                                               .getGroupId(), currModule.getArtifactId(), currModule
+                                               .getVersion()));
                        }
-
-                       return new MyCategorizedNameVersion(category, symbolicName, version);
+                       return new MyModularDistribution(distribution, modules);
                } catch (Exception e) {
                        throw new SlcException("Cannot list artifacts", e);
                } finally {
@@ -223,16 +217,16 @@ public class ModularDistributionIndexer implements NodeIndexer, SlcNames {
                }
        }
 
-       protected MyCategorizedNameVersion listModulesFromPomIndex(
-                       Set<Artifact> artifacts, Node fileNode, Binary fileBinary) {
+       private MyModularDistribution listModulesFromPomIndex(Node fileNode,
+                       Binary fileBinary) {
                InputStream input = null;
+               List<CategorizedNameVersion> modules = new ArrayList<CategorizedNameVersion>();
                try {
                        input = fileBinary.getStream();
 
                        DocumentBuilder documentBuilder = DocumentBuilderFactory
                                        .newInstance().newDocumentBuilder();
                        Document doc = documentBuilder.parse(input);
-
                        // properties
                        Properties props = new Properties();
                        // props.setProperty("project.version",
@@ -262,29 +256,8 @@ public class ModularDistributionIndexer implements NodeIndexer, SlcNames {
                                                .getTextContent().trim();
                                String version = dependency.getElementsByTagName("version")
                                                .item(0).getTextContent().trim();
-                               // if (version.startsWith("${")) {
-                               // String versionKey = version.substring(0,
-                               // version.length() - 1).substring(2);
-                               // if (!props.containsKey(versionKey))
-                               // throw new SlcException("Cannot interpret version "
-                               // + version);
-                               // version = props.getProperty(versionKey);
-                               // }
-                               // NodeList scopes = dependency.getElementsByTagName("scope");
-                               // if (scopes.getLength() > 0
-                               // && scopes.item(0).getTextContent().equals("import")) {
-                               // // recurse
-                               // gatherPomDependencies(aetherTemplate, artifacts,
-                               // new DefaultArtifact(groupId, artifactId, "pom",
-                               // version));
-                               // } else {
-                               // TODO: deal with scope?
-                               // TODO: deal with type
-                               String type = "jar";
-                               Artifact artifact = new DefaultArtifact(groupId, artifactId,
-                                               type, version);
-                               artifacts.add(artifact);
-                               // }
+                               modules.add(new MyCategorizedNameVersion(groupId, artifactId,
+                                               version));
                        }
 
                        String groupId = doc.getElementsByTagName("groupId").item(0)
@@ -294,8 +267,10 @@ public class ModularDistributionIndexer implements NodeIndexer, SlcNames {
                        String version = doc.getElementsByTagName("version").item(0)
                                        .getTextContent().trim();
 
-                       return new MyCategorizedNameVersion(groupId, artifactId, version);
+                       Artifact currDist = new DefaultArtifact(groupId, artifactId, "pom",
+                                       version);
 
+                       return new MyModularDistribution(currDist, modules);
                } catch (Exception e) {
                        throw new SlcException("Cannot process pom " + fileNode, e);
                } finally {
@@ -303,11 +278,6 @@ public class ModularDistributionIndexer implements NodeIndexer, SlcNames {
                }
        }
 
-       /** Separator used to parse the tabular file, default is "," */
-       public void setSeparator(String modulesUrlSeparator) {
-               this.separator = modulesUrlSeparator;
-       }
-
        /** The created modular distribution */
        private static class MyCategorizedNameVersion extends DefaultNameVersion
                        implements CategorizedNameVersion {
@@ -323,4 +293,40 @@ public class ModularDistributionIndexer implements NodeIndexer, SlcNames {
                        return category;
                }
        }
+
+       /**
+        * A consistent and versioned OSGi distribution, which can be built and
+        * tested.
+        */
+       private class MyModularDistribution extends ArtifactDistribution implements
+                       ArgeoOsgiDistribution {
+
+               private List<CategorizedNameVersion> modules;
+
+               public MyModularDistribution(Artifact artifact,
+                               List<CategorizedNameVersion> modules) {
+                       super(artifact);
+                       this.modules = modules;
+               }
+
+               public Iterator<CategorizedNameVersion> nameVersions() {
+                       return modules.iterator();
+               }
+
+               // Modular distribution interface methods. Not yet used.
+               public Distribution getModuleDistribution(String moduleName,
+                               String moduleVersion) {
+                       return null;
+               }
+
+               public Object getModulesDescriptor(String descriptorType) {
+                       return null;
+               }
+       }
+
+       /** Separator used to parse the tabular file, default is "," */
+       public void setSeparator(String modulesUrlSeparator) {
+               this.separator = modulesUrlSeparator;
+       }
+
 }
\ No newline at end of file
index 7a81e71022449471e55a4f62801fa28cc8248508..4358e9865017ebd99db230f6c6ba554bc98c8086 100644 (file)
@@ -31,4 +31,7 @@ public interface RepoConstants {
        public final static String BINARIES_ARTIFACT_ID = "binaries";
        public final static String SOURCES_ARTIFACT_ID = "sources";
        public final static String SDK_ARTIFACT_ID = "sdk";
+       
+       // TODO might exists somewhere else
+       public final static String SLC_GROUP_ID = "SLC-GroupId";
 }
index b0e65bce51612e757daedc4265c343ad9b620f9e..1aee15835ba9551a7fe5b91bdcad2190ea526ad3 100644 (file)
@@ -483,7 +483,7 @@ public class RepoUtils implements ArgeoNames, SlcNames {
 
        /**
         * Write group indexes: 'binaries' lists all bundles and their versions,
-        * 'sources' list theire sources, and 'sdk' aggregates both.
+        * 'sources' list their sources, and 'sdk' aggregates both.
         */
        public static void writeGroupIndexes(Session session,
                        String artifactBasePath, String groupId, String version,
index 4591598df82f668625083ae8f20ffaf40b3068cc..08746b5e20032d9e0f8f4c4c0ea23e8f61d6b638 100644 (file)
@@ -69,17 +69,6 @@ public class ArgeoOsgiDistributionImpl extends ArtifactDistribution implements
 
        }
 
-       public Distribution getModuleDistribution(String moduleName,
-                       String moduleVersion) {
-               // NameVersion searched = new DefaultNameVersion(moduleName,
-               // moduleVersion);
-               // for (Distribution ad : modules) {
-               // if (ad.equals(searched))
-               // return ad;
-               // }
-               return null;
-       }
-
        public Iterator<NameVersion> nameVersions() {
                List<NameVersion> nameVersions = new ArrayList<NameVersion>();
                for (Object module : modules) {
@@ -109,13 +98,25 @@ public class ArgeoOsgiDistributionImpl extends ArtifactDistribution implements
                }
        }
 
+       // Modular distribution interface methods. Not yet used.
+       public Distribution getModuleDistribution(String moduleName,
+                       String moduleVersion) {
+               // NameVersion searched = new DefaultNameVersion(moduleName,
+               // moduleVersion);
+               // for (Distribution ad : modules) {
+               // if (ad.equals(searched))
+               // return ad;
+               // }
+               return null;
+       }
+
        public Object getModulesDescriptor(String descriptorType) {
                // TODO Auto-generated method stub
                return null;
        }
 
+       /* DEPENDENCY INJECTION */
        public void setModules(List<Object> modules) {
                this.modules = modules;
        }
-
 }
index bca8356c92ba70b1f2578d6233bd5809bc685980..d852fb623b249fe9a41312797c484b5db4a139b8 100644 (file)
@@ -12,6 +12,7 @@ import org.argeo.slc.CategorizedNameVersion;
 import org.argeo.slc.NameVersion;
 import org.argeo.slc.SlcException;
 import org.argeo.slc.repo.ArgeoOsgiDistribution;
+import org.argeo.slc.repo.ModularDistributionFactory;
 import org.argeo.slc.repo.OsgiFactory;
 import org.argeo.slc.repo.maven.MavenConventionsUtils;
 import org.sonatype.aether.artifact.Artifact;
@@ -33,8 +34,15 @@ public class ProcessDistribution implements Runnable {
                                        .nameVersions(); it.hasNext();)
                                processNameVersion(javaSession, it.next());
 
-                       // TODO generate distribution indexes (pom.xml, P2, OBR)
+                       ModularDistributionFactory mdf = new ModularDistributionFactory(
+                                       javaSession, osgiDistribution);
+                       mdf.run();
+                       // javaSession.save();
+
                        // osgiFactory.indexNode(node);
+                       // Node artifact = createDistributionArtifact(javaSession,
+                       // osgiDistribution);
+
                } catch (RepositoryException e) {
                        throw new SlcException("Cannot process distribution "
                                        + osgiDistribution, e);
@@ -65,9 +73,9 @@ public class ProcessDistribution implements Runnable {
                        if (log.isDebugEnabled())
                                log.debug("Already available : " + nv);
                }
-
        }
 
+       /* DEPENDENCY INJECTION */
        public void setOsgiDistribution(ArgeoOsgiDistribution osgiDistribution) {
                this.osgiDistribution = osgiDistribution;
        }
@@ -75,5 +83,4 @@ public class ProcessDistribution implements Runnable {
        public void setOsgiFactory(OsgiFactory osgiFactory) {
                this.osgiFactory = osgiFactory;
        }
-
-}
+}
\ No newline at end of file