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<>(); 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, 110 "repository event dispatcher cannot be null" ); 111 return this; 112 } 113 114 public DefaultInstaller addMetadataGeneratorFactory( MetadataGeneratorFactory factory ) 115 { 116 metadataFactories.add( requireNonNull( factory, "metadata generator factory cannot be null" ) ); 117 return this; 118 } 119 120 public DefaultInstaller setMetadataGeneratorFactories( Collection<MetadataGeneratorFactory> metadataFactories ) 121 { 122 if ( metadataFactories == null ) 123 { 124 this.metadataFactories = new ArrayList<>(); 125 } 126 else 127 { 128 this.metadataFactories = metadataFactories; 129 } 130 return this; 131 } 132 133 public DefaultInstaller setSyncContextFactory( SyncContextFactory syncContextFactory ) 134 { 135 this.syncContextFactory = requireNonNull( syncContextFactory, "sync context factory cannot be null" ); 136 return this; 137 } 138 139 public InstallResult install( RepositorySystemSession session, InstallRequest request ) 140 throws InstallationException 141 { 142 143 try ( SyncContext syncContext = syncContextFactory.newInstance( session, false ) ) 144 { 145 return install( syncContext, session, request ); 146 } 147 } 148 149 private InstallResult install( SyncContext syncContext, RepositorySystemSession session, InstallRequest request ) 150 throws InstallationException 151 { 152 InstallResult result = new InstallResult( request ); 153 154 RequestTrace trace = RequestTrace.newChild( request.getTrace(), request ); 155 156 List<? extends MetadataGenerator> generators = getMetadataGenerators( session, request ); 157 158 List<Artifact> artifacts = new ArrayList<>( request.getArtifacts() ); 159 160 IdentityHashMap<Metadata, Object> processedMetadata = new IdentityHashMap<>(); 161 162 List<Metadata> metadatas = Utils.prepareMetadata( generators, artifacts ); 163 164 syncContext.acquire( artifacts, Utils.combine( request.getMetadata(), metadatas ) ); 165 166 for ( Metadata metadata : metadatas ) 167 { 168 install( session, trace, metadata ); 169 processedMetadata.put( metadata, null ); 170 result.addMetadata( metadata ); 171 } 172 173 for ( int i = 0; i < artifacts.size(); i++ ) 174 { 175 Artifact artifact = artifacts.get( i ); 176 177 for ( MetadataGenerator generator : generators ) 178 { 179 artifact = generator.transformArtifact( artifact ); 180 } 181 182 artifacts.set( i, artifact ); 183 184 install( session, trace, artifact ); 185 result.addArtifact( artifact ); 186 } 187 188 metadatas = Utils.finishMetadata( generators, artifacts ); 189 190 syncContext.acquire( null, 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 ( Metadata metadata : request.getMetadata() ) 200 { 201 if ( !processedMetadata.containsKey( metadata ) ) 202 { 203 install( session, trace, metadata ); 204 result.addMetadata( metadata ); 205 } 206 } 207 208 return result; 209 } 210 211 private List<? extends MetadataGenerator> getMetadataGenerators( RepositorySystemSession session, 212 InstallRequest request ) 213 { 214 PrioritizedComponents<MetadataGeneratorFactory> factories = 215 Utils.sortMetadataGeneratorFactories( session, this.metadataFactories ); 216 217 List<MetadataGenerator> generators = new ArrayList<>(); 218 219 for ( PrioritizedComponent<MetadataGeneratorFactory> factory : factories.getEnabled() ) 220 { 221 MetadataGenerator generator = factory.getComponent().newInstance( session, request ); 222 if ( generator != null ) 223 { 224 generators.add( generator ); 225 } 226 } 227 228 return generators; 229 } 230 231 private void install( RepositorySystemSession session, RequestTrace trace, Artifact artifact ) 232 throws InstallationException 233 { 234 LocalRepositoryManager lrm = session.getLocalRepositoryManager(); 235 236 File srcFile = artifact.getFile(); 237 238 Collection<FileTransformer> fileTransformers = session.getFileTransformerManager() 239 .getTransformersForArtifact( artifact ); 240 if ( fileTransformers.isEmpty() ) 241 { 242 install( session, trace, artifact, lrm, srcFile, null ); 243 } 244 else 245 { 246 for ( FileTransformer fileTransformer : fileTransformers ) 247 { 248 install( session, trace, artifact, lrm, srcFile, fileTransformer ); 249 } 250 } 251 } 252 253 private void install( RepositorySystemSession session, RequestTrace trace, Artifact artifact, 254 LocalRepositoryManager lrm, File srcFile, FileTransformer fileTransformer ) 255 throws InstallationException 256 { 257 final Artifact targetArtifact; 258 if ( fileTransformer != null ) 259 { 260 targetArtifact = fileTransformer.transformArtifact( artifact ); 261 } 262 else 263 { 264 targetArtifact = artifact; 265 } 266 267 File dstFile = new File( lrm.getRepository().getBasedir(), lrm.getPathForLocalArtifact( targetArtifact ) ); 268 269 artifactInstalling( session, trace, targetArtifact, dstFile ); 270 271 Exception exception = null; 272 try 273 { 274 if ( dstFile.equals( srcFile ) ) 275 { 276 throw new IllegalStateException( "cannot install " + dstFile + " to same path" ); 277 } 278 279 boolean copy = 280 "pom".equals( targetArtifact.getExtension() ) || srcFile.lastModified() != dstFile.lastModified() 281 || srcFile.length() != dstFile.length() || !srcFile.exists(); 282 283 if ( !copy ) 284 { 285 LOGGER.debug( "Skipped re-installing {} to {}, seems unchanged", srcFile, dstFile ); 286 } 287 else if ( fileTransformer != null ) 288 { 289 try ( InputStream is = fileTransformer.transformData( srcFile ) ) 290 { 291 fileProcessor.write( dstFile, is ); 292 dstFile.setLastModified( srcFile.lastModified() ); 293 } 294 } 295 else 296 { 297 fileProcessor.copy( srcFile, dstFile ); 298 dstFile.setLastModified( srcFile.lastModified() ); 299 } 300 301 lrm.add( session, new LocalArtifactRegistration( targetArtifact ) ); 302 } 303 catch ( Exception e ) 304 { 305 exception = e; 306 throw new InstallationException( "Failed to install artifact " + targetArtifact + ": " + e.getMessage(), 307 e ); 308 } 309 finally 310 { 311 artifactInstalled( session, trace, targetArtifact, dstFile, exception ); 312 } 313 } 314 315 private void install( RepositorySystemSession session, RequestTrace trace, Metadata metadata ) 316 throws InstallationException 317 { 318 LocalRepositoryManager lrm = session.getLocalRepositoryManager(); 319 320 File dstFile = new File( lrm.getRepository().getBasedir(), lrm.getPathForLocalMetadata( metadata ) ); 321 322 metadataInstalling( session, trace, metadata, dstFile ); 323 324 Exception exception = null; 325 try 326 { 327 if ( metadata instanceof MergeableMetadata ) 328 { 329 ( (MergeableMetadata) metadata ).merge( dstFile, dstFile ); 330 } 331 else 332 { 333 if ( dstFile.equals( metadata.getFile() ) ) 334 { 335 throw new IllegalStateException( "cannot install " + dstFile + " to same path" ); 336 } 337 fileProcessor.copy( metadata.getFile(), dstFile ); 338 } 339 340 lrm.add( session, new LocalMetadataRegistration( metadata ) ); 341 } 342 catch ( Exception e ) 343 { 344 exception = e; 345 throw new InstallationException( "Failed to install metadata " + metadata + ": " + e.getMessage(), e ); 346 } 347 finally 348 { 349 metadataInstalled( session, trace, metadata, dstFile, exception ); 350 } 351 } 352 353 private void artifactInstalling( RepositorySystemSession session, RequestTrace trace, Artifact artifact, 354 File dstFile ) 355 { 356 RepositoryEvent.Builder event = new RepositoryEvent.Builder( session, EventType.ARTIFACT_INSTALLING ); 357 event.setTrace( trace ); 358 event.setArtifact( artifact ); 359 event.setRepository( session.getLocalRepositoryManager().getRepository() ); 360 event.setFile( dstFile ); 361 362 repositoryEventDispatcher.dispatch( event.build() ); 363 } 364 365 private void artifactInstalled( RepositorySystemSession session, RequestTrace trace, Artifact artifact, 366 File dstFile, Exception exception ) 367 { 368 RepositoryEvent.Builder event = new RepositoryEvent.Builder( session, EventType.ARTIFACT_INSTALLED ); 369 event.setTrace( trace ); 370 event.setArtifact( artifact ); 371 event.setRepository( session.getLocalRepositoryManager().getRepository() ); 372 event.setFile( dstFile ); 373 event.setException( exception ); 374 375 repositoryEventDispatcher.dispatch( event.build() ); 376 } 377 378 private void metadataInstalling( RepositorySystemSession session, RequestTrace trace, Metadata metadata, 379 File dstFile ) 380 { 381 RepositoryEvent.Builder event = new RepositoryEvent.Builder( session, EventType.METADATA_INSTALLING ); 382 event.setTrace( trace ); 383 event.setMetadata( metadata ); 384 event.setRepository( session.getLocalRepositoryManager().getRepository() ); 385 event.setFile( dstFile ); 386 387 repositoryEventDispatcher.dispatch( event.build() ); 388 } 389 390 private void metadataInstalled( RepositorySystemSession session, RequestTrace trace, Metadata metadata, 391 File dstFile, Exception exception ) 392 { 393 RepositoryEvent.Builder event = new RepositoryEvent.Builder( session, EventType.METADATA_INSTALLED ); 394 event.setTrace( trace ); 395 event.setMetadata( metadata ); 396 event.setRepository( session.getLocalRepositoryManager().getRepository() ); 397 event.setFile( dstFile ); 398 event.setException( exception ); 399 400 repositoryEventDispatcher.dispatch( event.build() ); 401 } 402 403}