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