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             children = Collections.unmodifiableList( children );
106         }
107         else
108         {
109             children = Collections.emptyList();
110         }
111         trail = null;
112     }
113 
114     /**
115      * @return {@link List} &lt; {@link String} &gt; with artifact ids
116      * @throws OverConstrainedVersionException
117      */
118     public List<String> getDependencyTrail()
119         throws OverConstrainedVersionException
120     {
121         List<Artifact> trial = getTrail();
122 
123         List<String> ret = new ArrayList<>( trial.size() );
124 
125         for ( Artifact artifact : trial )
126         {
127             ret.add( artifact.getId() );
128         }
129 
130         return ret;
131     }
132 
133     private List<Artifact> getTrail()
134         throws OverConstrainedVersionException
135     {
136         if ( trail == null )
137         {
138             List<Artifact> ids = new LinkedList<>();
139             ResolutionNode node = this;
140             while ( node != null )
141             {
142                 Artifact artifact = node.getArtifact();
143                 if ( artifact.getVersion() == null )
144                 {
145                     // set the recommended version
146                     ArtifactVersion selected = artifact.getSelectedVersion();
147                     // MNG-2123: null is a valid response to getSelectedVersion, don't
148                     // assume it won't ever be.
149                     if ( selected != null )
150                     {
151                         artifact.selectVersion( selected.toString() );
152                     }
153                     else
154                     {
155                         throw new OverConstrainedVersionException( "Unable to get a selected Version for "
156                             + artifact.getArtifactId(), artifact );
157                     }
158                 }
159 
160                 ids.add( 0, artifact );
161                 node = node.parent;
162             }
163             trail = ids;
164         }
165         return trail;
166     }
167 
168     public boolean isResolved()
169     {
170         return children != null;
171     }
172 
173     /**
174      * Test whether the node is direct or transitive dependency.
175      */
176     public boolean isChildOfRootNode()
177     {
178         return parent != null && parent.parent == null;
179     }
180 
181     public Iterator<ResolutionNode> getChildrenIterator()
182     {
183         return children.iterator();
184     }
185 
186     public int getDepth()
187     {
188         return depth;
189     }
190 
191     public List<ArtifactRepository> getRemoteRepositories()
192     {
193         return remoteRepositories;
194     }
195 
196     public boolean isActive()
197     {
198         return active;
199     }
200 
201     public void enable()
202     {
203         active = true;
204 
205         // TODO if it was null, we really need to go find them now... or is this taken care of by the ordering?
206         if ( children != null )
207         {
208             for ( ResolutionNode node : children )
209             {
210                 node.enable();
211             }
212         }
213     }
214 
215     public void disable()
216     {
217         active = false;
218         if ( children != null )
219         {
220             for ( ResolutionNode node : children )
221             {
222                 node.disable();
223             }
224         }
225     }
226 
227     public boolean filterTrail( ArtifactFilter filter )
228         throws OverConstrainedVersionException
229     {
230         boolean success = true;
231         if ( filter != null )
232         {
233             for ( Artifact artifact : getTrail() )
234             {
235                 if ( !filter.include( artifact ) )
236                 {
237                     success = false;
238                 }
239             }
240         }
241         return success;
242     }
243 
244     @Override
245     public String toString()
246     {
247         return artifact.toString() + " (" + depth + "; " + ( active ? "enabled" : "disabled" ) + ")";
248     }
249 
250     public void setArtifact( Artifact artifact )
251     {
252         this.artifact = artifact;
253     }
254 
255 }