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 static java.util.Objects.requireNonNull;
23
24 import java.io.File;
25 import java.io.InputStream;
26 import java.util.ArrayList;
27 import java.util.Collection;
28 import java.util.IdentityHashMap;
29 import java.util.List;
30 import java.util.ListIterator;
31 import java.util.Set;
32
33 import javax.inject.Inject;
34 import javax.inject.Named;
35 import javax.inject.Singleton;
36
37 import org.eclipse.aether.RepositoryEvent;
38 import org.eclipse.aether.RepositoryEvent.EventType;
39 import org.eclipse.aether.RepositorySystemSession;
40 import org.eclipse.aether.RequestTrace;
41 import org.eclipse.aether.SyncContext;
42 import org.eclipse.aether.artifact.Artifact;
43 import org.eclipse.aether.impl.Installer;
44 import org.eclipse.aether.impl.MetadataGenerator;
45 import org.eclipse.aether.impl.MetadataGeneratorFactory;
46 import org.eclipse.aether.impl.RepositoryEventDispatcher;
47 import org.eclipse.aether.spi.synccontext.SyncContextFactory;
48 import org.eclipse.aether.installation.InstallRequest;
49 import org.eclipse.aether.installation.InstallResult;
50 import org.eclipse.aether.installation.InstallationException;
51 import org.eclipse.aether.metadata.MergeableMetadata;
52 import org.eclipse.aether.metadata.Metadata;
53 import org.eclipse.aether.repository.LocalArtifactRegistration;
54 import org.eclipse.aether.repository.LocalMetadataRegistration;
55 import org.eclipse.aether.repository.LocalRepositoryManager;
56 import org.eclipse.aether.spi.io.FileProcessor;
57 import org.eclipse.aether.spi.locator.Service;
58 import org.eclipse.aether.spi.locator.ServiceLocator;
59 import org.eclipse.aether.transform.FileTransformer;
60 import org.slf4j.Logger;
61 import org.slf4j.LoggerFactory;
62
63
64
65 @Singleton
66 @Named
67 public class DefaultInstaller
68 implements Installer, Service
69 {
70
71 private static final Logger LOGGER = LoggerFactory.getLogger( DefaultInstaller.class );
72
73 private FileProcessor fileProcessor;
74
75 private RepositoryEventDispatcher repositoryEventDispatcher;
76
77 private Collection<MetadataGeneratorFactory> metadataFactories = new ArrayList<>();
78
79 private SyncContextFactory syncContextFactory;
80
81 public DefaultInstaller()
82 {
83
84 }
85
86 @Inject
87 DefaultInstaller( FileProcessor fileProcessor, RepositoryEventDispatcher repositoryEventDispatcher,
88 Set<MetadataGeneratorFactory> metadataFactories, SyncContextFactory syncContextFactory )
89 {
90 setFileProcessor( fileProcessor );
91 setRepositoryEventDispatcher( repositoryEventDispatcher );
92 setMetadataGeneratorFactories( metadataFactories );
93 setSyncContextFactory( syncContextFactory );
94 }
95
96 public void initService( ServiceLocator locator )
97 {
98 setFileProcessor( locator.getService( FileProcessor.class ) );
99 setRepositoryEventDispatcher( locator.getService( RepositoryEventDispatcher.class ) );
100 setMetadataGeneratorFactories( locator.getServices( MetadataGeneratorFactory.class ) );
101 setSyncContextFactory( locator.getService( SyncContextFactory.class ) );
102 }
103
104 public DefaultInstaller setFileProcessor( FileProcessor fileProcessor )
105 {
106 this.fileProcessor = requireNonNull( fileProcessor, "file processor cannot be null" );
107 return this;
108 }
109
110 public DefaultInstaller setRepositoryEventDispatcher( RepositoryEventDispatcher repositoryEventDispatcher )
111 {
112 this.repositoryEventDispatcher = requireNonNull( repositoryEventDispatcher,
113 "repository event dispatcher cannot be null" );
114 return this;
115 }
116
117 public DefaultInstaller addMetadataGeneratorFactory( MetadataGeneratorFactory factory )
118 {
119 metadataFactories.add( requireNonNull( factory, "metadata generator factory cannot be null" ) );
120 return this;
121 }
122
123 public DefaultInstaller setMetadataGeneratorFactories( Collection<MetadataGeneratorFactory> metadataFactories )
124 {
125 if ( metadataFactories == null )
126 {
127 this.metadataFactories = new ArrayList<>();
128 }
129 else
130 {
131 this.metadataFactories = metadataFactories;
132 }
133 return this;
134 }
135
136 public DefaultInstaller setSyncContextFactory( SyncContextFactory syncContextFactory )
137 {
138 this.syncContextFactory = requireNonNull( syncContextFactory, "sync context factory cannot be null" );
139 return this;
140 }
141
142 public InstallResult install( RepositorySystemSession session, InstallRequest request )
143 throws InstallationException
144 {
145
146 try ( SyncContext syncContext = syncContextFactory.newInstance( session, false ) )
147 {
148 return install( syncContext, session, request );
149 }
150 }
151
152 private InstallResult install( SyncContext syncContext, RepositorySystemSession session, InstallRequest request )
153 throws InstallationException
154 {
155 InstallResult result = new InstallResult( request );
156
157 RequestTrace trace = RequestTrace.newChild( request.getTrace(), request );
158
159 List<? extends MetadataGenerator> generators = getMetadataGenerators( session, request );
160
161 List<Artifact> artifacts = new ArrayList<>( request.getArtifacts() );
162
163 IdentityHashMap<Metadata, Object> processedMetadata = new IdentityHashMap<>();
164
165 List<Metadata> metadatas = Utils.prepareMetadata( generators, artifacts );
166
167 syncContext.acquire( artifacts, Utils.combine( request.getMetadata(), metadatas ) );
168
169 for ( Metadata metadata : metadatas )
170 {
171 install( session, trace, metadata );
172 processedMetadata.put( metadata, null );
173 result.addMetadata( metadata );
174 }
175
176 for ( ListIterator<Artifact> iterator = artifacts.listIterator(); iterator.hasNext(); )
177 {
178 Artifact artifact = iterator.next();
179
180 for ( MetadataGenerator generator : generators )
181 {
182 artifact = generator.transformArtifact( artifact );
183 }
184
185 iterator.set( artifact );
186
187 install( session, trace, artifact );
188 result.addArtifact( artifact );
189 }
190
191 metadatas = Utils.finishMetadata( generators, artifacts );
192
193 syncContext.acquire( null, metadatas );
194
195 for ( Metadata metadata : metadatas )
196 {
197 install( session, trace, metadata );
198 processedMetadata.put( metadata, null );
199 result.addMetadata( metadata );
200 }
201
202 for ( Metadata metadata : request.getMetadata() )
203 {
204 if ( !processedMetadata.containsKey( metadata ) )
205 {
206 install( session, trace, metadata );
207 result.addMetadata( metadata );
208 }
209 }
210
211 return result;
212 }
213
214 private List<? extends MetadataGenerator> getMetadataGenerators( RepositorySystemSession session,
215 InstallRequest request )
216 {
217 PrioritizedComponents<MetadataGeneratorFactory> factories =
218 Utils.sortMetadataGeneratorFactories( session, this.metadataFactories );
219
220 List<MetadataGenerator> generators = new ArrayList<>();
221
222 for ( PrioritizedComponent<MetadataGeneratorFactory> factory : factories.getEnabled() )
223 {
224 MetadataGenerator generator = factory.getComponent().newInstance( session, request );
225 if ( generator != null )
226 {
227 generators.add( generator );
228 }
229 }
230
231 return generators;
232 }
233
234 private void install( RepositorySystemSession session, RequestTrace trace, Artifact artifact )
235 throws InstallationException
236 {
237 LocalRepositoryManager lrm = session.getLocalRepositoryManager();
238
239 File srcFile = artifact.getFile();
240
241 Collection<FileTransformer> fileTransformers = session.getFileTransformerManager()
242 .getTransformersForArtifact( artifact );
243 if ( fileTransformers.isEmpty() )
244 {
245 install( session, trace, artifact, lrm, srcFile, null );
246 }
247 else
248 {
249 for ( FileTransformer fileTransformer : fileTransformers )
250 {
251 install( session, trace, artifact, lrm, srcFile, fileTransformer );
252 }
253 }
254 }
255
256 private void install( RepositorySystemSession session, RequestTrace trace, Artifact artifact,
257 LocalRepositoryManager lrm, File srcFile, FileTransformer fileTransformer )
258 throws InstallationException
259 {
260 final Artifact targetArtifact;
261 if ( fileTransformer != null )
262 {
263 targetArtifact = fileTransformer.transformArtifact( artifact );
264 }
265 else
266 {
267 targetArtifact = artifact;
268 }
269
270 File dstFile = new File( lrm.getRepository().getBasedir(), lrm.getPathForLocalArtifact( targetArtifact ) );
271
272 artifactInstalling( session, trace, targetArtifact, dstFile );
273
274 Exception exception = null;
275 try
276 {
277 if ( dstFile.equals( srcFile ) )
278 {
279 throw new IllegalStateException( "cannot install " + dstFile + " to same path" );
280 }
281
282 boolean copy =
283 "pom".equals( targetArtifact.getExtension() ) || srcFile.lastModified() != dstFile.lastModified()
284 || srcFile.length() != dstFile.length() || !srcFile.exists();
285
286 if ( !copy )
287 {
288 LOGGER.debug( "Skipped re-installing {} to {}, seems unchanged", srcFile, dstFile );
289 }
290 else if ( fileTransformer != null )
291 {
292 try ( InputStream is = fileTransformer.transformData( srcFile ) )
293 {
294 fileProcessor.write( dstFile, is );
295 dstFile.setLastModified( srcFile.lastModified() );
296 }
297 }
298 else
299 {
300 fileProcessor.copy( srcFile, dstFile );
301 dstFile.setLastModified( srcFile.lastModified() );
302 }
303
304 lrm.add( session, new LocalArtifactRegistration( targetArtifact ) );
305 }
306 catch ( Exception e )
307 {
308 exception = e;
309 throw new InstallationException( "Failed to install artifact " + targetArtifact + ": " + e.getMessage(),
310 e );
311 }
312 finally
313 {
314 artifactInstalled( session, trace, targetArtifact, dstFile, exception );
315 }
316 }
317
318 private void install( RepositorySystemSession session, RequestTrace trace, Metadata metadata )
319 throws InstallationException
320 {
321 LocalRepositoryManager lrm = session.getLocalRepositoryManager();
322
323 File dstFile = new File( lrm.getRepository().getBasedir(), lrm.getPathForLocalMetadata( metadata ) );
324
325 metadataInstalling( session, trace, metadata, dstFile );
326
327 Exception exception = null;
328 try
329 {
330 if ( metadata instanceof MergeableMetadata )
331 {
332 ( (MergeableMetadata) metadata ).merge( dstFile, dstFile );
333 }
334 else
335 {
336 if ( dstFile.equals( metadata.getFile() ) )
337 {
338 throw new IllegalStateException( "cannot install " + dstFile + " to same path" );
339 }
340 fileProcessor.copy( metadata.getFile(), dstFile );
341 }
342
343 lrm.add( session, new LocalMetadataRegistration( metadata ) );
344 }
345 catch ( Exception e )
346 {
347 exception = e;
348 throw new InstallationException( "Failed to install metadata " + metadata + ": " + e.getMessage(), e );
349 }
350 finally
351 {
352 metadataInstalled( session, trace, metadata, dstFile, exception );
353 }
354 }
355
356 private void artifactInstalling( RepositorySystemSession session, RequestTrace trace, Artifact artifact,
357 File dstFile )
358 {
359 RepositoryEvent.Builder event = new RepositoryEvent.Builder( session, EventType.ARTIFACT_INSTALLING );
360 event.setTrace( trace );
361 event.setArtifact( artifact );
362 event.setRepository( session.getLocalRepositoryManager().getRepository() );
363 event.setFile( dstFile );
364
365 repositoryEventDispatcher.dispatch( event.build() );
366 }
367
368 private void artifactInstalled( RepositorySystemSession session, RequestTrace trace, Artifact artifact,
369 File dstFile, Exception exception )
370 {
371 RepositoryEvent.Builder event = new RepositoryEvent.Builder( session, EventType.ARTIFACT_INSTALLED );
372 event.setTrace( trace );
373 event.setArtifact( artifact );
374 event.setRepository( session.getLocalRepositoryManager().getRepository() );
375 event.setFile( dstFile );
376 event.setException( exception );
377
378 repositoryEventDispatcher.dispatch( event.build() );
379 }
380
381 private void metadataInstalling( RepositorySystemSession session, RequestTrace trace, Metadata metadata,
382 File dstFile )
383 {
384 RepositoryEvent.Builder event = new RepositoryEvent.Builder( session, EventType.METADATA_INSTALLING );
385 event.setTrace( trace );
386 event.setMetadata( metadata );
387 event.setRepository( session.getLocalRepositoryManager().getRepository() );
388 event.setFile( dstFile );
389
390 repositoryEventDispatcher.dispatch( event.build() );
391 }
392
393 private void metadataInstalled( RepositorySystemSession session, RequestTrace trace, Metadata metadata,
394 File dstFile, Exception exception )
395 {
396 RepositoryEvent.Builder event = new RepositoryEvent.Builder( session, EventType.METADATA_INSTALLED );
397 event.setTrace( trace );
398 event.setMetadata( metadata );
399 event.setRepository( session.getLocalRepositoryManager().getRepository() );
400 event.setFile( dstFile );
401 event.setException( exception );
402
403 repositoryEventDispatcher.dispatch( event.build() );
404 }
405
406 }