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