2 * Copyright (C) 2007-2012 Mathieu Baudier
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package org
.argeo
.slc
.repo
.maven
;
18 import java
.io
.ByteArrayInputStream
;
19 import java
.io
.ByteArrayOutputStream
;
21 import java
.io
.FileInputStream
;
22 import java
.io
.InputStream
;
23 import java
.util
.ArrayList
;
24 import java
.util
.Comparator
;
25 import java
.util
.HashSet
;
26 import java
.util
.List
;
27 import java
.util
.Properties
;
29 import java
.util
.TreeSet
;
30 import java
.util
.jar
.Attributes
;
31 import java
.util
.jar
.Attributes
.Name
;
32 import java
.util
.jar
.JarInputStream
;
33 import java
.util
.jar
.Manifest
;
35 import javax
.jcr
.Binary
;
36 import javax
.jcr
.Node
;
37 import javax
.jcr
.NodeIterator
;
38 import javax
.jcr
.Property
;
39 import javax
.jcr
.RepositoryException
;
40 import javax
.jcr
.Session
;
41 import javax
.jcr
.nodetype
.NodeType
;
42 import javax
.xml
.parsers
.DocumentBuilder
;
43 import javax
.xml
.parsers
.DocumentBuilderFactory
;
45 import org
.apache
.commons
.io
.FilenameUtils
;
46 import org
.apache
.commons
.io
.IOUtils
;
47 import org
.apache
.commons
.logging
.Log
;
48 import org
.apache
.commons
.logging
.LogFactory
;
49 import org
.argeo
.jcr
.JcrUtils
;
50 import org
.argeo
.slc
.SlcException
;
51 import org
.argeo
.slc
.aether
.AetherTemplate
;
52 import org
.argeo
.slc
.jcr
.SlcNames
;
53 import org
.argeo
.slc
.jcr
.SlcTypes
;
54 import org
.argeo
.slc
.repo
.ArtifactIndexer
;
55 import org
.argeo
.slc
.repo
.RepoConstants
;
56 import org
.osgi
.framework
.Constants
;
57 import org
.osgi
.framework
.Version
;
58 import org
.sonatype
.aether
.artifact
.Artifact
;
59 import org
.sonatype
.aether
.graph
.DependencyNode
;
60 import org
.sonatype
.aether
.util
.artifact
.DefaultArtifact
;
61 import org
.w3c
.dom
.Document
;
62 import org
.w3c
.dom
.Element
;
63 import org
.w3c
.dom
.NodeList
;
65 public class ImportMavenDependencies
implements Runnable
{
66 private final static Log log
= LogFactory
67 .getLog(ImportMavenDependencies
.class);
69 private AetherTemplate aetherTemplate
;
70 private String rootCoordinates
;
71 private Set
<String
> excludedArtifacts
= new HashSet
<String
>();
73 private Session jcrSession
;
74 private String artifactBasePath
= RepoConstants
.ARTIFACTS_BASE_PATH
;
75 private String distributionsBasePath
= RepoConstants
.DISTRIBUTIONS_BASE_PATH
;
76 private String distributionName
;
78 private ArtifactIndexer artifactIndexer
= new ArtifactIndexer();
81 log
.debug(jcrSession
.getUserID());
82 Set
<Artifact
> artifacts
= resolveDistribution();
83 syncDistribution(artifacts
);
86 public Set
<Artifact
> resolveDistribution() {
88 Artifact pomArtifact
= new DefaultArtifact(rootCoordinates
);
89 Comparator
<Artifact
> artifactComparator
= new Comparator
<Artifact
>() {
90 public int compare(Artifact o1
, Artifact o2
) {
91 return o1
.getArtifactId().compareTo(o2
.getArtifactId());
95 Set
<Artifact
> registeredArtifacts
= new TreeSet
<Artifact
>(
97 parsePom(aetherTemplate
, registeredArtifacts
, pomArtifact
);
98 if (log
.isDebugEnabled())
99 log
.debug("Gathered " + registeredArtifacts
.size()
102 // Resolve and add non-optional dependencies
103 Set
<Artifact
> artifacts
= new TreeSet
<Artifact
>(artifactComparator
);
104 for (Artifact artifact
: registeredArtifacts
) {
106 addArtifact(artifacts
, artifact
);
107 DependencyNode node
= aetherTemplate
108 .resolveDependencies(artifact
);
109 addDependencies(artifacts
, node
);
110 } catch (Exception e
) {
111 log
.error("Could not resolve dependencies of " + artifact
112 + ": " + e
.getCause().getMessage());
117 if (log
.isDebugEnabled())
118 log
.debug("Resolved " + artifacts
.size() + " artifacts");
119 Properties distributionDescriptor
= new Properties();
120 for (Artifact artifact
: artifacts
) {
121 log
.debug(artifact
.getArtifactId() + " ["
122 + artifact
.getVersion() + "]\t(" + artifact
+ ")");
123 distributionDescriptor
.setProperty(artifact
.getArtifactId()
124 + ":" + artifact
.getVersion(), artifact
.toString());
127 ByteArrayOutputStream out
= new ByteArrayOutputStream();
128 distributionDescriptor
.store(out
, "");
129 log
.debug(new String(out
.toByteArray()));
133 } catch (Exception e
) {
134 throw new SlcException("Cannot resolve distribution", e
);
138 protected void syncDistribution(Set
<Artifact
> artifacts
) {
139 Long begin
= System
.currentTimeMillis();
141 JcrUtils
.mkdirs(jcrSession
, artifactBasePath
);
142 JcrUtils
.mkdirs(jcrSession
, distributionsBasePath
+ '/'
144 artifacts
: for (Artifact artifact
: artifacts
) {
145 File file
= artifact
.getFile();
147 log
.warn("File not found for " + artifact
);
149 file
= artifactToFile(artifact
);
151 if (!file
.exists()) {
152 log
.warn("Generated file " + file
+ " for " + artifact
153 + " does not exist");
159 String parentPath
= artifactBasePath
160 + (artifactBasePath
.endsWith("/") ?
"" : "/")
161 + artifactParentPath(artifact
);
163 if (!jcrSession
.itemExists(parentPath
)) {
164 parentNode
= JcrUtils
.mkdirs(jcrSession
, parentPath
,
167 parentNode
= jcrSession
.getNode(parentPath
);
171 if (!parentNode
.hasNode(file
.getName())) {
172 fileNode
= createFileNode(parentNode
, file
);
174 fileNode
= parentNode
.getNode(file
.getName());
177 if (artifactIndexer
.support(fileNode
.getPath()))
178 artifactIndexer
.index(fileNode
);
179 if (fileNode
.isNodeType(SlcTypes
.SLC_JAR_FILE
)) {
180 processOsgiBundle(fileNode
);
185 .itemExists(bundleDistributionPath(fileNode
))
187 .isNodeType(SlcTypes
.SLC_BUNDLE_ARTIFACT
))
188 jcrSession
.getWorkspace().clone(
189 jcrSession
.getWorkspace().getName(),
191 bundleDistributionPath(fileNode
), false);
193 if (log
.isDebugEnabled())
194 log
.debug("Synchronized " + fileNode
);
195 } catch (Exception e
) {
196 log
.error("Could not synchronize " + artifact
, e
);
197 jcrSession
.refresh(false);
202 Long duration
= (System
.currentTimeMillis() - begin
) / 1000;
203 if (log
.isDebugEnabled())
204 log
.debug("Synchronized distribution in " + duration
+ "s");
205 } catch (Exception e
) {
206 throw new SlcException("Cannot synchronize distribution", e
);
210 protected String
artifactParentPath(Artifact artifact
) {
211 return artifact
.getGroupId().replace('.', '/') + '/'
212 + artifact
.getArtifactId() + '/' + artifact
.getVersion();
215 protected String
bundleDistributionPath(Node fileNode
) {
217 return distributionsBasePath
221 + fileNode
.getProperty(SlcNames
.SLC_SYMBOLIC_NAME
)
224 + fileNode
.getProperty(SlcNames
.SLC_BUNDLE_VERSION
)
226 } catch (RepositoryException e
) {
227 throw new SlcException("Cannot create distribution path for "
232 protected File
artifactToFile(Artifact artifact
) {
233 return new File(System
.getProperty("user.home")
239 + artifact
.getGroupId().replace('.', File
.separatorChar
)
241 + artifact
.getArtifactId()
243 + artifact
.getVersion()
245 + artifact
.getArtifactId()
247 + artifact
.getVersion()
248 + (artifact
.getClassifier().equals("") ?
""
249 : '-' + artifact
.getClassifier()) + '.'
250 + artifact
.getExtension());
253 protected void processOsgiBundle(Node fileNode
) {
254 Binary manifestBinary
= null;
255 InputStream manifestIn
= null;
257 manifestBinary
= fileNode
.getProperty(SlcNames
.SLC_MANIFEST
)
259 manifestIn
= manifestBinary
.getStream();
260 Manifest manifest
= new Manifest(manifestIn
);
261 Attributes attrs
= manifest
.getMainAttributes();
263 if (log
.isTraceEnabled())
264 for (Object key
: attrs
.keySet())
265 log
.trace(key
+ ": " + attrs
.getValue(key
.toString()));
267 if (!attrs
.containsKey(new Name(Constants
.BUNDLE_SYMBOLICNAME
))) {
268 log
.warn(fileNode
+ " is not an OSGi bundle");
269 return;// not an osgi bundle
272 fileNode
.addMixin(SlcTypes
.SLC_BUNDLE_ARTIFACT
);
275 String symbolicName
= attrs
.getValue(Constants
.BUNDLE_SYMBOLICNAME
);
276 // make sure there is no directive
277 symbolicName
= symbolicName
.split(";")[0];
278 fileNode
.setProperty(SlcNames
.SLC_SYMBOLIC_NAME
, symbolicName
);
281 addAttr(Constants
.BUNDLE_SYMBOLICNAME
, fileNode
, attrs
);
282 addAttr(Constants
.BUNDLE_NAME
, fileNode
, attrs
);
283 addAttr(Constants
.BUNDLE_DESCRIPTION
, fileNode
, attrs
);
284 addAttr(Constants
.BUNDLE_MANIFESTVERSION
, fileNode
, attrs
);
285 addAttr(Constants
.BUNDLE_CATEGORY
, fileNode
, attrs
);
286 addAttr(Constants
.BUNDLE_ACTIVATIONPOLICY
, fileNode
, attrs
);
287 addAttr(Constants
.BUNDLE_COPYRIGHT
, fileNode
, attrs
);
288 addAttr(Constants
.BUNDLE_VENDOR
, fileNode
, attrs
);
289 addAttr("Bundle-License", fileNode
, attrs
);
290 addAttr(Constants
.BUNDLE_DOCURL
, fileNode
, attrs
);
291 addAttr(Constants
.BUNDLE_CONTACTADDRESS
, fileNode
, attrs
);
292 addAttr(Constants
.BUNDLE_ACTIVATOR
, fileNode
, attrs
);
293 addAttr(Constants
.BUNDLE_UPDATELOCATION
, fileNode
, attrs
);
294 addAttr(Constants
.BUNDLE_LOCALIZATION
, fileNode
, attrs
);
296 // required execution environment
297 if (attrs
.containsKey(new Name(
298 Constants
.BUNDLE_REQUIREDEXECUTIONENVIRONMENT
)))
299 fileNode
.setProperty(
301 + Constants
.BUNDLE_REQUIREDEXECUTIONENVIRONMENT
,
303 Constants
.BUNDLE_REQUIREDEXECUTIONENVIRONMENT
)
307 if (attrs
.containsKey(new Name(Constants
.BUNDLE_CLASSPATH
)))
308 fileNode
.setProperty(
309 SlcNames
.SLC_
+ Constants
.BUNDLE_CLASSPATH
, attrs
310 .getValue(Constants
.BUNDLE_CLASSPATH
)
314 Version version
= new Version(
315 attrs
.getValue(Constants
.BUNDLE_VERSION
));
316 fileNode
.setProperty(SlcNames
.SLC_BUNDLE_VERSION
,
318 cleanSubNodes(fileNode
, SlcNames
.SLC_
+ Constants
.BUNDLE_VERSION
);
319 Node bundleVersionNode
= fileNode
.addNode(SlcNames
.SLC_
320 + Constants
.BUNDLE_VERSION
, SlcTypes
.SLC_OSGI_VERSION
);
321 mapOsgiVersion(version
, bundleVersionNode
);
324 cleanSubNodes(fileNode
, SlcNames
.SLC_
+ Constants
.FRAGMENT_HOST
);
325 if (attrs
.containsKey(new Name(Constants
.FRAGMENT_HOST
))) {
326 String fragmentHost
= attrs
.getValue(Constants
.FRAGMENT_HOST
);
327 String
[] tokens
= fragmentHost
.split(";");
328 Node node
= fileNode
.addNode(SlcNames
.SLC_
329 + Constants
.FRAGMENT_HOST
, SlcTypes
.SLC_FRAGMENT_HOST
);
330 node
.setProperty(SlcNames
.SLC_SYMBOLIC_NAME
, tokens
[0]);
331 for (int i
= 1; i
< tokens
.length
; i
++) {
333 .startsWith(Constants
.BUNDLE_VERSION_ATTRIBUTE
)) {
334 node
.setProperty(SlcNames
.SLC_BUNDLE_VERSION
,
335 attributeValue(tokens
[i
]));
341 cleanSubNodes(fileNode
, SlcNames
.SLC_
+ Constants
.IMPORT_PACKAGE
);
342 if (attrs
.containsKey(new Name(Constants
.IMPORT_PACKAGE
))) {
343 String importPackages
= attrs
344 .getValue(Constants
.IMPORT_PACKAGE
);
345 List
<String
> packages
= parsePackages(importPackages
);
346 for (String pkg
: packages
) {
347 String
[] tokens
= pkg
.split(";");
348 Node node
= fileNode
.addNode(SlcNames
.SLC_
349 + Constants
.IMPORT_PACKAGE
,
350 SlcTypes
.SLC_IMPORTED_PACKAGE
);
351 node
.setProperty(SlcNames
.SLC_NAME
, tokens
[0]);
352 for (int i
= 1; i
< tokens
.length
; i
++) {
353 if (tokens
[i
].startsWith(Constants
.VERSION_ATTRIBUTE
)) {
354 node
.setProperty(SlcNames
.SLC_VERSION
,
355 attributeValue(tokens
[i
]));
357 .startsWith(Constants
.RESOLUTION_DIRECTIVE
)) {
359 SlcNames
.SLC_OPTIONAL
,
360 directiveValue(tokens
[i
]).equals(
361 Constants
.RESOLUTION_OPTIONAL
));
367 // dynamic import package
368 cleanSubNodes(fileNode
, SlcNames
.SLC_
369 + Constants
.DYNAMICIMPORT_PACKAGE
);
370 if (attrs
.containsKey(new Name(Constants
.DYNAMICIMPORT_PACKAGE
))) {
371 String importPackages
= attrs
372 .getValue(Constants
.DYNAMICIMPORT_PACKAGE
);
373 List
<String
> packages
= parsePackages(importPackages
);
374 for (String pkg
: packages
) {
375 String
[] tokens
= pkg
.split(";");
376 Node node
= fileNode
.addNode(SlcNames
.SLC_
377 + Constants
.DYNAMICIMPORT_PACKAGE
,
378 SlcTypes
.SLC_DYNAMIC_IMPORTED_PACKAGE
);
379 node
.setProperty(SlcNames
.SLC_NAME
, tokens
[0]);
380 for (int i
= 1; i
< tokens
.length
; i
++) {
381 if (tokens
[i
].startsWith(Constants
.VERSION_ATTRIBUTE
)) {
382 node
.setProperty(SlcNames
.SLC_VERSION
,
383 attributeValue(tokens
[i
]));
390 cleanSubNodes(fileNode
, SlcNames
.SLC_
+ Constants
.EXPORT_PACKAGE
);
391 if (attrs
.containsKey(new Name(Constants
.EXPORT_PACKAGE
))) {
392 String exportPackages
= attrs
393 .getValue(Constants
.EXPORT_PACKAGE
);
394 List
<String
> packages
= parsePackages(exportPackages
);
395 for (String pkg
: packages
) {
396 String
[] tokens
= pkg
.split(";");
397 Node node
= fileNode
.addNode(SlcNames
.SLC_
398 + Constants
.EXPORT_PACKAGE
,
399 SlcTypes
.SLC_EXPORTED_PACKAGE
);
400 node
.setProperty(SlcNames
.SLC_NAME
, tokens
[0]);
401 // TODO: are these cleans really necessary?
402 cleanSubNodes(node
, SlcNames
.SLC_USES
);
403 cleanSubNodes(node
, SlcNames
.SLC_VERSION
);
404 for (int i
= 1; i
< tokens
.length
; i
++) {
405 if (tokens
[i
].startsWith(Constants
.VERSION_ATTRIBUTE
)) {
406 String versionStr
= attributeValue(tokens
[i
]);
407 Node versionNode
= node
.addNode(
408 SlcNames
.SLC_VERSION
,
409 SlcTypes
.SLC_OSGI_VERSION
);
410 mapOsgiVersion(new Version(versionStr
), versionNode
);
412 .startsWith(Constants
.USES_DIRECTIVE
)) {
413 String usedPackages
= directiveValue(tokens
[i
]);
414 // log.debug("uses='" + usedPackages + "'");
415 for (String usedPackage
: usedPackages
.split(",")) {
416 // log.debug("usedPackage='" + usedPackage +
418 Node usesNode
= node
.addNode(SlcNames
.SLC_USES
,
419 SlcTypes
.SLC_JAVA_PACKAGE
);
420 usesNode
.setProperty(SlcNames
.SLC_NAME
,
429 cleanSubNodes(fileNode
, SlcNames
.SLC_
+ Constants
.REQUIRE_BUNDLE
);
430 if (attrs
.containsKey(new Name(Constants
.REQUIRE_BUNDLE
))) {
431 String requireBundle
= attrs
.getValue(Constants
.REQUIRE_BUNDLE
);
432 String
[] bundles
= requireBundle
.split(",");
433 for (String bundle
: bundles
) {
434 String
[] tokens
= bundle
.split(";");
435 Node node
= fileNode
.addNode(SlcNames
.SLC_
436 + Constants
.REQUIRE_BUNDLE
,
437 SlcTypes
.SLC_REQUIRED_BUNDLE
);
438 node
.setProperty(SlcNames
.SLC_SYMBOLIC_NAME
, tokens
[0]);
439 for (int i
= 1; i
< tokens
.length
; i
++) {
441 .startsWith(Constants
.BUNDLE_VERSION_ATTRIBUTE
)) {
442 node
.setProperty(SlcNames
.SLC_BUNDLE_VERSION
,
443 attributeValue(tokens
[i
]));
445 .startsWith(Constants
.RESOLUTION_DIRECTIVE
)) {
447 SlcNames
.SLC_OPTIONAL
,
448 directiveValue(tokens
[i
]).equals(
449 Constants
.RESOLUTION_OPTIONAL
));
454 } catch (Exception e
) {
455 throw new SlcException("Cannot process OSGi bundle " + fileNode
, e
);
457 if (manifestBinary
!= null)
458 manifestBinary
.dispose();
459 IOUtils
.closeQuietly(manifestIn
);
463 /** Parse package list with nested directive with ',' */
464 private List
<String
> parsePackages(String str
) {
465 List
<String
> res
= new ArrayList
<String
>();
466 StringBuffer curr
= new StringBuffer("");
468 for (char c
: str
.toCharArray()) {
471 res
.add(curr
.toString());
472 curr
= new StringBuffer("");
474 } else if (c
== '\"') {
481 res
.add(curr
.toString());
486 private void addAttr(String key
, Node node
, Attributes attrs
)
487 throws RepositoryException
{
488 addAttr(new Name(key
), node
, attrs
);
491 private void addAttr(Name key
, Node node
, Attributes attrs
)
492 throws RepositoryException
{
493 if (attrs
.containsKey(key
)) {
494 String value
= attrs
.getValue(key
);
495 node
.setProperty(SlcNames
.SLC_
+ key
, value
);
499 private void cleanSubNodes(Node node
, String name
)
500 throws RepositoryException
{
501 if (node
.hasNode(name
)) {
502 NodeIterator nit
= node
.getNodes(name
);
503 while (nit
.hasNext())
504 nit
.nextNode().remove();
508 protected void mapOsgiVersion(Version version
, Node versionNode
)
509 throws RepositoryException
{
510 versionNode
.setProperty(SlcNames
.SLC_AS_STRING
, version
.toString());
511 versionNode
.setProperty(SlcNames
.SLC_MAJOR
, version
.getMajor());
512 versionNode
.setProperty(SlcNames
.SLC_MINOR
, version
.getMinor());
513 versionNode
.setProperty(SlcNames
.SLC_MICRO
, version
.getMicro());
514 if (!version
.getQualifier().equals(""))
515 versionNode
.setProperty(SlcNames
.SLC_QUALIFIER
,
516 version
.getQualifier());
519 private String
attributeValue(String str
) {
520 return extractValue(str
, "=");
523 private String
directiveValue(String str
) {
524 return extractValue(str
, ":=");
527 private String
extractValue(String str
, String eq
) {
528 String
[] tokens
= str
.split(eq
);
529 // String key = tokens[0];
530 String value
= tokens
[1].trim();
532 if (value
.startsWith("\""))
533 value
= value
.substring(1);
534 if (value
.endsWith("\""))
535 value
= value
.substring(0, value
.length() - 1);
539 protected Node
createFileNode(Node parentNode
, File file
) {
540 Binary binary
= null;
542 Node fileNode
= parentNode
543 .addNode(file
.getName(), NodeType
.NT_FILE
);
544 Node contentNode
= fileNode
.addNode(Node
.JCR_CONTENT
,
545 NodeType
.NT_RESOURCE
);
546 binary
= jcrSession
.getValueFactory().createBinary(
547 new FileInputStream(file
));
548 contentNode
.setProperty(Property
.JCR_DATA
, binary
);
550 if (FilenameUtils
.isExtension(file
.getName(), "jar")) {
551 JarInputStream jarIn
= null;
552 ByteArrayOutputStream bo
= null;
553 ByteArrayInputStream bi
= null;
554 Binary manifestBinary
= null;
556 jarIn
= new JarInputStream(binary
.getStream());
557 Manifest manifest
= jarIn
.getManifest();
558 bo
= new ByteArrayOutputStream();
560 bi
= new ByteArrayInputStream(bo
.toByteArray());
561 manifestBinary
= jcrSession
.getValueFactory().createBinary(
563 fileNode
.addMixin(SlcTypes
.SLC_JAR_FILE
);
564 fileNode
.setProperty(SlcNames
.SLC_MANIFEST
, manifestBinary
);
565 Attributes attrs
= manifest
.getMainAttributes();
566 addAttr(Attributes
.Name
.MANIFEST_VERSION
, fileNode
, attrs
);
567 addAttr(Attributes
.Name
.SIGNATURE_VERSION
, fileNode
, attrs
);
568 addAttr(Attributes
.Name
.CLASS_PATH
, fileNode
, attrs
);
569 addAttr(Attributes
.Name
.MAIN_CLASS
, fileNode
, attrs
);
570 addAttr(Attributes
.Name
.EXTENSION_NAME
, fileNode
, attrs
);
571 addAttr(Attributes
.Name
.IMPLEMENTATION_VERSION
, fileNode
,
573 addAttr(Attributes
.Name
.IMPLEMENTATION_VENDOR
, fileNode
,
575 addAttr(Attributes
.Name
.IMPLEMENTATION_VENDOR_ID
, fileNode
,
577 addAttr(Attributes
.Name
.SPECIFICATION_TITLE
, fileNode
,
579 addAttr(Attributes
.Name
.SPECIFICATION_VERSION
, fileNode
,
581 addAttr(Attributes
.Name
.SPECIFICATION_VENDOR
, fileNode
,
583 addAttr(Attributes
.Name
.SEALED
, fileNode
, attrs
);
585 if (manifestBinary
!= null)
586 manifestBinary
.dispose();
587 IOUtils
.closeQuietly(bi
);
588 IOUtils
.closeQuietly(bo
);
589 IOUtils
.closeQuietly(jarIn
);
593 } catch (Exception e
) {
594 throw new SlcException("Cannot create file node based on " + file
595 + " under " + parentNode
, e
);
602 /** Recursively adds non optional dependencies */
603 private void addDependencies(Set
<Artifact
> artifacts
, DependencyNode node
) {
604 for (DependencyNode child
: node
.getChildren()) {
605 if (!child
.getDependency().isOptional()) {
606 addArtifact(artifacts
, child
.getDependency().getArtifact());
607 addDependencies(artifacts
, child
);
612 private void addArtifact(Set
<Artifact
> artifacts
, Artifact artifact
) {
613 if (!excludedArtifacts
.contains(artifact
.getGroupId() + ":"
614 + artifact
.getArtifactId()))
615 artifacts
.add(artifact
);
619 * Directly parses Maven POM XML format in order to find all artifacts
620 * references under the dependency and dependencyManagement tags. This is
621 * meant to migrate existing pom registering a lot of artifacts, not to
622 * replace Maven resolving.
624 protected void parsePom(AetherTemplate aetherTemplate
,
625 Set
<Artifact
> artifacts
, Artifact pomArtifact
) {
626 if (log
.isDebugEnabled())
627 log
.debug("Gather dependencies for " + pomArtifact
);
630 File file
= aetherTemplate
.getResolvedFile(pomArtifact
);
631 DocumentBuilder documentBuilder
= DocumentBuilderFactory
632 .newInstance().newDocumentBuilder();
633 Document doc
= documentBuilder
.parse(file
);
636 Properties props
= new Properties();
637 props
.setProperty("project.version", pomArtifact
.getBaseVersion());
638 NodeList properties
= doc
.getElementsByTagName("properties");
639 if (properties
.getLength() > 0) {
640 NodeList propertiesElems
= properties
.item(0).getChildNodes();
641 for (int i
= 0; i
< propertiesElems
.getLength(); i
++) {
642 if (propertiesElems
.item(i
) instanceof Element
) {
643 Element property
= (Element
) propertiesElems
.item(i
);
644 props
.put(property
.getNodeName(),
645 property
.getTextContent());
650 // dependencies (direct and dependencyManagement)
651 NodeList dependencies
= doc
.getElementsByTagName("dependency");
652 for (int i
= 0; i
< dependencies
.getLength(); i
++) {
653 Element dependency
= (Element
) dependencies
.item(i
);
654 String groupId
= dependency
.getElementsByTagName("groupId")
655 .item(0).getTextContent().trim();
656 String artifactId
= dependency
657 .getElementsByTagName("artifactId").item(0)
658 .getTextContent().trim();
659 String version
= dependency
.getElementsByTagName("version")
660 .item(0).getTextContent().trim();
661 if (version
.startsWith("${")) {
662 String versionKey
= version
.substring(0,
663 version
.length() - 1).substring(2);
664 if (!props
.containsKey(versionKey
))
665 throw new SlcException("Cannot interpret version "
667 version
= props
.getProperty(versionKey
);
669 NodeList scopes
= dependency
.getElementsByTagName("scope");
670 if (scopes
.getLength() > 0
671 && scopes
.item(0).getTextContent().equals("import")) {
673 parsePom(aetherTemplate
, artifacts
, new DefaultArtifact(
674 groupId
, artifactId
, "pom", version
));
676 // TODO: deal with scope?
677 // TODO: deal with type
679 Artifact artifact
= new DefaultArtifact(groupId
,
680 artifactId
, type
, version
);
681 artifacts
.add(artifact
);
684 } catch (Exception e
) {
685 throw new SlcException("Cannot process " + pomArtifact
, e
);
689 public void setAetherTemplate(AetherTemplate aetherTemplate
) {
690 this.aetherTemplate
= aetherTemplate
;
693 public void setExcludedArtifacts(Set
<String
> excludedArtifactIds
) {
694 this.excludedArtifacts
= excludedArtifactIds
;
697 public void setRootCoordinates(String rootCoordinates
) {
698 this.rootCoordinates
= rootCoordinates
;
701 public void setJcrSession(Session jcrSession
) {
702 this.jcrSession
= jcrSession
;
705 public void setDistributionName(String distributionName
) {
706 this.distributionName
= distributionName
;