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.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.RepositorySystemSession;
38  import org.eclipse.aether.RequestTrace;
39  import org.eclipse.aether.SyncContext;
40  import org.eclipse.aether.artifact.Artifact;
41  import org.eclipse.aether.impl.Installer;
42  import org.eclipse.aether.impl.MetadataGenerator;
43  import org.eclipse.aether.impl.MetadataGeneratorFactory;
44  import org.eclipse.aether.impl.RepositoryEventDispatcher;
45  import org.eclipse.aether.impl.SyncContextFactory;
46  import org.eclipse.aether.installation.InstallRequest;
47  import org.eclipse.aether.installation.InstallResult;
48  import org.eclipse.aether.installation.InstallationException;
49  import org.eclipse.aether.metadata.MergeableMetadata;
50  import org.eclipse.aether.metadata.Metadata;
51  import org.eclipse.aether.repository.LocalArtifactRegistration;
52  import org.eclipse.aether.repository.LocalMetadataRegistration;
53  import org.eclipse.aether.repository.LocalRepositoryManager;
54  import org.eclipse.aether.spi.io.FileProcessor;
55  import org.eclipse.aether.spi.locator.Service;
56  import org.eclipse.aether.spi.locator.ServiceLocator;
57  import org.eclipse.aether.transform.FileTransformer;
58  import org.slf4j.Logger;
59  import org.slf4j.LoggerFactory;
60  
61  /**
62   */
63  @Named
64  public class DefaultInstaller
65      implements Installer, Service
66  {
67  
68      private static final Logger LOGGER = LoggerFactory.getLogger( DefaultInstaller.class );
69  
70      private FileProcessor fileProcessor;
71  
72      private RepositoryEventDispatcher repositoryEventDispatcher;
73  
74      private Collection<MetadataGeneratorFactory> metadataFactories = new ArrayList<MetadataGeneratorFactory>();
75  
76      private SyncContextFactory syncContextFactory;
77  
78      public DefaultInstaller()
79      {
80          // enables default constructor
81      }
82  
83      @Inject
84      DefaultInstaller( FileProcessor fileProcessor, RepositoryEventDispatcher repositoryEventDispatcher,
85                        Set<MetadataGeneratorFactory> metadataFactories, SyncContextFactory syncContextFactory )
86      {
87          setFileProcessor( fileProcessor );
88          setRepositoryEventDispatcher( repositoryEventDispatcher );
89          setMetadataGeneratorFactories( metadataFactories );
90          setSyncContextFactory( syncContextFactory );
91      }
92  
93      public void initService( ServiceLocator locator )
94      {
95          setFileProcessor( locator.getService( FileProcessor.class ) );
96          setRepositoryEventDispatcher( locator.getService( RepositoryEventDispatcher.class ) );
97          setMetadataGeneratorFactories( locator.getServices( MetadataGeneratorFactory.class ) );
98          setSyncContextFactory( locator.getService( SyncContextFactory.class ) );
99      }
100 
101     public DefaultInstaller setFileProcessor( FileProcessor fileProcessor )
102     {
103         this.fileProcessor = requireNonNull( fileProcessor, "file processor cannot be null" );
104         return this;
105     }
106 
107     public DefaultInstaller setRepositoryEventDispatcher( RepositoryEventDispatcher repositoryEventDispatcher )
108     {
109         this.repositoryEventDispatcher = requireNonNull( repositoryEventDispatcher, "repository event dispatcher cannot be null" );
110         return this;
111     }
112 
113     public DefaultInstaller addMetadataGeneratorFactory( MetadataGeneratorFactory factory )
114     {
115         metadataFactories.add( requireNonNull( factory, "metadata generator factory cannot be null" ) );
116         return this;
117     }
118 
119     public DefaultInstaller setMetadataGeneratorFactories( Collection<MetadataGeneratorFactory> metadataFactories )
120     {
121         if ( metadataFactories == null )
122         {
123             this.metadataFactories = new ArrayList<MetadataGeneratorFactory>();
124         }
125         else
126         {
127             this.metadataFactories = metadataFactories;
128         }
129         return this;
130     }
131 
132     public DefaultInstaller setSyncContextFactory( SyncContextFactory syncContextFactory )
133     {
134         this.syncContextFactory = requireNonNull( syncContextFactory, "sync context factory cannot be null" );
135         return this;
136     }
137 
138     public InstallResult install( RepositorySystemSession session, InstallRequest request )
139         throws InstallationException
140     {
141         SyncContext syncContext = syncContextFactory.newInstance( session, false );
142 
143         try
144         {
145             return install( syncContext, session, request );
146         }
147         finally
148         {
149             syncContext.close();
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<Artifact>( request.getArtifacts() );
163 
164         IdentityHashMap<Metadata, Object> processedMetadata = new IdentityHashMap<Metadata, Object>();
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 ( int i = 0; i < artifacts.size(); i++ )
178         {
179             Artifact artifact = artifacts.get( i );
180 
181             for ( MetadataGenerator generator : generators )
182             {
183                 artifact = generator.transformArtifact( artifact );
184             }
185 
186             artifacts.set( i, 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<MetadataGenerator>();
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().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(), e );
310         }
311         finally
312         {
313             artifactInstalled( session, trace, targetArtifact, dstFile, exception );
314         }
315     }
316 
317     private void install( RepositorySystemSession session, RequestTrace trace, Metadata metadata )
318         throws InstallationException
319     {
320         LocalRepositoryManager lrm = session.getLocalRepositoryManager();
321 
322         File dstFile = new File( lrm.getRepository().getBasedir(), lrm.getPathForLocalMetadata( metadata ) );
323 
324         metadataInstalling( session, trace, metadata, dstFile );
325 
326         Exception exception = null;
327         try
328         {
329             if ( metadata instanceof MergeableMetadata )
330             {
331                 ( (MergeableMetadata) metadata ).merge( dstFile, dstFile );
332             }
333             else
334             {
335                 if ( dstFile.equals( metadata.getFile() ) )
336                 {
337                     throw new IllegalStateException( "cannot install " + dstFile + " to same path" );
338                 }
339                 fileProcessor.copy( metadata.getFile(), dstFile );
340             }
341 
342             lrm.add( session, new LocalMetadataRegistration( metadata ) );
343         }
344         catch ( Exception e )
345         {
346             exception = e;
347             throw new InstallationException( "Failed to install metadata " + metadata + ": " + e.getMessage(), e );
348         }
349         finally
350         {
351             metadataInstalled( session, trace, metadata, dstFile, exception );
352         }
353     }
354 
355     private void artifactInstalling( RepositorySystemSession session, RequestTrace trace, Artifact artifact,
356                                      File dstFile )
357     {
358         RepositoryEvent.Builder event = new RepositoryEvent.Builder( session, EventType.ARTIFACT_INSTALLING );
359         event.setTrace( trace );
360         event.setArtifact( artifact );
361         event.setRepository( session.getLocalRepositoryManager().getRepository() );
362         event.setFile( dstFile );
363 
364         repositoryEventDispatcher.dispatch( event.build() );
365     }
366 
367     private void artifactInstalled( RepositorySystemSession session, RequestTrace trace, Artifact artifact,
368                                     File dstFile, Exception exception )
369     {
370         RepositoryEvent.Builder event = new RepositoryEvent.Builder( session, EventType.ARTIFACT_INSTALLED );
371         event.setTrace( trace );
372         event.setArtifact( artifact );
373         event.setRepository( session.getLocalRepositoryManager().getRepository() );
374         event.setFile( dstFile );
375         event.setException( exception );
376 
377         repositoryEventDispatcher.dispatch( event.build() );
378     }
379 
380     private void metadataInstalling( RepositorySystemSession session, RequestTrace trace, Metadata metadata,
381                                      File dstFile )
382     {
383         RepositoryEvent.Builder event = new RepositoryEvent.Builder( session, EventType.METADATA_INSTALLING );
384         event.setTrace( trace );
385         event.setMetadata( metadata );
386         event.setRepository( session.getLocalRepositoryManager().getRepository() );
387         event.setFile( dstFile );
388 
389         repositoryEventDispatcher.dispatch( event.build() );
390     }
391 
392     private void metadataInstalled( RepositorySystemSession session, RequestTrace trace, Metadata metadata,
393                                     File dstFile, Exception exception )
394     {
395         RepositoryEvent.Builder event = new RepositoryEvent.Builder( session, EventType.METADATA_INSTALLED );
396         event.setTrace( trace );
397         event.setMetadata( metadata );
398         event.setRepository( session.getLocalRepositoryManager().getRepository() );
399         event.setFile( dstFile );
400         event.setException( exception );
401 
402         repositoryEventDispatcher.dispatch( event.build() );
403     }
404 
405 }