1 package org.sonatype.aether.connector.wagon;
2
3
4
5
6
7
8
9
10
11 import java.io.ByteArrayInputStream;
12 import java.io.File;
13 import java.io.IOException;
14 import java.lang.reflect.Method;
15 import java.util.ArrayList;
16 import java.util.Collection;
17 import java.util.Collections;
18 import java.util.LinkedHashMap;
19 import java.util.Locale;
20 import java.util.Map;
21 import java.util.Properties;
22 import java.util.Queue;
23 import java.util.UUID;
24 import java.util.concurrent.ConcurrentLinkedQueue;
25 import java.util.concurrent.Executor;
26 import java.util.concurrent.ExecutorService;
27 import java.util.concurrent.LinkedBlockingQueue;
28 import java.util.concurrent.ThreadPoolExecutor;
29 import java.util.concurrent.TimeUnit;
30
31 import org.apache.maven.wagon.ResourceDoesNotExistException;
32 import org.apache.maven.wagon.StreamingWagon;
33 import org.apache.maven.wagon.Wagon;
34 import org.apache.maven.wagon.WagonException;
35 import org.apache.maven.wagon.authentication.AuthenticationInfo;
36 import org.apache.maven.wagon.observers.ChecksumObserver;
37 import org.apache.maven.wagon.proxy.ProxyInfo;
38 import org.apache.maven.wagon.proxy.ProxyInfoProvider;
39 import org.apache.maven.wagon.repository.Repository;
40 import org.apache.maven.wagon.repository.RepositoryPermissions;
41 import org.sonatype.aether.ConfigurationProperties;
42 import org.sonatype.aether.RepositorySystemSession;
43 import org.sonatype.aether.repository.Authentication;
44 import org.sonatype.aether.repository.Proxy;
45 import org.sonatype.aether.repository.RemoteRepository;
46 import org.sonatype.aether.repository.RepositoryPolicy;
47 import org.sonatype.aether.spi.connector.ArtifactDownload;
48 import org.sonatype.aether.spi.connector.ArtifactTransfer;
49 import org.sonatype.aether.spi.connector.ArtifactUpload;
50 import org.sonatype.aether.spi.connector.MetadataDownload;
51 import org.sonatype.aether.spi.connector.MetadataTransfer;
52 import org.sonatype.aether.spi.connector.MetadataUpload;
53 import org.sonatype.aether.spi.connector.RepositoryConnector;
54 import org.sonatype.aether.spi.connector.Transfer;
55 import org.sonatype.aether.spi.io.FileProcessor;
56 import org.sonatype.aether.spi.log.Logger;
57 import org.sonatype.aether.transfer.ArtifactNotFoundException;
58 import org.sonatype.aether.transfer.ArtifactTransferException;
59 import org.sonatype.aether.transfer.ChecksumFailureException;
60 import org.sonatype.aether.transfer.MetadataNotFoundException;
61 import org.sonatype.aether.transfer.MetadataTransferException;
62 import org.sonatype.aether.transfer.NoRepositoryConnectorException;
63 import org.sonatype.aether.transfer.TransferEvent;
64 import org.sonatype.aether.transfer.TransferListener;
65 import org.sonatype.aether.util.ChecksumUtils;
66 import org.sonatype.aether.util.ConfigUtils;
67 import org.sonatype.aether.util.concurrency.RunnableErrorForwarder;
68 import org.sonatype.aether.util.layout.MavenDefaultLayout;
69 import org.sonatype.aether.util.layout.RepositoryLayout;
70 import org.sonatype.aether.util.listener.DefaultTransferEvent;
71
72
73
74
75
76
77 class WagonRepositoryConnector
78 implements RepositoryConnector
79 {
80
81 private static final String PROP_THREADS = "aether.connector.wagon.threads";
82
83 private static final String PROP_CONFIG = "aether.connector.wagon.config";
84
85 private static final String PROP_FILE_MODE = "aether.connector.perms.fileMode";
86
87 private static final String PROP_DIR_MODE = "aether.connector.perms.dirMode";
88
89 private static final String PROP_GROUP = "aether.connector.perms.group";
90
91 private final Logger logger;
92
93 private final FileProcessor fileProcessor;
94
95 private final RemoteRepository repository;
96
97 private final RepositorySystemSession session;
98
99 private final WagonProvider wagonProvider;
100
101 private final WagonConfigurator wagonConfigurator;
102
103 private final String wagonHint;
104
105 private final Repository wagonRepo;
106
107 private final AuthenticationInfo wagonAuth;
108
109 private final ProxyInfoProvider wagonProxy;
110
111 private final RepositoryLayout layout = new MavenDefaultLayout();
112
113 private final TransferListener listener;
114
115 private final Queue<Wagon> wagons = new ConcurrentLinkedQueue<Wagon>();
116
117 private final Executor executor;
118
119 private boolean closed;
120
121 private final Map<String, String> checksumAlgos;
122
123 private final Properties headers;
124
125 public WagonRepositoryConnector( WagonProvider wagonProvider, WagonConfigurator wagonConfigurator,
126 RemoteRepository repository, RepositorySystemSession session,
127 FileProcessor fileProcessor, Logger logger )
128 throws NoRepositoryConnectorException
129 {
130 this.logger = logger;
131 this.fileProcessor = fileProcessor;
132 this.wagonProvider = wagonProvider;
133 this.wagonConfigurator = wagonConfigurator;
134 this.repository = repository;
135 this.session = session;
136 this.listener = session.getTransferListener();
137
138 if ( !"default".equals( repository.getContentType() ) )
139 {
140 throw new NoRepositoryConnectorException( repository );
141 }
142
143 wagonRepo = new Repository( repository.getId(), repository.getUrl() );
144 wagonRepo.setPermissions( getPermissions( repository.getId(), session ) );
145
146 wagonHint = wagonRepo.getProtocol().toLowerCase( Locale.ENGLISH );
147 if ( wagonHint == null || wagonHint.length() <= 0 )
148 {
149 throw new NoRepositoryConnectorException( repository );
150 }
151
152 try
153 {
154 wagons.add( lookupWagon() );
155 }
156 catch ( Exception e )
157 {
158 logger.debug( e.getMessage(), e );
159 throw new NoRepositoryConnectorException( repository );
160 }
161
162 wagonAuth = getAuthenticationInfo( repository );
163 wagonProxy = getProxy( repository );
164
165 int threads = ConfigUtils.getInteger( session, 5, PROP_THREADS, "maven.artifact.threads" );
166 executor = getExecutor( threads );
167
168 checksumAlgos = new LinkedHashMap<String, String>();
169 checksumAlgos.put( "SHA-1", ".sha1" );
170 checksumAlgos.put( "MD5", ".md5" );
171
172 headers = new Properties();
173 headers.put( "User-Agent", ConfigUtils.getString( session, ConfigurationProperties.DEFAULT_USER_AGENT,
174 ConfigurationProperties.USER_AGENT ) );
175 Map<?, ?> headers =
176 ConfigUtils.getMap( session, null, ConfigurationProperties.HTTP_HEADERS + "." + repository.getId(),
177 ConfigurationProperties.HTTP_HEADERS );
178 if ( headers != null )
179 {
180 this.headers.putAll( headers );
181 }
182 }
183
184 private Executor getExecutor( int threads )
185 {
186 if ( threads <= 1 )
187 {
188 return new Executor()
189 {
190 public void execute( Runnable command )
191 {
192 command.run();
193 }
194 };
195 }
196 else
197 {
198 return new ThreadPoolExecutor( threads, threads, 3, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>() );
199 }
200 }
201
202 private static RepositoryPermissions getPermissions( String repoId, RepositorySystemSession session )
203 {
204 RepositoryPermissions result = null;
205
206 RepositoryPermissions perms = new RepositoryPermissions();
207
208 String suffix = '.' + repoId;
209
210 String fileMode = ConfigUtils.getString( session, (String) null, PROP_FILE_MODE + suffix );
211 if ( fileMode != null )
212 {
213 perms.setFileMode( fileMode );
214 result = perms;
215 }
216
217 String dirMode = ConfigUtils.getString( session, (String) null, PROP_DIR_MODE + suffix );
218 if ( dirMode != null )
219 {
220 perms.setDirectoryMode( dirMode );
221 result = perms;
222 }
223
224 String group = ConfigUtils.getString( session, (String) null, PROP_GROUP + suffix );
225 if ( group != null )
226 {
227 perms.setGroup( group );
228 result = perms;
229 }
230
231 return result;
232 }
233
234 private AuthenticationInfo getAuthenticationInfo( RemoteRepository repository )
235 {
236 AuthenticationInfo auth = null;
237
238 Authentication a = repository.getAuthentication();
239 if ( a != null )
240 {
241 auth = new AuthenticationInfo();
242 auth.setUserName( a.getUsername() );
243 auth.setPassword( a.getPassword() );
244 auth.setPrivateKey( a.getPrivateKeyFile() );
245 auth.setPassphrase( a.getPassphrase() );
246 }
247
248 return auth;
249 }
250
251 private ProxyInfoProvider getProxy( RemoteRepository repository )
252 {
253 ProxyInfoProvider proxy = null;
254
255 Proxy p = repository.getProxy();
256 if ( p != null )
257 {
258 final ProxyInfo prox = new ProxyInfo();
259 prox.setType( p.getType() );
260 prox.setHost( p.getHost() );
261 prox.setPort( p.getPort() );
262 if ( p.getAuthentication() != null )
263 {
264 prox.setUserName( p.getAuthentication().getUsername() );
265 prox.setPassword( p.getAuthentication().getPassword() );
266 }
267 proxy = new ProxyInfoProvider()
268 {
269 public ProxyInfo getProxyInfo( String protocol )
270 {
271 return prox;
272 }
273 };
274 }
275
276 return proxy;
277 }
278
279 private Wagon lookupWagon()
280 throws Exception
281 {
282 return wagonProvider.lookup( wagonHint );
283 }
284
285 private void releaseWagon( Wagon wagon )
286 {
287 wagonProvider.release( wagon );
288 }
289
290 private void connectWagon( Wagon wagon )
291 throws Exception
292 {
293 if ( !headers.isEmpty() )
294 {
295 try
296 {
297 Method setHttpHeaders = wagon.getClass().getMethod( "setHttpHeaders", Properties.class );
298 setHttpHeaders.invoke( wagon, headers );
299 }
300 catch ( NoSuchMethodException e )
301 {
302
303 }
304 catch ( Exception e )
305 {
306 logger.debug( "Could not set user agent for wagon " + wagon.getClass().getName() + ": " + e );
307 }
308 }
309
310 int connectTimeout =
311 ConfigUtils.getInteger( session, ConfigurationProperties.DEFAULT_CONNECT_TIMEOUT,
312 ConfigurationProperties.CONNECT_TIMEOUT );
313 int requestTimeout =
314 ConfigUtils.getInteger( session, ConfigurationProperties.DEFAULT_REQUEST_TIMEOUT,
315 ConfigurationProperties.REQUEST_TIMEOUT );
316
317 wagon.setTimeout( Math.max( Math.max( connectTimeout, requestTimeout ), 0 ) );
318
319 wagon.setInteractive( ConfigUtils.getBoolean( session, ConfigurationProperties.DEFAULT_INTERACTIVE,
320 ConfigurationProperties.INTERACTIVE ) );
321
322 Object configuration = ConfigUtils.getObject( session, null, PROP_CONFIG + "." + repository.getId() );
323 if ( configuration != null && wagonConfigurator != null )
324 {
325 try
326 {
327 wagonConfigurator.configure( wagon, configuration );
328 }
329 catch ( Exception e )
330 {
331 String msg =
332 "Could not apply configuration for " + repository.getId() + " to wagon "
333 + wagon.getClass().getName() + ":" + e.getMessage();
334 if ( logger.isDebugEnabled() )
335 {
336 logger.warn( msg, e );
337 }
338 else
339 {
340 logger.warn( msg );
341 }
342 }
343 }
344
345 wagon.connect( wagonRepo, wagonAuth, wagonProxy );
346 }
347
348 private void disconnectWagon( Wagon wagon )
349 {
350 try
351 {
352 if ( wagon != null )
353 {
354 wagon.disconnect();
355 }
356 }
357 catch ( Exception e )
358 {
359
360 }
361 }
362
363 Wagon pollWagon()
364 throws Exception
365 {
366 Wagon wagon = wagons.poll();
367
368 if ( wagon == null )
369 {
370 try
371 {
372 wagon = lookupWagon();
373 connectWagon( wagon );
374 }
375 catch ( Exception e )
376 {
377 releaseWagon( wagon );
378 throw e;
379 }
380 }
381 else if ( wagon.getRepository() == null )
382 {
383 try
384 {
385 connectWagon( wagon );
386 }
387 catch ( Exception e )
388 {
389 wagons.add( wagon );
390 throw e;
391 }
392 }
393
394 return wagon;
395 }
396
397 private <T> Collection<T> safe( Collection<T> items )
398 {
399 return ( items != null ) ? items : Collections.<T> emptyList();
400 }
401
402 private File getTmpFile( String path )
403 {
404 File file;
405 do
406 {
407 file = new File( path + ".tmp" + UUID.randomUUID().toString().replace( "-", "" ).substring( 0, 16 ) );
408 }
409 while ( file.exists() );
410 return file;
411 }
412
413 public void get( Collection<? extends ArtifactDownload> artifactDownloads,
414 Collection<? extends MetadataDownload> metadataDownloads )
415 {
416 if ( closed )
417 {
418 throw new IllegalStateException( "connector closed" );
419 }
420
421 artifactDownloads = safe( artifactDownloads );
422 metadataDownloads = safe( metadataDownloads );
423
424 Collection<GetTask<?>> tasks = new ArrayList<GetTask<?>>();
425
426 RunnableErrorForwarder errorForwarder = new RunnableErrorForwarder();
427
428 for ( MetadataDownload download : metadataDownloads )
429 {
430 String resource = layout.getPath( download.getMetadata() ).getPath();
431 GetTask<?> task =
432 new GetTask<MetadataTransfer>( resource, download.getFile(), download.getChecksumPolicy(), download,
433 METADATA );
434 tasks.add( task );
435 executor.execute( errorForwarder.wrap( task ) );
436 }
437
438 for ( ArtifactDownload download : artifactDownloads )
439 {
440 String resource = layout.getPath( download.getArtifact() ).getPath();
441 GetTask<?> task =
442 new GetTask<ArtifactTransfer>( resource, download.isExistenceCheck() ? null : download.getFile(),
443 download.getChecksumPolicy(), download, ARTIFACT );
444 tasks.add( task );
445 executor.execute( errorForwarder.wrap( task ) );
446 }
447
448 errorForwarder.await();
449 }
450
451 public void put( Collection<? extends ArtifactUpload> artifactUploads,
452 Collection<? extends MetadataUpload> metadataUploads )
453 {
454 if ( closed )
455 {
456 throw new IllegalStateException( "connector closed" );
457 }
458
459 artifactUploads = safe( artifactUploads );
460 metadataUploads = safe( metadataUploads );
461
462 for ( ArtifactUpload upload : artifactUploads )
463 {
464 String path = layout.getPath( upload.getArtifact() ).getPath();
465
466 PutTask<?> task = new PutTask<ArtifactTransfer>( path, upload.getFile(), upload, ARTIFACT );
467 task.run();
468 }
469
470 for ( MetadataUpload upload : metadataUploads )
471 {
472 String path = layout.getPath( upload.getMetadata() ).getPath();
473
474 PutTask<?> task = new PutTask<MetadataTransfer>( path, upload.getFile(), upload, METADATA );
475 task.run();
476 }
477 }
478
479 public void close()
480 {
481 closed = true;
482
483 for ( Wagon wagon = wagons.poll(); wagon != null; wagon = wagons.poll() )
484 {
485 disconnectWagon( wagon );
486 releaseWagon( wagon );
487 }
488
489 shutdown( executor );
490 }
491
492 private void shutdown( Executor executor )
493 {
494 if ( executor instanceof ExecutorService )
495 {
496 ( (ExecutorService) executor ).shutdown();
497 }
498 }
499
500 @Override
501 protected void finalize()
502 throws Throwable
503 {
504 try
505 {
506 close();
507 }
508 finally
509 {
510 super.finalize();
511 }
512 }
513
514 @Override
515 public String toString()
516 {
517 return String.valueOf( repository );
518 }
519
520 class GetTask<T extends Transfer>
521 implements Runnable
522 {
523
524 private final T download;
525
526 private final String path;
527
528 private final File file;
529
530 private final String checksumPolicy;
531
532 private final ExceptionWrapper<T> wrapper;
533
534 public GetTask( String path, File file, String checksumPolicy, T download, ExceptionWrapper<T> wrapper )
535 {
536 this.path = path;
537 this.file = file;
538 this.checksumPolicy = checksumPolicy;
539 this.download = download;
540 this.wrapper = wrapper;
541 }
542
543 public T getDownload()
544 {
545 return download;
546 }
547
548 public void run()
549 {
550 download.setState( Transfer.State.ACTIVE );
551
552 WagonTransferListenerAdapter wagonListener = null;
553 if ( listener != null )
554 {
555 wagonListener =
556 new WagonTransferListenerAdapter( listener, wagonRepo.getUrl(), path, file, download.getTrace() );
557 }
558
559 try
560 {
561 if ( listener != null )
562 {
563 DefaultTransferEvent event = wagonListener.newEvent();
564 event.setRequestType( TransferEvent.RequestType.GET );
565 event.setType( TransferEvent.EventType.INITIATED );
566 listener.transferInitiated( event );
567 }
568
569 File tmp = ( file != null ) ? getTmpFile( file.getPath() ) : null;
570
571 Wagon wagon = pollWagon();
572
573 try
574 {
575 if ( file == null )
576 {
577 if ( !wagon.resourceExists( path ) )
578 {
579 throw new ResourceDoesNotExistException( "Could not find " + path + " in "
580 + wagonRepo.getUrl() );
581 }
582 }
583 else
584 {
585 for ( int trial = 1; trial >= 0; trial-- )
586 {
587 ChecksumObserver sha1 = new ChecksumObserver( "SHA-1" );
588 ChecksumObserver md5 = new ChecksumObserver( "MD5" );
589 try
590 {
591 wagon.addTransferListener( wagonListener );
592 wagon.addTransferListener( md5 );
593 wagon.addTransferListener( sha1 );
594
595
596
597
598
599 fileProcessor.mkdirs( tmp.getParentFile() );
600
601 wagon.get( path, tmp );
602 }
603 finally
604 {
605 wagon.removeTransferListener( wagonListener );
606 wagon.removeTransferListener( md5 );
607 wagon.removeTransferListener( sha1 );
608 }
609
610 if ( RepositoryPolicy.CHECKSUM_POLICY_IGNORE.equals( checksumPolicy ) )
611 {
612 break;
613 }
614 else
615 {
616 try
617 {
618 if ( !verifyChecksum( wagon, sha1.getActualChecksum(), ".sha1" )
619 && !verifyChecksum( wagon, md5.getActualChecksum(), ".md5" ) )
620 {
621 trial = 0;
622 throw new ChecksumFailureException( "Checksum validation failed"
623 + ", no checksums available from the repository" );
624 }
625 break;
626 }
627 catch ( ChecksumFailureException e )
628 {
629 if ( trial <= 0 && RepositoryPolicy.CHECKSUM_POLICY_FAIL.equals( checksumPolicy ) )
630 {
631 throw e;
632 }
633 if ( listener != null )
634 {
635 DefaultTransferEvent event = wagonListener.newEvent();
636 event.setRequestType( TransferEvent.RequestType.GET );
637 event.setType( TransferEvent.EventType.CORRUPTED );
638 event.setException( e );
639 listener.transferCorrupted( event );
640 }
641 }
642 }
643 }
644
645 rename( tmp, file );
646 }
647
648 wrapper.wrap( download, null, repository );
649
650 if ( listener != null )
651 {
652 DefaultTransferEvent event = wagonListener.newEvent();
653 event.setRequestType( TransferEvent.RequestType.GET );
654 event.setType( TransferEvent.EventType.SUCCEEDED );
655 listener.transferSucceeded( event );
656 }
657 }
658 finally
659 {
660 if ( tmp != null )
661 {
662 tmp.delete();
663 }
664 wagons.add( wagon );
665 }
666 }
667 catch ( Exception e )
668 {
669 e = wrapper.wrap( download, e, repository );
670
671 if ( listener != null )
672 {
673 DefaultTransferEvent event = wagonListener.newEvent();
674 event.setRequestType( TransferEvent.RequestType.GET );
675 event.setType( TransferEvent.EventType.FAILED );
676 event.setException( e );
677 listener.transferFailed( event );
678 }
679 }
680 finally
681 {
682 download.setState( Transfer.State.DONE );
683 }
684 }
685
686 private boolean verifyChecksum( Wagon wagon, String actual, String ext )
687 throws ChecksumFailureException
688 {
689 File tmp = getTmpFile( file.getPath() + ext );
690
691 try
692 {
693 try
694 {
695 wagon.get( path + ext, tmp );
696 }
697 catch ( ResourceDoesNotExistException e )
698 {
699 return false;
700 }
701 catch ( WagonException e )
702 {
703 throw new ChecksumFailureException( e );
704 }
705
706 String expected;
707
708 try
709 {
710 expected = ChecksumUtils.read( tmp );
711 }
712 catch ( IOException e )
713 {
714 throw new ChecksumFailureException( e );
715 }
716
717 if ( expected.equalsIgnoreCase( actual ) )
718 {
719 try
720 {
721 rename( tmp, new File( file.getPath() + ext ) );
722 }
723 catch ( IOException e )
724 {
725 logger.debug( "Failed to write checksum file " + file.getPath() + ext + ": " + e.getMessage(),
726 e );
727 }
728 }
729 else
730 {
731 throw new ChecksumFailureException( expected, actual );
732 }
733 }
734 finally
735 {
736 tmp.delete();
737 }
738
739 return true;
740 }
741
742 private void rename( File from, File to )
743 throws IOException
744 {
745 if ( !from.exists() )
746 {
747
748
749
750
751
752 fileProcessor.write( to, "" );
753 }
754 else
755 {
756 fileProcessor.move( from, to );
757 }
758 }
759
760 }
761
762 class PutTask<T extends Transfer>
763 implements Runnable
764 {
765
766 private final T upload;
767
768 private final ExceptionWrapper<T> wrapper;
769
770 private final String path;
771
772 private final File file;
773
774 public PutTask( String path, File file, T upload, ExceptionWrapper<T> wrapper )
775 {
776 this.path = path;
777 this.file = file;
778 this.upload = upload;
779 this.wrapper = wrapper;
780 }
781
782 public void run()
783 {
784 upload.setState( Transfer.State.ACTIVE );
785
786 WagonTransferListenerAdapter wagonListener = null;
787 if ( listener != null )
788 {
789 wagonListener =
790 new WagonTransferListenerAdapter( listener, wagonRepo.getUrl(), path, file, upload.getTrace() );
791 }
792
793 try
794 {
795 if ( listener != null )
796 {
797 DefaultTransferEvent event = wagonListener.newEvent();
798 event.setRequestType( TransferEvent.RequestType.PUT );
799 event.setType( TransferEvent.EventType.INITIATED );
800 listener.transferInitiated( event );
801 }
802
803 Wagon wagon = pollWagon();
804
805 try
806 {
807 try
808 {
809 wagon.addTransferListener( wagonListener );
810
811 wagon.put( file, path );
812 }
813 finally
814 {
815 wagon.removeTransferListener( wagonListener );
816 }
817
818 uploadChecksums( wagon, file, path );
819
820 wrapper.wrap( upload, null, repository );
821
822 if ( listener != null )
823 {
824 DefaultTransferEvent event = wagonListener.newEvent();
825 event.setRequestType( TransferEvent.RequestType.PUT );
826 event.setType( TransferEvent.EventType.SUCCEEDED );
827 listener.transferSucceeded( event );
828 }
829 }
830 finally
831 {
832 wagons.add( wagon );
833 }
834 }
835 catch ( Exception e )
836 {
837 e = wrapper.wrap( upload, e, repository );
838
839 if ( listener != null )
840 {
841 DefaultTransferEvent event = wagonListener.newEvent();
842 event.setRequestType( TransferEvent.RequestType.PUT );
843 event.setType( TransferEvent.EventType.FAILED );
844 event.setException( e );
845 listener.transferFailed( event );
846 }
847 }
848 finally
849 {
850 upload.setState( Transfer.State.DONE );
851 }
852 }
853
854 private void uploadChecksums( Wagon wagon, File file, String path )
855 {
856 try
857 {
858 Map<String, Object> checksums = ChecksumUtils.calc( file, checksumAlgos.keySet() );
859 for ( Map.Entry<String, Object> entry : checksums.entrySet() )
860 {
861 uploadChecksum( wagon, file, path, entry.getKey(), entry.getValue() );
862 }
863 }
864 catch ( IOException e )
865 {
866 logger.debug( "Failed to upload checksums for " + file + ": " + e.getMessage(), e );
867 }
868 }
869
870 private void uploadChecksum( Wagon wagon, File file, String path, String algo, Object checksum )
871 {
872 try
873 {
874 if ( checksum instanceof Exception )
875 {
876 throw (Exception) checksum;
877 }
878
879 String ext = checksumAlgos.get( algo );
880 String dst = path + ext;
881 String sum = String.valueOf( checksum );
882
883 if ( wagon instanceof StreamingWagon )
884 {
885 byte[] data = sum.getBytes( "UTF-8" );
886 ( (StreamingWagon) wagon ).putFromStream( new ByteArrayInputStream( data ), dst, data.length, -1 );
887 }
888 else
889 {
890 File tmpFile = File.createTempFile( "wagon" + UUID.randomUUID().toString().replace( "-", "" ), ext );
891 try
892 {
893 fileProcessor.write( tmpFile, sum );
894 wagon.put( tmpFile, dst );
895 }
896 finally
897 {
898 tmpFile.delete();
899 }
900 }
901 }
902 catch ( Exception e )
903 {
904 logger.warn( "Failed to upload " + algo + " checksum for " + file + ": " + e.getMessage(), e );
905 }
906 }
907
908 }
909
910 static interface ExceptionWrapper<T>
911 {
912
913 Exception wrap( T transfer, Exception e, RemoteRepository repository );
914
915 }
916
917 private static final ExceptionWrapper<MetadataTransfer> METADATA = new ExceptionWrapper<MetadataTransfer>()
918 {
919
920 public Exception wrap( MetadataTransfer transfer, Exception e, RemoteRepository repository )
921 {
922 MetadataTransferException ex = null;
923 e = WagonCancelledException.unwrap( e );
924 if ( e instanceof ResourceDoesNotExistException )
925 {
926 ex = new MetadataNotFoundException( transfer.getMetadata(), repository );
927 }
928 else if ( e != null )
929 {
930 ex = new MetadataTransferException( transfer.getMetadata(), repository, e );
931 }
932 transfer.setException( ex );
933 return ex;
934 }
935
936 };
937
938 private static final ExceptionWrapper<ArtifactTransfer> ARTIFACT = new ExceptionWrapper<ArtifactTransfer>()
939 {
940
941 public Exception wrap( ArtifactTransfer transfer, Exception e, RemoteRepository repository )
942 {
943 ArtifactTransferException ex = null;
944 e = WagonCancelledException.unwrap( e );
945 if ( e instanceof ResourceDoesNotExistException )
946 {
947 ex = new ArtifactNotFoundException( transfer.getArtifact(), repository );
948 }
949 else if ( e != null )
950 {
951 ex = new ArtifactTransferException( transfer.getArtifact(), repository, e );
952 }
953 transfer.setException( ex );
954 return ex;
955 }
956
957 };
958
959 }