1 package org
.argeo
.slc
.repo
.maven
;
3 import java
.io
.ByteArrayInputStream
;
4 import java
.io
.ByteArrayOutputStream
;
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
;
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
;
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
;
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
;
49 public class ImportMavenDependencies
implements Runnable
{
50 private final static Log log
= LogFactory
51 .getLog(ImportMavenDependencies
.class);
53 private AetherTemplate aetherTemplate
;
54 private String rootCoordinates
;
55 private Set
<String
> excludedArtifacts
= new HashSet
<String
>();
57 private Session jcrSession
;
58 private String artifactBasePath
= "/slc/repo/artifacts";
59 private String distributionsBasePath
= "/slc/repo/distributions";
60 private String distributionName
;
63 log
.debug(jcrSession
.getUserID());
64 Set
<Artifact
> artifacts
= resolveDistribution();
65 syncDistribution(artifacts
);
68 public Set
<Artifact
> resolveDistribution() {
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());
77 Set
<Artifact
> registeredArtifacts
= new TreeSet
<Artifact
>(
79 parsePom(aetherTemplate
, registeredArtifacts
, pomArtifact
);
80 if (log
.isDebugEnabled())
81 log
.debug("Gathered " + registeredArtifacts
.size()
84 // Resolve and add non-optional dependencies
85 Set
<Artifact
> artifacts
= new TreeSet
<Artifact
>(artifactComparator
);
86 for (Artifact artifact
: registeredArtifacts
) {
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());
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());
109 ByteArrayOutputStream out
= new ByteArrayOutputStream();
110 distributionDescriptor
.store(out
, "");
111 log
.debug(new String(out
.toByteArray()));
115 } catch (Exception e
) {
116 throw new SlcException("Cannot resolve distribution", e
);
120 protected void syncDistribution(Set
<Artifact
> artifacts
) {
121 Long begin
= System
.currentTimeMillis();
123 JcrUtils
.mkdirs(jcrSession
, artifactBasePath
);
124 JcrUtils
.mkdirs(jcrSession
, distributionsBasePath
+ '/'
126 artifacts
: for (Artifact artifact
: artifacts
) {
127 File file
= artifact
.getFile();
129 log
.warn("File not found for " + artifact
);
131 file
= artifactToFile(artifact
);
133 if (!file
.exists()) {
134 log
.warn("Generated file " + file
+ " for " + artifact
135 + " does not exist");
141 String parentPath
= artifactBasePath
+ '/'
142 + artifactParentPath(artifact
);
144 if (!jcrSession
.itemExists(parentPath
)) {
145 parentNode
= JcrUtils
.mkdirs(jcrSession
, parentPath
,
146 NodeType
.NT_FOLDER
, false);
148 parentNode
= jcrSession
.getNode(parentPath
);
152 if (!parentNode
.hasNode(file
.getName())) {
153 fileNode
= createFileNode(parentNode
, file
);
155 fileNode
= parentNode
.getNode(file
.getName());
157 processArtifact(fileNode
, artifact
);
158 if (fileNode
.isNodeType(RepoTypes
.SLC_JAR_FILE
)) {
159 processOsgiBundle(fileNode
);
164 .itemExists(bundleDistributionPath(fileNode
))
166 .isNodeType(RepoTypes
.SLC_BUNDLE_ARTIFACT
))
167 jcrSession
.getWorkspace().clone(
168 jcrSession
.getWorkspace().getName(),
170 bundleDistributionPath(fileNode
), false);
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);
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
);
189 protected String
artifactParentPath(Artifact artifact
) {
190 return artifact
.getGroupId().replace('.', '/') + '/'
191 + artifact
.getArtifactId() + '/' + artifact
.getVersion();
194 protected String
bundleDistributionPath(Node fileNode
) {
196 return distributionsBasePath
200 + fileNode
.getProperty(RepoNames
.SLC_SYMBOLIC_NAME
)
203 + fileNode
.getProperty(RepoNames
.SLC_BUNDLE_VERSION
)
205 } catch (RepositoryException e
) {
206 throw new SlcException("Cannot create distribution path for "
211 protected void processArtifact(Node fileNode
, Artifact artifact
) {
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
);
230 protected File
artifactToFile(Artifact artifact
) {
231 return new File(System
.getProperty("user.home")
237 + artifact
.getGroupId().replace('.', File
.separatorChar
)
239 + artifact
.getArtifactId()
241 + artifact
.getVersion()
243 + artifact
.getArtifactId()
245 + artifact
.getVersion()
246 + (artifact
.getClassifier().equals("") ?
""
247 : '-' + artifact
.getClassifier()) + '.'
248 + artifact
.getExtension());
251 protected void processOsgiBundle(Node fileNode
) {
252 Binary manifestBinary
= null;
253 InputStream manifestIn
= null;
255 manifestBinary
= fileNode
.getProperty(RepoNames
.SLC_MANIFEST
)
257 manifestIn
= manifestBinary
.getStream();
258 Manifest manifest
= new Manifest(manifestIn
);
259 Attributes attrs
= manifest
.getMainAttributes();
261 if (log
.isTraceEnabled())
262 for (Object key
: attrs
.keySet())
263 log
.trace(key
+ ": " + attrs
.getValue(key
.toString()));
265 if (!attrs
.containsKey(new Name(Constants
.BUNDLE_SYMBOLICNAME
))) {
266 log
.warn(fileNode
+ " is not an OSGi bundle");
267 return;// not an osgi bundle
270 fileNode
.addMixin(RepoTypes
.SLC_BUNDLE_ARTIFACT
);
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
);
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
);
294 // required execution environment
295 if (attrs
.containsKey(new Name(
296 Constants
.BUNDLE_REQUIREDEXECUTIONENVIRONMENT
)))
297 fileNode
.setProperty(
299 + Constants
.BUNDLE_REQUIREDEXECUTIONENVIRONMENT
,
301 Constants
.BUNDLE_REQUIREDEXECUTIONENVIRONMENT
)
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(","));
311 Version version
= new Version(
312 attrs
.getValue(Constants
.BUNDLE_VERSION
));
313 fileNode
.setProperty(RepoNames
.SLC_BUNDLE_VERSION
,
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
);
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
++) {
330 .startsWith(Constants
.BUNDLE_VERSION_ATTRIBUTE
)) {
331 node
.setProperty(RepoNames
.SLC_BUNDLE_VERSION
,
332 attributeValue(tokens
[i
]));
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
]));
354 .startsWith(Constants
.RESOLUTION_DIRECTIVE
)) {
356 RepoNames
.SLC_OPTIONAL
,
357 directiveValue(tokens
[i
]).equals(
358 Constants
.RESOLUTION_OPTIONAL
));
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
]));
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
);
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 +
415 Node usesNode
= node
.addNode(
417 RepoTypes
.SLC_JAVA_PACKAGE
);
418 usesNode
.setProperty(RepoNames
.SLC_NAME
,
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
++) {
439 .startsWith(Constants
.BUNDLE_VERSION_ATTRIBUTE
)) {
440 node
.setProperty(RepoNames
.SLC_BUNDLE_VERSION
,
441 attributeValue(tokens
[i
]));
443 .startsWith(Constants
.RESOLUTION_DIRECTIVE
)) {
445 RepoNames
.SLC_OPTIONAL
,
446 directiveValue(tokens
[i
]).equals(
447 Constants
.RESOLUTION_OPTIONAL
));
452 } catch (Exception e
) {
453 throw new SlcException("Cannot process OSGi bundle " + fileNode
, e
);
455 if (manifestBinary
!= null)
456 manifestBinary
.dispose();
457 IOUtils
.closeQuietly(manifestIn
);
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("");
466 for (char c
: str
.toCharArray()) {
469 res
.add(curr
.toString());
470 curr
= new StringBuffer("");
472 } else if (c
== '\"') {
479 res
.add(curr
.toString());
484 private void addAttr(String key
, Node node
, Attributes attrs
)
485 throws RepositoryException
{
486 addAttr(new Name(key
), node
, attrs
);
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
);
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();
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());
517 private String
attributeValue(String str
) {
518 return extractValue(str
, "=");
521 private String
directiveValue(String str
) {
522 return extractValue(str
, ":=");
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();
530 if (value
.startsWith("\""))
531 value
= value
.substring(1);
532 if (value
.endsWith("\""))
533 value
= value
.substring(0, value
.length() - 1);
537 protected Node
createFileNode(Node parentNode
, File file
) {
538 Binary binary
= null;
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
);
548 if (FilenameUtils
.isExtension(file
.getName(), "jar")) {
549 JarInputStream jarIn
= null;
550 ByteArrayOutputStream bo
= null;
551 ByteArrayInputStream bi
= null;
552 Binary manifestBinary
= null;
554 jarIn
= new JarInputStream(binary
.getStream());
555 Manifest manifest
= jarIn
.getManifest();
556 bo
= new ByteArrayOutputStream();
558 bi
= new ByteArrayInputStream(bo
.toByteArray());
559 manifestBinary
= jcrSession
.getValueFactory().createBinary(
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
,
571 addAttr(Attributes
.Name
.IMPLEMENTATION_VENDOR
, fileNode
,
573 addAttr(Attributes
.Name
.IMPLEMENTATION_VENDOR_ID
, fileNode
,
575 addAttr(Attributes
.Name
.SPECIFICATION_TITLE
, fileNode
,
577 addAttr(Attributes
.Name
.SPECIFICATION_VERSION
, fileNode
,
579 addAttr(Attributes
.Name
.SPECIFICATION_VENDOR
, fileNode
,
581 addAttr(Attributes
.Name
.SEALED
, fileNode
, attrs
);
583 if (manifestBinary
!= null)
584 manifestBinary
.dispose();
585 IOUtils
.closeQuietly(bi
);
586 IOUtils
.closeQuietly(bo
);
587 IOUtils
.closeQuietly(jarIn
);
591 } catch (Exception e
) {
592 throw new SlcException("Cannot create file node based on " + file
593 + " under " + parentNode
, e
);
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
);
610 private void addArtifact(Set
<Artifact
> artifacts
, Artifact artifact
) {
611 if (!excludedArtifacts
.contains(artifact
.getGroupId() + ":"
612 + artifact
.getArtifactId()))
613 artifacts
.add(artifact
);
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.
622 protected void parsePom(AetherTemplate aetherTemplate
,
623 Set
<Artifact
> artifacts
, Artifact pomArtifact
) {
624 if (log
.isDebugEnabled())
625 log
.debug("Gather dependencies for " + pomArtifact
);
628 File file
= aetherTemplate
.getResolvedFile(pomArtifact
);
629 DocumentBuilder documentBuilder
= DocumentBuilderFactory
630 .newInstance().newDocumentBuilder();
631 Document doc
= documentBuilder
.parse(file
);
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());
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 "
665 version
= props
.getProperty(versionKey
);
667 NodeList scopes
= dependency
.getElementsByTagName("scope");
668 if (scopes
.getLength() > 0
669 && scopes
.item(0).getTextContent().equals("import")) {
671 parsePom(aetherTemplate
, artifacts
, new DefaultArtifact(
672 groupId
, artifactId
, "pom", version
));
674 // TODO: deal with scope?
675 // TODO: deal with type
677 Artifact artifact
= new DefaultArtifact(groupId
,
678 artifactId
, type
, version
);
679 artifacts
.add(artifact
);
682 } catch (Exception e
) {
683 throw new SlcException("Cannot process " + pomArtifact
, e
);
687 public void setAetherTemplate(AetherTemplate aetherTemplate
) {
688 this.aetherTemplate
= aetherTemplate
;
691 public void setExcludedArtifacts(Set
<String
> excludedArtifactIds
) {
692 this.excludedArtifacts
= excludedArtifactIds
;
695 public void setRootCoordinates(String rootCoordinates
) {
696 this.rootCoordinates
= rootCoordinates
;
699 public void setJcrSession(Session jcrSession
) {
700 this.jcrSession
= jcrSession
;
703 public void setDistributionName(String distributionName
) {
704 this.distributionName
= distributionName
;