View Javadoc

1   /* ==========================================================================
2    * Copyright 2008 mkleint
3    *
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
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
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.
15   * =========================================================================
16   */
17  package org.codehaus.mojo.nbm;
18  
19  import java.util.ArrayList;
20  import java.util.Collections;
21  import java.util.HashMap;
22  import java.util.List;
23  import java.util.Map;
24  import java.util.Stack;
25  import org.apache.maven.artifact.Artifact;
26  import org.apache.maven.plugin.MojoExecutionException;
27  import org.apache.maven.plugin.logging.Log;
28  import org.apache.maven.shared.dependency.graph.DependencyNode;
29  import org.apache.maven.shared.dependency.graph.traversal.DependencyNodeVisitor;
30  import org.codehaus.mojo.nbm.utils.ExamineManifest;
31  
32  /**
33   * A dependency node visitor that collects visited nodes that are known libraries or are
34   * children of known libraries
35   * @author milos kleint
36   */
37  public class CollectModuleLibrariesNodeVisitor
38      implements DependencyNodeVisitor
39  {
40  
41      /**
42       * The collected list of nodes.
43       */
44      private final Map<String, List<Artifact>> directNodes;
45  
46      private final Map<String, List<Artifact>> transitiveNodes;
47  
48      private Map<String, Artifact> artifacts;
49  
50      private Map<Artifact, ExamineManifest> examinerCache;
51  
52      private final Log log;
53  
54      private MojoExecutionException throwable;
55  
56      private DependencyNode root;
57  
58      private Stack<String> currentModule = new Stack<String>();
59      private static final String LIB_ID = "!@#$%^&ROOT";
60  
61      private final boolean useOSGiDependencies;
62  
63      /**
64       * Creates a dependency node visitor that collects visited nodes for further processing.
65       */
66      public CollectModuleLibrariesNodeVisitor(
67          List<Artifact> runtimeArtifacts, Map<Artifact, ExamineManifest> examinerCache,
68          Log log, DependencyNode root, boolean useOSGiDependencies )
69      {
70          directNodes = new HashMap<String, List<Artifact>>();
71          transitiveNodes = new HashMap<String, List<Artifact>>();
72          artifacts = new HashMap<String, Artifact>();
73          for ( Artifact a : runtimeArtifacts )
74          {
75              artifacts.put( a.getDependencyConflictId(), a );
76          }
77          this.examinerCache = examinerCache;
78          this.log = log;
79          this.root = root;
80          this.useOSGiDependencies = useOSGiDependencies;
81      }
82  
83      /**
84       * {@inheritDoc}
85       */
86      public boolean visit( DependencyNode node )
87      {
88          if ( throwable != null )
89          {
90              return false;
91          }
92          if ( root == node )
93          {
94              return true;
95          }
96          try
97          {
98              Artifact artifact = node.getArtifact();
99              if ( !artifacts.containsKey( artifact.getDependencyConflictId() ) )
100             {
101                 //ignore non-runtime stuff..
102                 return false;
103             }
104             // somehow the transitive artifacts in the  tree are not always resolved?
105             artifact = artifacts.get( artifact.getDependencyConflictId() );
106 
107             ExamineManifest depExaminator = examinerCache.get( artifact );
108             if ( depExaminator == null )
109             {
110                 depExaminator = new ExamineManifest( log );
111                 depExaminator.setArtifactFile( artifact.getFile() );
112                 depExaminator.checkFile();
113                 examinerCache.put( artifact, depExaminator );
114             }
115             if ( depExaminator.isNetBeansModule() || ( useOSGiDependencies && depExaminator.isOsgiBundle() ) )
116             {
117                 currentModule.push( artifact.getDependencyConflictId() );
118                 ArrayList<Artifact> arts = new ArrayList<Artifact>();
119                 arts.add( artifact );
120                 if ( currentModule.size() == 1 )
121                 {
122                     directNodes.put( currentModule.peek(), arts );
123                 }
124                 else
125                 {
126                     transitiveNodes.put( currentModule.peek(), arts );
127                 }
128                 return true;
129             }
130             if ( currentModule.size() > 0 )
131             {
132                 ////MNBMODULE-95 we are only interested in the module owned libraries
133                 if ( !currentModule.peek().startsWith( LIB_ID ) &&
134                         AbstractNbmMojo.matchesLibrary( artifact, Collections.<String>emptyList(), depExaminator, log, useOSGiDependencies ) )
135                 {
136                     if ( currentModule.size() == 1 )
137                     {
138                         directNodes.get( currentModule.peek() ).add( artifact );
139                     }
140                     else
141                     {
142                         transitiveNodes.get( currentModule.peek() ).add( artifact );
143                     }
144                     // if a library, iterate to it's child nodes.
145                     return true;
146                 }
147             }
148             else
149             {
150                 //MNBMODULE-95 we check the non-module dependencies to see if they
151                 // depend on modules/bundles. these bundles are transitive, so
152                 // we add the root module as the first currentModule to keep
153                 //any bundle/module underneath it as transitive
154                 currentModule.push( LIB_ID + artifact.getDependencyConflictId() );
155             }
156         }
157         catch ( MojoExecutionException mojoExecutionException )
158         {
159             throwable = mojoExecutionException;
160         }
161         return true;
162     }
163 
164     /**
165      * {@inheritDoc}
166      */
167     public boolean endVisit( DependencyNode node )
168     {
169         if ( throwable != null )
170         {
171             return false;
172         }
173         if ( !currentModule.empty()
174             && ( currentModule.peek().equals( node.getArtifact().getDependencyConflictId() )
175                             || currentModule.peek().equals( LIB_ID + node.getArtifact().getDependencyConflictId() ) ) )
176         {
177             currentModule.pop();
178         }
179         return true;
180     }
181 
182     /**
183      * modules declared in the project's pom
184      * @return a map of module artifact lists, key is the dependencyConflictId
185      * @throws org.apache.maven.plugin.MojoExecutionException
186      */
187     public Map<String, List<Artifact>> getDeclaredArtifacts()
188         throws MojoExecutionException
189     {
190         if ( throwable != null )
191         {
192             throw throwable;
193         }
194         return directNodes;
195     }
196 
197     /**
198      * modules that were picked up transitively
199      * @return a map of module artifact lists, key is the dependencyConflictId
200      * @throws org.apache.maven.plugin.MojoExecutionException
201      */
202     public Map<String, List<Artifact>> getTransitiveArtifacts()
203         throws MojoExecutionException
204     {
205         if ( throwable != null )
206         {
207             throw throwable;
208         }
209         return transitiveNodes;
210     }
211 }