View Javadoc

1   package org.apache.maven.repository.legacy.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.Arrays;
24  import java.util.Collections;
25  import java.util.HashMap;
26  import java.util.HashSet;
27  import java.util.Iterator;
28  import java.util.LinkedHashSet;
29  import java.util.List;
30  import java.util.Map;
31  import java.util.Set;
32  
33  import org.apache.maven.artifact.Artifact;
34  import org.apache.maven.artifact.factory.ArtifactFactory;
35  import org.apache.maven.artifact.metadata.ArtifactMetadataRetrievalException;
36  import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
37  import org.apache.maven.artifact.metadata.ResolutionGroup;
38  import org.apache.maven.artifact.repository.ArtifactRepository;
39  import org.apache.maven.artifact.resolver.ArtifactResolutionException;
40  import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
41  import org.apache.maven.artifact.resolver.CyclicDependencyException;
42  import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
43  import org.apache.maven.artifact.resolver.filter.ExclusionSetFilter;
44  import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter;
45  import org.apache.maven.artifact.versioning.ArtifactVersion;
46  import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
47  import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
48  import org.apache.maven.artifact.versioning.OverConstrainedVersionException;
49  import org.apache.maven.artifact.versioning.VersionRange;
50  import org.apache.maven.repository.legacy.metadata.MetadataResolutionRequest;
51  import org.codehaus.plexus.PlexusTestCase;
52  
53  /**
54   * Test the default artifact collector.
55   *
56   * @author <a href="mailto:brett@apache.org">Brett Porter</a>
57   */
58  public class DefaultArtifactCollectorTest
59      extends PlexusTestCase
60  {
61      private LegacyArtifactCollector artifactCollector;
62  
63      private ArtifactFactory artifactFactory;
64  
65      private ArtifactSpec projectArtifact;
66  
67      private Source source;
68  
69      private static final String GROUP_ID = "test";
70  
71      @Override
72      protected void setUp()
73          throws Exception
74      {
75          super.setUp();
76  
77          source = new Source();
78          artifactFactory = (ArtifactFactory) lookup( ArtifactFactory.ROLE );
79          artifactCollector = (LegacyArtifactCollector) lookup( LegacyArtifactCollector.class );
80  
81          projectArtifact = createArtifactSpec( "project", "1.0", null );
82      }
83  
84      @Override
85      protected void tearDown()
86          throws Exception
87      {
88          artifactCollector = null;
89          artifactFactory = null;
90          super.tearDown();
91      }
92  
93      // works, but we don't fail on cycles presently
94      public void disabledtestCircularDependencyNotIncludingCurrentProject()
95          throws ArtifactResolutionException, InvalidVersionSpecificationException
96      {
97          ArtifactSpec a = createArtifactSpec( "a", "1.0" );
98          ArtifactSpec b = a.addDependency( "b", "1.0" );
99          b.addDependency( "a", "1.0" );
100         try
101         {
102             collect( a );
103             fail( "Should have failed on cyclic dependency not involving project" );
104         }
105         catch ( CyclicDependencyException expected )
106         {
107             assertTrue( true );
108         }
109     }
110 
111     // works, but we don't fail on cycles presently
112     public void disabledtestCircularDependencyIncludingCurrentProject()
113         throws ArtifactResolutionException, InvalidVersionSpecificationException
114     {
115         ArtifactSpec a = createArtifactSpec( "a", "1.0" );
116         ArtifactSpec b = a.addDependency( "b", "1.0" );
117         b.addDependency( "project", "1.0" );
118         try
119         {
120             collect( a );
121             fail( "Should have failed on cyclic dependency involving project" );
122         }
123         catch ( CyclicDependencyException expected )
124         {
125             assertTrue( true );
126         }
127     }
128 
129     public void testResolveWithFilter()
130         throws ArtifactResolutionException, InvalidVersionSpecificationException
131     {
132         ArtifactSpec a = createArtifactSpec( "a", "1.0" );
133         ArtifactSpec b = a.addDependency( "b", "1.0" );
134         ArtifactSpec c = a.addDependency( "c", "3.0" );
135 
136         b.addDependency( "c", "2.0" );
137         ArtifactSpec d = b.addDependency( "d", "4.0" );
138 
139         ArtifactResolutionResult res = collect( a );
140         assertEquals( "Check artifact list",
141                       createSet( new Object[] { a.artifact, b.artifact, c.artifact, d.artifact } ), res.getArtifacts() );
142 
143         ArtifactFilter filter = new ExclusionSetFilter( new String[] { "b" } );
144         res = collect( a, filter );
145         assertEquals( "Check artifact list", createSet( new Object[] { a.artifact, c.artifact } ), res.getArtifacts() );
146     }
147 
148     public void testResolveCorrectDependenciesWhenDifferentDependenciesOnNearest()
149         throws ArtifactResolutionException, InvalidVersionSpecificationException
150     {
151         ArtifactSpec a = createArtifactSpec( "a", "1.0" );
152         ArtifactSpec b = a.addDependency( "b", "1.0" );
153         ArtifactSpec c2 = b.addDependency( "c", "2.0" );
154         c2.addDependency( "d", "1.0" );
155 
156         ArtifactSpec e = createArtifactSpec( "e", "1.0" );
157         ArtifactSpec c1 = e.addDependency( "c", "1.0" );
158         ArtifactSpec f = c1.addDependency( "f", "1.0" );
159 
160         ArtifactResolutionResult res = collect( createSet( new Object[] { a.artifact, e.artifact } ) );
161         assertEquals( "Check artifact list", createSet( new Object[] { a.artifact, b.artifact, e.artifact, c1.artifact,
162             f.artifact } ), res.getArtifacts() );
163         assertEquals( "Check version", "1.0", getArtifact( "c", res.getArtifacts() ).getVersion() );
164     }
165 
166     public void disabledtestResolveCorrectDependenciesWhenDifferentDependenciesOnNewest()
167         throws ArtifactResolutionException, InvalidVersionSpecificationException
168     {
169         // TODO: use newest conflict resolver
170         ArtifactSpec a = createArtifactSpec( "a", "1.0" );
171         ArtifactSpec b = a.addDependency( "b", "1.0" );
172         ArtifactSpec c2 = b.addDependency( "c", "2.0" );
173         ArtifactSpec d = c2.addDependency( "d", "1.0" );
174 
175         ArtifactSpec e = createArtifactSpec( "e", "1.0" );
176         ArtifactSpec c1 = e.addDependency( "c", "1.0" );
177         c1.addDependency( "f", "1.0" );
178 
179         ArtifactResolutionResult res = collect( createSet( new Object[] { a.artifact, e.artifact } ) );
180         assertEquals( "Check artifact list", createSet( new Object[] { a.artifact, b.artifact, e.artifact, c2.artifact,
181             d.artifact } ), res.getArtifacts() );
182         assertEquals( "Check version", "2.0", getArtifact( "c", res.getArtifacts() ).getVersion() );
183     }
184 
185     public void disabledtestResolveCorrectDependenciesWhenDifferentDependenciesOnNewestVersionReplaced()
186         throws ArtifactResolutionException, InvalidVersionSpecificationException
187     {
188         // TODO: use newest conflict resolver
189         ArtifactSpec a = createArtifactSpec( "a", "1.0" );
190         ArtifactSpec b1 = a.addDependency( "b", "1.0" );
191         ArtifactSpec c = a.addDependency( "c", "1.0" );
192         ArtifactSpec d2 = b1.addDependency( "d", "2.0" );
193         d2.addDependency( "h", "1.0" );
194         ArtifactSpec d1 = c.addDependency( "d", "1.0" );
195         ArtifactSpec b2 = c.addDependency( "b", "2.0" );
196         ArtifactSpec e = b2.addDependency( "e", "1.0" );
197         ArtifactSpec g = d1.addDependency( "g", "1.0" );
198 
199         ArtifactResolutionResult res = collect( createSet( new Object[] { a.artifact } ) );
200         Object[] artifacts = new Object[] { a.artifact, c.artifact, d1.artifact, b2.artifact, e.artifact, g.artifact };
201         assertEquals( "Check artifact list", createSet( artifacts ), res.getArtifacts() );
202         assertEquals( "Check version", "1.0", getArtifact( "d", res.getArtifacts() ).getVersion() );
203         assertEquals( "Check version", "2.0", getArtifact( "b", res.getArtifacts() ).getVersion() );
204     }
205 
206     public void testResolveNearestNewestIsNearest()
207         throws ArtifactResolutionException, InvalidVersionSpecificationException
208     {
209         ArtifactSpec a = createArtifactSpec( "a", "1.0" );
210         ArtifactSpec b = a.addDependency( "b", "1.0" );
211         ArtifactSpec c = a.addDependency( "c", "3.0" );
212 
213         b.addDependency( "c", "2.0" );
214 
215         ArtifactResolutionResult res = collect( a );
216         assertEquals( "Check artifact list", createSet( new Object[] { a.artifact, b.artifact, c.artifact } ),
217                       res.getArtifacts() );
218         assertEquals( "Check version", "3.0", getArtifact( "c", res.getArtifacts() ).getVersion() );
219     }
220 
221     public void testResolveNearestOldestIsNearest()
222         throws ArtifactResolutionException, InvalidVersionSpecificationException
223     {
224         ArtifactSpec a = createArtifactSpec( "a", "1.0" );
225         ArtifactSpec b = a.addDependency( "b", "1.0" );
226         ArtifactSpec c = a.addDependency( "c", "2.0" );
227 
228         b.addDependency( "c", "3.0" );
229 
230         ArtifactResolutionResult res = collect( a );
231         assertEquals( "Check artifact list", createSet( new Object[] { a.artifact, b.artifact, c.artifact } ),
232                       res.getArtifacts() );
233         assertEquals( "Check version", "2.0", getArtifact( "c", res.getArtifacts() ).getVersion() );
234     }
235 
236     public void testResolveLocalNewestIsLocal()
237         throws ArtifactResolutionException, InvalidVersionSpecificationException
238     {
239         ArtifactSpec a = createArtifactSpec( "a", "1.0" );
240         a.addDependency( "b", "2.0" );
241         ArtifactSpec b = createArtifactSpec( "b", "3.0" );
242 
243         ArtifactResolutionResult res = collect( createSet( new Object[] { a.artifact, b.artifact } ) );
244         assertEquals( "Check artifact list", createSet( new Object[] { a.artifact, b.artifact } ), res.getArtifacts() );
245         assertEquals( "Check version", "3.0", getArtifact( "b", res.getArtifacts() ).getVersion() );
246     }
247 
248     public void testResolveLocalOldestIsLocal()
249         throws ArtifactResolutionException, InvalidVersionSpecificationException
250     {
251         ArtifactSpec a = createArtifactSpec( "a", "1.0" );
252         a.addDependency( "b", "3.0" );
253         ArtifactSpec b = createArtifactSpec( "b", "2.0" );
254 
255         ArtifactResolutionResult res = collect( createSet( new Object[] { a.artifact, b.artifact } ) );
256         assertEquals( "Check artifact list", createSet( new Object[] { a.artifact, b.artifact } ), res.getArtifacts() );
257         assertEquals( "Check version", "2.0", getArtifact( "b", res.getArtifacts() ).getVersion() );
258     }
259 
260     public void testResolveLocalWithNewerVersionButLesserScope()
261         throws ArtifactResolutionException, InvalidVersionSpecificationException
262     {
263         ArtifactSpec a = createArtifactSpec( "commons-logging", "1.0" );
264         a.addDependency( "junit", "3.7" );
265         ArtifactSpec b = createArtifactSpec( "junit", "3.8.1", Artifact.SCOPE_TEST );
266 
267         ArtifactResolutionResult res = collect( createSet( new Object[] { a.artifact, b.artifact } ) );
268         assertEquals( "Check artifact list", createSet( new Object[] { a.artifact, b.artifact } ), res.getArtifacts() );
269         assertEquals( "Check version", "3.8.1", getArtifact( "junit", res.getArtifacts() ).getVersion() );
270         assertEquals( "Check artifactScope", Artifact.SCOPE_TEST, getArtifact( "junit", res.getArtifacts() ).getScope() );
271     }
272 
273     public void testResolveLocalWithNewerVersionButLesserScopeResolvedFirst()
274         throws ArtifactResolutionException, InvalidVersionSpecificationException
275     {
276         ArtifactSpec b = createArtifactSpec( "junit", "3.8.1", Artifact.SCOPE_TEST );
277         ArtifactSpec a = createArtifactSpec( "commons-logging", "1.0" );
278         a.addDependency( "junit", "3.7" );
279 
280         ArtifactResolutionResult res = collect( createSet( new Object[] { a.artifact, b.artifact } ) );
281         assertEquals( "Check artifact list", createSet( new Object[] { a.artifact, b.artifact } ), res.getArtifacts() );
282         assertEquals( "Check version", "3.8.1", getArtifact( "junit", res.getArtifacts() ).getVersion() );
283         assertEquals( "Check artifactScope", Artifact.SCOPE_TEST, getArtifact( "junit", res.getArtifacts() ).getScope() );
284     }
285 
286     public void testResolveNearestWithRanges()
287         throws ArtifactResolutionException, InvalidVersionSpecificationException
288     {
289         ArtifactSpec a = createArtifactSpec( "a", "1.0" );
290         ArtifactSpec b = a.addDependency( "b", "1.0" );
291         ArtifactSpec c = a.addDependency( "c", "2.0" );
292 
293         b.addDependency( "c", "[1.0,3.0]" );
294 
295         ArtifactResolutionResult res = collect( a );
296         assertEquals( "Check artifact list", createSet( new Object[] { a.artifact, b.artifact, c.artifact } ),
297                       res.getArtifacts() );
298         assertEquals( "Check version", "2.0", getArtifact( "c", res.getArtifacts() ).getVersion() );
299     }
300 
301     public void testResolveRangeWithManagedVersion()
302         throws ArtifactResolutionException, InvalidVersionSpecificationException
303     {
304         ArtifactSpec a = createArtifactSpec( "a", "1.0" );
305         ArtifactSpec b = a.addDependency( "b", "[1.0,3.0]" );
306 
307         ArtifactSpec managedB = createArtifactSpec( "b", "5.0" );
308 
309         ArtifactResolutionResult res = collect( a, managedB.artifact );
310         assertEquals( "Check artifact list", createSet( new Object[] { a.artifact, managedB.artifact } ),
311                       res.getArtifacts() );
312         assertEquals( "Check version", "5.0", getArtifact( "b", res.getArtifacts() ).getVersion() );
313     }
314 
315     public void testCompatibleRanges()
316         throws ArtifactResolutionException, InvalidVersionSpecificationException
317     {
318         ArtifactSpec a = createArtifactSpec( "a", "1.0" );
319         ArtifactSpec b = a.addDependency( "b", "1.0" );
320         a.addDependency( "c", "[2.0,2.5]" );
321         b.addDependency( "c", "[1.0,3.0]" );
322         ArtifactSpec c = createArtifactSpec( "c", "2.5" );
323 
324         ArtifactResolutionResult res = collect( a );
325 
326         assertEquals( "Check artifact list", createSet( new Object[] { a.artifact, b.artifact, c.artifact } ),
327                       res.getArtifacts() );
328         assertEquals( "Check version", "2.5", getArtifact( "c", res.getArtifacts() ).getVersion() );
329     }
330 
331     public void testIncompatibleRanges()
332         throws ArtifactResolutionException, InvalidVersionSpecificationException
333     {
334         ArtifactSpec a = createArtifactSpec( "a", "1.0" );
335         ArtifactSpec b = a.addDependency( "b", "1.0" );
336         a.addDependency( "c", "[2.4,3.0]" );
337 
338         b.addDependency( "c", "[1.0,2.0]" );
339 
340         ArtifactResolutionResult res = collect( a );
341 
342         assertTrue( res.hasVersionRangeViolations() );
343     }
344 
345     public void testUnboundedRangeWhenVersionUnavailable()
346         throws ArtifactResolutionException, InvalidVersionSpecificationException
347     {
348         ArtifactSpec a = createArtifactSpec( "a", "1.0" );
349         ArtifactSpec b = a.addDependency( "b", "1.0" );
350         a.addDependency( "c", "[2.0,]" );
351         b.addDependency( "c", "[1.0,]" );
352 
353         ArtifactResolutionResult res = collect( a );
354 
355         assertTrue( res.hasVersionRangeViolations() );
356     }
357 
358     public void testUnboundedRangeBelowLastRelease()
359         throws ArtifactResolutionException, InvalidVersionSpecificationException
360     {
361         ArtifactSpec a = createArtifactSpec( "a", "1.0" );
362         createArtifactSpec( "c", "1.5" );
363         ArtifactSpec c = createArtifactSpec( "c", "2.0" );
364         createArtifactSpec( "c", "1.1" );
365         a.addDependency( "c", "[1.0,)" );
366 
367         ArtifactResolutionResult res = collect( a );
368 
369         assertEquals( "Check artifact list", createSet( new Object[] { a.artifact, c.artifact } ), res.getArtifacts() );
370         assertEquals( "Check version", "2.0", getArtifact( "c", res.getArtifacts() ).getVersion() );
371     }
372 
373     public void testUnboundedRangeAboveLastRelease()
374         throws ArtifactResolutionException, InvalidVersionSpecificationException
375     {
376         ArtifactSpec a = createArtifactSpec( "a", "1.0" );
377         createArtifactSpec( "c", "2.0" );
378         a.addDependency( "c", "[10.0,)" );
379 
380         ArtifactResolutionResult res = collect( a );
381 
382         assertTrue( res.hasVersionRangeViolations() );
383     }
384 
385     public void testResolveManagedVersion()
386         throws ArtifactResolutionException, InvalidVersionSpecificationException
387     {
388         ArtifactSpec a = createArtifactSpec( "a", "1.0" );
389         a.addDependency( "b", "3.0", Artifact.SCOPE_RUNTIME );
390 
391         Artifact managedVersion = createArtifactSpec( "b", "5.0" ).artifact;
392         Artifact modifiedB = createArtifactSpec( "b", "5.0", Artifact.SCOPE_RUNTIME ).artifact;
393 
394         ArtifactResolutionResult res = collect( a, managedVersion );
395         assertEquals( "Check artifact list", createSet( new Object[] { a.artifact, modifiedB } ), res.getArtifacts() );
396     }
397 
398     public void testCollectChangesVersionOfOriginatingArtifactIfInDependencyManagementHasDifferentVersion()
399         throws ArtifactResolutionException, InvalidVersionSpecificationException
400     {
401         ArtifactSpec a = createArtifactSpec( "a", "1.0" );
402 
403         Artifact artifact = projectArtifact.artifact;
404         Artifact managedVersion = createArtifactSpec( artifact.getArtifactId(), "2.0" ).artifact;
405 
406         ArtifactResolutionResult result = collect( a, managedVersion );
407 
408         assertEquals( "collect has modified version in originating artifact", "1.0", artifact.getVersion() );
409 
410         Artifact resolvedArtifact = result.getArtifacts().iterator().next();
411 
412         assertEquals( "Resolved version don't match original artifact version", "1.0", resolvedArtifact.getVersion() );
413     }
414 
415     public void testResolveCompileScopeOverTestScope()
416         throws ArtifactResolutionException, InvalidVersionSpecificationException
417     {
418         ArtifactSpec a = createArtifactSpec( "a", "1.0" );
419         ArtifactSpec c = createArtifactSpec( "c", "3.0", Artifact.SCOPE_TEST );
420 
421         a.addDependency( "c", "2.0", Artifact.SCOPE_COMPILE );
422 
423         Artifact modifiedC = createArtifactSpec( "c", "3.0", Artifact.SCOPE_COMPILE ).artifact;
424 
425         ArtifactResolutionResult res = collect( createSet( new Object[] { a.artifact, c.artifact } ) );
426         assertEquals( "Check artifact list", createSet( new Object[] { a.artifact, modifiedC } ), res.getArtifacts() );
427         Artifact artifact = getArtifact( "c", res.getArtifacts() );
428         // local wins now, and irrelevant if not local as test/provided aren't transitive
429         // assertEquals( "Check artifactScope", Artifact.SCOPE_COMPILE, artifact.getArtifactScope() );
430         assertEquals( "Check artifactScope", Artifact.SCOPE_TEST, artifact.getScope() );
431     }
432 
433     public void testResolveRuntimeScopeOverTestScope()
434         throws ArtifactResolutionException, InvalidVersionSpecificationException
435     {
436         ArtifactSpec a = createArtifactSpec( "a", "1.0" );
437         ArtifactSpec c = createArtifactSpec( "c", "3.0", Artifact.SCOPE_TEST );
438 
439         a.addDependency( "c", "2.0", Artifact.SCOPE_RUNTIME );
440 
441         Artifact modifiedC = createArtifactSpec( "c", "3.0", Artifact.SCOPE_RUNTIME ).artifact;
442 
443         ArtifactResolutionResult res = collect( createSet( new Object[] { a.artifact, c.artifact } ) );
444         assertEquals( "Check artifact list", createSet( new Object[] { a.artifact, modifiedC } ), res.getArtifacts() );
445         Artifact artifact = getArtifact( "c", res.getArtifacts() );
446         // local wins now, and irrelevant if not local as test/provided aren't transitive
447         // assertEquals( "Check artifactScope", Artifact.SCOPE_RUNTIME, artifact.getArtifactScope() );
448         assertEquals( "Check artifactScope", Artifact.SCOPE_TEST, artifact.getScope() );
449     }
450 
451     public void testResolveCompileScopeOverRuntimeScope()
452         throws ArtifactResolutionException, InvalidVersionSpecificationException
453     {
454         ArtifactSpec root = createArtifactSpec( "root", "1.0" );
455         ArtifactSpec a = root.addDependency( "a", "1.0" );
456         root.addDependency( "c", "3.0", Artifact.SCOPE_RUNTIME );
457 
458         a.addDependency( "c", "2.0", Artifact.SCOPE_COMPILE );
459 
460         Artifact modifiedC = createArtifactSpec( "c", "3.0", Artifact.SCOPE_COMPILE ).artifact;
461 
462         ArtifactResolutionResult res = collect( createSet( new Object[] { root.artifact } ) );
463         assertEquals( "Check artifact list", createSet( new Object[] { a.artifact, root.artifact, modifiedC } ),
464                       res.getArtifacts() );
465         Artifact artifact = getArtifact( "c", res.getArtifacts() );
466         assertEquals( "Check artifactScope", Artifact.SCOPE_COMPILE, artifact.getScope() );
467     }
468 
469     public void testResolveCompileScopeOverProvidedScope()
470         throws ArtifactResolutionException, InvalidVersionSpecificationException
471     {
472         ArtifactSpec a = createArtifactSpec( "a", "1.0" );
473         ArtifactSpec c = createArtifactSpec( "c", "3.0", Artifact.SCOPE_PROVIDED );
474 
475         a.addDependency( "c", "2.0", Artifact.SCOPE_COMPILE );
476 
477         Artifact modifiedC = createArtifactSpec( "c", "3.0", Artifact.SCOPE_COMPILE ).artifact;
478 
479         ArtifactResolutionResult res = collect( createSet( new Object[] { a.artifact, c.artifact } ) );
480         assertEquals( "Check artifact list", createSet( new Object[] { a.artifact, modifiedC } ), res.getArtifacts() );
481         Artifact artifact = getArtifact( "c", res.getArtifacts() );
482         // local wins now, and irrelevant if not local as test/provided aren't transitive
483         // assertEquals( "Check artifactScope", Artifact.SCOPE_COMPILE, artifact.getArtifactScope() );
484         assertEquals( "Check artifactScope", Artifact.SCOPE_PROVIDED, artifact.getScope() );
485     }
486 
487     public void testResolveRuntimeScopeOverProvidedScope()
488         throws ArtifactResolutionException, InvalidVersionSpecificationException
489     {
490         ArtifactSpec a = createArtifactSpec( "a", "1.0" );
491         ArtifactSpec c = createArtifactSpec( "c", "3.0", Artifact.SCOPE_PROVIDED );
492 
493         a.addDependency( "c", "2.0", Artifact.SCOPE_RUNTIME );
494 
495         Artifact modifiedC = createArtifactSpec( "c", "3.0", Artifact.SCOPE_RUNTIME ).artifact;
496 
497         ArtifactResolutionResult res = collect( createSet( new Object[] { a.artifact, c.artifact } ) );
498         assertEquals( "Check artifact list", createSet( new Object[] { a.artifact, modifiedC } ), res.getArtifacts() );
499         Artifact artifact = getArtifact( "c", res.getArtifacts() );
500         // local wins now, and irrelevant if not local as test/provided aren't transitive
501         // assertEquals( "Check artifactScope", Artifact.SCOPE_RUNTIME, artifact.getArtifactScope() );
502         assertEquals( "Check artifactScope", Artifact.SCOPE_PROVIDED, artifact.getScope() );
503     }
504 
505     public void testProvidedScopeNotTransitive()
506         throws ArtifactResolutionException, InvalidVersionSpecificationException
507     {
508         ArtifactSpec a = createArtifactSpec( "a", "1.0", Artifact.SCOPE_PROVIDED );
509         ArtifactSpec b = createArtifactSpec( "b", "1.0" );
510         b.addDependency( "c", "3.0", Artifact.SCOPE_PROVIDED );
511 
512         ArtifactResolutionResult res = collect( createSet( new Object[] { a.artifact, b.artifact } ) );
513         assertEquals( "Check artifact list", createSet( new Object[] { a.artifact, b.artifact } ), res.getArtifacts() );
514     }
515 
516     public void testOptionalNotTransitive()
517         throws ArtifactResolutionException, InvalidVersionSpecificationException
518     {
519         ArtifactSpec a = createArtifactSpec( "a", "1.0" );
520         ArtifactSpec b = createArtifactSpec( "b", "1.0" );
521         b.addDependency( "c", "3.0", true );
522 
523         ArtifactResolutionResult res = collect( createSet( new Object[] { a.artifact, b.artifact } ) );
524         assertEquals( "Check artifact list", createSet( new Object[] { a.artifact, b.artifact } ), res.getArtifacts() );
525     }
526 
527     public void testOptionalIncludedAtRoot()
528         throws ArtifactResolutionException, InvalidVersionSpecificationException
529     {
530         ArtifactSpec a = createArtifactSpec( "a", "1.0" );
531 
532         ArtifactSpec b = createArtifactSpec( "b", "1.0", true );
533 
534         ArtifactResolutionResult res = collect( createSet( new Object[] { a.artifact, b.artifact } ) );
535         assertEquals( "Check artifact list", createSet( new Object[] { a.artifact, b.artifact } ), res.getArtifacts() );
536     }
537 
538     public void testScopeUpdate()
539         throws InvalidVersionSpecificationException, ArtifactResolutionException
540     {
541         /* farthest = compile */
542         checkScopeUpdate( Artifact.SCOPE_COMPILE, Artifact.SCOPE_COMPILE, Artifact.SCOPE_COMPILE );
543         checkScopeUpdate( Artifact.SCOPE_COMPILE, Artifact.SCOPE_PROVIDED, Artifact.SCOPE_COMPILE );
544         checkScopeUpdate( Artifact.SCOPE_COMPILE, Artifact.SCOPE_RUNTIME, Artifact.SCOPE_COMPILE );
545         checkScopeUpdate( Artifact.SCOPE_COMPILE, Artifact.SCOPE_SYSTEM, Artifact.SCOPE_COMPILE );
546         checkScopeUpdate( Artifact.SCOPE_COMPILE, Artifact.SCOPE_TEST, Artifact.SCOPE_COMPILE );
547 
548         /* farthest = provided */
549         checkScopeUpdate( Artifact.SCOPE_PROVIDED, Artifact.SCOPE_COMPILE, Artifact.SCOPE_COMPILE );
550         checkScopeUpdate( Artifact.SCOPE_PROVIDED, Artifact.SCOPE_PROVIDED, Artifact.SCOPE_PROVIDED );
551         checkScopeUpdate( Artifact.SCOPE_PROVIDED, Artifact.SCOPE_RUNTIME, Artifact.SCOPE_RUNTIME );
552         checkScopeUpdate( Artifact.SCOPE_PROVIDED, Artifact.SCOPE_SYSTEM, Artifact.SCOPE_SYSTEM );
553         checkScopeUpdate( Artifact.SCOPE_PROVIDED, Artifact.SCOPE_TEST, Artifact.SCOPE_TEST );
554 
555         /* farthest = runtime */
556         checkScopeUpdate( Artifact.SCOPE_RUNTIME, Artifact.SCOPE_COMPILE, Artifact.SCOPE_COMPILE );
557         checkScopeUpdate( Artifact.SCOPE_RUNTIME, Artifact.SCOPE_PROVIDED, Artifact.SCOPE_RUNTIME );
558         checkScopeUpdate( Artifact.SCOPE_RUNTIME, Artifact.SCOPE_RUNTIME, Artifact.SCOPE_RUNTIME );
559         checkScopeUpdate( Artifact.SCOPE_RUNTIME, Artifact.SCOPE_SYSTEM, Artifact.SCOPE_SYSTEM );
560         checkScopeUpdate( Artifact.SCOPE_RUNTIME, Artifact.SCOPE_TEST, Artifact.SCOPE_RUNTIME );
561 
562         /* farthest = system */
563         checkScopeUpdate( Artifact.SCOPE_SYSTEM, Artifact.SCOPE_COMPILE, Artifact.SCOPE_COMPILE );
564         checkScopeUpdate( Artifact.SCOPE_SYSTEM, Artifact.SCOPE_PROVIDED, Artifact.SCOPE_PROVIDED );
565         checkScopeUpdate( Artifact.SCOPE_SYSTEM, Artifact.SCOPE_RUNTIME, Artifact.SCOPE_RUNTIME );
566         checkScopeUpdate( Artifact.SCOPE_SYSTEM, Artifact.SCOPE_SYSTEM, Artifact.SCOPE_SYSTEM );
567         checkScopeUpdate( Artifact.SCOPE_SYSTEM, Artifact.SCOPE_TEST, Artifact.SCOPE_TEST );
568 
569         /* farthest = test */
570         checkScopeUpdate( Artifact.SCOPE_TEST, Artifact.SCOPE_COMPILE, Artifact.SCOPE_COMPILE );
571         checkScopeUpdate( Artifact.SCOPE_TEST, Artifact.SCOPE_PROVIDED, Artifact.SCOPE_PROVIDED );
572         checkScopeUpdate( Artifact.SCOPE_TEST, Artifact.SCOPE_RUNTIME, Artifact.SCOPE_RUNTIME );
573         checkScopeUpdate( Artifact.SCOPE_TEST, Artifact.SCOPE_SYSTEM, Artifact.SCOPE_SYSTEM );
574         checkScopeUpdate( Artifact.SCOPE_TEST, Artifact.SCOPE_TEST, Artifact.SCOPE_TEST );
575     }
576 
577     private void checkScopeUpdate( String farthestScope, String nearestScope, String expectedScope )
578         throws ArtifactResolutionException, InvalidVersionSpecificationException
579     {
580         checkScopeUpdateDirect( farthestScope, nearestScope, expectedScope );
581         checkScopeUpdateTransitively( farthestScope, nearestScope, expectedScope );
582     }
583 
584     private void checkScopeUpdateTransitively( String farthestScope, String nearestScope, String expectedScope )
585         throws ArtifactResolutionException, InvalidVersionSpecificationException
586     {
587         ArtifactSpec a = createArtifactSpec( "a", "1.0" );
588         ArtifactSpec b = createArtifactSpec( "b", "1.0", nearestScope );
589         ArtifactSpec c = createArtifactSpec( "c", "1.0" );
590         a.addDependency( c );
591         ArtifactSpec dNearest = createArtifactSpec( "d", "2.0" );
592         b.addDependency( dNearest );
593         ArtifactSpec dFarthest = createArtifactSpec( "d", "3.0", farthestScope );
594         c.addDependency( dFarthest );
595 
596         /* system and provided dependencies are not transitive */
597         if ( !Artifact.SCOPE_SYSTEM.equals( nearestScope ) && !Artifact.SCOPE_PROVIDED.equals( nearestScope ) )
598         {
599             checkScopeUpdate( a, b, expectedScope, "2.0" );
600         }
601     }
602 
603     private void checkScopeUpdateDirect( String farthestScope, String nearestScope, String expectedScope )
604         throws ArtifactResolutionException, InvalidVersionSpecificationException
605     {
606         ArtifactSpec a = createArtifactSpec( "a", "1.0" );
607         ArtifactSpec b = createArtifactSpec( "b", "1.0" );
608         ArtifactSpec c = createArtifactSpec( "c", "1.0" );
609         a.addDependency( c );
610         ArtifactSpec dNearest = createArtifactSpec( "d", "2.0", nearestScope );
611         b.addDependency( dNearest );
612         ArtifactSpec dFarthest = createArtifactSpec( "d", "3.0", farthestScope );
613         c.addDependency( dFarthest );
614 
615         checkScopeUpdate( a, b, expectedScope, "2.0" );
616     }
617 
618     private void checkScopeUpdate( ArtifactSpec a, ArtifactSpec b, String expectedScope, String expectedVersion )
619         throws ArtifactResolutionException, InvalidVersionSpecificationException
620     {
621         ScopeArtifactFilter filter;
622         if ( Artifact.SCOPE_PROVIDED.equals( expectedScope ) )
623         {
624             filter = new ScopeArtifactFilter( Artifact.SCOPE_COMPILE );
625         }
626         else if ( Artifact.SCOPE_SYSTEM.equals( expectedScope ) )
627         {
628             filter = new ScopeArtifactFilter( Artifact.SCOPE_COMPILE );
629         }
630         else
631         {
632             filter = new ScopeArtifactFilter( expectedScope );
633         }
634 
635         ArtifactResolutionResult res = collect( createSet( new Object[] { a.artifact, b.artifact } ), filter );
636         Artifact artifact = getArtifact( "d", res.getArtifacts() );
637         assertNotNull( "MNG-1895 Dependency was not added to resolution", artifact );
638         assertEquals( "Check artifactScope", expectedScope, artifact.getScope() );
639         assertEquals( "Check version", expectedVersion, artifact.getVersion() );
640 
641         ArtifactSpec d = createArtifactSpec( "d", "1.0" );
642         res = collect( createSet( new Object[] { a.artifact, b.artifact, d.artifact } ), filter );
643         artifact = getArtifact( "d", res.getArtifacts() );
644         assertNotNull( "MNG-1895 Dependency was not added to resolution", artifact );
645         assertEquals( "Check artifactScope", d.artifact.getScope(), artifact.getScope() );
646         assertEquals( "Check version", "1.0", artifact.getVersion() );
647     }
648 
649     public void disabledtestOptionalNotTransitiveButVersionIsInfluential()
650         throws ArtifactResolutionException, InvalidVersionSpecificationException
651     {
652         ArtifactSpec a = createArtifactSpec( "a", "1.0" );
653         ArtifactSpec b = createArtifactSpec( "b", "1.0" );
654         b.addDependency( "c", "3.0", true );
655         ArtifactSpec d = a.addDependency( "d", "1.0" );
656         ArtifactSpec e = d.addDependency( "e", "1.0" );
657         e.addDependency( "c", "2.0" );
658 
659         ArtifactSpec c = createArtifactSpec( "c", "3.0" );
660 
661         ArtifactResolutionResult res = collect( createSet( new Object[] { a.artifact, b.artifact } ) );
662         assertEquals( "Check artifact list", createSet( new Object[] { a.artifact, b.artifact, c.artifact, d.artifact,
663             e.artifact } ), res.getArtifacts() );
664         Artifact artifact = getArtifact( "c", res.getArtifacts() );
665         assertEquals( "Check version", "3.0", artifact.getVersion() );
666     }
667 
668     public void testTestScopeNotTransitive()
669         throws ArtifactResolutionException, InvalidVersionSpecificationException
670     {
671         ArtifactSpec a = createArtifactSpec( "a", "1.0", Artifact.SCOPE_TEST );
672         ArtifactSpec b = createArtifactSpec( "b", "1.0" );
673         b.addDependency( "c", "3.0", Artifact.SCOPE_TEST );
674 
675         ArtifactResolutionResult res = collect( createSet( new Object[] { a.artifact, b.artifact } ) );
676         assertEquals( "Check artifact list", createSet( new Object[] { a.artifact, b.artifact } ), res.getArtifacts() );
677     }
678 
679     public void testSnapshotNotIncluded()
680         throws ArtifactResolutionException, InvalidVersionSpecificationException
681     {
682         ArtifactSpec a = createArtifactSpec( "a", "1.0" );
683         a.addDependency( "b", "[1.0,)" );
684         createArtifactSpec( "b", "1.0-SNAPSHOT" );
685 
686         ArtifactResolutionResult res = collect( a );
687 
688         assertTrue( res.hasVersionRangeViolations() );
689 
690         /*
691          * try { ArtifactResolutionResult res = collect( a ); fail( "Expected b not to resolve: " + res ); } catch (
692          * OverConstrainedVersionException e ) { assertTrue( e.getMessage().indexOf( "[1.0-SNAPSHOT]" ) <
693          * e.getMessage().indexOf( "[1.0,)" ) ); }
694          */
695     }
696 
697     public void testOverConstrainedVersionException()
698         throws ArtifactResolutionException, InvalidVersionSpecificationException
699     {
700         ArtifactSpec a = createArtifactSpec( "a", "1.0" );
701         a.addDependency( "b", "[1.0, 2.0)" );
702         a.addDependency( "c", "[3.3.0,4.0.0)" );
703 
704         ArtifactSpec b = createArtifactSpec( "b", "1.0.0" );
705         b.addDependency( "c", "3.3.0-v3346" );
706 
707         ArtifactSpec c = createArtifactSpec( "c", "3.2.1-v3235e" );
708 
709         try
710         {
711             ArtifactResolutionResult res = collect( createSet( new Object[] { a.artifact } ) );
712         }
713         catch ( OverConstrainedVersionException e )
714         {
715             assertTrue( "Versions unordered", e.getMessage().indexOf( "[3.2.1-v3235e, 3.3.0-v3346]" ) != -1 );
716             assertTrue( "DependencyTrail unresolved", e.getMessage().indexOf( "Path to dependency:" ) != -1 );
717         }
718     }
719 
720     private Artifact getArtifact( String id, Set artifacts )
721     {
722         for ( Iterator i = artifacts.iterator(); i.hasNext(); )
723         {
724             Artifact a = (Artifact) i.next();
725             if ( a.getArtifactId().equals( id ) && a.getGroupId().equals( GROUP_ID ) )
726             {
727                 return a;
728             }
729         }
730         return null;
731     }
732 
733     private ArtifactResolutionResult collect( Set artifacts )
734         throws ArtifactResolutionException
735     {
736         return collect( artifacts, null );
737     }
738 
739     private ArtifactResolutionResult collect( Set artifacts, ArtifactFilter filter )
740         throws ArtifactResolutionException
741     {
742         return artifactCollector.collect( artifacts, projectArtifact.artifact, null, null, null, source, filter,
743                                           Collections.EMPTY_LIST, null );
744     }
745 
746     private ArtifactResolutionResult collect( ArtifactSpec a )
747         throws ArtifactResolutionException
748     {
749         return artifactCollector.collect( Collections.singleton( a.artifact ), projectArtifact.artifact, null, null,
750                                           null, source, null, Collections.EMPTY_LIST, null );
751     }
752 
753     private ArtifactResolutionResult collect( ArtifactSpec a, ArtifactFilter filter )
754         throws ArtifactResolutionException
755     {
756         return artifactCollector.collect( Collections.singleton( a.artifact ), projectArtifact.artifact, null, null,
757                                           null, source, filter, Collections.EMPTY_LIST, null );
758     }
759 
760     private ArtifactResolutionResult collect( ArtifactSpec a, Artifact managedVersion )
761         throws ArtifactResolutionException
762     {
763         Map managedVersions = Collections.singletonMap( managedVersion.getDependencyConflictId(), managedVersion );
764         return artifactCollector.collect( Collections.singleton( a.artifact ), projectArtifact.artifact,
765                                           managedVersions, null, null, source, null, Collections.EMPTY_LIST, null );
766     }
767 
768     private ArtifactSpec createArtifactSpec( String id, String version )
769         throws InvalidVersionSpecificationException
770     {
771         return createArtifactSpec( id, version, Artifact.SCOPE_COMPILE );
772     }
773 
774     private ArtifactSpec createArtifactSpec( String id, String version, boolean optional )
775         throws InvalidVersionSpecificationException
776     {
777         return createArtifactSpec( id, version, Artifact.SCOPE_COMPILE, null, optional );
778     }
779 
780     private ArtifactSpec createArtifactSpec( String id, String version, String scope )
781         throws InvalidVersionSpecificationException
782     {
783         return createArtifactSpec( id, version, scope, null, false );
784     }
785 
786     private ArtifactSpec createArtifactSpec( String id, String version, String scope, String inheritedScope,
787                                              boolean optional )
788         throws InvalidVersionSpecificationException
789     {
790         VersionRange versionRange = VersionRange.createFromVersionSpec( version );
791         Artifact artifact =
792             artifactFactory.createDependencyArtifact( GROUP_ID, id, versionRange, "jar", null, scope, inheritedScope,
793                                                       optional );
794         ArtifactSpec spec = null;
795         if ( artifact != null )
796         {
797             spec = new ArtifactSpec();
798             spec.artifact = artifact;
799             source.addArtifact( spec );
800         }
801         return spec;
802     }
803 
804     private static Set createSet( Object[] x )
805     {
806         return new LinkedHashSet( Arrays.asList( x ) );
807     }
808 
809     private class ArtifactSpec
810     {
811         private Artifact artifact;
812 
813         private Set dependencies = new HashSet();
814 
815         public ArtifactSpec addDependency( String id, String version )
816             throws InvalidVersionSpecificationException
817         {
818             return addDependency( id, version, Artifact.SCOPE_COMPILE );
819         }
820 
821         public ArtifactSpec addDependency( String id, String version, String scope )
822             throws InvalidVersionSpecificationException
823         {
824             return addDependency( id, version, scope, false );
825         }
826 
827         private ArtifactSpec addDependency( ArtifactSpec dep )
828             throws InvalidVersionSpecificationException
829         {
830             if ( dep != null )
831             {
832                 dependencies.add( dep.artifact );
833             }
834             return dep;
835         }
836 
837         private ArtifactSpec addDependency( String id, String version, String scope, boolean optional )
838             throws InvalidVersionSpecificationException
839         {
840             ArtifactSpec dep = createArtifactSpec( id, version, scope, artifact.getScope(), optional );
841             return addDependency( dep );
842         }
843 
844         public ArtifactSpec addDependency( String id, String version, boolean optional )
845             throws InvalidVersionSpecificationException
846         {
847             return addDependency( id, version, Artifact.SCOPE_COMPILE, optional );
848         }
849     }
850 
851     private class Source
852         implements ArtifactMetadataSource
853     {
854         private Map artifacts = new HashMap();
855 
856         private Map versions = new HashMap();
857 
858         public ResolutionGroup retrieve( Artifact artifact, ArtifactRepository localRepository,
859                                          List<ArtifactRepository> remoteRepositories )
860             throws ArtifactMetadataRetrievalException
861         {
862             String key = getKey( artifact );
863 
864             ArtifactSpec a = (ArtifactSpec) artifacts.get( key );
865             try
866             {
867                 return new ResolutionGroup( artifact, createArtifacts( artifactFactory, a.dependencies,
868                                                                        artifact.getScope(),
869                                                                        artifact.getDependencyFilter() ),
870                                             Collections.EMPTY_LIST );
871             }
872             catch ( InvalidVersionSpecificationException e )
873             {
874                 throw new ArtifactMetadataRetrievalException( "Invalid version creating artifacts", e, artifact );
875             }
876         }
877 
878         private String getKey( Artifact artifact )
879         {
880             return artifact.getDependencyConflictId();
881         }
882 
883         private Set createArtifacts( ArtifactFactory artifactFactory, Set dependencies, String inheritedScope,
884                                      ArtifactFilter dependencyFilter )
885             throws InvalidVersionSpecificationException
886         {
887             Set projectArtifacts = new HashSet();
888 
889             for ( Iterator i = dependencies.iterator(); i.hasNext(); )
890             {
891                 Artifact d = (Artifact) i.next();
892 
893                 VersionRange versionRange;
894                 if ( d.getVersionRange() != null )
895                 {
896                     versionRange = d.getVersionRange();
897                 }
898                 else
899                 {
900                     versionRange = VersionRange.createFromVersionSpec( d.getVersion() );
901                 }
902                 Artifact artifact;
903                 if ( d.getScope().equals( Artifact.SCOPE_TEST ) || d.getScope().equals( Artifact.SCOPE_PROVIDED ) )
904                 {
905                     /* don't call createDependencyArtifact as it'll ignore test and provided scopes */
906                     artifact =
907                         artifactFactory.createArtifact( d.getGroupId(), d.getArtifactId(), d.getVersion(),
908                                                         d.getScope(), d.getType() );
909                 }
910                 else
911                 {
912                     artifact =
913                         artifactFactory.createDependencyArtifact( d.getGroupId(), d.getArtifactId(), versionRange,
914                                                                   d.getType(), d.getClassifier(), d.getScope(),
915                                                                   inheritedScope, d.isOptional() );
916                 }
917 
918                 if ( artifact != null && ( dependencyFilter == null || dependencyFilter.include( artifact ) ) )
919                 {
920                     artifact.setDependencyFilter( dependencyFilter );
921 
922                     projectArtifacts.add( artifact );
923                 }
924             }
925 
926             return projectArtifacts;
927         }
928 
929         public void addArtifact( ArtifactSpec spec )
930         {
931             artifacts.put( getKey( spec.artifact ), spec );
932 
933             String key = spec.artifact.getDependencyConflictId();
934             List artifactVersions = (List) versions.get( key );
935             if ( artifactVersions == null )
936             {
937                 artifactVersions = new ArrayList();
938                 versions.put( key, artifactVersions );
939             }
940             if ( spec.artifact.getVersion() != null )
941             {
942                 artifactVersions.add( new DefaultArtifactVersion( spec.artifact.getVersion() ) );
943             }
944         }
945 
946         public List<ArtifactVersion> retrieveAvailableVersions( Artifact artifact, ArtifactRepository localRepository,
947                                                                 List<ArtifactRepository> remoteRepositories )
948             throws ArtifactMetadataRetrievalException
949         {
950             return retrieveAvailableVersions( artifact );
951         }
952 
953         public List<ArtifactVersion> retrieveAvailableVersionsFromDeploymentRepository(
954                                                                                         Artifact artifact,
955                                                                                         ArtifactRepository localRepository,
956                                                                                         ArtifactRepository remoteRepository )
957             throws ArtifactMetadataRetrievalException
958         {
959             return retrieveAvailableVersions( artifact );
960         }
961 
962         private List<ArtifactVersion> retrieveAvailableVersions( Artifact artifact )
963         {
964             List artifactVersions = (List) versions.get( artifact.getDependencyConflictId() );
965             if ( artifactVersions == null )
966             {
967                 artifactVersions = Collections.EMPTY_LIST;
968             }
969             return artifactVersions;
970         }
971 
972         public ResolutionGroup retrieve( MetadataResolutionRequest request )
973             throws ArtifactMetadataRetrievalException
974         {
975             return retrieve( request.getArtifact(), request.getLocalRepository(), request.getRemoteRepositories() );
976         }
977 
978         public List<ArtifactVersion> retrieveAvailableVersions( MetadataResolutionRequest request )
979             throws ArtifactMetadataRetrievalException
980         {
981             return retrieveAvailableVersions( request.getArtifact(), request.getLocalRepository(), request.getRemoteRepositories() );
982         }
983     }
984 }