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.Files; 026import java.nio.file.Path; 027import java.util.*; 028import java.util.ArrayList; 029import java.util.Collections; 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.io.PathProcessor; 056import org.eclipse.aether.spi.synccontext.SyncContextFactory; 057import org.slf4j.Logger; 058import org.slf4j.LoggerFactory; 059 060import static java.util.Objects.requireNonNull; 061 062/** 063 */ 064@Singleton 065@Named 066public class DefaultInstaller implements Installer { 067 private final Logger logger = LoggerFactory.getLogger(getClass()); 068 069 private final PathProcessor pathProcessor; 070 071 private final RepositoryEventDispatcher repositoryEventDispatcher; 072 073 private final Map<String, ArtifactGeneratorFactory> artifactFactories; 074 075 private final Map<String, MetadataGeneratorFactory> metadataFactories; 076 077 private final SyncContextFactory syncContextFactory; 078 079 @Inject 080 public DefaultInstaller( 081 PathProcessor pathProcessor, 082 RepositoryEventDispatcher repositoryEventDispatcher, 083 Map<String, ArtifactGeneratorFactory> artifactFactories, 084 Map<String, MetadataGeneratorFactory> metadataFactories, 085 SyncContextFactory syncContextFactory) { 086 this.pathProcessor = requireNonNull(pathProcessor, "path processor cannot be null"); 087 this.repositoryEventDispatcher = 088 requireNonNull(repositoryEventDispatcher, "repository event dispatcher cannot be null"); 089 this.artifactFactories = Collections.unmodifiableMap(artifactFactories); 090 this.metadataFactories = Collections.unmodifiableMap(metadataFactories); 091 this.syncContextFactory = requireNonNull(syncContextFactory, "sync context factory cannot be null"); 092 } 093 094 @Override 095 public InstallResult install(RepositorySystemSession session, InstallRequest request) throws InstallationException { 096 requireNonNull(session, "session cannot be null"); 097 requireNonNull(request, "request cannot be null"); 098 try (SyncContext syncContext = syncContextFactory.newInstance(session, false)) { 099 return install(syncContext, session, request); 100 } 101 } 102 103 private InstallResult install(SyncContext syncContext, RepositorySystemSession session, InstallRequest request) 104 throws InstallationException { 105 InstallResult result = new InstallResult(request); 106 107 RequestTrace trace = RequestTrace.newChild(request.getTrace(), request); 108 109 List<Artifact> artifacts = new ArrayList<>(request.getArtifacts()); 110 List<? extends ArtifactGenerator> artifactGenerators = getArtifactGenerators(session, 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 = getMetadataGenerators(session, request); 127 128 IdentityHashMap<Metadata, Object> processedMetadata = new IdentityHashMap<>(); 129 130 List<Metadata> metadatas = Utils.prepareMetadata(metadataGenerators, artifacts); 131 132 syncContext.acquire(artifacts, Utils.combine(request.getMetadata(), metadatas)); 133 134 for (Metadata metadata : metadatas) { 135 install(session, trace, metadata); 136 processedMetadata.put(metadata, null); 137 result.addMetadata(metadata); 138 } 139 140 for (ListIterator<Artifact> iterator = artifacts.listIterator(); iterator.hasNext(); ) { 141 Artifact artifact = iterator.next(); 142 143 for (MetadataGenerator generator : metadataGenerators) { 144 artifact = generator.transformArtifact(artifact); 145 } 146 147 iterator.set(artifact); 148 149 install(session, trace, artifact); 150 if (artifact.getProperty(ArtifactGeneratorFactory.ARTIFACT_GENERATOR_ID, null) == null) { 151 result.addArtifact(artifact); 152 } 153 } 154 155 metadatas = Utils.finishMetadata(metadataGenerators, artifacts); 156 157 syncContext.acquire(null, metadatas); 158 159 for (Metadata metadata : metadatas) { 160 install(session, trace, metadata); 161 processedMetadata.put(metadata, null); 162 result.addMetadata(metadata); 163 } 164 165 for (Metadata metadata : request.getMetadata()) { 166 if (!processedMetadata.containsKey(metadata)) { 167 install(session, trace, metadata); 168 result.addMetadata(metadata); 169 } 170 } 171 172 return result; 173 } finally { 174 for (ArtifactGenerator artifactGenerator : artifactGenerators) { 175 try { 176 artifactGenerator.close(); 177 } catch (Exception e) { 178 logger.warn("ArtifactGenerator close failure: {}", artifactGenerator.generatorId(), e); 179 } 180 } 181 } 182 } 183 184 private List<? extends ArtifactGenerator> getArtifactGenerators( 185 RepositorySystemSession session, InstallRequest request) { 186 PrioritizedComponents<ArtifactGeneratorFactory> factories = 187 Utils.sortArtifactGeneratorFactories(session, artifactFactories); 188 189 List<ArtifactGenerator> generators = new ArrayList<>(); 190 191 for (PrioritizedComponent<ArtifactGeneratorFactory> factory : factories.getEnabled()) { 192 ArtifactGenerator generator = factory.getComponent().newInstance(session, request); 193 if (generator != null) { 194 generators.add(generator); 195 } 196 } 197 198 return generators; 199 } 200 201 private List<? extends MetadataGenerator> getMetadataGenerators( 202 RepositorySystemSession session, InstallRequest request) { 203 PrioritizedComponents<MetadataGeneratorFactory> factories = 204 Utils.sortMetadataGeneratorFactories(session, metadataFactories); 205 206 List<MetadataGenerator> generators = new ArrayList<>(); 207 208 for (PrioritizedComponent<MetadataGeneratorFactory> factory : factories.getEnabled()) { 209 MetadataGenerator generator = factory.getComponent().newInstance(session, request); 210 if (generator != null) { 211 generators.add(generator); 212 } 213 } 214 215 return generators; 216 } 217 218 private void install(RepositorySystemSession session, RequestTrace trace, Artifact artifact) 219 throws InstallationException { 220 final LocalRepositoryManager lrm = session.getLocalRepositoryManager(); 221 final Path srcPath = artifact.getPath(); 222 final Path dstPath = lrm.getRepository().getBasePath().resolve(lrm.getPathForLocalArtifact(artifact)); 223 224 artifactInstalling(session, trace, artifact, dstPath); 225 226 Exception exception = null; 227 try { 228 if (dstPath.equals(srcPath)) { 229 throw new IllegalStateException("cannot install " + dstPath + " to same path"); 230 } 231 232 pathProcessor.copy(srcPath, dstPath); 233 Files.setLastModifiedTime(dstPath, Files.getLastModifiedTime(srcPath)); 234 lrm.add(session, new LocalArtifactRegistration(artifact)); 235 } catch (Exception e) { 236 exception = e; 237 throw new InstallationException("Failed to install artifact " + artifact + ": " + e.getMessage(), e); 238 } finally { 239 artifactInstalled(session, trace, artifact, dstPath, exception); 240 } 241 } 242 243 private void install(RepositorySystemSession session, RequestTrace trace, Metadata metadata) 244 throws InstallationException { 245 LocalRepositoryManager lrm = session.getLocalRepositoryManager(); 246 247 Path dstPath = lrm.getRepository().getBasePath().resolve(lrm.getPathForLocalMetadata(metadata)); 248 249 metadataInstalling(session, trace, metadata, dstPath); 250 251 Exception exception = null; 252 try { 253 if (metadata instanceof MergeableMetadata) { 254 ((MergeableMetadata) metadata).merge(dstPath, dstPath); 255 } else { 256 if (dstPath.equals(metadata.getPath())) { 257 throw new IllegalStateException("cannot install " + dstPath + " to same path"); 258 } 259 pathProcessor.copy(metadata.getPath(), dstPath); 260 } 261 262 lrm.add(session, new LocalMetadataRegistration(metadata)); 263 } catch (Exception e) { 264 exception = e; 265 throw new InstallationException("Failed to install metadata " + metadata + ": " + e.getMessage(), e); 266 } finally { 267 metadataInstalled(session, trace, metadata, dstPath, exception); 268 } 269 } 270 271 private void artifactInstalling( 272 RepositorySystemSession session, RequestTrace trace, Artifact artifact, Path dstPath) { 273 RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.ARTIFACT_INSTALLING); 274 event.setTrace(trace); 275 event.setArtifact(artifact); 276 event.setRepository(session.getLocalRepositoryManager().getRepository()); 277 event.setPath(dstPath); 278 279 repositoryEventDispatcher.dispatch(event.build()); 280 } 281 282 private void artifactInstalled( 283 RepositorySystemSession session, RequestTrace trace, Artifact artifact, Path dstPath, Exception exception) { 284 RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.ARTIFACT_INSTALLED); 285 event.setTrace(trace); 286 event.setArtifact(artifact); 287 event.setRepository(session.getLocalRepositoryManager().getRepository()); 288 event.setPath(dstPath); 289 event.setException(exception); 290 291 repositoryEventDispatcher.dispatch(event.build()); 292 } 293 294 private void metadataInstalling( 295 RepositorySystemSession session, RequestTrace trace, Metadata metadata, Path dstPath) { 296 RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.METADATA_INSTALLING); 297 event.setTrace(trace); 298 event.setMetadata(metadata); 299 event.setRepository(session.getLocalRepositoryManager().getRepository()); 300 event.setPath(dstPath); 301 302 repositoryEventDispatcher.dispatch(event.build()); 303 } 304 305 private void metadataInstalled( 306 RepositorySystemSession session, RequestTrace trace, Metadata metadata, Path dstPath, Exception exception) { 307 RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.METADATA_INSTALLED); 308 event.setTrace(trace); 309 event.setMetadata(metadata); 310 event.setRepository(session.getLocalRepositoryManager().getRepository()); 311 event.setPath(dstPath); 312 event.setException(exception); 313 314 repositoryEventDispatcher.dispatch(event.build()); 315 } 316}