1 package org.apache.maven.artifact.manager;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.maven.artifact.Artifact;
23 import org.apache.maven.artifact.metadata.ArtifactMetadata;
24 import org.apache.maven.artifact.repository.ArtifactRepository;
25 import org.apache.maven.artifact.repository.ArtifactRepositoryFactory;
26 import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
27 import org.apache.maven.artifact.repository.DefaultArtifactRepository;
28 import org.apache.maven.wagon.ConnectionException;
29 import org.apache.maven.wagon.ResourceDoesNotExistException;
30 import org.apache.maven.wagon.TransferFailedException;
31 import org.apache.maven.wagon.UnsupportedProtocolException;
32 import org.apache.maven.wagon.Wagon;
33 import org.apache.maven.wagon.authentication.AuthenticationException;
34 import org.apache.maven.wagon.authentication.AuthenticationInfo;
35 import org.apache.maven.wagon.authorization.AuthorizationException;
36 import org.apache.maven.wagon.events.TransferListener;
37 import org.apache.maven.wagon.observers.ChecksumObserver;
38 import org.apache.maven.wagon.proxy.ProxyInfo;
39 import org.apache.maven.wagon.proxy.ProxyInfoProvider;
40 import org.apache.maven.wagon.repository.Repository;
41 import org.apache.maven.wagon.repository.RepositoryPermissions;
42 import org.codehaus.plexus.PlexusConstants;
43 import org.codehaus.plexus.PlexusContainer;
44 import org.codehaus.plexus.component.configurator.ComponentConfigurationException;
45 import org.codehaus.plexus.component.configurator.ComponentConfigurator;
46 import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException;
47 import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
48 import org.codehaus.plexus.configuration.PlexusConfiguration;
49 import org.codehaus.plexus.configuration.PlexusConfigurationException;
50 import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration;
51 import org.codehaus.plexus.context.Context;
52 import org.codehaus.plexus.context.ContextException;
53 import org.codehaus.plexus.logging.AbstractLogEnabled;
54 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
55 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
56 import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
57 import org.codehaus.plexus.util.FileUtils;
58 import org.codehaus.plexus.util.IOUtil;
59 import org.codehaus.plexus.util.xml.Xpp3Dom;
60
61 import java.io.File;
62 import java.io.IOException;
63 import java.io.InputStream;
64 import java.net.MalformedURLException;
65 import java.net.URL;
66 import java.security.NoSuchAlgorithmException;
67 import java.util.Collection;
68 import java.util.HashMap;
69 import java.util.Iterator;
70 import java.util.LinkedHashMap;
71 import java.util.List;
72 import java.util.Map;
73 import java.util.Properties;
74 import java.util.Set;
75
76 public class DefaultWagonManager
77 extends AbstractLogEnabled
78 implements WagonManager, Contextualizable, Initializable
79 {
80 private static final String WILDCARD = "*";
81
82 private static final String EXTERNAL_WILDCARD = "external:*";
83
84 private static final String MAVEN_ARTIFACT_PROPERTIES = "META-INF/maven/org.apache.maven/maven-artifact/pom.properties";
85
86 private static final String WAGON_PROVIDER_CONFIGURATION = "wagonProvider";
87
88 private static int anonymousMirrorIdSeed = 0;
89
90 private PlexusContainer container;
91
92
93
94 private Map proxies = new HashMap();
95
96 private Map authenticationInfoMap = new HashMap();
97
98 private Map serverPermissionsMap = new HashMap();
99
100
101 private Map mirrors = new LinkedHashMap();
102
103
104 private Map<String, XmlPlexusConfiguration> serverConfigurationMap = new HashMap<String, XmlPlexusConfiguration>();
105
106 private Map<String, String> serverWagonProviderMap = new HashMap<String, String>();
107
108 private TransferListener downloadMonitor;
109
110 private boolean online = true;
111
112 private ArtifactRepositoryFactory repositoryFactory;
113
114 private boolean interactive = true;
115
116 private Map<String, PlexusContainer> availableWagons = new HashMap<String, PlexusContainer>();
117
118 private RepositoryPermissions defaultRepositoryPermissions;
119
120 private String httpUserAgent;
121
122 private WagonProviderMapping providerMapping = new DefaultWagonProviderMapping();
123
124
125 public Wagon getWagon( Repository repository )
126 throws UnsupportedProtocolException, WagonConfigurationException
127 {
128 String protocol = repository.getProtocol();
129
130 if ( protocol == null )
131 {
132 throw new UnsupportedProtocolException( "The repository " + repository + " does not specify a protocol" );
133 }
134
135 Wagon wagon = getWagon( protocol, repository.getId() );
136
137 configureWagon( wagon, repository.getId(), protocol );
138
139 return wagon;
140 }
141
142 public Wagon getWagon( String protocol )
143 throws UnsupportedProtocolException
144 {
145 return getWagon( protocol, null );
146 }
147
148 private Wagon getWagon( String protocol, String repositoryId )
149 throws UnsupportedProtocolException
150 {
151 String hint = getWagonHint( protocol, repositoryId );
152 PlexusContainer container = getWagonContainer( hint );
153
154 Wagon wagon;
155 try
156 {
157 wagon = (Wagon) container.lookup( Wagon.ROLE, hint );
158 }
159 catch ( ComponentLookupException e1 )
160 {
161 throw new UnsupportedProtocolException(
162 "Cannot find wagon which supports the requested protocol: " + protocol, e1 );
163 }
164
165 wagon.setInteractive( interactive );
166
167 return wagon;
168 }
169
170 private String getWagonHint( String protocol, String repositoryId )
171 {
172
173 String impl = null;
174
175 if ( repositoryId != null && serverWagonProviderMap.containsKey( repositoryId ) )
176 {
177 impl = serverWagonProviderMap.get( repositoryId );
178 getLogger().debug( "Using Wagon implementation " + impl + " from settings for server " + repositoryId );
179 }
180 else
181 {
182 impl = providerMapping.getWagonProvider( protocol );
183 if ( impl != null )
184 {
185 getLogger().debug( "Using Wagon implementation " + impl + " from default mapping for protocol " + protocol );
186 }
187 }
188
189 String hint;
190 if ( impl != null )
191 {
192 hint = protocol + "-" + impl;
193 PlexusContainer container = getWagonContainer( hint );
194 if ( container == null || !container.hasComponent( Wagon.ROLE, hint ) )
195 {
196 getLogger().debug(
197 "Cannot find wagon for protocol-provider hint: '" + hint
198 + "', configured for repository: '" + repositoryId + "'. Using protocol hint: '"
199 + protocol + "' instead." );
200 hint = protocol;
201 }
202 }
203 else
204 {
205 hint = protocol;
206 }
207
208 return hint;
209 }
210
211 private PlexusContainer getWagonContainer( String hint )
212 {
213 PlexusContainer container = this.container;
214 if ( availableWagons.containsKey( hint ) )
215 {
216 container = availableWagons.get( hint );
217 }
218
219 return container;
220 }
221
222 public void putArtifact( File source,
223 Artifact artifact,
224 ArtifactRepository deploymentRepository )
225 throws TransferFailedException
226 {
227 putRemoteFile( deploymentRepository, source, deploymentRepository.pathOf( artifact ), downloadMonitor );
228 }
229
230 public void putArtifactMetadata( File source,
231 ArtifactMetadata artifactMetadata,
232 ArtifactRepository repository )
233 throws TransferFailedException
234 {
235 getLogger().info( "Uploading " + artifactMetadata );
236 putRemoteFile( repository, source, repository.pathOfRemoteRepositoryMetadata( artifactMetadata ), null );
237 }
238
239 private void putRemoteFile( ArtifactRepository repository,
240 File source,
241 String remotePath,
242 TransferListener downloadMonitor )
243 throws TransferFailedException
244 {
245 failIfNotOnline();
246
247 String protocol = repository.getProtocol();
248
249 Wagon wagon;
250 try
251 {
252 wagon = getWagon( protocol, repository.getId() );
253
254 configureWagon( wagon, repository );
255 }
256 catch ( UnsupportedProtocolException e )
257 {
258 throw new TransferFailedException( "Unsupported Protocol: '" + protocol + "': " + e.getMessage(), e );
259 }
260
261 if ( downloadMonitor != null )
262 {
263 wagon.addTransferListener( downloadMonitor );
264 }
265
266 Map checksums = new HashMap( 2 );
267 Map sums = new HashMap( 2 );
268
269
270 try
271 {
272 ChecksumObserver checksumObserver = new ChecksumObserver( "MD5" );
273 wagon.addTransferListener( checksumObserver );
274 checksums.put( "md5", checksumObserver );
275 checksumObserver = new ChecksumObserver( "SHA-1" );
276 wagon.addTransferListener( checksumObserver );
277 checksums.put( "sha1", checksumObserver );
278 }
279 catch ( NoSuchAlgorithmException e )
280 {
281 throw new TransferFailedException( "Unable to add checksum methods: " + e.getMessage(), e );
282 }
283
284 try
285 {
286 Repository artifactRepository = new Repository( repository.getId(), repository.getUrl() );
287
288 if ( serverPermissionsMap.containsKey( repository.getId() ) )
289 {
290 RepositoryPermissions perms = (RepositoryPermissions) serverPermissionsMap.get( repository.getId() );
291
292 getLogger().debug(
293 "adding permissions to wagon connection: " + perms.getFileMode() + " " + perms.getDirectoryMode() );
294
295 artifactRepository.setPermissions( perms );
296 }
297 else
298 {
299 if ( defaultRepositoryPermissions != null )
300 {
301 artifactRepository.setPermissions( defaultRepositoryPermissions );
302 }
303 else
304 {
305 getLogger().debug( "not adding permissions to wagon connection" );
306 }
307 }
308
309 wagon.connect( artifactRepository, getAuthenticationInfo( repository.getId() ), new ProxyInfoProvider()
310 {
311 public ProxyInfo getProxyInfo( String protocol )
312 {
313 return getProxy( protocol );
314 }
315 });
316
317 wagon.put( source, remotePath );
318
319 wagon.removeTransferListener( downloadMonitor );
320
321
322 for ( Iterator i = checksums.keySet().iterator(); i.hasNext(); )
323 {
324 String extension = (String) i.next();
325 ChecksumObserver observer = (ChecksumObserver) checksums.get( extension );
326 sums.put( extension, observer.getActualChecksum() );
327 }
328
329
330 for ( Iterator i = checksums.keySet().iterator(); i.hasNext(); )
331 {
332 String extension = (String) i.next();
333
334
335 File temp = File.createTempFile( "maven-artifact", null );
336 temp.deleteOnExit();
337 FileUtils.fileWrite( temp.getAbsolutePath(), "UTF-8", (String) sums.get( extension ) );
338
339 wagon.put( temp, remotePath + "." + extension );
340 }
341 }
342 catch ( ConnectionException e )
343 {
344 throw new TransferFailedException( "Connection failed: " + e.getMessage(), e );
345 }
346 catch ( AuthenticationException e )
347 {
348 throw new TransferFailedException( "Authentication failed: " + e.getMessage(), e );
349 }
350 catch ( AuthorizationException e )
351 {
352 throw new TransferFailedException( "Authorization failed: " + e.getMessage(), e );
353 }
354 catch ( ResourceDoesNotExistException e )
355 {
356 throw new TransferFailedException( "Resource to deploy not found: " + e.getMessage(), e );
357 }
358 catch ( IOException e )
359 {
360 throw new TransferFailedException( "Error creating temporary file for deployment: " + e.getMessage(), e );
361 }
362 finally
363 {
364 disconnectWagon( wagon );
365
366 releaseWagon( protocol, wagon, repository.getId() );
367 }
368 }
369
370 public void getArtifact( Artifact artifact,
371 List remoteRepositories )
372 throws TransferFailedException, ResourceDoesNotExistException
373 {
374
375 boolean successful = false;
376 for ( Iterator iter = remoteRepositories.iterator(); iter.hasNext() && !successful; )
377 {
378 ArtifactRepository repository = (ArtifactRepository) iter.next();
379
380 try
381 {
382 getArtifact( artifact, repository );
383
384 successful = artifact.isResolved();
385 }
386 catch ( ResourceDoesNotExistException e )
387 {
388
389
390
391 getLogger().info( "Unable to find resource '" + artifact.getId() + "' in repository " +
392 repository.getId() + " (" + repository.getUrl() + ")" );
393 }
394 catch ( TransferFailedException e )
395 {
396 getLogger().warn( "Unable to get resource '" + artifact.getId() + "' from repository " +
397 repository.getId() + " (" + repository.getUrl() + "): " + e.getMessage() );
398 }
399 }
400
401
402 if ( !successful && !artifact.getFile().exists() )
403 {
404 throw new ResourceDoesNotExistException( "Unable to download the artifact from any repository" );
405 }
406 }
407
408 public void getArtifact( Artifact artifact,
409 ArtifactRepository repository )
410 throws TransferFailedException, ResourceDoesNotExistException
411 {
412 String remotePath = repository.pathOf( artifact );
413
414 ArtifactRepositoryPolicy policy = artifact.isSnapshot() ? repository.getSnapshots() : repository.getReleases();
415
416 if ( !policy.isEnabled() )
417 {
418 getLogger().debug( "Skipping disabled repository " + repository.getId() );
419 }
420 else if ( repository.isBlacklisted() )
421 {
422 getLogger().debug( "Skipping blacklisted repository " + repository.getId() );
423 }
424 else
425 {
426 getLogger().debug( "Trying repository " + repository.getId() );
427 getRemoteFile( getMirrorRepository( repository ), artifact.getFile(), remotePath, downloadMonitor,
428 policy.getChecksumPolicy(), false );
429 getLogger().debug( " Artifact resolved" );
430
431 artifact.setResolved( true );
432 }
433 }
434
435 public void getArtifactMetadata( ArtifactMetadata metadata,
436 ArtifactRepository repository,
437 File destination,
438 String checksumPolicy )
439 throws TransferFailedException, ResourceDoesNotExistException
440 {
441 String remotePath = repository.pathOfRemoteRepositoryMetadata( metadata );
442
443 getRemoteFile( getMirrorRepository( repository ), destination, remotePath, null, checksumPolicy, true );
444 }
445
446 public void getArtifactMetadataFromDeploymentRepository( ArtifactMetadata metadata, ArtifactRepository repository,
447 File destination, String checksumPolicy )
448 throws TransferFailedException, ResourceDoesNotExistException
449 {
450 String remotePath = repository.pathOfRemoteRepositoryMetadata( metadata );
451
452 getRemoteFile( repository, destination, remotePath, null, checksumPolicy, true );
453 }
454
455 private void getRemoteFile( ArtifactRepository repository,
456 File destination,
457 String remotePath,
458 TransferListener downloadMonitor,
459 String checksumPolicy,
460 boolean force )
461 throws TransferFailedException, ResourceDoesNotExistException
462 {
463
464
465 failIfNotOnline();
466
467 String protocol = repository.getProtocol();
468 Wagon wagon;
469 try
470 {
471 wagon = getWagon( protocol, repository.getId() );
472
473 configureWagon( wagon, repository );
474 }
475 catch ( UnsupportedProtocolException e )
476 {
477 throw new TransferFailedException( "Unsupported Protocol: '" + protocol + "': " + e.getMessage(), e );
478 }
479
480 if ( downloadMonitor != null )
481 {
482 wagon.addTransferListener( downloadMonitor );
483 }
484
485 File temp = new File( destination + ".tmp" );
486 temp.deleteOnExit();
487
488 boolean downloaded = false;
489
490 try
491 {
492 getLogger().debug( "Connecting to repository: \'" + repository.getId() + "\' with url: \'" + repository.getUrl() + "\'." );
493
494 wagon.connect( new Repository( repository.getId(), repository.getUrl() ),
495 getAuthenticationInfo( repository.getId() ), new ProxyInfoProvider()
496 {
497 public ProxyInfo getProxyInfo( String protocol )
498 {
499 return getProxy( protocol );
500 }
501 });
502
503 boolean firstRun = true;
504 boolean retry = true;
505
506
507
508
509 while ( firstRun || retry )
510 {
511
512 retry = false;
513
514
515 ChecksumObserver md5ChecksumObserver = null;
516 ChecksumObserver sha1ChecksumObserver = null;
517 try
518 {
519 md5ChecksumObserver = new ChecksumObserver( "MD5" );
520 wagon.addTransferListener( md5ChecksumObserver );
521
522 sha1ChecksumObserver = new ChecksumObserver( "SHA-1" );
523 wagon.addTransferListener( sha1ChecksumObserver );
524
525
526 if ( destination.exists() && !force )
527 {
528 try
529 {
530 downloaded = wagon.getIfNewer( remotePath, temp, destination.lastModified() );
531 if ( !downloaded )
532 {
533
534 destination.setLastModified( System.currentTimeMillis() );
535 }
536 }
537 catch ( UnsupportedOperationException e )
538 {
539
540 wagon.get( remotePath, temp );
541 downloaded = true;
542 }
543 }
544 else
545 {
546 wagon.get( remotePath, temp );
547 downloaded = true;
548 }
549 }
550 catch ( NoSuchAlgorithmException e )
551 {
552 throw new TransferFailedException( "Unable to add checksum methods: " + e.getMessage(), e );
553 }
554 finally
555 {
556 if ( md5ChecksumObserver != null )
557 {
558 wagon.removeTransferListener( md5ChecksumObserver );
559 }
560 if ( sha1ChecksumObserver != null )
561 {
562 wagon.removeTransferListener( sha1ChecksumObserver );
563 }
564 }
565
566 if ( downloaded )
567 {
568
569 if ( downloadMonitor != null )
570 {
571 wagon.removeTransferListener( downloadMonitor );
572 }
573
574
575 try
576 {
577 verifyChecksum( sha1ChecksumObserver, destination, temp, remotePath, ".sha1", wagon );
578 }
579 catch ( ChecksumFailedException e )
580 {
581
582
583
584
585 if ( firstRun )
586 {
587 getLogger().warn( "*** CHECKSUM FAILED - " + e.getMessage() + " - RETRYING" );
588 retry = true;
589 }
590 else
591 {
592 handleChecksumFailure( checksumPolicy, e.getMessage(), e.getCause() );
593 }
594 }
595 catch ( ResourceDoesNotExistException sha1TryException )
596 {
597 getLogger().debug( "SHA1 not found, trying MD5", sha1TryException );
598
599
600
601 try
602 {
603 verifyChecksum( md5ChecksumObserver, destination, temp, remotePath, ".md5", wagon );
604 }
605 catch ( ChecksumFailedException e )
606 {
607
608
609 if ( firstRun )
610 {
611 retry = true;
612 }
613 else
614 {
615 handleChecksumFailure( checksumPolicy, e.getMessage(), e.getCause() );
616 }
617 }
618 catch ( ResourceDoesNotExistException md5TryException )
619 {
620
621 handleChecksumFailure( checksumPolicy, "Error retrieving checksum file for " + remotePath,
622 md5TryException );
623 }
624 }
625
626
627 if ( downloadMonitor != null )
628 {
629 wagon.addTransferListener( downloadMonitor );
630 }
631 }
632
633
634 firstRun = false;
635 }
636 }
637 catch ( ConnectionException e )
638 {
639 throw new TransferFailedException( "Connection failed: " + e.getMessage(), e );
640 }
641 catch ( AuthenticationException e )
642 {
643 throw new TransferFailedException( "Authentication failed: " + e.getMessage(), e );
644 }
645 catch ( AuthorizationException e )
646 {
647 throw new TransferFailedException( "Authorization failed: " + e.getMessage(), e );
648 }
649 finally
650 {
651 disconnectWagon( wagon );
652
653 releaseWagon( protocol, wagon, repository.getId() );
654 }
655
656 if ( downloaded )
657 {
658 if ( !temp.exists() )
659 {
660 throw new ResourceDoesNotExistException( "Downloaded file does not exist: " + temp );
661 }
662
663
664
665
666
667
668
669 if ( !temp.renameTo( destination ) )
670 {
671 try
672 {
673 FileUtils.copyFile( temp, destination );
674
675 temp.delete();
676 }
677 catch ( IOException e )
678 {
679 throw new TransferFailedException(
680 "Error copying temporary file to the final destination: " + e.getMessage(), e );
681 }
682 }
683 }
684 }
685
686 public ArtifactRepository getMirrorRepository( ArtifactRepository repository )
687 {
688 ArtifactRepository mirror = getMirror( repository );
689 if ( mirror != null )
690 {
691 String id = mirror.getId();
692 if ( id == null )
693 {
694
695 id = repository.getId();
696 }
697
698 getLogger().debug( "Using mirror: " + mirror.getUrl() + " (id: " + id + ")" );
699
700 repository = repositoryFactory.createArtifactRepository( id, mirror.getUrl(),
701 repository.getLayout(), repository.getSnapshots(),
702 repository.getReleases() );
703 }
704 return repository;
705 }
706
707 private void failIfNotOnline()
708 throws TransferFailedException
709 {
710 if ( !isOnline() )
711 {
712 throw new TransferFailedException( "System is offline." );
713 }
714 }
715
716 private void handleChecksumFailure( String checksumPolicy,
717 String message,
718 Throwable cause )
719 throws ChecksumFailedException
720 {
721 if ( ArtifactRepositoryPolicy.CHECKSUM_POLICY_FAIL.equals( checksumPolicy ) )
722 {
723 throw new ChecksumFailedException( message, cause );
724 }
725 else if ( !ArtifactRepositoryPolicy.CHECKSUM_POLICY_IGNORE.equals( checksumPolicy ) )
726 {
727
728 getLogger().warn( "*** CHECKSUM FAILED - " + message + " - IGNORING" );
729 }
730
731 }
732
733 private void verifyChecksum( ChecksumObserver checksumObserver,
734 File destination,
735 File tempDestination,
736 String remotePath,
737 String checksumFileExtension,
738 Wagon wagon )
739 throws ResourceDoesNotExistException, TransferFailedException, AuthorizationException
740 {
741 try
742 {
743
744 String actualChecksum = checksumObserver.getActualChecksum();
745
746 File tempChecksumFile = new File( tempDestination + checksumFileExtension + ".tmp" );
747 tempChecksumFile.deleteOnExit();
748 wagon.get( remotePath + checksumFileExtension, tempChecksumFile );
749
750 String expectedChecksum = FileUtils.fileRead( tempChecksumFile, "UTF-8" );
751
752
753 expectedChecksum = expectedChecksum.trim();
754
755
756 if ( expectedChecksum.regionMatches( true, 0, "MD", 0, 2 )
757 || expectedChecksum.regionMatches( true, 0, "SHA", 0, 3 ) )
758 {
759 int lastSpacePos = expectedChecksum.lastIndexOf( ' ' );
760 expectedChecksum = expectedChecksum.substring( lastSpacePos + 1 );
761 }
762 else
763 {
764
765 int spacePos = expectedChecksum.indexOf( ' ' );
766
767 if ( spacePos != -1 )
768 {
769 expectedChecksum = expectedChecksum.substring( 0, spacePos );
770 }
771 }
772 if ( expectedChecksum.equalsIgnoreCase( actualChecksum ) )
773 {
774 File checksumFile = new File( destination + checksumFileExtension );
775 if ( checksumFile.exists() )
776 {
777 checksumFile.delete();
778 }
779 FileUtils.copyFile( tempChecksumFile, checksumFile );
780 }
781 else
782 {
783 throw new ChecksumFailedException( "Checksum failed on download: local = '" + actualChecksum +
784 "'; remote = '" + expectedChecksum + "'" );
785 }
786 }
787 catch ( IOException e )
788 {
789 throw new ChecksumFailedException( "Invalid checksum file", e );
790 }
791 }
792
793
794 private void disconnectWagon( Wagon wagon )
795 {
796 try
797 {
798 wagon.disconnect();
799 }
800 catch ( ConnectionException e )
801 {
802 getLogger().error( "Problem disconnecting from wagon - ignoring: " + e.getMessage() );
803 }
804 }
805
806 private void releaseWagon( String protocol,
807 Wagon wagon, String repositoryId )
808 {
809 String hint = getWagonHint( protocol, repositoryId );
810
811 PlexusContainer container = getWagonContainer( hint );
812 try
813 {
814 container.release( wagon );
815 }
816 catch ( ComponentLifecycleException e )
817 {
818 getLogger().error( "Problem releasing wagon - ignoring: " + e.getMessage() );
819 }
820 }
821
822 public ProxyInfo getProxy( String protocol )
823 {
824 ProxyInfo info = (ProxyInfo) proxies.get( protocol );
825
826 if ( info != null )
827 {
828 getLogger().debug( "Using Proxy: " + info.getHost() );
829 }
830
831 return info;
832 }
833
834 public AuthenticationInfo getAuthenticationInfo( String id )
835 {
836 return (AuthenticationInfo) authenticationInfoMap.get( id );
837 }
838
839
840
841
842
843
844
845
846 public ArtifactRepository getMirror( ArtifactRepository originalRepository )
847 {
848 ArtifactRepository selectedMirror = (ArtifactRepository) mirrors.get( originalRepository.getId() );
849 if ( null == selectedMirror )
850 {
851
852 Set keySet = mirrors.keySet();
853 if ( keySet != null )
854 {
855 Iterator iter = keySet.iterator();
856 while ( iter.hasNext() )
857 {
858 String pattern = (String) iter.next();
859 if ( matchPattern( originalRepository, pattern ) )
860 {
861 selectedMirror = (ArtifactRepository) mirrors.get( pattern );
862 break;
863 }
864 }
865 }
866
867 }
868 return selectedMirror;
869 }
870
871
872
873
874
875
876
877
878
879
880
881
882
883 public boolean matchPattern( ArtifactRepository originalRepository, String pattern )
884 {
885 boolean result = false;
886 String originalId = originalRepository.getId();
887
888
889 if ( WILDCARD.equals( pattern ) || pattern.equals( originalId ) )
890 {
891 result = true;
892 }
893 else
894 {
895
896 String[] repos = pattern.split( "," );
897 for ( int i = 0; i < repos.length; i++ )
898 {
899 String repo = repos[i];
900
901
902 if ( repo.length() > 1 && repo.startsWith( "!" ) )
903 {
904 if ( originalId.equals( repo.substring( 1 ) ) )
905 {
906
907 result = false;
908 break;
909 }
910 }
911
912 else if ( originalId.equals( repo ) )
913 {
914 result = true;
915 break;
916 }
917
918 else if ( EXTERNAL_WILDCARD.equals( repo ) && isExternalRepo( originalRepository ) )
919 {
920 result = true;
921
922 }
923 else if ( WILDCARD.equals( repo ) )
924 {
925 result = true;
926
927 }
928 }
929 }
930 return result;
931 }
932
933
934
935
936
937
938
939 public boolean isExternalRepo( ArtifactRepository originalRepository )
940 {
941 try
942 {
943 URL url = new URL( originalRepository.getUrl() );
944 return !( url.getHost().equals( "localhost" ) || url.getHost().equals( "127.0.0.1" ) || url.getProtocol().equals(
945 "file" ) );
946 }
947 catch ( MalformedURLException e )
948 {
949
950 return false;
951 }
952 }
953
954
955
956
957
958
959
960
961
962
963
964
965
966 public void addProxy( String protocol,
967 String host,
968 int port,
969 String username,
970 String password,
971 String nonProxyHosts )
972 {
973 ProxyInfo proxyInfo = new ProxyInfo();
974 proxyInfo.setHost( host );
975 proxyInfo.setType( protocol );
976 proxyInfo.setPort( port );
977 proxyInfo.setNonProxyHosts( nonProxyHosts );
978 proxyInfo.setUserName( username );
979 proxyInfo.setPassword( password );
980
981 proxies.put( protocol, proxyInfo );
982 }
983
984 public void contextualize( Context context )
985 throws ContextException
986 {
987 container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
988 }
989
990
991 public void setDownloadMonitor( TransferListener downloadMonitor )
992 {
993 this.downloadMonitor = downloadMonitor;
994 }
995
996 public void addAuthenticationInfo( String repositoryId,
997 String username,
998 String password,
999 String privateKey,
1000 String passphrase )
1001 {
1002 AuthenticationInfo authInfo = new AuthenticationInfo();
1003
1004 authInfo.setUserName( username );
1005
1006 authInfo.setPassword( password );
1007
1008 authInfo.setPrivateKey( privateKey );
1009
1010 authInfo.setPassphrase( passphrase );
1011
1012 authenticationInfoMap.put( repositoryId, authInfo );
1013 }
1014
1015 public void addPermissionInfo( String repositoryId,
1016 String filePermissions,
1017 String directoryPermissions )
1018 {
1019
1020 RepositoryPermissions permissions = new RepositoryPermissions();
1021 boolean addPermissions = false;
1022
1023 if ( filePermissions != null )
1024 {
1025 permissions.setFileMode( filePermissions );
1026 addPermissions = true;
1027 }
1028
1029 if ( directoryPermissions != null )
1030 {
1031 permissions.setDirectoryMode( directoryPermissions );
1032 addPermissions = true;
1033 }
1034
1035 if ( addPermissions )
1036 {
1037 serverPermissionsMap.put( repositoryId, permissions );
1038 }
1039 }
1040
1041 public void addMirror( String id,
1042 String mirrorOf,
1043 String url )
1044 {
1045 if ( id == null )
1046 {
1047 id = "mirror-" + anonymousMirrorIdSeed++;
1048 getLogger().warn( "You are using a mirror that doesn't declare an <id/> element. Using \'" + id + "\' instead:\nId: " + id + "\nmirrorOf: " + mirrorOf + "\nurl: " + url + "\n" );
1049 }
1050
1051 ArtifactRepository mirror = new DefaultArtifactRepository( id, url, null );
1052
1053
1054 if (!mirrors.containsKey( mirrorOf ))
1055 {
1056 mirrors.put( mirrorOf, mirror );
1057 }
1058 }
1059
1060 public void setOnline( boolean online )
1061 {
1062 this.online = online;
1063 }
1064
1065 public boolean isOnline()
1066 {
1067 return online;
1068 }
1069
1070 public void setInteractive( boolean interactive )
1071 {
1072 this.interactive = interactive;
1073 }
1074
1075 @SuppressWarnings( "unchecked" )
1076 public void registerWagons( Collection wagons,
1077 PlexusContainer extensionContainer )
1078 {
1079 for ( Iterator<String> i = wagons.iterator(); i.hasNext(); )
1080 {
1081 availableWagons.put( i.next(), extensionContainer );
1082 }
1083 }
1084
1085
1086
1087
1088
1089
1090
1091
1092 private void configureWagon( Wagon wagon,
1093 ArtifactRepository repository )
1094 throws WagonConfigurationException
1095 {
1096 configureWagon( wagon, repository.getId(), repository.getProtocol() );
1097 }
1098
1099 private void configureWagon( Wagon wagon, String repositoryId, String protocol )
1100 throws WagonConfigurationException
1101 {
1102 PlexusConfiguration config = (PlexusConfiguration) serverConfigurationMap.get( repositoryId );
1103 if ( protocol.startsWith( "http" ) || protocol.startsWith( "dav" ) )
1104 {
1105 config = updateUserAgentForHttp( wagon, config );
1106 }
1107
1108 if ( config != null )
1109 {
1110 ComponentConfigurator componentConfigurator = null;
1111 try
1112 {
1113 componentConfigurator = (ComponentConfigurator) container.lookup( ComponentConfigurator.ROLE, "wagon" );
1114 componentConfigurator.configureComponent( wagon, config, container.getContainerRealm() );
1115 }
1116 catch ( final ComponentLookupException e )
1117 {
1118 throw new WagonConfigurationException( repositoryId,
1119 "Unable to lookup wagon configurator. Wagon configuration cannot be applied.",
1120 e );
1121 }
1122 catch ( ComponentConfigurationException e )
1123 {
1124 throw new WagonConfigurationException( repositoryId, "Unable to apply wagon configuration.", e );
1125 }
1126 finally
1127 {
1128 if ( componentConfigurator != null )
1129 {
1130 try
1131 {
1132 container.release( componentConfigurator );
1133 }
1134 catch ( ComponentLifecycleException e )
1135 {
1136 getLogger().error( "Problem releasing configurator - ignoring: " + e.getMessage() );
1137 }
1138 }
1139
1140 }
1141 }
1142 }
1143
1144
1145 private PlexusConfiguration updateUserAgentForHttp( Wagon wagon, PlexusConfiguration config )
1146 {
1147 if ( config == null )
1148 {
1149 config = new XmlPlexusConfiguration( "configuration" );
1150 }
1151
1152 if ( httpUserAgent != null )
1153 {
1154 try
1155 {
1156 wagon.getClass().getMethod( "setHttpHeaders", new Class[]{ Properties.class } );
1157
1158 PlexusConfiguration headerConfig = config.getChild( "httpHeaders", true );
1159 PlexusConfiguration[] children = headerConfig.getChildren( "property" );
1160 boolean found = false;
1161
1162 getLogger().debug( "Checking for pre-existing User-Agent configuration." );
1163 for ( int i = 0; i < children.length; i++ )
1164 {
1165 PlexusConfiguration c = children[i].getChild( "name", false );
1166 if ( c != null && "User-Agent".equals( c.getValue( null ) ) )
1167 {
1168 found = true;
1169 break;
1170 }
1171 }
1172
1173 if ( !found )
1174 {
1175 getLogger().debug( "Adding User-Agent configuration." );
1176 XmlPlexusConfiguration propertyConfig = new XmlPlexusConfiguration( "property" );
1177 headerConfig.addChild( propertyConfig );
1178
1179 XmlPlexusConfiguration nameConfig = new XmlPlexusConfiguration( "name" );
1180 nameConfig.setValue( "User-Agent" );
1181 propertyConfig.addChild( nameConfig );
1182
1183 XmlPlexusConfiguration versionConfig = new XmlPlexusConfiguration( "value" );
1184 versionConfig.setValue( httpUserAgent );
1185 propertyConfig.addChild( versionConfig );
1186 }
1187 else
1188 {
1189 getLogger().debug( "User-Agent configuration found." );
1190 }
1191 }
1192 catch ( SecurityException e )
1193 {
1194 getLogger().debug( "setHttpHeaders method not accessible on wagon: " + wagon + "; skipping User-Agent configuration." );
1195
1196 }
1197 catch ( NoSuchMethodException e )
1198 {
1199 getLogger().debug( "setHttpHeaders method not found on wagon: " + wagon + "; skipping User-Agent configuration." );
1200
1201 }
1202 }
1203
1204 return config;
1205 }
1206
1207 public void addConfiguration( String repositoryId,
1208 Xpp3Dom configuration )
1209 {
1210 if ( repositoryId == null || configuration == null )
1211 {
1212 throw new IllegalArgumentException( "arguments can't be null" );
1213 }
1214
1215 final XmlPlexusConfiguration xmlConf = new XmlPlexusConfiguration( configuration );
1216
1217 for ( int i = 0; i < configuration.getChildCount(); i++ )
1218 {
1219 Xpp3Dom domChild = configuration.getChild( i );
1220 if ( WAGON_PROVIDER_CONFIGURATION.equals( domChild.getName() ) )
1221 {
1222 serverWagonProviderMap.put( repositoryId, domChild.getValue() );
1223 configuration.removeChild( i );
1224 break;
1225 }
1226
1227 i++;
1228 }
1229
1230 serverConfigurationMap.put( repositoryId, xmlConf );
1231 }
1232
1233 public void setDefaultRepositoryPermissions( RepositoryPermissions defaultRepositoryPermissions )
1234 {
1235 this.defaultRepositoryPermissions = defaultRepositoryPermissions;
1236 }
1237
1238
1239 public void initialize()
1240 throws InitializationException
1241 {
1242 if ( httpUserAgent == null )
1243 {
1244 InputStream resourceAsStream = null;
1245 try
1246 {
1247 Properties properties = new Properties();
1248 resourceAsStream = getClass().getClassLoader().getResourceAsStream( MAVEN_ARTIFACT_PROPERTIES );
1249
1250 if ( resourceAsStream != null )
1251 {
1252 try
1253 {
1254 properties.load( resourceAsStream );
1255
1256 httpUserAgent =
1257 "maven-artifact/" + properties.getProperty( "version" ) + " (Java "
1258 + System.getProperty( "java.version" ) + "; " + System.getProperty( "os.name" ) + " "
1259 + System.getProperty( "os.version" ) + ")";
1260 }
1261 catch ( IOException e )
1262 {
1263 getLogger().warn(
1264 "Failed to load Maven artifact properties from:\n" + MAVEN_ARTIFACT_PROPERTIES
1265 + "\n\nUser-Agent HTTP header may be incorrect for artifact resolution." );
1266 }
1267 }
1268 }
1269 finally
1270 {
1271 IOUtil.close( resourceAsStream );
1272 }
1273 }
1274 }
1275
1276
1277
1278
1279 public void setHttpUserAgent( String userAgent )
1280 {
1281 this.httpUserAgent = userAgent;
1282 }
1283
1284
1285
1286
1287 public String getHttpUserAgent()
1288 {
1289 return httpUserAgent;
1290 }
1291 }