]> git.argeo.org Git - gpl/argeo-slc.git/blob - ImportMavenDependencies.java
8d5ff5ae251594fbfed194ac2b9c5923694172a4
[gpl/argeo-slc.git] / ImportMavenDependencies.java
1 package org.argeo.slc.repo.maven;
2
3 import java.io.ByteArrayInputStream;
4 import java.io.ByteArrayOutputStream;
5 import java.io.File;
6 import java.io.FileInputStream;
7 import java.io.InputStream;
8 import java.util.ArrayList;
9 import java.util.Comparator;
10 import java.util.HashSet;
11 import java.util.List;
12 import java.util.Properties;
13 import java.util.Set;
14 import java.util.TreeSet;
15 import java.util.jar.Attributes;
16 import java.util.jar.Attributes.Name;
17 import java.util.jar.JarInputStream;
18 import java.util.jar.Manifest;
19
20 import javax.jcr.Binary;
21 import javax.jcr.Node;
22 import javax.jcr.NodeIterator;
23 import javax.jcr.PathNotFoundException;
24 import javax.jcr.Property;
25 import javax.jcr.RepositoryException;
26 import javax.jcr.Session;
27 import javax.jcr.nodetype.NodeType;
28 import javax.xml.parsers.DocumentBuilder;
29 import javax.xml.parsers.DocumentBuilderFactory;
30
31 import org.apache.commons.io.FilenameUtils;
32 import org.apache.commons.io.IOUtils;
33 import org.apache.commons.logging.Log;
34 import org.apache.commons.logging.LogFactory;
35 import org.argeo.jcr.JcrUtils;
36 import org.argeo.slc.SlcException;
37 import org.argeo.slc.aether.AetherTemplate;
38 import org.argeo.slc.repo.RepoNames;
39 import org.argeo.slc.repo.RepoTypes;
40 import org.osgi.framework.Constants;
41 import org.osgi.framework.Version;
42 import org.sonatype.aether.artifact.Artifact;
43 import org.sonatype.aether.graph.DependencyNode;
44 import org.sonatype.aether.util.artifact.DefaultArtifact;
45 import org.w3c.dom.Document;
46 import org.w3c.dom.Element;
47 import org.w3c.dom.NodeList;
48
49 public class ImportMavenDependencies implements Runnable {
50 private final static Log log = LogFactory
51 .getLog(ImportMavenDependencies.class);
52
53 private AetherTemplate aetherTemplate;
54 private String rootCoordinates;
55 private Set<String> excludedArtifacts = new HashSet<String>();
56
57 private Session jcrSession;
58 private String artifactBasePath = "/slc/repo/artifacts";
59 private String distributionsBasePath = "/slc/repo/distributions";
60 private String distributionName;
61
62 public void run() {
63 log.debug(jcrSession.getUserID());
64 Set<Artifact> artifacts = resolveDistribution();
65 syncDistribution(artifacts);
66 }
67
68 public Set<Artifact> resolveDistribution() {
69 try {
70 Artifact pomArtifact = new DefaultArtifact(rootCoordinates);
71 Comparator<Artifact> artifactComparator = new Comparator<Artifact>() {
72 public int compare(Artifact o1, Artifact o2) {
73 return o1.getArtifactId().compareTo(o2.getArtifactId());
74 }
75 };
76
77 Set<Artifact> registeredArtifacts = new TreeSet<Artifact>(
78 artifactComparator);
79 parsePom(aetherTemplate, registeredArtifacts, pomArtifact);
80 if (log.isDebugEnabled())
81 log.debug("Gathered " + registeredArtifacts.size()
82 + " artifacts");
83
84 // Resolve and add non-optional dependencies
85 Set<Artifact> artifacts = new TreeSet<Artifact>(artifactComparator);
86 for (Artifact artifact : registeredArtifacts) {
87 try {
88 addArtifact(artifacts, artifact);
89 DependencyNode node = aetherTemplate
90 .resolveDependencies(artifact);
91 addDependencies(artifacts, node);
92 } catch (Exception e) {
93 log.error("Could not resolve dependencies of " + artifact
94 + ": " + e.getCause().getMessage());
95 }
96
97 }
98
99 if (log.isDebugEnabled())
100 log.debug("Resolved " + artifacts.size() + " artifacts");
101 Properties distributionDescriptor = new Properties();
102 for (Artifact artifact : artifacts) {
103 log.debug(artifact.getArtifactId() + " ["
104 + artifact.getVersion() + "]\t(" + artifact + ")");
105 distributionDescriptor.setProperty(artifact.getArtifactId()
106 + ":" + artifact.getVersion(), artifact.toString());
107 }
108
109 ByteArrayOutputStream out = new ByteArrayOutputStream();
110 distributionDescriptor.store(out, "");
111 log.debug(new String(out.toByteArray()));
112 out.close();
113
114 return artifacts;
115 } catch (Exception e) {
116 throw new SlcException("Cannot resolve distribution", e);
117 }
118 }
119
120 protected void syncDistribution(Set<Artifact> artifacts) {
121 Long begin = System.currentTimeMillis();
122 try {
123 JcrUtils.mkdirs(jcrSession, artifactBasePath);
124 JcrUtils.mkdirs(jcrSession, distributionsBasePath + '/'
125 + distributionName);
126 artifacts: for (Artifact artifact : artifacts) {
127 File file = artifact.getFile();
128 if (file == null) {
129 log.warn("File not found for " + artifact);
130
131 file = artifactToFile(artifact);
132
133 if (!file.exists()) {
134 log.warn("Generated file " + file + " for " + artifact
135 + " does not exist");
136 continue artifacts;
137 }
138 }
139
140 try {
141 String parentPath = artifactBasePath + '/'
142 + artifactParentPath(artifact);
143 Node parentNode;
144 if (!jcrSession.itemExists(parentPath)) {
145 parentNode = JcrUtils.mkdirs(jcrSession, parentPath,
146 NodeType.NT_FOLDER, false);
147 } else {
148 parentNode = jcrSession.getNode(parentPath);
149 }
150
151 Node fileNode;
152 if (!parentNode.hasNode(file.getName())) {
153 fileNode = createFileNode(parentNode, file);
154 } else {
155 fileNode = parentNode.getNode(file.getName());
156 }
157 processArtifact(fileNode, artifact);
158 if (fileNode.isNodeType(RepoTypes.SLC_JAR_FILE)) {
159 processOsgiBundle(fileNode);
160 }
161 jcrSession.save();
162
163 if (!jcrSession
164 .itemExists(bundleDistributionPath(fileNode))
165 && fileNode
166 .isNodeType(RepoTypes.SLC_BUNDLE_ARTIFACT))
167 jcrSession.getWorkspace().clone(
168 jcrSession.getWorkspace().getName(),
169 fileNode.getPath(),
170 bundleDistributionPath(fileNode), false);
171
172 if (log.isDebugEnabled())
173 log.debug("Synchronized " + fileNode);
174 } catch (Exception e) {
175 log.error("Could not synchronize " + artifact, e);
176 jcrSession.refresh(false);
177 throw e;
178 }
179 }
180
181 Long duration = (System.currentTimeMillis() - begin) / 1000;
182 if (log.isDebugEnabled())
183 log.debug("Synchronized distribution in " + duration + "s");
184 } catch (Exception e) {
185 throw new SlcException("Cannot synchronize distribution", e);
186 }
187 }
188
189 protected String artifactParentPath(Artifact artifact) {
190 return artifact.getGroupId().replace('.', '/') + '/'
191 + artifact.getArtifactId() + '/' + artifact.getVersion();
192 }
193
194 protected String bundleDistributionPath(Node fileNode) {
195 try {
196 return distributionsBasePath
197 + '/'
198 + distributionName
199 + '/'
200 + fileNode.getProperty(RepoNames.SLC_SYMBOLIC_NAME)
201 .getString()
202 + '_'
203 + fileNode.getProperty(RepoNames.SLC_BUNDLE_VERSION)
204 .getString();
205 } catch (RepositoryException e) {
206 throw new SlcException("Cannot create distribution path for "
207 + fileNode, e);
208 }
209 }
210
211 protected void processArtifact(Node fileNode, Artifact artifact) {
212 try {
213 fileNode.addMixin(RepoTypes.SLC_ARTIFACT);
214 fileNode.setProperty(RepoNames.SLC_ARTIFACT_ID,
215 artifact.getArtifactId());
216 fileNode.setProperty(RepoNames.SLC_GROUP_ID, artifact.getGroupId());
217 fileNode.setProperty(RepoNames.SLC_ARTIFACT_VERSION,
218 artifact.getVersion());
219 fileNode.setProperty(RepoNames.SLC_ARTIFACT_EXTENSION,
220 artifact.getExtension());
221 fileNode.setProperty(RepoNames.SLC_ARTIFACT_CLASSIFIER,
222 artifact.getClassifier());
223 } catch (RepositoryException e) {
224 throw new SlcException("Cannot process artifact " + artifact
225 + " on node " + fileNode, e);
226 }
227
228 }
229
230 protected File artifactToFile(Artifact artifact) {
231 return new File(System.getProperty("user.home")
232 + File.separator
233 + ".m2"
234 + File.separator
235 + "repository"
236 + File.separator
237 + artifact.getGroupId().replace('.', File.separatorChar)
238 + File.separator
239 + artifact.getArtifactId()
240 + File.separator
241 + artifact.getVersion()
242 + File.separator
243 + artifact.getArtifactId()
244 + '-'
245 + artifact.getVersion()
246 + (artifact.getClassifier().equals("") ? ""
247 : '-' + artifact.getClassifier()) + '.'
248 + artifact.getExtension());
249 }
250
251 protected void processOsgiBundle(Node fileNode) {
252 Binary manifestBinary = null;
253 InputStream manifestIn = null;
254 try {
255 manifestBinary = fileNode.getProperty(RepoNames.SLC_MANIFEST)
256 .getBinary();
257 manifestIn = manifestBinary.getStream();
258 Manifest manifest = new Manifest(manifestIn);
259 Attributes attrs = manifest.getMainAttributes();
260
261 if (log.isTraceEnabled())
262 for (Object key : attrs.keySet())
263 log.trace(key + ": " + attrs.getValue(key.toString()));
264
265 if (!attrs.containsKey(new Name(Constants.BUNDLE_SYMBOLICNAME))) {
266 log.warn(fileNode + " is not an OSGi bundle");
267 return;// not an osgi bundle
268 }
269
270 fileNode.addMixin(RepoTypes.SLC_BUNDLE_ARTIFACT);
271
272 // symbolic name
273 String symbolicName = attrs.getValue(Constants.BUNDLE_SYMBOLICNAME);
274 // make sure there is no directive
275 symbolicName = symbolicName.split(";")[0];
276 fileNode.setProperty(RepoNames.SLC_SYMBOLIC_NAME, symbolicName);
277
278 // direct mapping
279 addAttr(Constants.BUNDLE_SYMBOLICNAME, fileNode, attrs);
280 addAttr(Constants.BUNDLE_NAME, fileNode, attrs);
281 addAttr(Constants.BUNDLE_DESCRIPTION, fileNode, attrs);
282 addAttr(Constants.BUNDLE_MANIFESTVERSION, fileNode, attrs);
283 addAttr(Constants.BUNDLE_CATEGORY, fileNode, attrs);
284 addAttr(Constants.BUNDLE_ACTIVATIONPOLICY, fileNode, attrs);
285 addAttr(Constants.BUNDLE_COPYRIGHT, fileNode, attrs);
286 addAttr(Constants.BUNDLE_VENDOR, fileNode, attrs);
287 addAttr("Bundle-License", fileNode, attrs);
288 addAttr(Constants.BUNDLE_DOCURL, fileNode, attrs);
289 addAttr(Constants.BUNDLE_CONTACTADDRESS, fileNode, attrs);
290 addAttr(Constants.BUNDLE_ACTIVATOR, fileNode, attrs);
291 addAttr(Constants.BUNDLE_UPDATELOCATION, fileNode, attrs);
292 addAttr(Constants.BUNDLE_LOCALIZATION, fileNode, attrs);
293
294 // required execution environment
295 if (attrs.containsKey(new Name(
296 Constants.BUNDLE_REQUIREDEXECUTIONENVIRONMENT)))
297 fileNode.setProperty(
298 RepoNames.SLC_
299 + Constants.BUNDLE_REQUIREDEXECUTIONENVIRONMENT,
300 attrs.getValue(
301 Constants.BUNDLE_REQUIREDEXECUTIONENVIRONMENT)
302 .split(","));
303
304 // bundle classpath
305 if (attrs.containsKey(new Name(Constants.BUNDLE_CLASSPATH)))
306 fileNode.setProperty(RepoNames.SLC_
307 + Constants.BUNDLE_CLASSPATH,
308 attrs.getValue(Constants.BUNDLE_CLASSPATH).split(","));
309
310 // version
311 Version version = new Version(
312 attrs.getValue(Constants.BUNDLE_VERSION));
313 fileNode.setProperty(RepoNames.SLC_BUNDLE_VERSION,
314 version.toString());
315 cleanSubNodes(fileNode, RepoNames.SLC_ + Constants.BUNDLE_VERSION);
316 Node bundleVersionNode = fileNode.addNode(RepoNames.SLC_
317 + Constants.BUNDLE_VERSION, RepoTypes.SLC_OSGI_VERSION);
318 mapOsgiVersion(version, bundleVersionNode);
319
320 // fragment
321 cleanSubNodes(fileNode, RepoNames.SLC_ + Constants.FRAGMENT_HOST);
322 if (attrs.containsKey(new Name(Constants.FRAGMENT_HOST))) {
323 String fragmentHost = attrs.getValue(Constants.FRAGMENT_HOST);
324 String[] tokens = fragmentHost.split(";");
325 Node node = fileNode.addNode(RepoNames.SLC_
326 + Constants.FRAGMENT_HOST, RepoTypes.SLC_FRAGMENT_HOST);
327 node.setProperty(RepoNames.SLC_SYMBOLIC_NAME, tokens[0]);
328 for (int i = 1; i < tokens.length; i++) {
329 if (tokens[i]
330 .startsWith(Constants.BUNDLE_VERSION_ATTRIBUTE)) {
331 node.setProperty(RepoNames.SLC_BUNDLE_VERSION,
332 attributeValue(tokens[i]));
333 }
334 }
335 }
336
337 // imported packages
338 cleanSubNodes(fileNode, RepoNames.SLC_ + Constants.IMPORT_PACKAGE);
339 if (attrs.containsKey(new Name(Constants.IMPORT_PACKAGE))) {
340 String importPackages = attrs
341 .getValue(Constants.IMPORT_PACKAGE);
342 List<String> packages = parsePackages(importPackages);
343 for (String pkg : packages) {
344 String[] tokens = pkg.split(";");
345 Node node = fileNode.addNode(RepoNames.SLC_
346 + Constants.IMPORT_PACKAGE,
347 RepoTypes.SLC_IMPORTED_PACKAGE);
348 node.setProperty(RepoNames.SLC_NAME, tokens[0]);
349 for (int i = 1; i < tokens.length; i++) {
350 if (tokens[i].startsWith(Constants.VERSION_ATTRIBUTE)) {
351 node.setProperty(RepoNames.SLC_VERSION,
352 attributeValue(tokens[i]));
353 } else if (tokens[i]
354 .startsWith(Constants.RESOLUTION_DIRECTIVE)) {
355 node.setProperty(
356 RepoNames.SLC_OPTIONAL,
357 directiveValue(tokens[i]).equals(
358 Constants.RESOLUTION_OPTIONAL));
359 }
360 }
361 }
362 }
363
364 // dynamic import package
365 cleanSubNodes(fileNode, RepoNames.SLC_
366 + Constants.DYNAMICIMPORT_PACKAGE);
367 if (attrs.containsKey(new Name(Constants.DYNAMICIMPORT_PACKAGE))) {
368 String importPackages = attrs
369 .getValue(Constants.DYNAMICIMPORT_PACKAGE);
370 List<String> packages = parsePackages(importPackages);
371 for (String pkg : packages) {
372 String[] tokens = pkg.split(";");
373 Node node = fileNode.addNode(RepoNames.SLC_
374 + Constants.DYNAMICIMPORT_PACKAGE,
375 RepoTypes.SLC_DYNAMIC_IMPORTED_PACKAGE);
376 node.setProperty(RepoNames.SLC_NAME, tokens[0]);
377 for (int i = 1; i < tokens.length; i++) {
378 if (tokens[i].startsWith(Constants.VERSION_ATTRIBUTE)) {
379 node.setProperty(RepoNames.SLC_VERSION,
380 attributeValue(tokens[i]));
381 }
382 }
383 }
384 }
385
386 // exported packages
387 cleanSubNodes(fileNode, RepoNames.SLC_ + Constants.EXPORT_PACKAGE);
388 if (attrs.containsKey(new Name(Constants.EXPORT_PACKAGE))) {
389 String exportPackages = attrs
390 .getValue(Constants.EXPORT_PACKAGE);
391 List<String> packages = parsePackages(exportPackages);
392 for (String pkg : packages) {
393 String[] tokens = pkg.split(";");
394 Node node = fileNode.addNode(RepoNames.SLC_
395 + Constants.EXPORT_PACKAGE,
396 RepoTypes.SLC_EXPORTED_PACKAGE);
397 node.setProperty(RepoNames.SLC_NAME, tokens[0]);
398 // TODO: are these cleans really necessary?
399 cleanSubNodes(node, RepoNames.SLC_USES);
400 cleanSubNodes(node, RepoNames.SLC_VERSION);
401 for (int i = 1; i < tokens.length; i++) {
402 if (tokens[i].startsWith(Constants.VERSION_ATTRIBUTE)) {
403 String versionStr = attributeValue(tokens[i]);
404 Node versionNode = node.addNode(
405 RepoNames.SLC_VERSION,
406 RepoTypes.SLC_OSGI_VERSION);
407 mapOsgiVersion(new Version(versionStr), versionNode);
408 } else if (tokens[i]
409 .startsWith(Constants.USES_DIRECTIVE)) {
410 String usedPackages = directiveValue(tokens[i]);
411 // log.debug("uses='" + usedPackages + "'");
412 for (String usedPackage : usedPackages.split(",")) {
413 // log.debug("usedPackage='" + usedPackage +
414 // "'");
415 Node usesNode = node.addNode(
416 RepoNames.SLC_USES,
417 RepoTypes.SLC_JAVA_PACKAGE);
418 usesNode.setProperty(RepoNames.SLC_NAME,
419 usedPackage);
420 }
421 }
422 }
423 }
424 }
425
426 // required bundle
427 cleanSubNodes(fileNode, RepoNames.SLC_ + Constants.REQUIRE_BUNDLE);
428 if (attrs.containsKey(new Name(Constants.REQUIRE_BUNDLE))) {
429 String requireBundle = attrs.getValue(Constants.REQUIRE_BUNDLE);
430 String[] bundles = requireBundle.split(",");
431 for (String bundle : bundles) {
432 String[] tokens = bundle.split(";");
433 Node node = fileNode.addNode(RepoNames.SLC_
434 + Constants.REQUIRE_BUNDLE,
435 RepoTypes.SLC_REQUIRED_BUNDLE);
436 node.setProperty(RepoNames.SLC_SYMBOLIC_NAME, tokens[0]);
437 for (int i = 1; i < tokens.length; i++) {
438 if (tokens[i]
439 .startsWith(Constants.BUNDLE_VERSION_ATTRIBUTE)) {
440 node.setProperty(RepoNames.SLC_BUNDLE_VERSION,
441 attributeValue(tokens[i]));
442 } else if (tokens[i]
443 .startsWith(Constants.RESOLUTION_DIRECTIVE)) {
444 node.setProperty(
445 RepoNames.SLC_OPTIONAL,
446 directiveValue(tokens[i]).equals(
447 Constants.RESOLUTION_OPTIONAL));
448 }
449 }
450 }
451 }
452 } catch (Exception e) {
453 throw new SlcException("Cannot process OSGi bundle " + fileNode, e);
454 } finally {
455 if (manifestBinary != null)
456 manifestBinary.dispose();
457 IOUtils.closeQuietly(manifestIn);
458 }
459 }
460
461 /** Parse package list with nested directive with ',' */
462 private List<String> parsePackages(String str) {
463 List<String> res = new ArrayList<String>();
464 StringBuffer curr = new StringBuffer("");
465 boolean in = false;
466 for (char c : str.toCharArray()) {
467 if (c == ',') {
468 if (!in) {
469 res.add(curr.toString());
470 curr = new StringBuffer("");
471 }
472 } else if (c == '\"') {
473 in = !in;
474 curr.append(c);
475 } else {
476 curr.append(c);
477 }
478 }
479 res.add(curr.toString());
480 log.debug(res);
481 return res;
482 }
483
484 private void addAttr(String key, Node node, Attributes attrs)
485 throws RepositoryException {
486 addAttr(new Name(key), node, attrs);
487 }
488
489 private void addAttr(Name key, Node node, Attributes attrs)
490 throws RepositoryException {
491 if (attrs.containsKey(key)) {
492 String value = attrs.getValue(key);
493 node.setProperty(RepoNames.SLC_ + key, value);
494 }
495 }
496
497 private void cleanSubNodes(Node node, String name)
498 throws RepositoryException {
499 if (node.hasNode(name)) {
500 NodeIterator nit = node.getNodes(name);
501 while (nit.hasNext())
502 nit.nextNode().remove();
503 }
504 }
505
506 protected void mapOsgiVersion(Version version, Node versionNode)
507 throws RepositoryException {
508 versionNode.setProperty(RepoNames.SLC_AS_STRING, version.toString());
509 versionNode.setProperty(RepoNames.SLC_MAJOR, version.getMajor());
510 versionNode.setProperty(RepoNames.SLC_MINOR, version.getMinor());
511 versionNode.setProperty(RepoNames.SLC_MICRO, version.getMicro());
512 if (!version.getQualifier().equals(""))
513 versionNode.setProperty(RepoNames.SLC_QUALIFIER,
514 version.getQualifier());
515 }
516
517 private String attributeValue(String str) {
518 return extractValue(str, "=");
519 }
520
521 private String directiveValue(String str) {
522 return extractValue(str, ":=");
523 }
524
525 private String extractValue(String str, String eq) {
526 String[] tokens = str.split(eq);
527 // String key = tokens[0];
528 String value = tokens[1].trim();
529 // TODO: optimize?
530 if (value.startsWith("\""))
531 value = value.substring(1);
532 if (value.endsWith("\""))
533 value = value.substring(0, value.length() - 1);
534 return value;
535 }
536
537 protected Node createFileNode(Node parentNode, File file) {
538 Binary binary = null;
539 try {
540 Node fileNode = parentNode
541 .addNode(file.getName(), NodeType.NT_FILE);
542 Node contentNode = fileNode.addNode(Node.JCR_CONTENT,
543 NodeType.NT_RESOURCE);
544 binary = jcrSession.getValueFactory().createBinary(
545 new FileInputStream(file));
546 contentNode.setProperty(Property.JCR_DATA, binary);
547 // jar file
548 if (FilenameUtils.isExtension(file.getName(), "jar")) {
549 JarInputStream jarIn = null;
550 ByteArrayOutputStream bo = null;
551 ByteArrayInputStream bi = null;
552 Binary manifestBinary = null;
553 try {
554 jarIn = new JarInputStream(binary.getStream());
555 Manifest manifest = jarIn.getManifest();
556 bo = new ByteArrayOutputStream();
557 manifest.write(bo);
558 bi = new ByteArrayInputStream(bo.toByteArray());
559 manifestBinary = jcrSession.getValueFactory().createBinary(
560 bi);
561 fileNode.addMixin(RepoTypes.SLC_JAR_FILE);
562 fileNode.setProperty(RepoNames.SLC_MANIFEST, manifestBinary);
563 Attributes attrs = manifest.getMainAttributes();
564 addAttr(Attributes.Name.MANIFEST_VERSION, fileNode, attrs);
565 addAttr(Attributes.Name.SIGNATURE_VERSION, fileNode, attrs);
566 addAttr(Attributes.Name.CLASS_PATH, fileNode, attrs);
567 addAttr(Attributes.Name.MAIN_CLASS, fileNode, attrs);
568 addAttr(Attributes.Name.EXTENSION_NAME, fileNode, attrs);
569 addAttr(Attributes.Name.IMPLEMENTATION_VERSION, fileNode,
570 attrs);
571 addAttr(Attributes.Name.IMPLEMENTATION_VENDOR, fileNode,
572 attrs);
573 addAttr(Attributes.Name.IMPLEMENTATION_VENDOR_ID, fileNode,
574 attrs);
575 addAttr(Attributes.Name.SPECIFICATION_TITLE, fileNode,
576 attrs);
577 addAttr(Attributes.Name.SPECIFICATION_VERSION, fileNode,
578 attrs);
579 addAttr(Attributes.Name.SPECIFICATION_VENDOR, fileNode,
580 attrs);
581 addAttr(Attributes.Name.SEALED, fileNode, attrs);
582 } finally {
583 if (manifestBinary != null)
584 manifestBinary.dispose();
585 IOUtils.closeQuietly(bi);
586 IOUtils.closeQuietly(bo);
587 IOUtils.closeQuietly(jarIn);
588 }
589 }
590 return fileNode;
591 } catch (Exception e) {
592 throw new SlcException("Cannot create file node based on " + file
593 + " under " + parentNode, e);
594 } finally {
595 if (binary != null)
596 binary.dispose();
597 }
598 }
599
600 /** Recursively adds non optional dependencies */
601 private void addDependencies(Set<Artifact> artifacts, DependencyNode node) {
602 for (DependencyNode child : node.getChildren()) {
603 if (!child.getDependency().isOptional()) {
604 addArtifact(artifacts, child.getDependency().getArtifact());
605 addDependencies(artifacts, child);
606 }
607 }
608 }
609
610 private void addArtifact(Set<Artifact> artifacts, Artifact artifact) {
611 if (!excludedArtifacts.contains(artifact.getGroupId() + ":"
612 + artifact.getArtifactId()))
613 artifacts.add(artifact);
614 }
615
616 /**
617 * Directly parses Maven POM XML format in order to find all artifacts
618 * references under the dependency and dependencyManagement tags. This is
619 * meant to migrate existing pom registering a lot of artifacts, not to
620 * replace Maven resolving.
621 */
622 protected void parsePom(AetherTemplate aetherTemplate,
623 Set<Artifact> artifacts, Artifact pomArtifact) {
624 if (log.isDebugEnabled())
625 log.debug("Gather dependencies for " + pomArtifact);
626
627 try {
628 File file = aetherTemplate.getResolvedFile(pomArtifact);
629 DocumentBuilder documentBuilder = DocumentBuilderFactory
630 .newInstance().newDocumentBuilder();
631 Document doc = documentBuilder.parse(file);
632
633 // properties
634 Properties props = new Properties();
635 props.setProperty("project.version", pomArtifact.getBaseVersion());
636 NodeList properties = doc.getElementsByTagName("properties");
637 if (properties.getLength() > 0) {
638 NodeList propertiesElems = properties.item(0).getChildNodes();
639 for (int i = 0; i < propertiesElems.getLength(); i++) {
640 if (propertiesElems.item(i) instanceof Element) {
641 Element property = (Element) propertiesElems.item(i);
642 props.put(property.getNodeName(),
643 property.getTextContent());
644 }
645 }
646 }
647
648 // dependencies (direct and dependencyManagement)
649 NodeList dependencies = doc.getElementsByTagName("dependency");
650 for (int i = 0; i < dependencies.getLength(); i++) {
651 Element dependency = (Element) dependencies.item(i);
652 String groupId = dependency.getElementsByTagName("groupId")
653 .item(0).getTextContent().trim();
654 String artifactId = dependency
655 .getElementsByTagName("artifactId").item(0)
656 .getTextContent().trim();
657 String version = dependency.getElementsByTagName("version")
658 .item(0).getTextContent().trim();
659 if (version.startsWith("${")) {
660 String versionKey = version.substring(0,
661 version.length() - 1).substring(2);
662 if (!props.containsKey(versionKey))
663 throw new SlcException("Cannot interpret version "
664 + version);
665 version = props.getProperty(versionKey);
666 }
667 NodeList scopes = dependency.getElementsByTagName("scope");
668 if (scopes.getLength() > 0
669 && scopes.item(0).getTextContent().equals("import")) {
670 // recurse
671 parsePom(aetherTemplate, artifacts, new DefaultArtifact(
672 groupId, artifactId, "pom", version));
673 } else {
674 // TODO: deal with scope?
675 // TODO: deal with type
676 String type = "jar";
677 Artifact artifact = new DefaultArtifact(groupId,
678 artifactId, type, version);
679 artifacts.add(artifact);
680 }
681 }
682 } catch (Exception e) {
683 throw new SlcException("Cannot process " + pomArtifact, e);
684 }
685 }
686
687 public void setAetherTemplate(AetherTemplate aetherTemplate) {
688 this.aetherTemplate = aetherTemplate;
689 }
690
691 public void setExcludedArtifacts(Set<String> excludedArtifactIds) {
692 this.excludedArtifacts = excludedArtifactIds;
693 }
694
695 public void setRootCoordinates(String rootCoordinates) {
696 this.rootCoordinates = rootCoordinates;
697 }
698
699 public void setJcrSession(Session jcrSession) {
700 this.jcrSession = jcrSession;
701 }
702
703 public void setDistributionName(String distributionName) {
704 this.distributionName = distributionName;
705 }
706
707 }