001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.eclipse.aether.internal.impl; 020 021import javax.inject.Inject; 022import javax.inject.Named; 023import javax.inject.Singleton; 024 025import java.nio.file.Path; 026import java.util.ArrayList; 027import java.util.Collection; 028import java.util.Collections; 029import java.util.HashMap; 030import java.util.IdentityHashMap; 031import java.util.List; 032import java.util.ListIterator; 033import java.util.Map; 034 035import org.eclipse.aether.RepositoryEvent; 036import org.eclipse.aether.RepositoryEvent.EventType; 037import org.eclipse.aether.RepositorySystemSession; 038import org.eclipse.aether.RequestTrace; 039import org.eclipse.aether.SyncContext; 040import org.eclipse.aether.artifact.Artifact; 041import org.eclipse.aether.impl.Installer; 042import org.eclipse.aether.impl.MetadataGenerator; 043import org.eclipse.aether.impl.MetadataGeneratorFactory; 044import org.eclipse.aether.impl.RepositoryEventDispatcher; 045import org.eclipse.aether.installation.InstallRequest; 046import org.eclipse.aether.installation.InstallResult; 047import org.eclipse.aether.installation.InstallationException; 048import org.eclipse.aether.metadata.MergeableMetadata; 049import org.eclipse.aether.metadata.Metadata; 050import org.eclipse.aether.repository.LocalArtifactRegistration; 051import org.eclipse.aether.repository.LocalMetadataRegistration; 052import org.eclipse.aether.repository.LocalRepositoryManager; 053import org.eclipse.aether.spi.artifact.generator.ArtifactGenerator; 054import org.eclipse.aether.spi.artifact.generator.ArtifactGeneratorFactory; 055import org.eclipse.aether.spi.artifact.transformer.ArtifactTransformer; 056import org.eclipse.aether.spi.io.PathProcessor; 057import org.eclipse.aether.spi.synccontext.SyncContextFactory; 058import org.slf4j.Logger; 059import org.slf4j.LoggerFactory; 060 061import static java.util.Objects.requireNonNull; 062 063/** 064 */ 065@Singleton 066@Named 067public class DefaultInstaller implements Installer { 068 private final Logger logger = LoggerFactory.getLogger(getClass()); 069 070 private final PathProcessor pathProcessor; 071 072 private final RepositoryEventDispatcher repositoryEventDispatcher; 073 074 private final Map<String, ArtifactGeneratorFactory> artifactFactories; 075 076 private final Map<String, MetadataGeneratorFactory> metadataFactories; 077 078 private final Map<String, ArtifactTransformer> artifactTransformers; 079 080 private final SyncContextFactory syncContextFactory; 081 082 @Inject 083 public DefaultInstaller( 084 PathProcessor pathProcessor, 085 RepositoryEventDispatcher repositoryEventDispatcher, 086 Map<String, ArtifactGeneratorFactory> artifactFactories, 087 Map<String, MetadataGeneratorFactory> metadataFactories, 088 Map<String, ArtifactTransformer> artifactTransformers, 089 SyncContextFactory syncContextFactory) { 090 this.pathProcessor = requireNonNull(pathProcessor, "path processor cannot be null"); 091 this.repositoryEventDispatcher = 092 requireNonNull(repositoryEventDispatcher, "repository event dispatcher cannot be null"); 093 this.artifactFactories = Collections.unmodifiableMap(artifactFactories); 094 this.metadataFactories = Collections.unmodifiableMap(metadataFactories); 095 this.artifactTransformers = Collections.unmodifiableMap(artifactTransformers); 096 this.syncContextFactory = requireNonNull(syncContextFactory, "sync context factory cannot be null"); 097 } 098 099 @Override 100 public InstallResult install(RepositorySystemSession session, InstallRequest request) throws InstallationException { 101 requireNonNull(session, "session cannot be null"); 102 requireNonNull(request, "request cannot be null"); 103 for (ArtifactTransformer transformer : artifactTransformers.values()) { 104 request = transformer.transformInstallArtifacts(session, request); 105 } 106 try (SyncContext syncContext = syncContextFactory.newInstance(session, false)) { 107 return install(syncContext, session, request); 108 } 109 } 110 111 private InstallResult install(SyncContext syncContext, RepositorySystemSession session, InstallRequest request) 112 throws InstallationException { 113 InstallResult result = new InstallResult(request); 114 115 RequestTrace trace = RequestTrace.newChild(request.getTrace(), request); 116 117 List<Artifact> artifacts = new ArrayList<>(request.getArtifacts()); 118 List<? extends ArtifactGenerator> artifactGenerators = 119 Utils.getArtifactGenerators(session, artifactFactories, request); 120 try { 121 List<Artifact> generatedArtifacts = new ArrayList<>(); 122 for (ArtifactGenerator artifactGenerator : artifactGenerators) { 123 Collection<? extends Artifact> generated = artifactGenerator.generate(generatedArtifacts); 124 for (Artifact generatedArtifact : generated) { 125 Map<String, String> properties = new HashMap<>(generatedArtifact.getProperties()); 126 properties.put( 127 ArtifactGeneratorFactory.ARTIFACT_GENERATOR_ID, 128 requireNonNull(artifactGenerator.generatorId(), "generatorId")); 129 Artifact ga = generatedArtifact.setProperties(properties); 130 generatedArtifacts.add(ga); 131 } 132 } 133 artifacts.addAll(generatedArtifacts); 134 135 List<? extends MetadataGenerator> metadataGenerators = 136 Utils.getMetadataGenerators(session, metadataFactories, request); 137 138 IdentityHashMap<Metadata, Object> processedMetadata = new IdentityHashMap<>(); 139 140 List<Metadata> metadatas = Utils.prepareMetadata(metadataGenerators, artifacts); 141 142 syncContext.acquire(artifacts, Utils.combine(request.getMetadata(), metadatas)); 143 144 for (Metadata metadata : metadatas) { 145 install(session, trace, metadata); 146 processedMetadata.put(metadata, null); 147 result.addMetadata(metadata); 148 } 149 150 for (ListIterator<Artifact> iterator = artifacts.listIterator(); iterator.hasNext(); ) { 151 Artifact artifact = iterator.next(); 152 153 for (MetadataGenerator generator : metadataGenerators) { 154 artifact = generator.transformArtifact(artifact); 155 } 156 157 iterator.set(artifact); 158 159 install(session, trace, artifact); 160 if (artifact.getProperty(ArtifactGeneratorFactory.ARTIFACT_GENERATOR_ID, null) == null) { 161 result.addArtifact(artifact); 162 } 163 } 164 165 metadatas = Utils.finishMetadata(metadataGenerators, artifacts); 166 167 syncContext.acquire(null, metadatas); 168 169 for (Metadata metadata : metadatas) { 170 install(session, trace, metadata); 171 processedMetadata.put(metadata, null); 172 result.addMetadata(metadata); 173 } 174 175 for (Metadata metadata : request.getMetadata()) { 176 if (!processedMetadata.containsKey(metadata)) { 177 install(session, trace, metadata); 178 result.addMetadata(metadata); 179 } 180 } 181 182 return result; 183 } finally { 184 for (ArtifactGenerator artifactGenerator : artifactGenerators) { 185 try { 186 artifactGenerator.close(); 187 } catch (Exception e) { 188 logger.warn("ArtifactGenerator close failure: {}", artifactGenerator.generatorId(), e); 189 } 190 } 191 } 192 } 193 194 private void install(RepositorySystemSession session, RequestTrace trace, Artifact artifact) 195 throws InstallationException { 196 final LocalRepositoryManager lrm = session.getLocalRepositoryManager(); 197 final Path srcPath = artifact.getPath(); 198 final Path dstPath = lrm.getAbsolutePathForLocalArtifact(artifact); 199 200 artifactInstalling(session, trace, artifact, dstPath); 201 202 Exception exception = null; 203 try { 204 if (dstPath.equals(srcPath)) { 205 throw new IllegalStateException("cannot install " + dstPath + " to same path"); 206 } 207 208 pathProcessor.copyWithTimestamp(srcPath, dstPath); 209 lrm.add(session, new LocalArtifactRegistration(artifact)); 210 } catch (Exception e) { 211 exception = e; 212 throw new InstallationException("Failed to install artifact " + artifact + ": " + e.getMessage(), e); 213 } finally { 214 artifactInstalled(session, trace, artifact, dstPath, exception); 215 } 216 } 217 218 private void install(RepositorySystemSession session, RequestTrace trace, Metadata metadata) 219 throws InstallationException { 220 LocalRepositoryManager lrm = session.getLocalRepositoryManager(); 221 222 Path dstPath = lrm.getAbsolutePathForLocalMetadata(metadata); 223 224 metadataInstalling(session, trace, metadata, dstPath); 225 226 Exception exception = null; 227 try { 228 if (metadata instanceof MergeableMetadata) { 229 ((MergeableMetadata) metadata).merge(dstPath, dstPath); 230 } else { 231 if (dstPath.equals(metadata.getPath())) { 232 throw new IllegalStateException("cannot install " + dstPath + " to same path"); 233 } 234 pathProcessor.copy(metadata.getPath(), dstPath); 235 } 236 237 lrm.add(session, new LocalMetadataRegistration(metadata)); 238 } catch (Exception e) { 239 exception = e; 240 throw new InstallationException("Failed to install metadata " + metadata + ": " + e.getMessage(), e); 241 } finally { 242 metadataInstalled(session, trace, metadata, dstPath, exception); 243 } 244 } 245 246 private void artifactInstalling( 247 RepositorySystemSession session, RequestTrace trace, Artifact artifact, Path dstPath) { 248 RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.ARTIFACT_INSTALLING); 249 event.setTrace(trace); 250 event.setArtifact(artifact); 251 event.setRepository(session.getLocalRepositoryManager().getRepository()); 252 event.setPath(dstPath); 253 254 repositoryEventDispatcher.dispatch(event.build()); 255 } 256 257 private void artifactInstalled( 258 RepositorySystemSession session, RequestTrace trace, Artifact artifact, Path dstPath, Exception exception) { 259 RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.ARTIFACT_INSTALLED); 260 event.setTrace(trace); 261 event.setArtifact(artifact); 262 event.setRepository(session.getLocalRepositoryManager().getRepository()); 263 event.setPath(dstPath); 264 event.setException(exception); 265 266 repositoryEventDispatcher.dispatch(event.build()); 267 } 268 269 private void metadataInstalling( 270 RepositorySystemSession session, RequestTrace trace, Metadata metadata, Path dstPath) { 271 RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.METADATA_INSTALLING); 272 event.setTrace(trace); 273 event.setMetadata(metadata); 274 event.setRepository(session.getLocalRepositoryManager().getRepository()); 275 event.setPath(dstPath); 276 277 repositoryEventDispatcher.dispatch(event.build()); 278 } 279 280 private void metadataInstalled( 281 RepositorySystemSession session, RequestTrace trace, Metadata metadata, Path dstPath, Exception exception) { 282 RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.METADATA_INSTALLED); 283 event.setTrace(trace); 284 event.setMetadata(metadata); 285 event.setRepository(session.getLocalRepositoryManager().getRepository()); 286 event.setPath(dstPath); 287 event.setException(exception); 288 289 repositoryEventDispatcher.dispatch(event.build()); 290 } 291}