1 package org.eclipse.aether.internal.impl;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.File;
23 import java.io.IOException;
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.Collection;
27 import java.util.IdentityHashMap;
28 import java.util.List;
29 import static java.util.Objects.requireNonNull;
30 import java.util.Set;
31
32 import javax.inject.Inject;
33 import javax.inject.Named;
34
35 import org.eclipse.aether.RepositoryEvent;
36 import org.eclipse.aether.RepositoryEvent.EventType;
37 import org.eclipse.aether.RepositoryException;
38 import org.eclipse.aether.RepositorySystemSession;
39 import org.eclipse.aether.RequestTrace;
40 import org.eclipse.aether.SyncContext;
41 import org.eclipse.aether.artifact.Artifact;
42 import org.eclipse.aether.deployment.DeployRequest;
43 import org.eclipse.aether.deployment.DeployResult;
44 import org.eclipse.aether.deployment.DeploymentException;
45 import org.eclipse.aether.impl.Deployer;
46 import org.eclipse.aether.impl.MetadataGenerator;
47 import org.eclipse.aether.impl.MetadataGeneratorFactory;
48 import org.eclipse.aether.impl.OfflineController;
49 import org.eclipse.aether.impl.RemoteRepositoryManager;
50 import org.eclipse.aether.impl.RepositoryConnectorProvider;
51 import org.eclipse.aether.impl.RepositoryEventDispatcher;
52 import org.eclipse.aether.impl.SyncContextFactory;
53 import org.eclipse.aether.impl.UpdateCheck;
54 import org.eclipse.aether.impl.UpdateCheckManager;
55 import org.eclipse.aether.metadata.MergeableMetadata;
56 import org.eclipse.aether.metadata.Metadata;
57 import org.eclipse.aether.repository.LocalRepositoryManager;
58 import org.eclipse.aether.repository.RemoteRepository;
59 import org.eclipse.aether.repository.RepositoryPolicy;
60 import org.eclipse.aether.spi.connector.ArtifactUpload;
61 import org.eclipse.aether.spi.connector.MetadataDownload;
62 import org.eclipse.aether.spi.connector.MetadataUpload;
63 import org.eclipse.aether.spi.connector.RepositoryConnector;
64 import org.eclipse.aether.spi.io.FileProcessor;
65 import org.eclipse.aether.spi.locator.Service;
66 import org.eclipse.aether.spi.locator.ServiceLocator;
67 import org.eclipse.aether.spi.log.Logger;
68 import org.eclipse.aether.spi.log.LoggerFactory;
69 import org.eclipse.aether.spi.log.NullLoggerFactory;
70 import org.eclipse.aether.transfer.ArtifactTransferException;
71 import org.eclipse.aether.transfer.MetadataNotFoundException;
72 import org.eclipse.aether.transfer.MetadataTransferException;
73 import org.eclipse.aether.transfer.NoRepositoryConnectorException;
74 import org.eclipse.aether.transfer.RepositoryOfflineException;
75 import org.eclipse.aether.transfer.TransferCancelledException;
76 import org.eclipse.aether.transfer.TransferEvent;
77
78
79
80 @Named
81 public class DefaultDeployer
82 implements Deployer, Service
83 {
84
85 private Logger logger = NullLoggerFactory.LOGGER;
86
87 private FileProcessor fileProcessor;
88
89 private RepositoryEventDispatcher repositoryEventDispatcher;
90
91 private RepositoryConnectorProvider repositoryConnectorProvider;
92
93 private RemoteRepositoryManager remoteRepositoryManager;
94
95 private UpdateCheckManager updateCheckManager;
96
97 private Collection<MetadataGeneratorFactory> metadataFactories = new ArrayList<MetadataGeneratorFactory>();
98
99 private SyncContextFactory syncContextFactory;
100
101 private OfflineController offlineController;
102
103 public DefaultDeployer()
104 {
105
106 }
107
108 @Inject
109 DefaultDeployer( FileProcessor fileProcessor, RepositoryEventDispatcher repositoryEventDispatcher,
110 RepositoryConnectorProvider repositoryConnectorProvider,
111 RemoteRepositoryManager remoteRepositoryManager, UpdateCheckManager updateCheckManager,
112 Set<MetadataGeneratorFactory> metadataFactories, SyncContextFactory syncContextFactory,
113 OfflineController offlineController, LoggerFactory loggerFactory )
114 {
115 setFileProcessor( fileProcessor );
116 setRepositoryEventDispatcher( repositoryEventDispatcher );
117 setRepositoryConnectorProvider( repositoryConnectorProvider );
118 setRemoteRepositoryManager( remoteRepositoryManager );
119 setUpdateCheckManager( updateCheckManager );
120 setMetadataGeneratorFactories( metadataFactories );
121 setSyncContextFactory( syncContextFactory );
122 setLoggerFactory( loggerFactory );
123 setOfflineController( offlineController );
124 }
125
126 public void initService( ServiceLocator locator )
127 {
128 setLoggerFactory( locator.getService( LoggerFactory.class ) );
129 setFileProcessor( locator.getService( FileProcessor.class ) );
130 setRepositoryEventDispatcher( locator.getService( RepositoryEventDispatcher.class ) );
131 setRepositoryConnectorProvider( locator.getService( RepositoryConnectorProvider.class ) );
132 setRemoteRepositoryManager( locator.getService( RemoteRepositoryManager.class ) );
133 setUpdateCheckManager( locator.getService( UpdateCheckManager.class ) );
134 setMetadataGeneratorFactories( locator.getServices( MetadataGeneratorFactory.class ) );
135 setSyncContextFactory( locator.getService( SyncContextFactory.class ) );
136 setOfflineController( locator.getService( OfflineController.class ) );
137 }
138
139 public DefaultDeployer setLoggerFactory( LoggerFactory loggerFactory )
140 {
141 this.logger = NullLoggerFactory.getSafeLogger( loggerFactory, getClass() );
142 return this;
143 }
144
145 public DefaultDeployer setFileProcessor( FileProcessor fileProcessor )
146 {
147 this.fileProcessor = requireNonNull( fileProcessor, "file processor cannot be null" );
148 return this;
149 }
150
151 public DefaultDeployer setRepositoryEventDispatcher( RepositoryEventDispatcher repositoryEventDispatcher )
152 {
153 this.repositoryEventDispatcher = requireNonNull( repositoryEventDispatcher, "repository event dispatcher cannot be null" );
154 return this;
155 }
156
157 public DefaultDeployer setRepositoryConnectorProvider( RepositoryConnectorProvider repositoryConnectorProvider )
158 {
159 this.repositoryConnectorProvider = requireNonNull( repositoryConnectorProvider, "repository connector provider cannot be null" );
160 return this;
161 }
162
163 public DefaultDeployer setRemoteRepositoryManager( RemoteRepositoryManager remoteRepositoryManager )
164 {
165 this.remoteRepositoryManager = requireNonNull( remoteRepositoryManager, "remote repository provider cannot be null" );
166 return this;
167 }
168
169 public DefaultDeployer setUpdateCheckManager( UpdateCheckManager updateCheckManager )
170 {
171 this.updateCheckManager = requireNonNull( updateCheckManager, "update check manager cannot be null" );
172 return this;
173 }
174
175 public DefaultDeployer addMetadataGeneratorFactory( MetadataGeneratorFactory factory )
176 {
177 metadataFactories.add( requireNonNull( factory, "metadata generator factory cannot be null" ) );
178 return this;
179 }
180
181 public DefaultDeployer setMetadataGeneratorFactories( Collection<MetadataGeneratorFactory> metadataFactories )
182 {
183 if ( metadataFactories == null )
184 {
185 this.metadataFactories = new ArrayList<MetadataGeneratorFactory>();
186 }
187 else
188 {
189 this.metadataFactories = metadataFactories;
190 }
191 return this;
192 }
193
194 public DefaultDeployer setSyncContextFactory( SyncContextFactory syncContextFactory )
195 {
196 this.syncContextFactory = requireNonNull( syncContextFactory, "sync context factory cannot be null" );
197 return this;
198 }
199
200 public DefaultDeployer setOfflineController( OfflineController offlineController )
201 {
202 this.offlineController = requireNonNull( offlineController, "offline controller cannot be null" );
203 return this;
204 }
205
206 public DeployResult deploy( RepositorySystemSession session, DeployRequest request )
207 throws DeploymentException
208 {
209 try
210 {
211 Utils.checkOffline( session, offlineController, request.getRepository() );
212 }
213 catch ( RepositoryOfflineException e )
214 {
215 throw new DeploymentException( "Cannot deploy while " + request.getRepository().getId() + " ("
216 + request.getRepository().getUrl() + ") is in offline mode", e );
217 }
218
219 SyncContext syncContext = syncContextFactory.newInstance( session, false );
220
221 try
222 {
223 return deploy( syncContext, session, request );
224 }
225 finally
226 {
227 syncContext.close();
228 }
229 }
230
231 private DeployResult deploy( SyncContext syncContext, RepositorySystemSession session, DeployRequest request )
232 throws DeploymentException
233 {
234 DeployResult result = new DeployResult( request );
235
236 RequestTrace trace = RequestTrace.newChild( request.getTrace(), request );
237
238 RemoteRepository repository = request.getRepository();
239
240 RepositoryConnector connector;
241 try
242 {
243 connector = repositoryConnectorProvider.newRepositoryConnector( session, repository );
244 }
245 catch ( NoRepositoryConnectorException e )
246 {
247 throw new DeploymentException( "Failed to deploy artifacts/metadata: " + e.getMessage(), e );
248 }
249
250 try
251 {
252 List<? extends MetadataGenerator> generators = getMetadataGenerators( session, request );
253
254 List<ArtifactUpload> artifactUploads = new ArrayList<ArtifactUpload>();
255 List<MetadataUpload> metadataUploads = new ArrayList<MetadataUpload>();
256 IdentityHashMap<Metadata, Object> processedMetadata = new IdentityHashMap<Metadata, Object>();
257
258 EventCatapult catapult = new EventCatapult( session, trace, repository, repositoryEventDispatcher );
259
260 List<Artifact> artifacts = new ArrayList<Artifact>( request.getArtifacts() );
261
262 List<Metadata> metadatas = Utils.prepareMetadata( generators, artifacts );
263
264 syncContext.acquire( artifacts, Utils.combine( request.getMetadata(), metadatas ) );
265
266 for ( Metadata metadata : metadatas )
267 {
268 upload( metadataUploads, session, metadata, repository, connector, catapult );
269 processedMetadata.put( metadata, null );
270 }
271
272 for ( int i = 0; i < artifacts.size(); i++ )
273 {
274 Artifact artifact = artifacts.get( i );
275
276 for ( MetadataGenerator generator : generators )
277 {
278 artifact = generator.transformArtifact( artifact );
279 }
280
281 artifacts.set( i, artifact );
282
283 ArtifactUpload upload = new ArtifactUpload( artifact, artifact.getFile() );
284 upload.setTrace( trace );
285 upload.setListener( new ArtifactUploadListener( catapult, upload, logger ) );
286 artifactUploads.add( upload );
287 }
288
289 connector.put( artifactUploads, null );
290
291 for ( ArtifactUpload upload : artifactUploads )
292 {
293 if ( upload.getException() != null )
294 {
295 throw new DeploymentException( "Failed to deploy artifacts: " + upload.getException().getMessage(),
296 upload.getException() );
297 }
298 result.addArtifact( upload.getArtifact() );
299 }
300
301 metadatas = Utils.finishMetadata( generators, artifacts );
302
303 syncContext.acquire( null, metadatas );
304
305 for ( Metadata metadata : metadatas )
306 {
307 upload( metadataUploads, session, metadata, repository, connector, catapult );
308 processedMetadata.put( metadata, null );
309 }
310
311 for ( Metadata metadata : request.getMetadata() )
312 {
313 if ( !processedMetadata.containsKey( metadata ) )
314 {
315 upload( metadataUploads, session, metadata, repository, connector, catapult );
316 processedMetadata.put( metadata, null );
317 }
318 }
319
320 connector.put( null, metadataUploads );
321
322 for ( MetadataUpload upload : metadataUploads )
323 {
324 if ( upload.getException() != null )
325 {
326 throw new DeploymentException( "Failed to deploy metadata: " + upload.getException().getMessage(),
327 upload.getException() );
328 }
329 result.addMetadata( upload.getMetadata() );
330 }
331 }
332 finally
333 {
334 connector.close();
335 }
336
337 return result;
338 }
339
340 private List<? extends MetadataGenerator> getMetadataGenerators( RepositorySystemSession session,
341 DeployRequest request )
342 {
343 PrioritizedComponents<MetadataGeneratorFactory> factories =
344 Utils.sortMetadataGeneratorFactories( session, this.metadataFactories );
345
346 List<MetadataGenerator> generators = new ArrayList<MetadataGenerator>();
347
348 for ( PrioritizedComponent<MetadataGeneratorFactory> factory : factories.getEnabled() )
349 {
350 MetadataGenerator generator = factory.getComponent().newInstance( session, request );
351 if ( generator != null )
352 {
353 generators.add( generator );
354 }
355 }
356
357 return generators;
358 }
359
360 private void upload( Collection<MetadataUpload> metadataUploads, RepositorySystemSession session,
361 Metadata metadata, RemoteRepository repository, RepositoryConnector connector,
362 EventCatapult catapult )
363 throws DeploymentException
364 {
365 LocalRepositoryManager lrm = session.getLocalRepositoryManager();
366 File basedir = lrm.getRepository().getBasedir();
367
368 File dstFile = new File( basedir, lrm.getPathForRemoteMetadata( metadata, repository, "" ) );
369
370 if ( metadata instanceof MergeableMetadata )
371 {
372 if ( !( (MergeableMetadata) metadata ).isMerged() )
373 {
374 {
375 RepositoryEvent.Builder event = new RepositoryEvent.Builder( session, EventType.METADATA_RESOLVING );
376 event.setTrace( catapult.getTrace() );
377 event.setMetadata( metadata );
378 event.setRepository( repository );
379 repositoryEventDispatcher.dispatch( event.build() );
380
381 event = new RepositoryEvent.Builder( session, EventType.METADATA_DOWNLOADING );
382 event.setTrace( catapult.getTrace() );
383 event.setMetadata( metadata );
384 event.setRepository( repository );
385 repositoryEventDispatcher.dispatch( event.build() );
386 }
387
388 RepositoryPolicy policy = getPolicy( session, repository, metadata.getNature() );
389 MetadataDownload download = new MetadataDownload();
390 download.setMetadata( metadata );
391 download.setFile( dstFile );
392 download.setChecksumPolicy( policy.getChecksumPolicy() );
393 download.setListener( SafeTransferListener.wrap( session, logger ) );
394 download.setTrace( catapult.getTrace() );
395 connector.get( null, Arrays.asList( download ) );
396
397 Exception error = download.getException();
398
399 if ( error instanceof MetadataNotFoundException )
400 {
401 dstFile.delete();
402 }
403
404 {
405 RepositoryEvent.Builder event =
406 new RepositoryEvent.Builder( session, EventType.METADATA_DOWNLOADED );
407 event.setTrace( catapult.getTrace() );
408 event.setMetadata( metadata );
409 event.setRepository( repository );
410 event.setException( error );
411 event.setFile( dstFile );
412 repositoryEventDispatcher.dispatch( event.build() );
413
414 event = new RepositoryEvent.Builder( session, EventType.METADATA_RESOLVED );
415 event.setTrace( catapult.getTrace() );
416 event.setMetadata( metadata );
417 event.setRepository( repository );
418 event.setException( error );
419 event.setFile( dstFile );
420 repositoryEventDispatcher.dispatch( event.build() );
421 }
422
423 if ( error != null && !( error instanceof MetadataNotFoundException ) )
424 {
425 throw new DeploymentException( "Failed to retrieve remote metadata " + metadata + ": "
426 + error.getMessage(), error );
427 }
428 }
429
430 try
431 {
432 ( (MergeableMetadata) metadata ).merge( dstFile, dstFile );
433 }
434 catch ( RepositoryException e )
435 {
436 throw new DeploymentException( "Failed to update metadata " + metadata + ": " + e.getMessage(), e );
437 }
438 }
439 else
440 {
441 if ( metadata.getFile() == null )
442 {
443 throw new DeploymentException( "Failed to update metadata " + metadata + ": No file attached." );
444 }
445 try
446 {
447 fileProcessor.copy( metadata.getFile(), dstFile );
448 }
449 catch ( IOException e )
450 {
451 throw new DeploymentException( "Failed to update metadata " + metadata + ": " + e.getMessage(), e );
452 }
453 }
454
455 UpdateCheck<Metadata, MetadataTransferException> check = new UpdateCheck<Metadata, MetadataTransferException>();
456 check.setItem( metadata );
457 check.setFile( dstFile );
458 check.setRepository( repository );
459 check.setAuthoritativeRepository( repository );
460 updateCheckManager.touchMetadata( session, check );
461
462 MetadataUpload upload = new MetadataUpload( metadata, dstFile );
463 upload.setTrace( catapult.getTrace() );
464 upload.setListener( new MetadataUploadListener( catapult, upload, logger ) );
465 metadataUploads.add( upload );
466 }
467
468 private RepositoryPolicy getPolicy( RepositorySystemSession session, RemoteRepository repository,
469 Metadata.Nature nature )
470 {
471 boolean releases = !Metadata.Nature.SNAPSHOT.equals( nature );
472 boolean snapshots = !Metadata.Nature.RELEASE.equals( nature );
473 return remoteRepositoryManager.getPolicy( session, repository, releases, snapshots );
474 }
475
476 static final class EventCatapult
477 {
478
479 private final RepositorySystemSession session;
480
481 private final RequestTrace trace;
482
483 private final RemoteRepository repository;
484
485 private final RepositoryEventDispatcher dispatcher;
486
487 EventCatapult( RepositorySystemSession session, RequestTrace trace, RemoteRepository repository,
488 RepositoryEventDispatcher dispatcher )
489 {
490 this.session = session;
491 this.trace = trace;
492 this.repository = repository;
493 this.dispatcher = dispatcher;
494 }
495
496 public RepositorySystemSession getSession()
497 {
498 return session;
499 }
500
501 public RequestTrace getTrace()
502 {
503 return trace;
504 }
505
506 public void artifactDeploying( Artifact artifact, File file )
507 {
508 RepositoryEvent.Builder event = new RepositoryEvent.Builder( session, EventType.ARTIFACT_DEPLOYING );
509 event.setTrace( trace );
510 event.setArtifact( artifact );
511 event.setRepository( repository );
512 event.setFile( file );
513
514 dispatcher.dispatch( event.build() );
515 }
516
517 public void artifactDeployed( Artifact artifact, File file, ArtifactTransferException exception )
518 {
519 RepositoryEvent.Builder event = new RepositoryEvent.Builder( session, EventType.ARTIFACT_DEPLOYED );
520 event.setTrace( trace );
521 event.setArtifact( artifact );
522 event.setRepository( repository );
523 event.setFile( file );
524 event.setException( exception );
525
526 dispatcher.dispatch( event.build() );
527 }
528
529 public void metadataDeploying( Metadata metadata, File file )
530 {
531 RepositoryEvent.Builder event = new RepositoryEvent.Builder( session, EventType.METADATA_DEPLOYING );
532 event.setTrace( trace );
533 event.setMetadata( metadata );
534 event.setRepository( repository );
535 event.setFile( file );
536
537 dispatcher.dispatch( event.build() );
538 }
539
540 public void metadataDeployed( Metadata metadata, File file, Exception exception )
541 {
542 RepositoryEvent.Builder event = new RepositoryEvent.Builder( session, EventType.METADATA_DEPLOYED );
543 event.setTrace( trace );
544 event.setMetadata( metadata );
545 event.setRepository( repository );
546 event.setFile( file );
547 event.setException( exception );
548
549 dispatcher.dispatch( event.build() );
550 }
551
552 }
553
554 static final class ArtifactUploadListener
555 extends SafeTransferListener
556 {
557
558 private final EventCatapult catapult;
559
560 private final ArtifactUpload transfer;
561
562 ArtifactUploadListener( EventCatapult catapult, ArtifactUpload transfer, Logger logger )
563 {
564 super( catapult.getSession(), logger );
565 this.catapult = catapult;
566 this.transfer = transfer;
567 }
568
569 @Override
570 public void transferInitiated( TransferEvent event )
571 throws TransferCancelledException
572 {
573 super.transferInitiated( event );
574 catapult.artifactDeploying( transfer.getArtifact(), transfer.getFile() );
575 }
576
577 @Override
578 public void transferFailed( TransferEvent event )
579 {
580 super.transferFailed( event );
581 catapult.artifactDeployed( transfer.getArtifact(), transfer.getFile(), transfer.getException() );
582 }
583
584 @Override
585 public void transferSucceeded( TransferEvent event )
586 {
587 super.transferSucceeded( event );
588 catapult.artifactDeployed( transfer.getArtifact(), transfer.getFile(), null );
589 }
590
591 }
592
593 static final class MetadataUploadListener
594 extends SafeTransferListener
595 {
596
597 private final EventCatapult catapult;
598
599 private final MetadataUpload transfer;
600
601 MetadataUploadListener( EventCatapult catapult, MetadataUpload transfer, Logger logger )
602 {
603 super( catapult.getSession(), logger );
604 this.catapult = catapult;
605 this.transfer = transfer;
606 }
607
608 @Override
609 public void transferInitiated( TransferEvent event )
610 throws TransferCancelledException
611 {
612 super.transferInitiated( event );
613 catapult.metadataDeploying( transfer.getMetadata(), transfer.getFile() );
614 }
615
616 @Override
617 public void transferFailed( TransferEvent event )
618 {
619 super.transferFailed( event );
620 catapult.metadataDeployed( transfer.getMetadata(), transfer.getFile(), transfer.getException() );
621 }
622
623 @Override
624 public void transferSucceeded( TransferEvent event )
625 {
626 super.transferSucceeded( event );
627 catapult.metadataDeployed( transfer.getMetadata(), transfer.getFile(), null );
628 }
629
630 }
631
632 }