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.*; 027import java.util.ArrayList; 028import java.util.Collections; 029import java.util.IdentityHashMap; 030import java.util.List; 031import java.util.ListIterator; 032import java.util.Map; 033 034import org.eclipse.aether.RepositoryEvent; 035import org.eclipse.aether.RepositoryEvent.EventType; 036import org.eclipse.aether.RepositorySystemSession; 037import org.eclipse.aether.RequestTrace; 038import org.eclipse.aether.SyncContext; 039import org.eclipse.aether.artifact.Artifact; 040import org.eclipse.aether.impl.Installer; 041import org.eclipse.aether.impl.MetadataGenerator; 042import org.eclipse.aether.impl.MetadataGeneratorFactory; 043import org.eclipse.aether.impl.RepositoryEventDispatcher; 044import org.eclipse.aether.installation.InstallRequest; 045import org.eclipse.aether.installation.InstallResult; 046import org.eclipse.aether.installation.InstallationException; 047import org.eclipse.aether.metadata.MergeableMetadata; 048import org.eclipse.aether.metadata.Metadata; 049import org.eclipse.aether.repository.LocalArtifactRegistration; 050import org.eclipse.aether.repository.LocalMetadataRegistration; 051import org.eclipse.aether.repository.LocalRepositoryManager; 052import org.eclipse.aether.spi.artifact.generator.ArtifactGenerator; 053import org.eclipse.aether.spi.artifact.generator.ArtifactGeneratorFactory; 054import org.eclipse.aether.spi.io.PathProcessor; 055import org.eclipse.aether.spi.synccontext.SyncContextFactory; 056import org.slf4j.Logger; 057import org.slf4j.LoggerFactory; 058 059import static java.util.Objects.requireNonNull; 060 061/** 062 */ 063@Singleton 064@Named 065public class DefaultInstaller implements Installer { 066 private final Logger logger = LoggerFactory.getLogger(getClass()); 067 068 private final PathProcessor pathProcessor; 069 070 private final RepositoryEventDispatcher repositoryEventDispatcher; 071 072 private final Map<String, ArtifactGeneratorFactory> artifactFactories; 073 074 private final Map<String, MetadataGeneratorFactory> metadataFactories; 075 076 private final SyncContextFactory syncContextFactory; 077 078 @Inject 079 public DefaultInstaller( 080 PathProcessor pathProcessor, 081 RepositoryEventDispatcher repositoryEventDispatcher, 082 Map<String, ArtifactGeneratorFactory> artifactFactories, 083 Map<String, MetadataGeneratorFactory> metadataFactories, 084 SyncContextFactory syncContextFactory) { 085 this.pathProcessor = requireNonNull(pathProcessor, "path processor cannot be null"); 086 this.repositoryEventDispatcher = 087 requireNonNull(repositoryEventDispatcher, "repository event dispatcher cannot be null"); 088 this.artifactFactories = Collections.unmodifiableMap(artifactFactories); 089 this.metadataFactories = Collections.unmodifiableMap(metadataFactories); 090 this.syncContextFactory = requireNonNull(syncContextFactory, "sync context factory cannot be null"); 091 } 092 093 @Override 094 public InstallResult install(RepositorySystemSession session, InstallRequest request) throws InstallationException { 095 requireNonNull(session, "session cannot be null"); 096 requireNonNull(request, "request cannot be null"); 097 try (SyncContext syncContext = syncContextFactory.newInstance(session, false)) { 098 return install(syncContext, session, request); 099 } 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}