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.util.ArrayList;
27  import java.util.Collections;
28  import java.util.IdentityHashMap;
29  import java.util.List;
30  import java.util.ListIterator;
31  import java.util.Map;
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.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.synccontext.SyncContextFactory;
53  
54  import static java.util.Objects.requireNonNull;
55  
56  /**
57   */
58  @Singleton
59  @Named
60  public class DefaultInstaller implements Installer {
61      private final FileProcessor fileProcessor;
62  
63      private final RepositoryEventDispatcher repositoryEventDispatcher;
64  
65      private final Map<String, MetadataGeneratorFactory> metadataFactories;
66  
67      private final SyncContextFactory syncContextFactory;
68  
69      @Inject
70      public DefaultInstaller(
71              FileProcessor fileProcessor,
72              RepositoryEventDispatcher repositoryEventDispatcher,
73              Map<String, MetadataGeneratorFactory> metadataFactories,
74              SyncContextFactory syncContextFactory) {
75          this.fileProcessor = requireNonNull(fileProcessor, "file processor cannot be null");
76          this.repositoryEventDispatcher =
77                  requireNonNull(repositoryEventDispatcher, "repository event dispatcher cannot be null");
78          this.metadataFactories = Collections.unmodifiableMap(metadataFactories);
79          this.syncContextFactory = requireNonNull(syncContextFactory, "sync context factory cannot be null");
80      }
81  
82      @Override
83      public InstallResult install(RepositorySystemSession session, InstallRequest request) throws InstallationException {
84          requireNonNull(session, "session cannot be null");
85          requireNonNull(request, "request cannot be null");
86          try (SyncContext syncContext = syncContextFactory.newInstance(session, false)) {
87              return install(syncContext, session, request);
88          }
89      }
90  
91      private InstallResult install(SyncContext syncContext, RepositorySystemSession session, InstallRequest request)
92              throws InstallationException {
93          InstallResult result = new InstallResult(request);
94  
95          RequestTrace trace = RequestTrace.newChild(request.getTrace(), request);
96  
97          List<? extends MetadataGenerator> generators = getMetadataGenerators(session, request);
98  
99          List<Artifact> artifacts = new ArrayList<>(request.getArtifacts());
100 
101         IdentityHashMap<Metadata, Object> processedMetadata = new IdentityHashMap<>();
102 
103         List<Metadata> metadatas = Utils.prepareMetadata(generators, artifacts);
104 
105         syncContext.acquire(artifacts, Utils.combine(request.getMetadata(), metadatas));
106 
107         for (Metadata metadata : metadatas) {
108             install(session, trace, metadata);
109             processedMetadata.put(metadata, null);
110             result.addMetadata(metadata);
111         }
112 
113         for (ListIterator<Artifact> iterator = artifacts.listIterator(); iterator.hasNext(); ) {
114             Artifact artifact = iterator.next();
115 
116             for (MetadataGenerator generator : generators) {
117                 artifact = generator.transformArtifact(artifact);
118             }
119 
120             iterator.set(artifact);
121 
122             install(session, trace, artifact);
123             result.addArtifact(artifact);
124         }
125 
126         metadatas = Utils.finishMetadata(generators, artifacts);
127 
128         syncContext.acquire(null, metadatas);
129 
130         for (Metadata metadata : metadatas) {
131             install(session, trace, metadata);
132             processedMetadata.put(metadata, null);
133             result.addMetadata(metadata);
134         }
135 
136         for (Metadata metadata : request.getMetadata()) {
137             if (!processedMetadata.containsKey(metadata)) {
138                 install(session, trace, metadata);
139                 result.addMetadata(metadata);
140             }
141         }
142 
143         return result;
144     }
145 
146     private List<? extends MetadataGenerator> getMetadataGenerators(
147             RepositorySystemSession session, InstallRequest request) {
148         PrioritizedComponents<MetadataGeneratorFactory> factories =
149                 Utils.sortMetadataGeneratorFactories(session, metadataFactories);
150 
151         List<MetadataGenerator> generators = new ArrayList<>();
152 
153         for (PrioritizedComponent<MetadataGeneratorFactory> factory : factories.getEnabled()) {
154             MetadataGenerator generator = factory.getComponent().newInstance(session, request);
155             if (generator != null) {
156                 generators.add(generator);
157             }
158         }
159 
160         return generators;
161     }
162 
163     private void install(RepositorySystemSession session, RequestTrace trace, Artifact artifact)
164             throws InstallationException {
165         final LocalRepositoryManager lrm = session.getLocalRepositoryManager();
166         final File srcFile = artifact.getFile();
167         final File dstFile = new File(lrm.getRepository().getBasedir(), lrm.getPathForLocalArtifact(artifact));
168 
169         artifactInstalling(session, trace, artifact, dstFile);
170 
171         Exception exception = null;
172         try {
173             if (dstFile.equals(srcFile)) {
174                 throw new IllegalStateException("cannot install " + dstFile + " to same path");
175             }
176 
177             fileProcessor.copy(srcFile, dstFile);
178             dstFile.setLastModified(srcFile.lastModified());
179             lrm.add(session, new LocalArtifactRegistration(artifact));
180         } catch (Exception e) {
181             exception = e;
182             throw new InstallationException("Failed to install artifact " + artifact + ": " + e.getMessage(), e);
183         } finally {
184             artifactInstalled(session, trace, artifact, dstFile, exception);
185         }
186     }
187 
188     private void install(RepositorySystemSession session, RequestTrace trace, Metadata metadata)
189             throws InstallationException {
190         LocalRepositoryManager lrm = session.getLocalRepositoryManager();
191 
192         File dstFile = new File(lrm.getRepository().getBasedir(), lrm.getPathForLocalMetadata(metadata));
193 
194         metadataInstalling(session, trace, metadata, dstFile);
195 
196         Exception exception = null;
197         try {
198             if (metadata instanceof MergeableMetadata) {
199                 ((MergeableMetadata) metadata).merge(dstFile, dstFile);
200             } else {
201                 if (dstFile.equals(metadata.getFile())) {
202                     throw new IllegalStateException("cannot install " + dstFile + " to same path");
203                 }
204                 fileProcessor.copy(metadata.getFile(), dstFile);
205             }
206 
207             lrm.add(session, new LocalMetadataRegistration(metadata));
208         } catch (Exception e) {
209             exception = e;
210             throw new InstallationException("Failed to install metadata " + metadata + ": " + e.getMessage(), e);
211         } finally {
212             metadataInstalled(session, trace, metadata, dstFile, exception);
213         }
214     }
215 
216     private void artifactInstalling(
217             RepositorySystemSession session, RequestTrace trace, Artifact artifact, File dstFile) {
218         RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.ARTIFACT_INSTALLING);
219         event.setTrace(trace);
220         event.setArtifact(artifact);
221         event.setRepository(session.getLocalRepositoryManager().getRepository());
222         event.setFile(dstFile);
223 
224         repositoryEventDispatcher.dispatch(event.build());
225     }
226 
227     private void artifactInstalled(
228             RepositorySystemSession session, RequestTrace trace, Artifact artifact, File dstFile, Exception exception) {
229         RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.ARTIFACT_INSTALLED);
230         event.setTrace(trace);
231         event.setArtifact(artifact);
232         event.setRepository(session.getLocalRepositoryManager().getRepository());
233         event.setFile(dstFile);
234         event.setException(exception);
235 
236         repositoryEventDispatcher.dispatch(event.build());
237     }
238 
239     private void metadataInstalling(
240             RepositorySystemSession session, RequestTrace trace, Metadata metadata, File dstFile) {
241         RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.METADATA_INSTALLING);
242         event.setTrace(trace);
243         event.setMetadata(metadata);
244         event.setRepository(session.getLocalRepositoryManager().getRepository());
245         event.setFile(dstFile);
246 
247         repositoryEventDispatcher.dispatch(event.build());
248     }
249 
250     private void metadataInstalled(
251             RepositorySystemSession session, RequestTrace trace, Metadata metadata, File dstFile, Exception exception) {
252         RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.METADATA_INSTALLED);
253         event.setTrace(trace);
254         event.setMetadata(metadata);
255         event.setRepository(session.getLocalRepositoryManager().getRepository());
256         event.setFile(dstFile);
257         event.setException(exception);
258 
259         repositoryEventDispatcher.dispatch(event.build());
260     }
261 }