001    package org.apache.maven.repository.legacy.resolver;
002    
003    /*
004     * Licensed to the Apache Software Foundation (ASF) under one
005     * or more contributor license agreements.  See the NOTICE file
006     * distributed with this work for additional information
007     * regarding copyright ownership.  The ASF licenses this file
008     * to you under the Apache License, Version 2.0 (the
009     * "License"); you may not use this file except in compliance
010     * with the License.  You may obtain a copy of the License at
011     *
012     *  http://www.apache.org/licenses/LICENSE-2.0
013     *
014     * Unless required by applicable law or agreed to in writing,
015     * software distributed under the License is distributed on an
016     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017     * KIND, either express or implied.  See the License for the
018     * specific language governing permissions and limitations
019     * under the License.
020     */
021    
022    import java.util.ArrayList;
023    import java.util.Arrays;
024    import java.util.Collections;
025    import java.util.HashMap;
026    import java.util.HashSet;
027    import java.util.Iterator;
028    import java.util.LinkedHashSet;
029    import java.util.List;
030    import java.util.Map;
031    import java.util.Set;
032    
033    import org.apache.maven.artifact.Artifact;
034    import org.apache.maven.artifact.factory.ArtifactFactory;
035    import org.apache.maven.artifact.metadata.ArtifactMetadataRetrievalException;
036    import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
037    import org.apache.maven.artifact.metadata.ResolutionGroup;
038    import org.apache.maven.artifact.repository.ArtifactRepository;
039    import org.apache.maven.artifact.resolver.ArtifactResolutionException;
040    import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
041    import org.apache.maven.artifact.resolver.CyclicDependencyException;
042    import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
043    import org.apache.maven.artifact.resolver.filter.ExclusionSetFilter;
044    import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter;
045    import org.apache.maven.artifact.versioning.ArtifactVersion;
046    import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
047    import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
048    import org.apache.maven.artifact.versioning.OverConstrainedVersionException;
049    import org.apache.maven.artifact.versioning.VersionRange;
050    import org.apache.maven.repository.legacy.metadata.MetadataResolutionRequest;
051    import org.codehaus.plexus.PlexusTestCase;
052    
053    /**
054     * Test the default artifact collector.
055     *
056     * @author <a href="mailto:brett@apache.org">Brett Porter</a>
057     */
058    public class DefaultArtifactCollectorTest
059        extends PlexusTestCase
060    {
061        private LegacyArtifactCollector artifactCollector;
062    
063        private ArtifactFactory artifactFactory;
064    
065        private ArtifactSpec projectArtifact;
066    
067        private Source source;
068    
069        private static final String GROUP_ID = "test";
070    
071        @Override
072        protected void setUp()
073            throws Exception
074        {
075            super.setUp();
076    
077            source = new Source();
078            artifactFactory = (ArtifactFactory) lookup( ArtifactFactory.ROLE );
079            artifactCollector = lookup( LegacyArtifactCollector.class );
080    
081            projectArtifact = createArtifactSpec( "project", "1.0", null );
082        }
083    
084        @Override
085        protected void tearDown()
086            throws Exception
087        {
088            artifactCollector = null;
089            artifactFactory = null;
090            super.tearDown();
091        }
092    
093        // works, but we don't fail on cycles presently
094        public void disabledtestCircularDependencyNotIncludingCurrentProject()
095            throws ArtifactResolutionException, InvalidVersionSpecificationException
096        {
097            ArtifactSpec a = createArtifactSpec( "a", "1.0" );
098            ArtifactSpec b = a.addDependency( "b", "1.0" );
099            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().contains( "[3.2.1-v3235e, 3.3.0-v3346]" ) );
716                assertTrue( "DependencyTrail unresolved", e.getMessage().contains( "Path to dependency:" ) );
717            }
718        }
719    
720        private Artifact getArtifact( String id, Set artifacts )
721        {
722            for ( Object artifact : artifacts )
723            {
724                Artifact a = (Artifact) artifact;
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 ( Object dependency : dependencies )
890                {
891                    Artifact d = (Artifact) dependency;
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(), d.getScope(),
908                                                            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    }