1   package org.apache.maven.artifact.manager;
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.io.File;
23  import java.io.IOException;
24  
25  import org.apache.maven.artifact.Artifact;
26  import org.apache.maven.artifact.DefaultArtifact;
27  import org.apache.maven.artifact.factory.ArtifactFactory;
28  import org.apache.maven.artifact.metadata.ArtifactMetadata;
29  import org.apache.maven.artifact.repository.ArtifactRepository;
30  import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
31  import org.apache.maven.artifact.repository.DefaultArtifactRepository;
32  import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
33  import org.apache.maven.artifact.repository.layout.DefaultRepositoryLayout;
34  import org.apache.maven.artifact.versioning.VersionRange;
35  import org.apache.maven.wagon.ResourceDoesNotExistException;
36  import org.apache.maven.wagon.TransferFailedException;
37  import org.apache.maven.wagon.UnsupportedProtocolException;
38  import org.apache.maven.wagon.Wagon;
39  import org.apache.maven.wagon.authorization.AuthorizationException;
40  import org.apache.maven.wagon.events.TransferListener;
41  import org.apache.maven.wagon.observers.Debug;
42  import org.apache.maven.wagon.repository.Repository;
43  import org.codehaus.plexus.PlexusTestCase;
44  import org.codehaus.plexus.util.FileUtils;
45  import org.codehaus.plexus.util.xml.Xpp3Dom;
46  import org.easymock.MockControl;
47  
48  /**
49   * @author <a href="michal.maczka@dimatics.com">Michal Maczka</a>
50   * @version $Id: DefaultWagonManagerTest.java 733068 2009-01-09 15:47:00Z brianf $
51   */
52  public class DefaultWagonManagerTest
53      extends PlexusTestCase
54  {
55      private DefaultWagonManager wagonManager;
56  
57      private TransferListener transferListener = new Debug();
58  
59      private ArtifactFactory artifactFactory;
60  
61      protected void setUp()
62          throws Exception
63      {
64          super.setUp();
65  
66          wagonManager = (DefaultWagonManager) lookup( WagonManager.ROLE );
67          
68          artifactFactory = (ArtifactFactory) lookup( ArtifactFactory.ROLE );
69      }
70  
71      private Artifact createTestPomArtifact( String directory )
72          throws IOException
73      {
74          File testData = getTestFile( directory );
75          FileUtils.deleteDirectory( testData );
76          testData.mkdirs();
77  
78          Artifact artifact = artifactFactory.createProjectArtifact( "test", "test", "1.0" );
79          artifact.setFile( new File( testData, "test-1.0.pom" ) );
80          assertFalse( artifact.getFile().exists() );
81          return artifact;
82      }
83      
84      public void testGetArtifactSha1MissingMd5Present()
85          throws IOException, UnsupportedProtocolException, TransferFailedException, ResourceDoesNotExistException
86      {
87          Artifact artifact = createTestPomArtifact( "target/test-data/get-remote-artifact" );
88  
89          ArtifactRepository repo = createStringRepo();
90  
91          StringWagon wagon = (StringWagon) wagonManager.getWagon( "string" );
92          wagon.addExpectedContent( repo.getLayout().pathOf( artifact ), "expected" );
93          wagon.addExpectedContent( repo.getLayout().pathOf( artifact ) + ".md5", "bad_checksum" );
94          
95          wagonManager.getArtifact( artifact, repo );
96  
97          assertTrue( artifact.getFile().exists() );
98      }
99  
100     private ArtifactRepository createStringRepo()
101     {
102         ArtifactRepository repo =
103             new DefaultArtifactRepository( "id", "string://url", new ArtifactRepositoryLayoutStub() );
104         return repo;
105     }
106     
107     /**
108      * checks the handling of urls
109      */
110     public void testExternalURL()
111     {
112         DefaultWagonManager mgr = new DefaultWagonManager();
113         assertTrue( mgr.isExternalRepo( getRepo( "foo", "http://somehost" ) ) );
114         assertTrue( mgr.isExternalRepo( getRepo( "foo", "http://somehost:9090/somepath" ) ) );
115         assertTrue( mgr.isExternalRepo( getRepo( "foo", "ftp://somehost" ) ) );
116         assertTrue( mgr.isExternalRepo( getRepo( "foo", "http://192.168.101.1" ) ) );
117         assertTrue( mgr.isExternalRepo( getRepo( "foo", "http://" ) ) );
118         // these are local
119         assertFalse( mgr.isExternalRepo( getRepo( "foo", "http://localhost:8080" ) ) );
120         assertFalse( mgr.isExternalRepo( getRepo( "foo", "http://127.0.0.1:9090" ) ) );
121         assertFalse( mgr.isExternalRepo( getRepo( "foo", "file://localhost/somepath" ) ) );
122         assertFalse( mgr.isExternalRepo( getRepo( "foo", "file://localhost/D:/somepath" ) ) );
123         assertFalse( mgr.isExternalRepo( getRepo( "foo", "http://localhost" ) ) );
124         assertFalse( mgr.isExternalRepo( getRepo( "foo", "http://127.0.0.1" ) ) );
125         assertFalse( mgr.isExternalRepo( getRepo( "foo", "file:///somepath" ) ) );
126         assertFalse( mgr.isExternalRepo( getRepo( "foo", "file://D:/somepath" ) ) );
127 
128         // not a proper url so returns false;
129         assertFalse( mgr.isExternalRepo( getRepo( "foo", "192.168.101.1" ) ) );
130         assertFalse( mgr.isExternalRepo( getRepo( "foo", "" ) ) );
131     }
132 
133     /**
134      * Check that lookups with exact matches work and that no matches don't corrupt the repo.
135      */
136     public void testMirrorLookup()
137     {
138         wagonManager.addMirror( "a", "a", "http://a" );
139         wagonManager.addMirror( "b", "b", "http://b" );
140 
141         ArtifactRepository repo = null;
142         repo = wagonManager.getMirrorRepository( getRepo( "a", "http://a.a" ) );
143         assertEquals( "http://a", repo.getUrl() );
144 
145         repo = wagonManager.getMirrorRepository( getRepo( "b", "http://a.a" ) );
146         assertEquals( "http://b", repo.getUrl() );
147 
148         repo = wagonManager.getMirrorRepository( getRepo( "c", "http://c.c" ) );
149         assertEquals( "http://c.c", repo.getUrl() );
150 
151     }
152 
153     /**
154      * Check that wildcards don't override exact id matches.
155      */
156     public void testMirrorWildcardLookup()
157     {
158         wagonManager.addMirror( "a", "a", "http://a" );
159         wagonManager.addMirror( "b", "b", "http://b" );
160         wagonManager.addMirror( "c", "*", "http://wildcard" );
161 
162         ArtifactRepository repo = null;
163         repo = wagonManager.getMirrorRepository( getRepo( "a", "http://a.a" ) );
164         assertEquals( "http://a", repo.getUrl() );
165 
166         repo = wagonManager.getMirrorRepository( getRepo( "b", "http://a.a" ) );
167         assertEquals( "http://b", repo.getUrl() );
168 
169         repo = wagonManager.getMirrorRepository( getRepo( "c", "http://c.c" ) );
170         assertEquals( "http://wildcard", repo.getUrl() );
171 
172     }
173 
174     /**
175      * Check that patterns are processed correctly Valid patterns: * = everything external:* = everything not on the
176      * localhost and not file based. repo,repo1 = repo or repo1 *,!repo1 = everything except repo1
177      */
178     public void testPatterns()
179     {
180         DefaultWagonManager mgr = new DefaultWagonManager();
181 
182         assertTrue( mgr.matchPattern( getRepo( "a" ), "*" ) );
183         assertTrue( mgr.matchPattern( getRepo( "a" ), "*," ) );
184         assertTrue( mgr.matchPattern( getRepo( "a" ), ",*," ) );
185         assertTrue( mgr.matchPattern( getRepo( "a" ), "*," ) );
186 
187         assertTrue( mgr.matchPattern( getRepo( "a" ), "a" ) );
188         assertTrue( mgr.matchPattern( getRepo( "a" ), "a," ) );
189         assertTrue( mgr.matchPattern( getRepo( "a" ), ",a," ) );
190         assertTrue( mgr.matchPattern( getRepo( "a" ), "a," ) );
191 
192         assertFalse( mgr.matchPattern( getRepo( "b" ), "a" ) );
193         assertFalse( mgr.matchPattern( getRepo( "b" ), "a," ) );
194         assertFalse( mgr.matchPattern( getRepo( "b" ), ",a" ) );
195         assertFalse( mgr.matchPattern( getRepo( "b" ), ",a," ) );
196 
197         assertTrue( mgr.matchPattern( getRepo( "a" ), "a,b" ) );
198         assertTrue( mgr.matchPattern( getRepo( "b" ), "a,b" ) );
199 
200         assertFalse( mgr.matchPattern( getRepo( "c" ), "a,b" ) );
201 
202         assertTrue( mgr.matchPattern( getRepo( "a" ), "*" ) );
203         assertTrue( mgr.matchPattern( getRepo( "a" ), "*,b" ) );
204         assertTrue( mgr.matchPattern( getRepo( "a" ), "*,!b" ) );
205 
206         assertFalse( mgr.matchPattern( getRepo( "a" ), "*,!a" ) );
207         assertFalse( mgr.matchPattern( getRepo( "a" ), "!a,*" ) );
208 
209         assertTrue( mgr.matchPattern( getRepo( "c" ), "*,!a" ) );
210         assertTrue( mgr.matchPattern( getRepo( "c" ), "!a,*" ) );
211 
212         assertFalse( mgr.matchPattern( getRepo( "c" ), "!a,!c" ) );
213         assertFalse( mgr.matchPattern( getRepo( "d" ), "!a,!c*" ) );
214     }
215 
216     /**
217      * make sure the external if is fully exercised. We can assume file and ips are also handled because they have a
218      * separate test above.
219      */
220     public void testPatternsWithExternal()
221     {
222         DefaultWagonManager mgr = new DefaultWagonManager();
223 
224         assertTrue( mgr.matchPattern( getRepo( "a", "http://localhost" ), "*" ) );
225         assertFalse( mgr.matchPattern( getRepo( "a", "http://localhost" ), "external:*" ) );
226 
227         assertTrue( mgr.matchPattern( getRepo( "a", "http://localhost" ), "external:*,a" ) );
228         assertFalse( mgr.matchPattern( getRepo( "a", "http://localhost" ), "external:*,!a" ) );
229         assertTrue( mgr.matchPattern( getRepo( "a", "http://localhost" ), "a,external:*" ) );
230         assertFalse( mgr.matchPattern( getRepo( "a", "http://localhost" ), "!a,external:*" ) );
231 
232         assertFalse( mgr.matchPattern( getRepo( "c", "http://localhost" ), "!a,external:*" ) );
233         assertTrue( mgr.matchPattern( getRepo( "c", "http://somehost" ), "!a,external:*" ) );
234     }
235 
236     /**
237      * Check that first match wins
238      */
239     public void testMirrorStopOnFirstMatch()
240     {
241         //exact matches win first
242         wagonManager.addMirror( "a2", "a,b", "http://a2" );
243         wagonManager.addMirror( "a", "a", "http://a" );
244         //make sure repeated entries are skipped
245         wagonManager.addMirror( "a", "a", "http://a3" );
246         
247         wagonManager.addMirror( "b", "b", "http://b" );
248         wagonManager.addMirror( "c", "d,e", "http://de" );
249         wagonManager.addMirror( "c", "*", "http://wildcard" );
250         wagonManager.addMirror( "c", "e,f", "http://ef" );
251         
252     
253 
254         ArtifactRepository repo = null;
255         repo = wagonManager.getMirrorRepository( getRepo( "a", "http://a.a" ) );
256         assertEquals( "http://a", repo.getUrl() );
257 
258         repo = wagonManager.getMirrorRepository( getRepo( "b", "http://a.a" ) );
259         assertEquals( "http://b", repo.getUrl() );
260 
261         repo = wagonManager.getMirrorRepository( getRepo( "c", "http://c.c" ) );
262         assertEquals( "http://wildcard", repo.getUrl() );
263         
264         repo = wagonManager.getMirrorRepository( getRepo( "d", "http://d" ) );
265         assertEquals( "http://de", repo.getUrl() );
266         
267         repo = wagonManager.getMirrorRepository( getRepo( "e", "http://e" ) );
268         assertEquals( "http://de", repo.getUrl() );
269         
270         repo = wagonManager.getMirrorRepository( getRepo( "f", "http://f" ) );
271         assertEquals( "http://wildcard", repo.getUrl() );
272 
273     }
274     
275     /**
276      * Build an ArtifactRepository object.
277      * 
278      * @param id
279      * @param url
280      * @return
281      */
282     private ArtifactRepository getRepo( String id, String url )
283     {
284         return new DefaultArtifactRepository( id, url, new DefaultRepositoryLayout() );
285     }
286 
287     /**
288      * Build an ArtifactRepository object.
289      * 
290      * @param id
291      * @return
292      */
293     private ArtifactRepository getRepo( String id )
294     {
295         return getRepo( id, "http://something" );
296     }
297 
298     public void testDefaultWagonManager()
299         throws Exception
300     {
301         assertWagon( "a" );
302 
303         assertWagon( "b1" );
304 
305         assertWagon( "b2" );
306 
307         assertWagon( "c" );
308 
309         assertWagon( "string" );
310 
311         try
312         {
313             assertWagon( "d" );
314 
315             fail( "Expected :" + UnsupportedProtocolException.class.getName() );
316         }
317         catch ( UnsupportedProtocolException e )
318         {
319             // ok
320             assertTrue( true );
321         }
322     }
323 
324     public void testGetWagonRepository()
325         throws Exception
326     {
327         assertWagonRepository( "a" );
328 
329         assertWagonRepository( "b1" );
330 
331         assertWagonRepository( "b2" );
332 
333         assertWagonRepository( "c" );
334 
335         try
336         {
337             assertWagonRepository( "d" );
338 
339             fail( "Expected :" + UnsupportedProtocolException.class.getName() );
340         }
341         catch ( UnsupportedProtocolException e )
342         {
343             // ok
344             assertTrue( true );
345         }
346     }
347 
348     public void testGetWagonRepositoryNullProtocol()
349         throws Exception
350     {
351         try
352         {
353             Repository repository = new Repository();
354 
355             repository.setProtocol( null );
356 
357             Wagon wagon = wagonManager.getWagon( repository );
358 
359             fail( "Expected :" + UnsupportedProtocolException.class.getName() );
360         }
361         catch ( UnsupportedProtocolException e )
362         {
363             // ok
364             assertTrue( true );
365         }
366     }
367 
368     /**
369      * Checks the verification of checksums.
370      */
371     public void testChecksumVerification()
372         throws Exception
373     {
374         ArtifactRepositoryPolicy policy =
375             new ArtifactRepositoryPolicy( true, ArtifactRepositoryPolicy.UPDATE_POLICY_ALWAYS,
376                                           ArtifactRepositoryPolicy.CHECKSUM_POLICY_FAIL );
377         ArtifactRepository repo =
378             new DefaultArtifactRepository( "id", "string://url", new ArtifactRepositoryLayoutStub(), policy, policy );
379 
380         Artifact artifact =
381             new DefaultArtifact( "sample.group", "sample-art", VersionRange.createFromVersion( "1.0" ), "scope",
382                                  "jar", "classifier", null );
383         artifact.setFile( getTestFile( "target/sample-art" ) );            
384 
385         StringWagon wagon = (StringWagon) wagonManager.getWagon( "string" );
386         
387         artifact.getFile().delete();
388         wagon.clearExpectedContent();
389         wagon.addExpectedContent( "path", "lower-case-checksum" );
390         wagon.addExpectedContent( "path.sha1", "2a25dc564a3b34f68237fc849066cbc7bb7a36a1" );
391 
392         try
393         {
394             wagonManager.getArtifact( artifact, repo );
395         }
396         catch ( ChecksumFailedException e )
397         {
398             fail( "Checksum verification did not pass: " + e.getMessage() );
399         }
400 
401         artifact.getFile().delete();
402         wagon.clearExpectedContent();
403         wagon.addExpectedContent( "path", "upper-case-checksum" );
404         wagon.addExpectedContent( "path.sha1", "B7BB97D7D0B9244398D9B47296907F73313663E6" );
405 
406         try
407         {
408             wagonManager.getArtifact( artifact, repo );
409         }
410         catch ( ChecksumFailedException e )
411         {
412             fail( "Checksum verification did not pass: " + e.getMessage() );
413         }
414 
415         artifact.getFile().delete();
416         wagon.clearExpectedContent();
417         wagon.addExpectedContent( "path", "expected-failure" );
418         wagon.addExpectedContent( "path.sha1", "b7bb97d7d0b9244398d9b47296907f73313663e6" );
419 
420         try
421         {
422             wagonManager.getArtifact( artifact, repo );
423             fail( "Checksum verification did not fail" );
424         }
425         catch ( ChecksumFailedException e )
426         {
427             // expected
428         }
429 
430         artifact.getFile().delete();
431         wagon.clearExpectedContent();
432         wagon.addExpectedContent( "path", "lower-case-checksum" );
433         wagon.addExpectedContent( "path.md5", "50b2cf50a103a965efac62b983035cac" );
434 
435         try
436         {
437             wagonManager.getArtifact( artifact, repo );
438         }
439         catch ( ChecksumFailedException e )
440         {
441             fail( "Checksum verification did not pass: " + e.getMessage() );
442         }
443 
444         artifact.getFile().delete();
445         wagon.clearExpectedContent();
446         wagon.addExpectedContent( "path", "upper-case-checksum" );
447         wagon.addExpectedContent( "path.md5", "842F568FCCFEB7E534DC72133D42FFDC" );
448 
449         try
450         {
451             wagonManager.getArtifact( artifact, repo );
452         }
453         catch ( ChecksumFailedException e )
454         {
455             fail( "Checksum verification did not pass: " + e.getMessage() );
456         }
457 
458         artifact.getFile().delete();
459         wagon.clearExpectedContent();
460         wagon.addExpectedContent( "path", "expected-failure" );
461         wagon.addExpectedContent( "path.md5", "b7bb97d7d0b9244398d9b47296907f73313663e6" );
462 
463         try
464         {
465             wagonManager.getArtifact( artifact, repo );
466             fail( "Checksum verification did not fail" );
467         }
468         catch ( ChecksumFailedException e )
469         {
470             // expected
471         }
472     }
473 
474     private void assertWagon( String protocol )
475         throws Exception
476     {
477         Wagon wagon = wagonManager.getWagon( protocol );
478 
479         assertNotNull( "Check wagon, protocol=" + protocol, wagon );
480     }
481 
482     private void assertWagonRepository( String protocol )
483         throws Exception
484     {
485         Repository repository = new Repository();
486 
487         String s = "value=" + protocol;
488 
489         repository.setId( "id=" + protocol );
490 
491         repository.setProtocol( protocol );
492 
493         Xpp3Dom conf = new Xpp3Dom( "configuration" );
494 
495         Xpp3Dom configurableField = new Xpp3Dom( "configurableField" );
496 
497         configurableField.setValue( s );
498 
499         conf.addChild( configurableField );
500 
501         wagonManager.addConfiguration( repository.getId(), conf );
502 
503         WagonMock wagon = (WagonMock) wagonManager.getWagon( repository );
504 
505         assertNotNull( "Check wagon, protocol=" + protocol, wagon );
506 
507         assertEquals( "Check configuration for wagon, protocol=" + protocol, s, wagon.getConfigurableField() );
508     }
509 
510     private final class ArtifactRepositoryLayoutStub
511         implements ArtifactRepositoryLayout
512     {
513         public String pathOfRemoteRepositoryMetadata( ArtifactMetadata metadata )
514         {
515             return "path";
516         }
517 
518         public String pathOfLocalRepositoryMetadata( ArtifactMetadata metadata, ArtifactRepository repository )
519         {
520             return "path";
521         }
522 
523         public String pathOf( Artifact artifact )
524         {
525             return "path";
526         }
527     }
528 
529 }