001package org.eclipse.aether.internal.impl; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022import static java.util.Objects.requireNonNull; 023 024import java.io.File; 025import java.io.InputStream; 026import java.util.ArrayList; 027import java.util.Collection; 028import java.util.IdentityHashMap; 029import java.util.List; 030import java.util.Set; 031 032import javax.inject.Inject; 033import javax.inject.Named; 034 035import org.eclipse.aether.RepositoryEvent; 036import org.eclipse.aether.RepositoryEvent.EventType; 037import org.eclipse.aether.RepositorySystemSession; 038import org.eclipse.aether.RequestTrace; 039import org.eclipse.aether.SyncContext; 040import org.eclipse.aether.artifact.Artifact; 041import org.eclipse.aether.impl.Installer; 042import org.eclipse.aether.impl.MetadataGenerator; 043import org.eclipse.aether.impl.MetadataGeneratorFactory; 044import org.eclipse.aether.impl.RepositoryEventDispatcher; 045import org.eclipse.aether.impl.SyncContextFactory; 046import org.eclipse.aether.installation.InstallRequest; 047import org.eclipse.aether.installation.InstallResult; 048import org.eclipse.aether.installation.InstallationException; 049import org.eclipse.aether.metadata.MergeableMetadata; 050import org.eclipse.aether.metadata.Metadata; 051import org.eclipse.aether.repository.LocalArtifactRegistration; 052import org.eclipse.aether.repository.LocalMetadataRegistration; 053import org.eclipse.aether.repository.LocalRepositoryManager; 054import org.eclipse.aether.spi.io.FileProcessor; 055import org.eclipse.aether.spi.locator.Service; 056import org.eclipse.aether.spi.locator.ServiceLocator; 057import org.eclipse.aether.transform.FileTransformer; 058import org.slf4j.Logger; 059import org.slf4j.LoggerFactory; 060 061/** 062 */ 063@Named 064public class DefaultInstaller 065 implements Installer, Service 066{ 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<MetadataGeneratorFactory>(); 075 076 private SyncContextFactory syncContextFactory; 077 078 public DefaultInstaller() 079 { 080 // enables default constructor 081 } 082 083 @Inject 084 DefaultInstaller( FileProcessor fileProcessor, RepositoryEventDispatcher repositoryEventDispatcher, 085 Set<MetadataGeneratorFactory> metadataFactories, SyncContextFactory syncContextFactory ) 086 { 087 setFileProcessor( fileProcessor ); 088 setRepositoryEventDispatcher( repositoryEventDispatcher ); 089 setMetadataGeneratorFactories( metadataFactories ); 090 setSyncContextFactory( syncContextFactory ); 091 } 092 093 public void initService( ServiceLocator locator ) 094 { 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 { 103 this.fileProcessor = requireNonNull( fileProcessor, "file processor cannot be null" ); 104 return this; 105 } 106 107 public DefaultInstaller setRepositoryEventDispatcher( RepositoryEventDispatcher repositoryEventDispatcher ) 108 { 109 this.repositoryEventDispatcher = requireNonNull( repositoryEventDispatcher, "repository event dispatcher cannot be null" ); 110 return this; 111 } 112 113 public DefaultInstaller addMetadataGeneratorFactory( MetadataGeneratorFactory factory ) 114 { 115 metadataFactories.add( requireNonNull( factory, "metadata generator factory cannot be null" ) ); 116 return this; 117 } 118 119 public DefaultInstaller setMetadataGeneratorFactories( Collection<MetadataGeneratorFactory> metadataFactories ) 120 { 121 if ( metadataFactories == null ) 122 { 123 this.metadataFactories = new ArrayList<MetadataGeneratorFactory>(); 124 } 125 else 126 { 127 this.metadataFactories = metadataFactories; 128 } 129 return this; 130 } 131 132 public DefaultInstaller setSyncContextFactory( SyncContextFactory syncContextFactory ) 133 { 134 this.syncContextFactory = requireNonNull( syncContextFactory, "sync context factory cannot be null" ); 135 return this; 136 } 137 138 public InstallResult install( RepositorySystemSession session, InstallRequest request ) 139 throws InstallationException 140 { 141 SyncContext syncContext = syncContextFactory.newInstance( session, false ); 142 143 try 144 { 145 return install( syncContext, session, request ); 146 } 147 finally 148 { 149 syncContext.close(); 150 } 151 } 152 153 private InstallResult install( SyncContext syncContext, RepositorySystemSession session, InstallRequest request ) 154 throws InstallationException 155 { 156 InstallResult result = new InstallResult( request ); 157 158 RequestTrace trace = RequestTrace.newChild( request.getTrace(), request ); 159 160 List<? extends MetadataGenerator> generators = getMetadataGenerators( session, request ); 161 162 List<Artifact> artifacts = new ArrayList<Artifact>( request.getArtifacts() ); 163 164 IdentityHashMap<Metadata, Object> processedMetadata = new IdentityHashMap<Metadata, Object>(); 165 166 List<Metadata> metadatas = Utils.prepareMetadata( generators, artifacts ); 167 168 syncContext.acquire( artifacts, Utils.combine( request.getMetadata(), metadatas ) ); 169 170 for ( Metadata metadata : metadatas ) 171 { 172 install( session, trace, metadata ); 173 processedMetadata.put( metadata, null ); 174 result.addMetadata( metadata ); 175 } 176 177 for ( int i = 0; i < artifacts.size(); i++ ) 178 { 179 Artifact artifact = artifacts.get( i ); 180 181 for ( MetadataGenerator generator : generators ) 182 { 183 artifact = generator.transformArtifact( artifact ); 184 } 185 186 artifacts.set( i, artifact ); 187 188 install( session, trace, artifact ); 189 result.addArtifact( artifact ); 190 } 191 192 metadatas = Utils.finishMetadata( generators, artifacts ); 193 194 syncContext.acquire( null, metadatas ); 195 196 for ( Metadata metadata : metadatas ) 197 { 198 install( session, trace, metadata ); 199 processedMetadata.put( metadata, null ); 200 result.addMetadata( metadata ); 201 } 202 203 for ( Metadata metadata : request.getMetadata() ) 204 { 205 if ( !processedMetadata.containsKey( metadata ) ) 206 { 207 install( session, trace, metadata ); 208 result.addMetadata( metadata ); 209 } 210 } 211 212 return result; 213 } 214 215 private List<? extends MetadataGenerator> getMetadataGenerators( RepositorySystemSession session, 216 InstallRequest request ) 217 { 218 PrioritizedComponents<MetadataGeneratorFactory> factories = 219 Utils.sortMetadataGeneratorFactories( session, this.metadataFactories ); 220 221 List<MetadataGenerator> generators = new ArrayList<MetadataGenerator>(); 222 223 for ( PrioritizedComponent<MetadataGeneratorFactory> factory : factories.getEnabled() ) 224 { 225 MetadataGenerator generator = factory.getComponent().newInstance( session, request ); 226 if ( generator != null ) 227 { 228 generators.add( generator ); 229 } 230 } 231 232 return generators; 233 } 234 235 private void install( RepositorySystemSession session, RequestTrace trace, Artifact artifact ) 236 throws InstallationException 237 { 238 LocalRepositoryManager lrm = session.getLocalRepositoryManager(); 239 240 File srcFile = artifact.getFile(); 241 242 Collection<FileTransformer> fileTransformers = session.getFileTransformerManager().getTransformersForArtifact( artifact ); 243 if ( fileTransformers.isEmpty() ) 244 { 245 install( session, trace, artifact, lrm, srcFile, null ); 246 } 247 else 248 { 249 for ( FileTransformer fileTransformer : fileTransformers ) 250 { 251 install( session, trace, artifact, lrm, srcFile, fileTransformer ); 252 } 253 } 254 } 255 256 private void install( RepositorySystemSession session, RequestTrace trace, Artifact artifact, 257 LocalRepositoryManager lrm, File srcFile, FileTransformer fileTransformer ) 258 throws InstallationException 259 { 260 final Artifact targetArtifact; 261 if ( fileTransformer != null ) 262 { 263 targetArtifact = fileTransformer.transformArtifact( artifact ); 264 } 265 else 266 { 267 targetArtifact = artifact; 268 } 269 270 File dstFile = new File( lrm.getRepository().getBasedir(), lrm.getPathForLocalArtifact( targetArtifact ) ); 271 272 artifactInstalling( session, trace, targetArtifact, dstFile ); 273 274 Exception exception = null; 275 try 276 { 277 if ( dstFile.equals( srcFile ) ) 278 { 279 throw new IllegalStateException( "cannot install " + dstFile + " to same path" ); 280 } 281 282 boolean copy = 283 "pom".equals( targetArtifact.getExtension() ) || srcFile.lastModified() != dstFile.lastModified() 284 || srcFile.length() != dstFile.length() || !srcFile.exists(); 285 286 if ( !copy ) 287 { 288 LOGGER.debug( "Skipped re-installing {} to {}, seems unchanged", srcFile, dstFile ); 289 } 290 else if ( fileTransformer != null ) 291 { 292 try ( InputStream is = fileTransformer.transformData( srcFile ) ) 293 { 294 fileProcessor.write( dstFile, is ); 295 dstFile.setLastModified( srcFile.lastModified() ); 296 } 297 } 298 else 299 { 300 fileProcessor.copy( srcFile, dstFile ); 301 dstFile.setLastModified( srcFile.lastModified() ); 302 } 303 304 lrm.add( session, new LocalArtifactRegistration( targetArtifact ) ); 305 } 306 catch ( Exception e ) 307 { 308 exception = e; 309 throw new InstallationException( "Failed to install artifact " + targetArtifact + ": " + e.getMessage(), e ); 310 } 311 finally 312 { 313 artifactInstalled( session, trace, targetArtifact, dstFile, exception ); 314 } 315 } 316 317 private void install( RepositorySystemSession session, RequestTrace trace, Metadata metadata ) 318 throws InstallationException 319 { 320 LocalRepositoryManager lrm = session.getLocalRepositoryManager(); 321 322 File dstFile = new File( lrm.getRepository().getBasedir(), lrm.getPathForLocalMetadata( metadata ) ); 323 324 metadataInstalling( session, trace, metadata, dstFile ); 325 326 Exception exception = null; 327 try 328 { 329 if ( metadata instanceof MergeableMetadata ) 330 { 331 ( (MergeableMetadata) metadata ).merge( dstFile, dstFile ); 332 } 333 else 334 { 335 if ( dstFile.equals( metadata.getFile() ) ) 336 { 337 throw new IllegalStateException( "cannot install " + dstFile + " to same path" ); 338 } 339 fileProcessor.copy( metadata.getFile(), dstFile ); 340 } 341 342 lrm.add( session, new LocalMetadataRegistration( metadata ) ); 343 } 344 catch ( Exception e ) 345 { 346 exception = e; 347 throw new InstallationException( "Failed to install metadata " + metadata + ": " + e.getMessage(), e ); 348 } 349 finally 350 { 351 metadataInstalled( session, trace, metadata, dstFile, exception ); 352 } 353 } 354 355 private void artifactInstalling( RepositorySystemSession session, RequestTrace trace, Artifact artifact, 356 File dstFile ) 357 { 358 RepositoryEvent.Builder event = new RepositoryEvent.Builder( session, EventType.ARTIFACT_INSTALLING ); 359 event.setTrace( trace ); 360 event.setArtifact( artifact ); 361 event.setRepository( session.getLocalRepositoryManager().getRepository() ); 362 event.setFile( dstFile ); 363 364 repositoryEventDispatcher.dispatch( event.build() ); 365 } 366 367 private void artifactInstalled( RepositorySystemSession session, RequestTrace trace, Artifact artifact, 368 File dstFile, Exception exception ) 369 { 370 RepositoryEvent.Builder event = new RepositoryEvent.Builder( session, EventType.ARTIFACT_INSTALLED ); 371 event.setTrace( trace ); 372 event.setArtifact( artifact ); 373 event.setRepository( session.getLocalRepositoryManager().getRepository() ); 374 event.setFile( dstFile ); 375 event.setException( exception ); 376 377 repositoryEventDispatcher.dispatch( event.build() ); 378 } 379 380 private void metadataInstalling( RepositorySystemSession session, RequestTrace trace, Metadata metadata, 381 File dstFile ) 382 { 383 RepositoryEvent.Builder event = new RepositoryEvent.Builder( session, EventType.METADATA_INSTALLING ); 384 event.setTrace( trace ); 385 event.setMetadata( metadata ); 386 event.setRepository( session.getLocalRepositoryManager().getRepository() ); 387 event.setFile( dstFile ); 388 389 repositoryEventDispatcher.dispatch( event.build() ); 390 } 391 392 private void metadataInstalled( RepositorySystemSession session, RequestTrace trace, Metadata metadata, 393 File dstFile, Exception exception ) 394 { 395 RepositoryEvent.Builder event = new RepositoryEvent.Builder( session, EventType.METADATA_INSTALLED ); 396 event.setTrace( trace ); 397 event.setMetadata( metadata ); 398 event.setRepository( session.getLocalRepositoryManager().getRepository() ); 399 event.setFile( dstFile ); 400 event.setException( exception ); 401 402 repositoryEventDispatcher.dispatch( event.build() ); 403 } 404 405}