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