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