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