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