View Javadoc
1   package org.eclipse.aether.internal.impl;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   * 
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   * 
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import 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          // enables default constructor
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         requireNonNull( session, "session cannot be null" );
146         requireNonNull( request, "request cannot be null" );
147         try ( SyncContext syncContext = syncContextFactory.newInstance( session, false ) )
148         {
149             return install( syncContext, session, request );
150         }
151     }
152 
153     private InstallResult install( SyncContext syncContext, RepositorySystemSession session, InstallRequest request )
154         throws InstallationException
155     {
156         InstallResult result = new InstallResult( request );
157 
158         RequestTrace trace = RequestTrace.newChild( request.getTrace(), request );
159 
160         List<? extends MetadataGenerator> generators = getMetadataGenerators( session, request );
161 
162         List<Artifact> artifacts = new ArrayList<>( request.getArtifacts() );
163 
164         IdentityHashMap<Metadata, Object> processedMetadata = new IdentityHashMap<>();
165 
166         List<Metadata> metadatas = Utils.prepareMetadata( generators, artifacts );
167 
168         syncContext.acquire( artifacts, Utils.combine( request.getMetadata(), metadatas ) );
169 
170         for ( Metadata metadata : metadatas )
171         {
172             install( session, trace, metadata );
173             processedMetadata.put( metadata, null );
174             result.addMetadata( metadata );
175         }
176 
177         for ( ListIterator<Artifact> iterator = artifacts.listIterator(); iterator.hasNext(); )
178         {
179             Artifact artifact = iterator.next();
180 
181             for ( MetadataGenerator generator : generators )
182             {
183                 artifact = generator.transformArtifact( artifact );
184             }
185 
186             iterator.set( artifact );
187 
188             install( session, trace, artifact );
189             result.addArtifact( artifact );
190         }
191 
192         metadatas = Utils.finishMetadata( generators, artifacts );
193 
194         syncContext.acquire( null, metadatas );
195 
196         for ( Metadata metadata : metadatas )
197         {
198             install( session, trace, metadata );
199             processedMetadata.put( metadata, null );
200             result.addMetadata( metadata );
201         }
202 
203         for ( Metadata metadata : request.getMetadata() )
204         {
205             if ( !processedMetadata.containsKey( metadata ) )
206             {
207                 install( session, trace, metadata );
208                 result.addMetadata( metadata );
209             }
210         }
211 
212         return result;
213     }
214 
215     private List<? extends MetadataGenerator> getMetadataGenerators( RepositorySystemSession session,
216                                                                      InstallRequest request )
217     {
218         PrioritizedComponents<MetadataGeneratorFactory> factories =
219             Utils.sortMetadataGeneratorFactories( session, this.metadataFactories );
220 
221         List<MetadataGenerator> generators = new ArrayList<>();
222 
223         for ( PrioritizedComponent<MetadataGeneratorFactory> factory : factories.getEnabled() )
224         {
225             MetadataGenerator generator = factory.getComponent().newInstance( session, request );
226             if ( generator != null )
227             {
228                 generators.add( generator );
229             }
230         }
231 
232         return generators;
233     }
234 
235     private void install( RepositorySystemSession session, RequestTrace trace, Artifact artifact )
236         throws InstallationException
237     {
238         LocalRepositoryManager lrm = session.getLocalRepositoryManager();
239 
240         File srcFile = artifact.getFile();
241 
242         Collection<FileTransformer> fileTransformers = session.getFileTransformerManager()
243                 .getTransformersForArtifact( artifact );
244         if ( fileTransformers.isEmpty() )
245         {
246             install( session, trace, artifact, lrm, srcFile, null );
247         }
248         else
249         {
250             for ( FileTransformer fileTransformer : fileTransformers )
251             {
252                 install( session, trace, artifact, lrm, srcFile, fileTransformer );
253             }
254         }
255     }
256 
257     private void install( RepositorySystemSession session, RequestTrace trace, Artifact artifact,
258                           LocalRepositoryManager lrm, File srcFile, FileTransformer fileTransformer )
259         throws InstallationException
260     {
261         final Artifact targetArtifact;
262         if ( fileTransformer != null )
263         {
264             targetArtifact = fileTransformer.transformArtifact( artifact );
265         }
266         else
267         {
268             targetArtifact = artifact;
269         }
270 
271         File dstFile = new File( lrm.getRepository().getBasedir(), lrm.getPathForLocalArtifact( targetArtifact ) );
272 
273         artifactInstalling( session, trace, targetArtifact, dstFile );
274 
275         Exception exception = null;
276         try
277         {
278             if ( dstFile.equals( srcFile ) )
279             {
280                 throw new IllegalStateException( "cannot install " + dstFile + " to same path" );
281             }
282 
283             boolean copy =
284                 "pom".equals( targetArtifact.getExtension() ) || srcFile.lastModified() != dstFile.lastModified()
285                     || srcFile.length() != dstFile.length() || !srcFile.exists();
286 
287             if ( !copy )
288             {
289                 LOGGER.debug( "Skipped re-installing {} to {}, seems unchanged", srcFile, dstFile );
290             }
291             else if ( fileTransformer != null ) 
292             {
293                 try ( InputStream is = fileTransformer.transformData( srcFile ) )
294                 {
295                     fileProcessor.write( dstFile, is );
296                     dstFile.setLastModified( srcFile.lastModified() );
297                 }
298             }
299             else
300             {
301                 fileProcessor.copy( srcFile, dstFile );
302                 dstFile.setLastModified( srcFile.lastModified() );
303             }
304 
305             lrm.add( session, new LocalArtifactRegistration( targetArtifact ) );
306         }
307         catch ( Exception e )
308         {
309             exception = e;
310             throw new InstallationException( "Failed to install artifact " + targetArtifact + ": " + e.getMessage(),
311                     e );
312         }
313         finally
314         {
315             artifactInstalled( session, trace, targetArtifact, dstFile, exception );
316         }
317     }
318 
319     private void install( RepositorySystemSession session, RequestTrace trace, Metadata metadata )
320         throws InstallationException
321     {
322         LocalRepositoryManager lrm = session.getLocalRepositoryManager();
323 
324         File dstFile = new File( lrm.getRepository().getBasedir(), lrm.getPathForLocalMetadata( metadata ) );
325 
326         metadataInstalling( session, trace, metadata, dstFile );
327 
328         Exception exception = null;
329         try
330         {
331             if ( metadata instanceof MergeableMetadata )
332             {
333                 ( (MergeableMetadata) metadata ).merge( dstFile, dstFile );
334             }
335             else
336             {
337                 if ( dstFile.equals( metadata.getFile() ) )
338                 {
339                     throw new IllegalStateException( "cannot install " + dstFile + " to same path" );
340                 }
341                 fileProcessor.copy( metadata.getFile(), dstFile );
342             }
343 
344             lrm.add( session, new LocalMetadataRegistration( metadata ) );
345         }
346         catch ( Exception e )
347         {
348             exception = e;
349             throw new InstallationException( "Failed to install metadata " + metadata + ": " + e.getMessage(), e );
350         }
351         finally
352         {
353             metadataInstalled( session, trace, metadata, dstFile, exception );
354         }
355     }
356 
357     private void artifactInstalling( RepositorySystemSession session, RequestTrace trace, Artifact artifact,
358                                      File dstFile )
359     {
360         RepositoryEvent.Builder event = new RepositoryEvent.Builder( session, EventType.ARTIFACT_INSTALLING );
361         event.setTrace( trace );
362         event.setArtifact( artifact );
363         event.setRepository( session.getLocalRepositoryManager().getRepository() );
364         event.setFile( dstFile );
365 
366         repositoryEventDispatcher.dispatch( event.build() );
367     }
368 
369     private void artifactInstalled( RepositorySystemSession session, RequestTrace trace, Artifact artifact,
370                                     File dstFile, Exception exception )
371     {
372         RepositoryEvent.Builder event = new RepositoryEvent.Builder( session, EventType.ARTIFACT_INSTALLED );
373         event.setTrace( trace );
374         event.setArtifact( artifact );
375         event.setRepository( session.getLocalRepositoryManager().getRepository() );
376         event.setFile( dstFile );
377         event.setException( exception );
378 
379         repositoryEventDispatcher.dispatch( event.build() );
380     }
381 
382     private void metadataInstalling( RepositorySystemSession session, RequestTrace trace, Metadata metadata,
383                                      File dstFile )
384     {
385         RepositoryEvent.Builder event = new RepositoryEvent.Builder( session, EventType.METADATA_INSTALLING );
386         event.setTrace( trace );
387         event.setMetadata( metadata );
388         event.setRepository( session.getLocalRepositoryManager().getRepository() );
389         event.setFile( dstFile );
390 
391         repositoryEventDispatcher.dispatch( event.build() );
392     }
393 
394     private void metadataInstalled( RepositorySystemSession session, RequestTrace trace, Metadata metadata,
395                                     File dstFile, Exception exception )
396     {
397         RepositoryEvent.Builder event = new RepositoryEvent.Builder( session, EventType.METADATA_INSTALLED );
398         event.setTrace( trace );
399         event.setMetadata( metadata );
400         event.setRepository( session.getLocalRepositoryManager().getRepository() );
401         event.setFile( dstFile );
402         event.setException( exception );
403 
404         repositoryEventDispatcher.dispatch( event.build() );
405     }
406 
407 }