X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;f=org.argeo.slc.repo%2Fsrc%2Forg%2Fargeo%2Fslc%2Frepo%2FModularDistributionIndexer.java;fp=org.argeo.slc.repo%2Fsrc%2Forg%2Fargeo%2Fslc%2Frepo%2FModularDistributionIndexer.java;h=7d854a1c5d23c3e7b0dbb744109b49c6d528c154;hb=825d60c5348dbe3f5be25b0bccf7bdebfe694219;hp=0000000000000000000000000000000000000000;hpb=5e991fff5cba01858dcc5747a27e637325bc5c8e;p=gpl%2Fargeo-jcr.git
diff --git a/org.argeo.slc.repo/src/org/argeo/slc/repo/ModularDistributionIndexer.java b/org.argeo.slc.repo/src/org/argeo/slc/repo/ModularDistributionIndexer.java
new file mode 100644
index 0000000..7d854a1
--- /dev/null
+++ b/org.argeo.slc.repo/src/org/argeo/slc/repo/ModularDistributionIndexer.java
@@ -0,0 +1,213 @@
+package org.argeo.slc.repo;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.StringTokenizer;
+import java.util.jar.JarEntry;
+import java.util.jar.JarInputStream;
+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 org.apache.commons.io.FilenameUtils;
+import org.apache.commons.io.IOUtils;
+import org.argeo.api.cms.CmsLog;
+import org.argeo.jcr.JcrUtils;
+import org.argeo.slc.CategoryNameVersion;
+import org.argeo.slc.DefaultCategoryNameVersion;
+import org.argeo.slc.NameVersion;
+import org.argeo.slc.SlcException;
+import org.argeo.slc.SlcNames;
+import org.argeo.slc.SlcTypes;
+import org.argeo.slc.build.Distribution;
+import org.argeo.slc.repo.maven.AetherUtils;
+import org.eclipse.aether.artifact.Artifact;
+import org.eclipse.aether.artifact.DefaultArtifact;
+import org.osgi.framework.Constants;
+
+/**
+ * Create or update JCR meta-data for an SLC Modular Distribution
+ *
+ * Currently, following types are managed:
+ * * .jar: dependency artifacts with csv index
+ * @Deprecated : .pom: artifact (binaries) that indexes a group, the .pom
+ * file contains a tag "dependencyManagement" that list all modules
+ */
+public class ModularDistributionIndexer implements NodeIndexer, SlcNames {
+ private final static CmsLog log = CmsLog.getLog(ModularDistributionIndexer.class);
+
+ // Constants for csv indexing
+ private final static String INDEX_FILE_NAME = "modularDistribution.csv";
+ private String separator = ",";
+
+ private Manifest manifest;
+
+ public Boolean support(String path) {
+ if (FilenameUtils.getExtension(path).equals("jar"))
+ return true;
+ return false;
+ }
+
+ public void index(Node fileNode) {
+ Binary fileBinary = null;
+ try {
+ String fileNodePath = fileNode.getPath();
+ if (!support(fileNodePath))
+ return;
+
+ if (!fileNode.isNodeType(NodeType.NT_FILE))
+ return;
+
+ Node contentNode = fileNode.getNode(Node.JCR_CONTENT);
+ fileBinary = contentNode.getProperty(Property.JCR_DATA).getBinary();
+
+ MyModularDistribution currDist = null;
+ if (FilenameUtils.getExtension(fileNode.getPath()).equals("jar"))
+ currDist = listModulesFromCsvIndex(fileNode, fileBinary);
+
+ if (fileNode.isNodeType(SlcTypes.SLC_MODULAR_DISTRIBUTION) || currDist == null
+ || !currDist.nameVersions().hasNext())
+ return; // already indexed or no modules found
+ else {
+ 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())
+ log.trace("Indexed " + fileNode + " as modular distribution");
+ } catch (Exception e) {
+ throw new SlcException("Cannot list dependencies from " + fileNode, e);
+ } finally {
+ JcrUtils.closeQuietly(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());
+ if (distNode.hasNode(SLC_MODULES))
+ distNode.getNode(SLC_MODULES).remove();
+ Node modules = distNode.addNode(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 {
+ CategoryNameVersion cnv = (CategoryNameVersion) 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 modules = new ArrayList();
+
+ // meta data
+ manifest = jarIn.getManifest();
+ if (manifest == null) {
+ log.error(fileNode + " has no MANIFEST");
+ return null;
+ }
+ String category = manifest.getMainAttributes().getValue(RepoConstants.SLC_CATEGORY_ID);
+ String name = manifest.getMainAttributes().getValue(Constants.BUNDLE_SYMBOLICNAME);
+ String version = manifest.getMainAttributes().getValue(Constants.BUNDLE_VERSION);
+
+ Artifact distribution = new DefaultArtifact(category, name, "jar", version);
+ // Retrieve the index file
+ JarEntry indexEntry;
+ while ((indexEntry = jarIn.getNextJarEntry()) != null) {
+ String entryName = indexEntry.getName();
+ if (entryName.equals(INDEX_FILE_NAME)) {
+ break;
+ }
+ try {
+ jarIn.closeEntry();
+ } catch (SecurityException se) {
+ log.error("Invalid signature file digest " + "for Manifest main attributes: " + entryName
+ + " while looking for an index in bundle " + name);
+ }
+ }
+ if (indexEntry == null)
+ return null; // Not a modular definition
+
+ if (category == null) {
+ log.warn("Modular definition found but no " + RepoConstants.SLC_CATEGORY_ID + " in " + fileNode);
+ }
+
+ // Process the index
+ reader = new BufferedReader(new InputStreamReader(jarIn));
+ String line = null;
+ while ((line = reader.readLine()) != null) {
+ StringTokenizer st = new StringTokenizer(line, separator);
+ st.nextToken(); // moduleName
+ st.nextToken(); // moduleVersion
+ String relativeUrl = st.nextToken();
+ Artifact currModule = AetherUtils.convertPathToArtifact(relativeUrl, null);
+ modules.add(new DefaultCategoryNameVersion(currModule.getGroupId(), currModule.getArtifactId(),
+ currModule.getVersion()));
+ }
+ return new MyModularDistribution(distribution, modules);
+ } catch (Exception e) {
+ throw new SlcException("Cannot list artifacts", e);
+ } finally {
+ IOUtils.closeQuietly(jarIn);
+ IOUtils.closeQuietly(reader);
+ }
+ }
+
+ /**
+ * A consistent and versioned OSGi distribution, which can be built and tested.
+ */
+ private class MyModularDistribution extends ArtifactDistribution implements ArgeoOsgiDistribution {
+
+ private List modules;
+
+ public MyModularDistribution(Artifact artifact, List modules) {
+ super(artifact);
+ this.modules = modules;
+ }
+
+ public Iterator 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