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.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.io.PathProcessor; 053import org.eclipse.aether.spi.synccontext.SyncContextFactory; 054 055import static java.util.Objects.requireNonNull; 056 057/** 058 */ 059@Singleton 060@Named 061public class DefaultInstaller implements Installer { 062 private final PathProcessor pathProcessor; 063 064 private final RepositoryEventDispatcher repositoryEventDispatcher; 065 066 private final Map<String, MetadataGeneratorFactory> metadataFactories; 067 068 private final SyncContextFactory syncContextFactory; 069 070 @Inject 071 public DefaultInstaller( 072 PathProcessor pathProcessor, 073 RepositoryEventDispatcher repositoryEventDispatcher, 074 Map<String, MetadataGeneratorFactory> metadataFactories, 075 SyncContextFactory syncContextFactory) { 076 this.pathProcessor = requireNonNull(pathProcessor, "path processor cannot be null"); 077 this.repositoryEventDispatcher = 078 requireNonNull(repositoryEventDispatcher, "repository event dispatcher cannot be null"); 079 this.metadataFactories = Collections.unmodifiableMap(metadataFactories); 080 this.syncContextFactory = requireNonNull(syncContextFactory, "sync context factory cannot be null"); 081 } 082 083 @Override 084 public InstallResult install(RepositorySystemSession session, InstallRequest request) throws InstallationException { 085 requireNonNull(session, "session cannot be null"); 086 requireNonNull(request, "request cannot be null"); 087 try (SyncContext syncContext = syncContextFactory.newInstance(session, false)) { 088 return install(syncContext, session, request); 089 } 090 } 091 092 private InstallResult install(SyncContext syncContext, RepositorySystemSession session, InstallRequest request) 093 throws InstallationException { 094 InstallResult result = new InstallResult(request); 095 096 RequestTrace trace = RequestTrace.newChild(request.getTrace(), request); 097 098 List<? extends MetadataGenerator> generators = getMetadataGenerators(session, request); 099 100 List<Artifact> artifacts = new ArrayList<>(request.getArtifacts()); 101 102 IdentityHashMap<Metadata, Object> processedMetadata = new IdentityHashMap<>(); 103 104 List<Metadata> metadatas = Utils.prepareMetadata(generators, artifacts); 105 106 syncContext.acquire(artifacts, Utils.combine(request.getMetadata(), metadatas)); 107 108 for (Metadata metadata : metadatas) { 109 install(session, trace, metadata); 110 processedMetadata.put(metadata, null); 111 result.addMetadata(metadata); 112 } 113 114 for (ListIterator<Artifact> iterator = artifacts.listIterator(); iterator.hasNext(); ) { 115 Artifact artifact = iterator.next(); 116 117 for (MetadataGenerator generator : generators) { 118 artifact = generator.transformArtifact(artifact); 119 } 120 121 iterator.set(artifact); 122 123 install(session, trace, artifact); 124 result.addArtifact(artifact); 125 } 126 127 metadatas = Utils.finishMetadata(generators, artifacts); 128 129 syncContext.acquire(null, metadatas); 130 131 for (Metadata metadata : metadatas) { 132 install(session, trace, metadata); 133 processedMetadata.put(metadata, null); 134 result.addMetadata(metadata); 135 } 136 137 for (Metadata metadata : request.getMetadata()) { 138 if (!processedMetadata.containsKey(metadata)) { 139 install(session, trace, metadata); 140 result.addMetadata(metadata); 141 } 142 } 143 144 return result; 145 } 146 147 private List<? extends MetadataGenerator> getMetadataGenerators( 148 RepositorySystemSession session, InstallRequest request) { 149 PrioritizedComponents<MetadataGeneratorFactory> factories = 150 Utils.sortMetadataGeneratorFactories(session, metadataFactories); 151 152 List<MetadataGenerator> generators = new ArrayList<>(); 153 154 for (PrioritizedComponent<MetadataGeneratorFactory> factory : factories.getEnabled()) { 155 MetadataGenerator generator = factory.getComponent().newInstance(session, request); 156 if (generator != null) { 157 generators.add(generator); 158 } 159 } 160 161 return generators; 162 } 163 164 private void install(RepositorySystemSession session, RequestTrace trace, Artifact artifact) 165 throws InstallationException { 166 final LocalRepositoryManager lrm = session.getLocalRepositoryManager(); 167 final Path srcPath = artifact.getPath(); 168 final Path dstPath = lrm.getRepository().getBasePath().resolve(lrm.getPathForLocalArtifact(artifact)); 169 170 artifactInstalling(session, trace, artifact, dstPath); 171 172 Exception exception = null; 173 try { 174 if (dstPath.equals(srcPath)) { 175 throw new IllegalStateException("cannot install " + dstPath + " to same path"); 176 } 177 178 pathProcessor.copy(srcPath, dstPath); 179 Files.setLastModifiedTime(dstPath, Files.getLastModifiedTime(srcPath)); 180 lrm.add(session, new LocalArtifactRegistration(artifact)); 181 } catch (Exception e) { 182 exception = e; 183 throw new InstallationException("Failed to install artifact " + artifact + ": " + e.getMessage(), e); 184 } finally { 185 artifactInstalled(session, trace, artifact, dstPath, exception); 186 } 187 } 188 189 private void install(RepositorySystemSession session, RequestTrace trace, Metadata metadata) 190 throws InstallationException { 191 LocalRepositoryManager lrm = session.getLocalRepositoryManager(); 192 193 Path dstPath = lrm.getRepository().getBasePath().resolve(lrm.getPathForLocalMetadata(metadata)); 194 195 metadataInstalling(session, trace, metadata, dstPath); 196 197 Exception exception = null; 198 try { 199 if (metadata instanceof MergeableMetadata) { 200 ((MergeableMetadata) metadata).merge(dstPath, dstPath); 201 } else { 202 if (dstPath.equals(metadata.getPath())) { 203 throw new IllegalStateException("cannot install " + dstPath + " to same path"); 204 } 205 pathProcessor.copy(metadata.getPath(), dstPath); 206 } 207 208 lrm.add(session, new LocalMetadataRegistration(metadata)); 209 } catch (Exception e) { 210 exception = e; 211 throw new InstallationException("Failed to install metadata " + metadata + ": " + e.getMessage(), e); 212 } finally { 213 metadataInstalled(session, trace, metadata, dstPath, exception); 214 } 215 } 216 217 private void artifactInstalling( 218 RepositorySystemSession session, RequestTrace trace, Artifact artifact, Path dstPath) { 219 RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.ARTIFACT_INSTALLING); 220 event.setTrace(trace); 221 event.setArtifact(artifact); 222 event.setRepository(session.getLocalRepositoryManager().getRepository()); 223 event.setPath(dstPath); 224 225 repositoryEventDispatcher.dispatch(event.build()); 226 } 227 228 private void artifactInstalled( 229 RepositorySystemSession session, RequestTrace trace, Artifact artifact, Path dstPath, Exception exception) { 230 RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.ARTIFACT_INSTALLED); 231 event.setTrace(trace); 232 event.setArtifact(artifact); 233 event.setRepository(session.getLocalRepositoryManager().getRepository()); 234 event.setPath(dstPath); 235 event.setException(exception); 236 237 repositoryEventDispatcher.dispatch(event.build()); 238 } 239 240 private void metadataInstalling( 241 RepositorySystemSession session, RequestTrace trace, Metadata metadata, Path dstPath) { 242 RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.METADATA_INSTALLING); 243 event.setTrace(trace); 244 event.setMetadata(metadata); 245 event.setRepository(session.getLocalRepositoryManager().getRepository()); 246 event.setPath(dstPath); 247 248 repositoryEventDispatcher.dispatch(event.build()); 249 } 250 251 private void metadataInstalled( 252 RepositorySystemSession session, RequestTrace trace, Metadata metadata, Path dstPath, Exception exception) { 253 RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.METADATA_INSTALLED); 254 event.setTrace(trace); 255 event.setMetadata(metadata); 256 event.setRepository(session.getLocalRepositoryManager().getRepository()); 257 event.setPath(dstPath); 258 event.setException(exception); 259 260 repositoryEventDispatcher.dispatch(event.build()); 261 } 262}