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