1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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.IOException;
26 import java.nio.file.Files;
27 import java.nio.file.Path;
28 import java.util.ArrayList;
29 import java.util.Collection;
30 import java.util.Collections;
31 import java.util.HashMap;
32 import java.util.IdentityHashMap;
33 import java.util.List;
34 import java.util.ListIterator;
35 import java.util.Map;
36
37 import org.eclipse.aether.ConfigurationProperties;
38 import org.eclipse.aether.RepositoryEvent;
39 import org.eclipse.aether.RepositoryEvent.EventType;
40 import org.eclipse.aether.RepositorySystemSession;
41 import org.eclipse.aether.RequestTrace;
42 import org.eclipse.aether.SyncContext;
43 import org.eclipse.aether.artifact.Artifact;
44 import org.eclipse.aether.impl.Installer;
45 import org.eclipse.aether.impl.MetadataGenerator;
46 import org.eclipse.aether.impl.MetadataGeneratorFactory;
47 import org.eclipse.aether.impl.RepositoryEventDispatcher;
48 import org.eclipse.aether.installation.InstallRequest;
49 import org.eclipse.aether.installation.InstallResult;
50 import org.eclipse.aether.installation.InstallationException;
51 import org.eclipse.aether.metadata.MergeableMetadata;
52 import org.eclipse.aether.metadata.Metadata;
53 import org.eclipse.aether.repository.LocalArtifactRegistration;
54 import org.eclipse.aether.repository.LocalMetadataRegistration;
55 import org.eclipse.aether.repository.LocalRepositoryManager;
56 import org.eclipse.aether.spi.artifact.generator.ArtifactGenerator;
57 import org.eclipse.aether.spi.artifact.generator.ArtifactGeneratorFactory;
58 import org.eclipse.aether.spi.artifact.transformer.ArtifactTransformer;
59 import org.eclipse.aether.spi.io.PathProcessor;
60 import org.eclipse.aether.spi.synccontext.SyncContextFactory;
61 import org.eclipse.aether.util.ConfigUtils;
62 import org.slf4j.Logger;
63 import org.slf4j.LoggerFactory;
64
65 import static java.util.Objects.requireNonNull;
66
67
68
69 @Singleton
70 @Named
71 public class DefaultInstaller implements Installer {
72 private final Logger logger = LoggerFactory.getLogger(getClass());
73
74 private final PathProcessor pathProcessor;
75
76 private final RepositoryEventDispatcher repositoryEventDispatcher;
77
78 private final Map<String, ArtifactGeneratorFactory> artifactFactories;
79
80 private final Map<String, MetadataGeneratorFactory> metadataFactories;
81
82 private final Map<String, ArtifactTransformer> artifactTransformers;
83
84 private final SyncContextFactory syncContextFactory;
85
86 @Inject
87 public DefaultInstaller(
88 PathProcessor pathProcessor,
89 RepositoryEventDispatcher repositoryEventDispatcher,
90 Map<String, ArtifactGeneratorFactory> artifactFactories,
91 Map<String, MetadataGeneratorFactory> metadataFactories,
92 Map<String, ArtifactTransformer> artifactTransformers,
93 SyncContextFactory syncContextFactory) {
94 this.pathProcessor = requireNonNull(pathProcessor, "path processor cannot be null");
95 this.repositoryEventDispatcher =
96 requireNonNull(repositoryEventDispatcher, "repository event dispatcher cannot be null");
97 this.artifactFactories = Collections.unmodifiableMap(artifactFactories);
98 this.metadataFactories = Collections.unmodifiableMap(metadataFactories);
99 this.artifactTransformers = Collections.unmodifiableMap(artifactTransformers);
100 this.syncContextFactory = requireNonNull(syncContextFactory, "sync context factory cannot be null");
101 }
102
103 @Override
104 public InstallResult install(RepositorySystemSession session, InstallRequest request) throws InstallationException {
105 requireNonNull(session, "session cannot be null");
106 requireNonNull(request, "request cannot be null");
107 for (ArtifactTransformer transformer : artifactTransformers.values()) {
108 request = transformer.transformInstallArtifacts(session, request);
109 }
110 try (SyncContext syncContext = syncContextFactory.newInstance(session, false)) {
111 return install(syncContext, session, request);
112 }
113 }
114
115 private InstallResult install(SyncContext syncContext, RepositorySystemSession session, InstallRequest request)
116 throws InstallationException {
117 InstallResult result = new InstallResult(request);
118
119 RequestTrace trace = RequestTrace.newChild(request.getTrace(), request);
120
121 List<Artifact> artifacts = new ArrayList<>(request.getArtifacts());
122 List<? extends ArtifactGenerator> artifactGenerators =
123 Utils.getArtifactGenerators(session, artifactFactories, request);
124 try {
125 List<Artifact> generatedArtifacts = new ArrayList<>();
126 for (ArtifactGenerator artifactGenerator : artifactGenerators) {
127 Collection<? extends Artifact> generated = artifactGenerator.generate(generatedArtifacts);
128 for (Artifact generatedArtifact : generated) {
129 Map<String, String> properties = new HashMap<>(generatedArtifact.getProperties());
130 properties.put(
131 ArtifactGeneratorFactory.ARTIFACT_GENERATOR_ID,
132 requireNonNull(artifactGenerator.generatorId(), "generatorId"));
133 Artifact ga = generatedArtifact.setProperties(properties);
134 generatedArtifacts.add(ga);
135 }
136 }
137 artifacts.addAll(generatedArtifacts);
138
139 List<? extends MetadataGenerator> metadataGenerators =
140 Utils.getMetadataGenerators(session, metadataFactories, request);
141
142 IdentityHashMap<Metadata, Object> processedMetadata = new IdentityHashMap<>();
143
144 List<Metadata> metadatas = Utils.prepareMetadata(metadataGenerators, artifacts);
145
146 syncContext.acquire(artifacts, Utils.combine(request.getMetadata(), metadatas));
147
148 for (Metadata metadata : metadatas) {
149 install(session, trace, metadata);
150 processedMetadata.put(metadata, null);
151 result.addMetadata(metadata);
152 }
153
154 boolean hardLink = ConfigUtils.getBoolean(
155 session,
156 ConfigurationProperties.DEFAULT_INSTALLER_HARD_LINK,
157 ConfigurationProperties.INSTALLER_HARD_LINK);
158
159 Exception linkFailure = null;
160 for (ListIterator<Artifact> iterator = artifacts.listIterator(); iterator.hasNext(); ) {
161 Artifact artifact = iterator.next();
162
163 for (MetadataGenerator generator : metadataGenerators) {
164 artifact = generator.transformArtifact(artifact);
165 }
166
167 iterator.set(artifact);
168
169 Exception failure = install(session, trace, artifact, hardLink);
170 if (failure != null && linkFailure == null) {
171 linkFailure = failure;
172 } else if (failure != null) {
173 linkFailure.addSuppressed(failure);
174 }
175 if (artifact.getProperty(ArtifactGeneratorFactory.ARTIFACT_GENERATOR_ID, null) == null) {
176 result.addArtifact(artifact);
177 }
178 }
179 if (linkFailure != null) {
180 logger.warn(
181 "Hard link not supported, falling back to copy for all artifacts: {}",
182 linkFailure.getMessage(),
183 linkFailure);
184 }
185
186 metadatas = Utils.finishMetadata(metadataGenerators, artifacts);
187
188 syncContext.acquire(null, metadatas);
189
190 for (Metadata metadata : metadatas) {
191 install(session, trace, metadata);
192 processedMetadata.put(metadata, null);
193 result.addMetadata(metadata);
194 }
195
196 for (Metadata metadata : request.getMetadata()) {
197 if (!processedMetadata.containsKey(metadata)) {
198 install(session, trace, metadata);
199 result.addMetadata(metadata);
200 }
201 }
202
203 return result;
204 } finally {
205 for (ArtifactGenerator artifactGenerator : artifactGenerators) {
206 try {
207 artifactGenerator.close();
208 } catch (Exception e) {
209 logger.warn("ArtifactGenerator close failure: {}", artifactGenerator.generatorId(), e);
210 }
211 }
212 }
213 }
214
215
216
217
218
219
220 private Exception install(RepositorySystemSession session, RequestTrace trace, Artifact artifact, boolean hardLink)
221 throws InstallationException {
222 final LocalRepositoryManager lrm = session.getLocalRepositoryManager();
223 final Path srcPath = artifact.getPath();
224 final Path dstPath = lrm.getAbsolutePathForLocalArtifact(artifact);
225
226 artifactInstalling(session, trace, artifact, dstPath);
227
228 Exception linkFailure = null;
229 Exception exception = null;
230 try {
231 if (dstPath.equals(srcPath)) {
232 throw new IllegalStateException("cannot install " + dstPath + " to same path");
233 }
234
235 if (hardLink) {
236 Files.createDirectories(dstPath.getParent());
237 if (Files.isDirectory(dstPath)) {
238 throw new IOException("destination is a directory: " + dstPath);
239 }
240 try {
241 Files.deleteIfExists(dstPath);
242 Files.createLink(dstPath, srcPath);
243 } catch (UnsupportedOperationException | IllegalArgumentException | IOException e) {
244
245 linkFailure = e;
246 pathProcessor.copyWithTimestamp(srcPath, dstPath);
247 }
248 } else {
249 pathProcessor.copyWithTimestamp(srcPath, dstPath);
250 }
251 lrm.add(session, new LocalArtifactRegistration(artifact));
252 } catch (Exception e) {
253 exception = e;
254 throw new InstallationException("Failed to install artifact " + artifact + ": " + e.getMessage(), e);
255 } finally {
256 artifactInstalled(session, trace, artifact, dstPath, exception);
257 }
258 return linkFailure;
259 }
260
261 private void install(RepositorySystemSession session, RequestTrace trace, Metadata metadata)
262 throws InstallationException {
263 LocalRepositoryManager lrm = session.getLocalRepositoryManager();
264
265 Path dstPath = lrm.getAbsolutePathForLocalMetadata(metadata);
266
267 metadataInstalling(session, trace, metadata, dstPath);
268
269 Exception exception = null;
270 try {
271 if (metadata instanceof MergeableMetadata) {
272 ((MergeableMetadata) metadata).merge(dstPath, dstPath);
273 } else {
274 if (dstPath.equals(metadata.getPath())) {
275 throw new IllegalStateException("cannot install " + dstPath + " to same path");
276 }
277 pathProcessor.copy(metadata.getPath(), dstPath);
278 }
279
280 lrm.add(session, new LocalMetadataRegistration(metadata));
281 } catch (Exception e) {
282 exception = e;
283 throw new InstallationException("Failed to install metadata " + metadata + ": " + e.getMessage(), e);
284 } finally {
285 metadataInstalled(session, trace, metadata, dstPath, exception);
286 }
287 }
288
289 private void artifactInstalling(
290 RepositorySystemSession session, RequestTrace trace, Artifact artifact, Path dstPath) {
291 RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.ARTIFACT_INSTALLING);
292 event.setTrace(trace);
293 event.setArtifact(artifact);
294 event.setRepository(session.getLocalRepositoryManager().getRepository());
295 event.setPath(dstPath);
296
297 repositoryEventDispatcher.dispatch(event.build());
298 }
299
300 private void artifactInstalled(
301 RepositorySystemSession session, RequestTrace trace, Artifact artifact, Path dstPath, Exception exception) {
302 RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.ARTIFACT_INSTALLED);
303 event.setTrace(trace);
304 event.setArtifact(artifact);
305 event.setRepository(session.getLocalRepositoryManager().getRepository());
306 event.setPath(dstPath);
307 event.setException(exception);
308
309 repositoryEventDispatcher.dispatch(event.build());
310 }
311
312 private void metadataInstalling(
313 RepositorySystemSession session, RequestTrace trace, Metadata metadata, Path dstPath) {
314 RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.METADATA_INSTALLING);
315 event.setTrace(trace);
316 event.setMetadata(metadata);
317 event.setRepository(session.getLocalRepositoryManager().getRepository());
318 event.setPath(dstPath);
319
320 repositoryEventDispatcher.dispatch(event.build());
321 }
322
323 private void metadataInstalled(
324 RepositorySystemSession session, RequestTrace trace, Metadata metadata, Path dstPath, Exception exception) {
325 RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.METADATA_INSTALLED);
326 event.setTrace(trace);
327 event.setMetadata(metadata);
328 event.setRepository(session.getLocalRepositoryManager().getRepository());
329 event.setPath(dstPath);
330 event.setException(exception);
331
332 repositoryEventDispatcher.dispatch(event.build());
333 }
334 }