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.io.File; 026import java.io.InputStream; 027import java.util.ArrayList; 028import java.util.Collection; 029import java.util.IdentityHashMap; 030import java.util.List; 031import java.util.ListIterator; 032import java.util.Set; 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.io.FileProcessor; 053import org.eclipse.aether.spi.locator.Service; 054import org.eclipse.aether.spi.locator.ServiceLocator; 055import org.eclipse.aether.spi.synccontext.SyncContextFactory; 056import org.eclipse.aether.transform.FileTransformer; 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, Service { 067 068 private static final Logger LOGGER = LoggerFactory.getLogger(DefaultInstaller.class); 069 070 private FileProcessor fileProcessor; 071 072 private RepositoryEventDispatcher repositoryEventDispatcher; 073 074 private Collection<MetadataGeneratorFactory> metadataFactories = new ArrayList<>(); 075 076 private SyncContextFactory syncContextFactory; 077 078 @Deprecated 079 public DefaultInstaller() { 080 // enables default constructor 081 } 082 083 @Inject 084 public DefaultInstaller( 085 FileProcessor fileProcessor, 086 RepositoryEventDispatcher repositoryEventDispatcher, 087 Set<MetadataGeneratorFactory> metadataFactories, 088 SyncContextFactory syncContextFactory) { 089 setFileProcessor(fileProcessor); 090 setRepositoryEventDispatcher(repositoryEventDispatcher); 091 setMetadataGeneratorFactories(metadataFactories); 092 setSyncContextFactory(syncContextFactory); 093 } 094 095 public void initService(ServiceLocator locator) { 096 setFileProcessor(locator.getService(FileProcessor.class)); 097 setRepositoryEventDispatcher(locator.getService(RepositoryEventDispatcher.class)); 098 setMetadataGeneratorFactories(locator.getServices(MetadataGeneratorFactory.class)); 099 setSyncContextFactory(locator.getService(SyncContextFactory.class)); 100 } 101 102 public DefaultInstaller setFileProcessor(FileProcessor fileProcessor) { 103 this.fileProcessor = requireNonNull(fileProcessor, "file processor cannot be null"); 104 return this; 105 } 106 107 public DefaultInstaller setRepositoryEventDispatcher(RepositoryEventDispatcher repositoryEventDispatcher) { 108 this.repositoryEventDispatcher = 109 requireNonNull(repositoryEventDispatcher, "repository event dispatcher cannot be null"); 110 return this; 111 } 112 113 public DefaultInstaller addMetadataGeneratorFactory(MetadataGeneratorFactory factory) { 114 metadataFactories.add(requireNonNull(factory, "metadata generator factory cannot be null")); 115 return this; 116 } 117 118 public DefaultInstaller setMetadataGeneratorFactories(Collection<MetadataGeneratorFactory> metadataFactories) { 119 if (metadataFactories == null) { 120 this.metadataFactories = new ArrayList<>(); 121 } else { 122 this.metadataFactories = metadataFactories; 123 } 124 return this; 125 } 126 127 public DefaultInstaller setSyncContextFactory(SyncContextFactory syncContextFactory) { 128 this.syncContextFactory = requireNonNull(syncContextFactory, "sync context factory cannot be null"); 129 return this; 130 } 131 132 public InstallResult install(RepositorySystemSession session, InstallRequest request) throws InstallationException { 133 requireNonNull(session, "session cannot be null"); 134 requireNonNull(request, "request cannot be null"); 135 try (SyncContext syncContext = syncContextFactory.newInstance(session, false)) { 136 return install(syncContext, session, request); 137 } 138 } 139 140 private InstallResult install(SyncContext syncContext, RepositorySystemSession session, InstallRequest request) 141 throws InstallationException { 142 InstallResult result = new InstallResult(request); 143 144 RequestTrace trace = RequestTrace.newChild(request.getTrace(), request); 145 146 List<? extends MetadataGenerator> generators = getMetadataGenerators(session, request); 147 148 List<Artifact> artifacts = new ArrayList<>(request.getArtifacts()); 149 150 IdentityHashMap<Metadata, Object> processedMetadata = new IdentityHashMap<>(); 151 152 List<Metadata> metadatas = Utils.prepareMetadata(generators, artifacts); 153 154 syncContext.acquire(artifacts, Utils.combine(request.getMetadata(), metadatas)); 155 156 for (Metadata metadata : metadatas) { 157 install(session, trace, metadata); 158 processedMetadata.put(metadata, null); 159 result.addMetadata(metadata); 160 } 161 162 for (ListIterator<Artifact> iterator = artifacts.listIterator(); iterator.hasNext(); ) { 163 Artifact artifact = iterator.next(); 164 165 for (MetadataGenerator generator : generators) { 166 artifact = generator.transformArtifact(artifact); 167 } 168 169 iterator.set(artifact); 170 171 install(session, trace, artifact); 172 result.addArtifact(artifact); 173 } 174 175 metadatas = Utils.finishMetadata(generators, artifacts); 176 177 syncContext.acquire(null, metadatas); 178 179 for (Metadata metadata : metadatas) { 180 install(session, trace, metadata); 181 processedMetadata.put(metadata, null); 182 result.addMetadata(metadata); 183 } 184 185 for (Metadata metadata : request.getMetadata()) { 186 if (!processedMetadata.containsKey(metadata)) { 187 install(session, trace, metadata); 188 result.addMetadata(metadata); 189 } 190 } 191 192 return result; 193 } 194 195 private List<? extends MetadataGenerator> getMetadataGenerators( 196 RepositorySystemSession session, InstallRequest request) { 197 PrioritizedComponents<MetadataGeneratorFactory> factories = 198 Utils.sortMetadataGeneratorFactories(session, this.metadataFactories); 199 200 List<MetadataGenerator> generators = new ArrayList<>(); 201 202 for (PrioritizedComponent<MetadataGeneratorFactory> factory : factories.getEnabled()) { 203 MetadataGenerator generator = factory.getComponent().newInstance(session, request); 204 if (generator != null) { 205 generators.add(generator); 206 } 207 } 208 209 return generators; 210 } 211 212 private void install(RepositorySystemSession session, RequestTrace trace, Artifact artifact) 213 throws InstallationException { 214 LocalRepositoryManager lrm = session.getLocalRepositoryManager(); 215 216 File srcFile = artifact.getFile(); 217 218 Collection<FileTransformer> fileTransformers = 219 session.getFileTransformerManager().getTransformersForArtifact(artifact); 220 if (fileTransformers.isEmpty()) { 221 install(session, trace, artifact, lrm, srcFile, null); 222 } else { 223 for (FileTransformer fileTransformer : fileTransformers) { 224 install(session, trace, artifact, lrm, srcFile, fileTransformer); 225 } 226 } 227 } 228 229 private void install( 230 RepositorySystemSession session, 231 RequestTrace trace, 232 Artifact artifact, 233 LocalRepositoryManager lrm, 234 File srcFile, 235 FileTransformer fileTransformer) 236 throws InstallationException { 237 final Artifact targetArtifact; 238 if (fileTransformer != null) { 239 targetArtifact = fileTransformer.transformArtifact(artifact); 240 } else { 241 targetArtifact = artifact; 242 } 243 244 File dstFile = new File(lrm.getRepository().getBasedir(), lrm.getPathForLocalArtifact(targetArtifact)); 245 246 artifactInstalling(session, trace, targetArtifact, dstFile); 247 248 Exception exception = null; 249 try { 250 if (dstFile.equals(srcFile)) { 251 throw new IllegalStateException("cannot install " + dstFile + " to same path"); 252 } 253 254 boolean copy = "pom".equals(targetArtifact.getExtension()) 255 || srcFile.lastModified() != dstFile.lastModified() 256 || srcFile.length() != dstFile.length() 257 || !srcFile.exists(); 258 259 if (!copy) { 260 LOGGER.debug("Skipped re-installing {} to {}, seems unchanged", srcFile, dstFile); 261 } else if (fileTransformer != null) { 262 try (InputStream is = fileTransformer.transformData(srcFile)) { 263 fileProcessor.write(dstFile, is); 264 dstFile.setLastModified(srcFile.lastModified()); 265 } 266 } else { 267 fileProcessor.copy(srcFile, dstFile); 268 dstFile.setLastModified(srcFile.lastModified()); 269 } 270 271 lrm.add(session, new LocalArtifactRegistration(targetArtifact)); 272 } catch (Exception e) { 273 exception = e; 274 throw new InstallationException("Failed to install artifact " + targetArtifact + ": " + e.getMessage(), e); 275 } finally { 276 artifactInstalled(session, trace, targetArtifact, dstFile, exception); 277 } 278 } 279 280 private void install(RepositorySystemSession session, RequestTrace trace, Metadata metadata) 281 throws InstallationException { 282 LocalRepositoryManager lrm = session.getLocalRepositoryManager(); 283 284 File dstFile = new File(lrm.getRepository().getBasedir(), lrm.getPathForLocalMetadata(metadata)); 285 286 metadataInstalling(session, trace, metadata, dstFile); 287 288 Exception exception = null; 289 try { 290 if (metadata instanceof MergeableMetadata) { 291 ((MergeableMetadata) metadata).merge(dstFile, dstFile); 292 } else { 293 if (dstFile.equals(metadata.getFile())) { 294 throw new IllegalStateException("cannot install " + dstFile + " to same path"); 295 } 296 fileProcessor.copy(metadata.getFile(), dstFile); 297 } 298 299 lrm.add(session, new LocalMetadataRegistration(metadata)); 300 } catch (Exception e) { 301 exception = e; 302 throw new InstallationException("Failed to install metadata " + metadata + ": " + e.getMessage(), e); 303 } finally { 304 metadataInstalled(session, trace, metadata, dstFile, exception); 305 } 306 } 307 308 private void artifactInstalling( 309 RepositorySystemSession session, RequestTrace trace, Artifact artifact, File dstFile) { 310 RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.ARTIFACT_INSTALLING); 311 event.setTrace(trace); 312 event.setArtifact(artifact); 313 event.setRepository(session.getLocalRepositoryManager().getRepository()); 314 event.setFile(dstFile); 315 316 repositoryEventDispatcher.dispatch(event.build()); 317 } 318 319 private void artifactInstalled( 320 RepositorySystemSession session, RequestTrace trace, Artifact artifact, File dstFile, Exception exception) { 321 RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.ARTIFACT_INSTALLED); 322 event.setTrace(trace); 323 event.setArtifact(artifact); 324 event.setRepository(session.getLocalRepositoryManager().getRepository()); 325 event.setFile(dstFile); 326 event.setException(exception); 327 328 repositoryEventDispatcher.dispatch(event.build()); 329 } 330 331 private void metadataInstalling( 332 RepositorySystemSession session, RequestTrace trace, Metadata metadata, File dstFile) { 333 RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.METADATA_INSTALLING); 334 event.setTrace(trace); 335 event.setMetadata(metadata); 336 event.setRepository(session.getLocalRepositoryManager().getRepository()); 337 event.setFile(dstFile); 338 339 repositoryEventDispatcher.dispatch(event.build()); 340 } 341 342 private void metadataInstalled( 343 RepositorySystemSession session, RequestTrace trace, Metadata metadata, File dstFile, Exception exception) { 344 RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.METADATA_INSTALLED); 345 event.setTrace(trace); 346 event.setMetadata(metadata); 347 event.setRepository(session.getLocalRepositoryManager().getRepository()); 348 event.setFile(dstFile); 349 event.setException(exception); 350 351 repositoryEventDispatcher.dispatch(event.build()); 352 } 353}