1 package org
.argeo
.slc
.repo
;
3 import java
.io
.BufferedReader
;
4 import java
.io
.InputStreamReader
;
5 import java
.util
.ArrayList
;
6 import java
.util
.Iterator
;
8 import java
.util
.StringTokenizer
;
9 import java
.util
.jar
.JarEntry
;
10 import java
.util
.jar
.JarInputStream
;
11 import java
.util
.jar
.Manifest
;
13 import javax
.jcr
.Binary
;
14 import javax
.jcr
.Node
;
15 import javax
.jcr
.Property
;
16 import javax
.jcr
.RepositoryException
;
17 import javax
.jcr
.nodetype
.NodeType
;
19 import org
.apache
.commons
.io
.FilenameUtils
;
20 import org
.apache
.commons
.io
.IOUtils
;
21 import org
.argeo
.api
.cms
.CmsLog
;
22 import org
.argeo
.jcr
.JcrUtils
;
23 import org
.argeo
.slc
.CategoryNameVersion
;
24 import org
.argeo
.slc
.DefaultCategoryNameVersion
;
25 import org
.argeo
.slc
.NameVersion
;
26 import org
.argeo
.slc
.SlcException
;
27 import org
.argeo
.slc
.SlcNames
;
28 import org
.argeo
.slc
.SlcTypes
;
29 import org
.argeo
.slc
.build
.Distribution
;
30 import org
.argeo
.slc
.repo
.maven
.AetherUtils
;
31 import org
.eclipse
.aether
.artifact
.Artifact
;
32 import org
.eclipse
.aether
.artifact
.DefaultArtifact
;
33 import org
.osgi
.framework
.Constants
;
36 * Create or update JCR meta-data for an SLC Modular Distribution
38 * Currently, following types are managed: <list>
39 * <li>* .jar: dependency artifacts with csv index</li>
40 * <li>@Deprecated : .pom: artifact (binaries) that indexes a group, the .pom
41 * file contains a tag "dependencyManagement" that list all modules</li> </list>
43 public class ModularDistributionIndexer
implements NodeIndexer
, SlcNames
{
44 private final static CmsLog log
= CmsLog
.getLog(ModularDistributionIndexer
.class);
46 // Constants for csv indexing
47 private final static String INDEX_FILE_NAME
= "modularDistribution.csv";
48 private String separator
= ",";
50 private Manifest manifest
;
52 public Boolean
support(String path
) {
53 if (FilenameUtils
.getExtension(path
).equals("jar"))
58 public void index(Node fileNode
) {
59 Binary fileBinary
= null;
61 String fileNodePath
= fileNode
.getPath();
62 if (!support(fileNodePath
))
65 if (!fileNode
.isNodeType(NodeType
.NT_FILE
))
68 Node contentNode
= fileNode
.getNode(Node
.JCR_CONTENT
);
69 fileBinary
= contentNode
.getProperty(Property
.JCR_DATA
).getBinary();
71 MyModularDistribution currDist
= null;
72 if (FilenameUtils
.getExtension(fileNode
.getPath()).equals("jar"))
73 currDist
= listModulesFromCsvIndex(fileNode
, fileBinary
);
75 if (fileNode
.isNodeType(SlcTypes
.SLC_MODULAR_DISTRIBUTION
) || currDist
== null
76 || !currDist
.nameVersions().hasNext())
77 return; // already indexed or no modules found
79 fileNode
.addMixin(SlcTypes
.SLC_MODULAR_DISTRIBUTION
);
80 fileNode
.addMixin(SlcTypes
.SLC_CATEGORIZED_NAME_VERSION
);
81 if (currDist
.getCategory() != null)
82 fileNode
.setProperty(SLC_CATEGORY
, currDist
.getCategory());
83 fileNode
.setProperty(SLC_NAME
, currDist
.getName());
84 fileNode
.setProperty(SLC_VERSION
, currDist
.getVersion());
85 indexDistribution(currDist
, fileNode
);
88 if (log
.isTraceEnabled())
89 log
.trace("Indexed " + fileNode
+ " as modular distribution");
90 } catch (Exception e
) {
91 throw new SlcException("Cannot list dependencies from " + fileNode
, e
);
93 JcrUtils
.closeQuietly(fileBinary
);
97 private void indexDistribution(ArgeoOsgiDistribution osgiDist
, Node distNode
) throws RepositoryException
{
98 distNode
.addMixin(SlcTypes
.SLC_MODULAR_DISTRIBUTION
);
99 distNode
.addMixin(SlcTypes
.SLC_CATEGORIZED_NAME_VERSION
);
100 distNode
.setProperty(SlcNames
.SLC_CATEGORY
, osgiDist
.getCategory());
101 distNode
.setProperty(SlcNames
.SLC_NAME
, osgiDist
.getName());
102 distNode
.setProperty(SlcNames
.SLC_VERSION
, osgiDist
.getVersion());
103 if (distNode
.hasNode(SLC_MODULES
))
104 distNode
.getNode(SLC_MODULES
).remove();
105 Node modules
= distNode
.addNode(SLC_MODULES
, NodeType
.NT_UNSTRUCTURED
);
107 for (Iterator
<?
extends NameVersion
> it
= osgiDist
.nameVersions(); it
.hasNext();)
108 addModule(modules
, it
.next());
112 private Node
addModule(Node modules
, NameVersion nameVersion
) throws RepositoryException
{
113 CategoryNameVersion cnv
= (CategoryNameVersion
) nameVersion
;
114 Node moduleCoord
= null;
115 moduleCoord
= modules
.addNode(cnv
.getName(), SlcTypes
.SLC_MODULE_COORDINATES
);
116 moduleCoord
.setProperty(SlcNames
.SLC_CATEGORY
, cnv
.getCategory());
117 moduleCoord
.setProperty(SlcNames
.SLC_NAME
, cnv
.getName());
118 moduleCoord
.setProperty(SlcNames
.SLC_VERSION
, cnv
.getVersion());
122 private MyModularDistribution
listModulesFromCsvIndex(Node fileNode
, Binary fileBinary
) {
123 JarInputStream jarIn
= null;
124 BufferedReader reader
= null;
126 jarIn
= new JarInputStream(fileBinary
.getStream());
128 List
<CategoryNameVersion
> modules
= new ArrayList
<CategoryNameVersion
>();
131 manifest
= jarIn
.getManifest();
132 if (manifest
== null) {
133 log
.error(fileNode
+ " has no MANIFEST");
136 String category
= manifest
.getMainAttributes().getValue(RepoConstants
.SLC_CATEGORY_ID
);
137 String name
= manifest
.getMainAttributes().getValue(Constants
.BUNDLE_SYMBOLICNAME
);
138 String version
= manifest
.getMainAttributes().getValue(Constants
.BUNDLE_VERSION
);
140 Artifact distribution
= new DefaultArtifact(category
, name
, "jar", version
);
141 // Retrieve the index file
143 while ((indexEntry
= jarIn
.getNextJarEntry()) != null) {
144 String entryName
= indexEntry
.getName();
145 if (entryName
.equals(INDEX_FILE_NAME
)) {
150 } catch (SecurityException se
) {
151 log
.error("Invalid signature file digest " + "for Manifest main attributes: " + entryName
152 + " while looking for an index in bundle " + name
);
155 if (indexEntry
== null)
156 return null; // Not a modular definition
158 if (category
== null) {
159 log
.warn("Modular definition found but no " + RepoConstants
.SLC_CATEGORY_ID
+ " in " + fileNode
);
163 reader
= new BufferedReader(new InputStreamReader(jarIn
));
165 while ((line
= reader
.readLine()) != null) {
166 StringTokenizer st
= new StringTokenizer(line
, separator
);
167 st
.nextToken(); // moduleName
168 st
.nextToken(); // moduleVersion
169 String relativeUrl
= st
.nextToken();
170 Artifact currModule
= AetherUtils
.convertPathToArtifact(relativeUrl
, null);
171 modules
.add(new DefaultCategoryNameVersion(currModule
.getGroupId(), currModule
.getArtifactId(),
172 currModule
.getVersion()));
174 return new MyModularDistribution(distribution
, modules
);
175 } catch (Exception e
) {
176 throw new SlcException("Cannot list artifacts", e
);
178 IOUtils
.closeQuietly(jarIn
);
179 IOUtils
.closeQuietly(reader
);
184 * A consistent and versioned OSGi distribution, which can be built and tested.
186 private class MyModularDistribution
extends ArtifactDistribution
implements ArgeoOsgiDistribution
{
188 private List
<CategoryNameVersion
> modules
;
190 public MyModularDistribution(Artifact artifact
, List
<CategoryNameVersion
> modules
) {
192 this.modules
= modules
;
195 public Iterator
<CategoryNameVersion
> nameVersions() {
196 return modules
.iterator();
199 // Modular distribution interface methods. Not yet used.
200 public Distribution
getModuleDistribution(String moduleName
, String moduleVersion
) {
204 public Object
getModulesDescriptor(String descriptorType
) {
209 /** Separator used to parse the tabular file, default is "," */
210 public void setSeparator(String modulesUrlSeparator
) {
211 this.separator
= modulesUrlSeparator
;