View Javadoc
1   package org.apache.maven.artifact.resolver;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.util.ArrayList;
23  import java.util.Collections;
24  import java.util.Iterator;
25  import java.util.LinkedList;
26  import java.util.List;
27  import java.util.Set;
28  
29  import org.apache.maven.artifact.Artifact;
30  import org.apache.maven.artifact.repository.ArtifactRepository;
31  import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
32  import org.apache.maven.artifact.versioning.ArtifactVersion;
33  import org.apache.maven.artifact.versioning.OverConstrainedVersionException;
34  
35  /**
36   * ResolutionNode
37   */
38  public class ResolutionNode
39  {
40      private Artifact artifact;
41  
42      private List<ResolutionNode> children;
43  
44      private final List<Object> parents;
45  
46      private final int depth;
47  
48      private final ResolutionNode parent;
49  
50      private final List<ArtifactRepository> remoteRepositories;
51  
52      private boolean active = true;
53  
54      private List<Artifact> trail;
55  
56      public ResolutionNode( Artifact artifact, List<ArtifactRepository> remoteRepositories )
57      {
58          this.artifact = artifact;
59          this.remoteRepositories = remoteRepositories;
60          depth = 0;
61          parents = Collections.emptyList();
62          parent = null;
63      }
64  
65      public ResolutionNode( Artifact artifact, List<ArtifactRepository> remoteRepositories, ResolutionNode parent )
66      {
67          this.artifact = artifact;
68          this.remoteRepositories = remoteRepositories;
69          depth = parent.depth + 1;
70          parents = new ArrayList<>();
71          parents.addAll( parent.parents );
72          parents.add( parent.getKey() );
73          this.parent = parent;
74      }
75  
76      public Artifact getArtifact()
77      {
78          return artifact;
79      }
80  
81      public Object getKey()
82      {
83          return artifact.getDependencyConflictId();
84      }
85  
86      public void addDependencies( Set<Artifact> artifacts, List<ArtifactRepository> remoteRepositories,
87                                   ArtifactFilter filter )
88          throws CyclicDependencyException, OverConstrainedVersionException
89      {
90          if ( artifacts != null && !artifacts.isEmpty() )
91          {
92              children = new ArrayList<>( artifacts.size() );
93  
94              for ( Artifact a : artifacts )
95              {
96                  if ( parents.contains( a.getDependencyConflictId() ) )
97                  {
98                      a.setDependencyTrail( getDependencyTrail() );
99  
100                     throw new CyclicDependencyException( "A dependency has introduced a cycle", a );
101                 }
102 
103                 children.add( new ResolutionNode( a, remoteRepositories, this ) );
104             }
105         }
106         else
107         {
108             children = Collections.emptyList();
109         }
110         trail = null;
111     }
112 
113     /**
114      * @return {@link List} &lt; {@link String} &gt; with artifact ids
115      * @throws OverConstrainedVersionException
116      */
117     public List<String> getDependencyTrail()
118         throws OverConstrainedVersionException
119     {
120         List<Artifact> trial = getTrail();
121 
122         List<String> ret = new ArrayList<>( trial.size() );
123 
124         for ( Artifact artifact : trial )
125         {
126             ret.add( artifact.getId() );
127         }
128 
129         return ret;
130     }
131 
132     private List<Artifact> getTrail()
133         throws OverConstrainedVersionException
134     {
135         if ( trail == null )
136         {
137             List<Artifact> ids = new LinkedList<>();
138             ResolutionNode node = this;
139             while ( node != null )
140             {
141                 Artifact artifact = node.getArtifact();
142                 if ( artifact.getVersion() == null )
143                 {
144                     // set the recommended version
145                     ArtifactVersion selected = artifact.getSelectedVersion();
146                     // MNG-2123: null is a valid response to getSelectedVersion, don't
147                     // assume it won't ever be.
148                     if ( selected != null )
149                     {
150                         artifact.selectVersion( selected.toString() );
151                     }
152                     else
153                     {
154                         throw new OverConstrainedVersionException( "Unable to get a selected Version for "
155                             + artifact.getArtifactId(), artifact );
156                     }
157                 }
158 
159                 ids.add( 0, artifact );
160                 node = node.parent;
161             }
162             trail = ids;
163         }
164         return trail;
165     }
166 
167     public boolean isResolved()
168     {
169         return children != null;
170     }
171 
172     /**
173      * Test whether the node is direct or transitive dependency.
174      */
175     public boolean isChildOfRootNode()
176     {
177         return parent != null && parent.parent == null;
178     }
179 
180     public Iterator<ResolutionNode> getChildrenIterator()
181     {
182         return children.iterator();
183     }
184 
185     public int getDepth()
186     {
187         return depth;
188     }
189 
190     public List<ArtifactRepository> getRemoteRepositories()
191     {
192         return remoteRepositories;
193     }
194 
195     public boolean isActive()
196     {
197         return active;
198     }
199 
200     public void enable()
201     {
202         active = true;
203 
204         // TODO if it was null, we really need to go find them now... or is this taken care of by the ordering?
205         if ( children != null )
206         {
207             for ( ResolutionNode node : children )
208             {
209                 node.enable();
210             }
211         }
212     }
213 
214     public void disable()
215     {
216         active = false;
217         if ( children != null )
218         {
219             for ( ResolutionNode node : children )
220             {
221                 node.disable();
222             }
223         }
224     }
225 
226     public boolean filterTrail( ArtifactFilter filter )
227         throws OverConstrainedVersionException
228     {
229         boolean success = true;
230         if ( filter != null )
231         {
232             for ( Artifact artifact : getTrail() )
233             {
234                 if ( !filter.include( artifact ) )
235                 {
236                     success = false;
237                 }
238             }
239         }
240         return success;
241     }
242 
243     @Override
244     public String toString()
245     {
246         return artifact.toString() + " (" + depth + "; " + ( active ? "enabled" : "disabled" ) + ")";
247     }
248 
249     public void setArtifact( Artifact artifact )
250     {
251         this.artifact = artifact;
252     }
253 
254 }