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