View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.eclipse.aether.internal.impl;
20  
21  import javax.inject.Inject;
22  import javax.inject.Named;
23  import javax.inject.Singleton;
24  
25  import java.io.File;
26  import java.io.InputStream;
27  import java.util.ArrayList;
28  import java.util.Collection;
29  import java.util.IdentityHashMap;
30  import java.util.List;
31  import java.util.ListIterator;
32  import java.util.Set;
33  
34  import org.eclipse.aether.RepositoryEvent;
35  import org.eclipse.aether.RepositoryEvent.EventType;
36  import org.eclipse.aether.RepositorySystemSession;
37  import org.eclipse.aether.RequestTrace;
38  import org.eclipse.aether.SyncContext;
39  import org.eclipse.aether.artifact.Artifact;
40  import org.eclipse.aether.impl.Installer;
41  import org.eclipse.aether.impl.MetadataGenerator;
42  import org.eclipse.aether.impl.MetadataGeneratorFactory;
43  import org.eclipse.aether.impl.RepositoryEventDispatcher;
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.synccontext.SyncContextFactory;
56  import org.eclipse.aether.transform.FileTransformer;
57  import org.slf4j.Logger;
58  import org.slf4j.LoggerFactory;
59  
60  import static java.util.Objects.requireNonNull;
61  
62  /**
63   */
64  @Singleton
65  @Named
66  public class DefaultInstaller implements Installer, Service {
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<>();
75  
76      private SyncContextFactory syncContextFactory;
77  
78      @Deprecated
79      public DefaultInstaller() {
80          // enables default constructor
81      }
82  
83      @Inject
84      public DefaultInstaller(
85              FileProcessor fileProcessor,
86              RepositoryEventDispatcher repositoryEventDispatcher,
87              Set<MetadataGeneratorFactory> metadataFactories,
88              SyncContextFactory syncContextFactory) {
89          setFileProcessor(fileProcessor);
90          setRepositoryEventDispatcher(repositoryEventDispatcher);
91          setMetadataGeneratorFactories(metadataFactories);
92          setSyncContextFactory(syncContextFactory);
93      }
94  
95      public void initService(ServiceLocator locator) {
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 setFileProcessor(FileProcessor fileProcessor) {
103         this.fileProcessor = requireNonNull(fileProcessor, "file processor cannot be null");
104         return this;
105     }
106 
107     public DefaultInstaller setRepositoryEventDispatcher(RepositoryEventDispatcher repositoryEventDispatcher) {
108         this.repositoryEventDispatcher =
109                 requireNonNull(repositoryEventDispatcher, "repository event dispatcher cannot be null");
110         return this;
111     }
112 
113     public DefaultInstaller addMetadataGeneratorFactory(MetadataGeneratorFactory factory) {
114         metadataFactories.add(requireNonNull(factory, "metadata generator factory cannot be null"));
115         return this;
116     }
117 
118     public DefaultInstaller setMetadataGeneratorFactories(Collection<MetadataGeneratorFactory> metadataFactories) {
119         if (metadataFactories == null) {
120             this.metadataFactories = new ArrayList<>();
121         } else {
122             this.metadataFactories = metadataFactories;
123         }
124         return this;
125     }
126 
127     public DefaultInstaller setSyncContextFactory(SyncContextFactory syncContextFactory) {
128         this.syncContextFactory = requireNonNull(syncContextFactory, "sync context factory cannot be null");
129         return this;
130     }
131 
132     public InstallResult install(RepositorySystemSession session, InstallRequest request) throws InstallationException {
133         requireNonNull(session, "session cannot be null");
134         requireNonNull(request, "request cannot be null");
135         try (SyncContext syncContext = syncContextFactory.newInstance(session, false)) {
136             return install(syncContext, session, request);
137         }
138     }
139 
140     private InstallResult install(SyncContext syncContext, RepositorySystemSession session, InstallRequest request)
141             throws InstallationException {
142         InstallResult result = new InstallResult(request);
143 
144         RequestTrace trace = RequestTrace.newChild(request.getTrace(), request);
145 
146         List<? extends MetadataGenerator> generators = getMetadataGenerators(session, request);
147 
148         List<Artifact> artifacts = new ArrayList<>(request.getArtifacts());
149 
150         IdentityHashMap<Metadata, Object> processedMetadata = new IdentityHashMap<>();
151 
152         List<Metadata> metadatas = Utils.prepareMetadata(generators, artifacts);
153 
154         syncContext.acquire(artifacts, Utils.combine(request.getMetadata(), metadatas));
155 
156         for (Metadata metadata : metadatas) {
157             install(session, trace, metadata);
158             processedMetadata.put(metadata, null);
159             result.addMetadata(metadata);
160         }
161 
162         for (ListIterator<Artifact> iterator = artifacts.listIterator(); iterator.hasNext(); ) {
163             Artifact artifact = iterator.next();
164 
165             for (MetadataGenerator generator : generators) {
166                 artifact = generator.transformArtifact(artifact);
167             }
168 
169             iterator.set(artifact);
170 
171             install(session, trace, artifact);
172             result.addArtifact(artifact);
173         }
174 
175         metadatas = Utils.finishMetadata(generators, artifacts);
176 
177         syncContext.acquire(null, metadatas);
178 
179         for (Metadata metadata : metadatas) {
180             install(session, trace, metadata);
181             processedMetadata.put(metadata, null);
182             result.addMetadata(metadata);
183         }
184 
185         for (Metadata metadata : request.getMetadata()) {
186             if (!processedMetadata.containsKey(metadata)) {
187                 install(session, trace, metadata);
188                 result.addMetadata(metadata);
189             }
190         }
191 
192         return result;
193     }
194 
195     private List<? extends MetadataGenerator> getMetadataGenerators(
196             RepositorySystemSession session, InstallRequest request) {
197         PrioritizedComponents<MetadataGeneratorFactory> factories =
198                 Utils.sortMetadataGeneratorFactories(session, this.metadataFactories);
199 
200         List<MetadataGenerator> generators = new ArrayList<>();
201 
202         for (PrioritizedComponent<MetadataGeneratorFactory> factory : factories.getEnabled()) {
203             MetadataGenerator generator = factory.getComponent().newInstance(session, request);
204             if (generator != null) {
205                 generators.add(generator);
206             }
207         }
208 
209         return generators;
210     }
211 
212     private void install(RepositorySystemSession session, RequestTrace trace, Artifact artifact)
213             throws InstallationException {
214         LocalRepositoryManager lrm = session.getLocalRepositoryManager();
215 
216         File srcFile = artifact.getFile();
217 
218         Collection<FileTransformer> fileTransformers =
219                 session.getFileTransformerManager().getTransformersForArtifact(artifact);
220         if (fileTransformers.isEmpty()) {
221             install(session, trace, artifact, lrm, srcFile, null);
222         } else {
223             for (FileTransformer fileTransformer : fileTransformers) {
224                 install(session, trace, artifact, lrm, srcFile, fileTransformer);
225             }
226         }
227     }
228 
229     private void install(
230             RepositorySystemSession session,
231             RequestTrace trace,
232             Artifact artifact,
233             LocalRepositoryManager lrm,
234             File srcFile,
235             FileTransformer fileTransformer)
236             throws InstallationException {
237         final Artifact targetArtifact;
238         if (fileTransformer != null) {
239             targetArtifact = fileTransformer.transformArtifact(artifact);
240         } else {
241             targetArtifact = artifact;
242         }
243 
244         File dstFile = new File(lrm.getRepository().getBasedir(), lrm.getPathForLocalArtifact(targetArtifact));
245 
246         artifactInstalling(session, trace, targetArtifact, dstFile);
247 
248         Exception exception = null;
249         try {
250             if (dstFile.equals(srcFile)) {
251                 throw new IllegalStateException("cannot install " + dstFile + " to same path");
252             }
253 
254             boolean copy = "pom".equals(targetArtifact.getExtension())
255                     || srcFile.lastModified() != dstFile.lastModified()
256                     || srcFile.length() != dstFile.length()
257                     || !srcFile.exists();
258 
259             if (!copy) {
260                 LOGGER.debug("Skipped re-installing {} to {}, seems unchanged", srcFile, dstFile);
261             } else if (fileTransformer != null) {
262                 try (InputStream is = fileTransformer.transformData(srcFile)) {
263                     fileProcessor.write(dstFile, is);
264                     dstFile.setLastModified(srcFile.lastModified());
265                 }
266             } else {
267                 fileProcessor.copy(srcFile, dstFile);
268                 dstFile.setLastModified(srcFile.lastModified());
269             }
270 
271             lrm.add(session, new LocalArtifactRegistration(targetArtifact));
272         } catch (Exception e) {
273             exception = e;
274             throw new InstallationException("Failed to install artifact " + targetArtifact + ": " + e.getMessage(), e);
275         } finally {
276             artifactInstalled(session, trace, targetArtifact, dstFile, exception);
277         }
278     }
279 
280     private void install(RepositorySystemSession session, RequestTrace trace, Metadata metadata)
281             throws InstallationException {
282         LocalRepositoryManager lrm = session.getLocalRepositoryManager();
283 
284         File dstFile = new File(lrm.getRepository().getBasedir(), lrm.getPathForLocalMetadata(metadata));
285 
286         metadataInstalling(session, trace, metadata, dstFile);
287 
288         Exception exception = null;
289         try {
290             if (metadata instanceof MergeableMetadata) {
291                 ((MergeableMetadata) metadata).merge(dstFile, dstFile);
292             } else {
293                 if (dstFile.equals(metadata.getFile())) {
294                     throw new IllegalStateException("cannot install " + dstFile + " to same path");
295                 }
296                 fileProcessor.copy(metadata.getFile(), dstFile);
297             }
298 
299             lrm.add(session, new LocalMetadataRegistration(metadata));
300         } catch (Exception e) {
301             exception = e;
302             throw new InstallationException("Failed to install metadata " + metadata + ": " + e.getMessage(), e);
303         } finally {
304             metadataInstalled(session, trace, metadata, dstFile, exception);
305         }
306     }
307 
308     private void artifactInstalling(
309             RepositorySystemSession session, RequestTrace trace, Artifact artifact, File dstFile) {
310         RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.ARTIFACT_INSTALLING);
311         event.setTrace(trace);
312         event.setArtifact(artifact);
313         event.setRepository(session.getLocalRepositoryManager().getRepository());
314         event.setFile(dstFile);
315 
316         repositoryEventDispatcher.dispatch(event.build());
317     }
318 
319     private void artifactInstalled(
320             RepositorySystemSession session, RequestTrace trace, Artifact artifact, File dstFile, Exception exception) {
321         RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.ARTIFACT_INSTALLED);
322         event.setTrace(trace);
323         event.setArtifact(artifact);
324         event.setRepository(session.getLocalRepositoryManager().getRepository());
325         event.setFile(dstFile);
326         event.setException(exception);
327 
328         repositoryEventDispatcher.dispatch(event.build());
329     }
330 
331     private void metadataInstalling(
332             RepositorySystemSession session, RequestTrace trace, Metadata metadata, File dstFile) {
333         RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.METADATA_INSTALLING);
334         event.setTrace(trace);
335         event.setMetadata(metadata);
336         event.setRepository(session.getLocalRepositoryManager().getRepository());
337         event.setFile(dstFile);
338 
339         repositoryEventDispatcher.dispatch(event.build());
340     }
341 
342     private void metadataInstalled(
343             RepositorySystemSession session, RequestTrace trace, Metadata metadata, File dstFile, Exception exception) {
344         RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.METADATA_INSTALLED);
345         event.setTrace(trace);
346         event.setMetadata(metadata);
347         event.setRepository(session.getLocalRepositoryManager().getRepository());
348         event.setFile(dstFile);
349         event.setException(exception);
350 
351         repositoryEventDispatcher.dispatch(event.build());
352     }
353 }