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
.apache
.commons
.logging
.Log
;
22 import org
.apache
.commons
.logging
.LogFactory
;
23 import org
.argeo
.jcr
.JcrUtils
;
24 import org
.argeo
.slc
.CategorizedNameVersion
;
25 import org
.argeo
.slc
.DefaultNameVersion
;
26 import org
.argeo
.slc
.NameVersion
;
27 import org
.argeo
.slc
.SlcException
;
28 import org
.argeo
.slc
.aether
.AetherUtils
;
29 import org
.argeo
.slc
.build
.Distribution
;
30 import org
.argeo
.slc
.jcr
.SlcNames
;
31 import org
.argeo
.slc
.jcr
.SlcTypes
;
32 import org
.osgi
.framework
.Constants
;
33 import org
.sonatype
.aether
.artifact
.Artifact
;
34 import org
.sonatype
.aether
.util
.artifact
.DefaultArtifact
;
37 * Create or update JCR meta-data for an SLC Modular Distribution
39 * Currently, following types are managed: <list><li>* .jar: dependency
40 * artifacts with csv index</li> <li>@Deprecated : .pom: artifact (binaries)
41 * that indexes a group, the .pom file contains a tag "dependencyManagement"
42 * that list all modules</li> </list>
44 public class ModularDistributionIndexer
implements NodeIndexer
, SlcNames
{
45 private final static Log log
= LogFactory
46 .getLog(ModularDistributionIndexer
.class);
48 // Constants for csv indexing
49 private final static String INDEX_FILE_NAME
= "modularDistribution.csv";
50 private String separator
= ",";
52 // TODO remove this: binaries have been replaced by modular distribution
53 // // Artifact indexing
54 // private final static List<String> BINARIES_ARTIFACTS_NAME;
56 // List<String> tmpList = new ArrayList<String>();
57 // tmpList.add(RepoConstants.BINARIES_ARTIFACT_ID);
58 // // tmpList.add(RepoConstants.SOURCES_ARTIFACT_ID);
59 // // tmpList.add(RepoConstants.SDK_ARTIFACT_ID);
60 // BINARIES_ARTIFACTS_NAME = Collections.unmodifiableList(tmpList);
63 private Manifest manifest
;
65 public Boolean
support(String path
) {
66 if (FilenameUtils
.getExtension(path
).equals("jar"))
68 // if (FilenameUtils.getExtension(path).equals("pom")
69 // && BINARIES_ARTIFACTS_NAME.contains(FilenameUtils.getName(path)
75 public void index(Node fileNode
) {
76 Binary fileBinary
= null;
79 String fileNodePath
= fileNode
.getPath();
80 if (!support(fileNodePath
))
83 if (!fileNode
.isNodeType(NodeType
.NT_FILE
))
86 Node contentNode
= fileNode
.getNode(Node
.JCR_CONTENT
);
87 fileBinary
= contentNode
.getProperty(Property
.JCR_DATA
).getBinary();
89 MyModularDistribution currDist
= null;
90 if (FilenameUtils
.getExtension(fileNode
.getPath()).equals("jar"))
91 currDist
= listModulesFromCsvIndex(fileNode
, fileBinary
);
92 // else if (FilenameUtils.getExtension(fileNode.getPath()).equals(
94 // currDist = listModulesFromPomIndex(fileNode, fileBinary);
96 if (fileNode
.isNodeType(SlcTypes
.SLC_MODULAR_DISTRIBUTION
)
97 || currDist
== null || !currDist
.nameVersions().hasNext())
98 return; // already indexed or no modules found
100 fileNode
.addMixin(SlcTypes
.SLC_MODULAR_DISTRIBUTION
);
101 fileNode
.addMixin(SlcTypes
.SLC_CATEGORIZED_NAME_VERSION
);
102 if (currDist
.getCategory() != null)
103 fileNode
.setProperty(SLC_CATEGORY
, currDist
.getCategory());
104 fileNode
.setProperty(SLC_NAME
, currDist
.getName());
105 fileNode
.setProperty(SLC_VERSION
, currDist
.getVersion());
106 indexDistribution(currDist
, fileNode
);
109 if (log
.isTraceEnabled())
110 log
.trace("Indexed " + fileNode
+ " as modular distribution");
111 } catch (Exception e
) {
112 throw new SlcException("Cannot list dependencies from " + fileNode
,
117 private void indexDistribution(ArgeoOsgiDistribution osgiDist
, Node distNode
)
118 throws RepositoryException
{
119 distNode
.addMixin(SlcTypes
.SLC_MODULAR_DISTRIBUTION
);
120 distNode
.addMixin(SlcTypes
.SLC_CATEGORIZED_NAME_VERSION
);
121 distNode
.setProperty(SlcNames
.SLC_CATEGORY
, osgiDist
.getCategory());
122 distNode
.setProperty(SlcNames
.SLC_NAME
, osgiDist
.getName());
123 distNode
.setProperty(SlcNames
.SLC_VERSION
, osgiDist
.getVersion());
124 Node modules
= JcrUtils
.mkdirs(distNode
, SlcNames
.SLC_MODULES
,
125 NodeType
.NT_UNSTRUCTURED
);
127 for (Iterator
<?
extends NameVersion
> it
= osgiDist
.nameVersions(); it
129 addModule(modules
, it
.next());
133 private Node
addModule(Node modules
, NameVersion nameVersion
)
134 throws RepositoryException
{
135 CategorizedNameVersion cnv
= (CategorizedNameVersion
) nameVersion
;
136 Node moduleCoord
= null;
137 moduleCoord
= modules
.addNode(cnv
.getName(),
138 SlcTypes
.SLC_MODULE_COORDINATES
);
139 moduleCoord
.setProperty(SlcNames
.SLC_CATEGORY
, cnv
.getCategory());
140 moduleCoord
.setProperty(SlcNames
.SLC_NAME
, cnv
.getName());
141 moduleCoord
.setProperty(SlcNames
.SLC_VERSION
, cnv
.getVersion());
145 private MyModularDistribution
listModulesFromCsvIndex(Node fileNode
,
147 JarInputStream jarIn
= null;
148 BufferedReader reader
= null;
150 jarIn
= new JarInputStream(fileBinary
.getStream());
152 List
<CategorizedNameVersion
> modules
= new ArrayList
<CategorizedNameVersion
>();
155 manifest
= jarIn
.getManifest();
156 if (manifest
== null) {
157 log
.error(fileNode
+ " has no MANIFEST");
160 String category
= manifest
.getMainAttributes().getValue(
161 RepoConstants
.SLC_GROUP_ID
);
162 String name
= manifest
.getMainAttributes().getValue(
163 Constants
.BUNDLE_SYMBOLICNAME
);
164 String version
= manifest
.getMainAttributes().getValue(
165 Constants
.BUNDLE_VERSION
);
167 Artifact distribution
= new DefaultArtifact(category
, name
, "jar",
169 // Retrieve the index file
171 while ((indexEntry
= jarIn
.getNextJarEntry()) != null) {
172 String entryName
= indexEntry
.getName();
173 if (entryName
.equals(INDEX_FILE_NAME
)) {
178 } catch (SecurityException se
) {
179 log
.error("Invalid signature file digest "
180 + "for Manifest main attributes: " + entryName
181 + " while looking for an index in bundle " + name
);
184 if (indexEntry
== null)
185 return null; // Not a modular definition
188 reader
= new BufferedReader(new InputStreamReader(jarIn
));
190 while ((line
= reader
.readLine()) != null) {
191 StringTokenizer st
= new StringTokenizer(line
, separator
);
192 st
.nextToken(); // moduleName
193 st
.nextToken(); // moduleVersion
194 String relativeUrl
= st
.nextToken();
195 Artifact currModule
= AetherUtils
.convertPathToArtifact(
197 modules
.add(new MyCategorizedNameVersion(currModule
198 .getGroupId(), currModule
.getArtifactId(), currModule
201 return new MyModularDistribution(distribution
, modules
);
202 } catch (Exception e
) {
203 throw new SlcException("Cannot list artifacts", e
);
205 IOUtils
.closeQuietly(jarIn
);
206 IOUtils
.closeQuietly(reader
);
210 // private MyModularDistribution listModulesFromPomIndex(Node fileNode,
211 // Binary fileBinary) {
212 // InputStream input = null;
213 // List<CategorizedNameVersion> modules = new
214 // ArrayList<CategorizedNameVersion>();
216 // input = fileBinary.getStream();
218 // DocumentBuilder documentBuilder = DocumentBuilderFactory
219 // .newInstance().newDocumentBuilder();
220 // Document doc = documentBuilder.parse(input);
222 // Properties props = new Properties();
223 // // props.setProperty("project.version",
224 // // pomArtifact.getBaseVersion());
225 // NodeList properties = doc.getElementsByTagName("properties");
226 // if (properties.getLength() > 0) {
227 // NodeList propertiesElems = properties.item(0).getChildNodes();
228 // for (int i = 0; i < propertiesElems.getLength(); i++) {
229 // if (propertiesElems.item(i) instanceof Element) {
230 // Element property = (Element) propertiesElems.item(i);
231 // props.put(property.getNodeName(),
232 // property.getTextContent());
237 // // full coordinates are under <dependencyManagement><dependencies>
238 // NodeList dependencies = ((Element) doc.getElementsByTagName(
239 // "dependencyManagement").item(0))
240 // .getElementsByTagName("dependency");
241 // for (int i = 0; i < dependencies.getLength(); i++) {
242 // Element dependency = (Element) dependencies.item(i);
243 // String groupId = dependency.getElementsByTagName("groupId")
244 // .item(0).getTextContent().trim();
245 // String artifactId = dependency
246 // .getElementsByTagName("artifactId").item(0)
247 // .getTextContent().trim();
248 // String version = dependency.getElementsByTagName("version")
249 // .item(0).getTextContent().trim();
250 // modules.add(new MyCategorizedNameVersion(groupId, artifactId,
254 // String groupId = doc.getElementsByTagName("groupId").item(0)
255 // .getTextContent().trim();
256 // String artifactId = doc.getElementsByTagName("artifactId").item(0)
257 // .getTextContent().trim();
258 // String version = doc.getElementsByTagName("version").item(0)
259 // .getTextContent().trim();
261 // Artifact currDist = new DefaultArtifact(groupId, artifactId, "pom",
264 // return new MyModularDistribution(currDist, modules);
265 // } catch (Exception e) {
266 // throw new SlcException("Cannot process pom " + fileNode, e);
268 // IOUtils.closeQuietly(input);
272 /** The created modular distribution */
273 private static class MyCategorizedNameVersion
extends DefaultNameVersion
274 implements CategorizedNameVersion
{
275 private final String category
;
277 public MyCategorizedNameVersion(String category
, String name
,
279 super(name
, version
);
280 this.category
= category
;
283 public String
getCategory() {
289 * A consistent and versioned OSGi distribution, which can be built and
292 private class MyModularDistribution
extends ArtifactDistribution
implements
293 ArgeoOsgiDistribution
{
295 private List
<CategorizedNameVersion
> modules
;
297 public MyModularDistribution(Artifact artifact
,
298 List
<CategorizedNameVersion
> modules
) {
300 this.modules
= modules
;
303 public Iterator
<CategorizedNameVersion
> nameVersions() {
304 return modules
.iterator();
307 // Modular distribution interface methods. Not yet used.
308 public Distribution
getModuleDistribution(String moduleName
,
309 String moduleVersion
) {
313 public Object
getModulesDescriptor(String descriptorType
) {
318 /** Separator used to parse the tabular file, default is "," */
319 public void setSeparator(String modulesUrlSeparator
) {
320 this.separator
= modulesUrlSeparator
;