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.ListIterator; 031import java.util.Set; 032 033import javax.inject.Inject; 034import javax.inject.Named; 035import javax.inject.Singleton; 036 037import org.eclipse.aether.RepositoryEvent; 038import org.eclipse.aether.RepositoryEvent.EventType; 039import org.eclipse.aether.RepositorySystemSession; 040import org.eclipse.aether.RequestTrace; 041import org.eclipse.aether.SyncContext; 042import org.eclipse.aether.artifact.Artifact; 043import org.eclipse.aether.impl.Installer; 044import org.eclipse.aether.impl.MetadataGenerator; 045import org.eclipse.aether.impl.MetadataGeneratorFactory; 046import org.eclipse.aether.impl.RepositoryEventDispatcher; 047import org.eclipse.aether.spi.synccontext.SyncContextFactory; 048import org.eclipse.aether.installation.InstallRequest; 049import org.eclipse.aether.installation.InstallResult; 050import org.eclipse.aether.installation.InstallationException; 051import org.eclipse.aether.metadata.MergeableMetadata; 052import org.eclipse.aether.metadata.Metadata; 053import org.eclipse.aether.repository.LocalArtifactRegistration; 054import org.eclipse.aether.repository.LocalMetadataRegistration; 055import org.eclipse.aether.repository.LocalRepositoryManager; 056import org.eclipse.aether.spi.io.FileProcessor; 057import org.eclipse.aether.spi.locator.Service; 058import org.eclipse.aether.spi.locator.ServiceLocator; 059import org.eclipse.aether.transform.FileTransformer; 060import org.slf4j.Logger; 061import org.slf4j.LoggerFactory; 062 063/** 064 */ 065@Singleton 066@Named 067public class DefaultInstaller 068 implements Installer, Service 069{ 070 071 private static final Logger LOGGER = LoggerFactory.getLogger( DefaultInstaller.class ); 072 073 private FileProcessor fileProcessor; 074 075 private RepositoryEventDispatcher repositoryEventDispatcher; 076 077 private Collection<MetadataGeneratorFactory> metadataFactories = new ArrayList<>(); 078 079 private SyncContextFactory syncContextFactory; 080 081 public DefaultInstaller() 082 { 083 // enables default constructor 084 } 085 086 @Inject 087 DefaultInstaller( FileProcessor fileProcessor, RepositoryEventDispatcher repositoryEventDispatcher, 088 Set<MetadataGeneratorFactory> metadataFactories, SyncContextFactory syncContextFactory ) 089 { 090 setFileProcessor( fileProcessor ); 091 setRepositoryEventDispatcher( repositoryEventDispatcher ); 092 setMetadataGeneratorFactories( metadataFactories ); 093 setSyncContextFactory( syncContextFactory ); 094 } 095 096 public void initService( ServiceLocator locator ) 097 { 098 setFileProcessor( locator.getService( FileProcessor.class ) ); 099 setRepositoryEventDispatcher( locator.getService( RepositoryEventDispatcher.class ) ); 100 setMetadataGeneratorFactories( locator.getServices( MetadataGeneratorFactory.class ) ); 101 setSyncContextFactory( locator.getService( SyncContextFactory.class ) ); 102 } 103 104 public DefaultInstaller setFileProcessor( FileProcessor fileProcessor ) 105 { 106 this.fileProcessor = requireNonNull( fileProcessor, "file processor cannot be null" ); 107 return this; 108 } 109 110 public DefaultInstaller setRepositoryEventDispatcher( RepositoryEventDispatcher repositoryEventDispatcher ) 111 { 112 this.repositoryEventDispatcher = requireNonNull( repositoryEventDispatcher, 113 "repository event dispatcher cannot be null" ); 114 return this; 115 } 116 117 public DefaultInstaller addMetadataGeneratorFactory( MetadataGeneratorFactory factory ) 118 { 119 metadataFactories.add( requireNonNull( factory, "metadata generator factory cannot be null" ) ); 120 return this; 121 } 122 123 public DefaultInstaller setMetadataGeneratorFactories( Collection<MetadataGeneratorFactory> metadataFactories ) 124 { 125 if ( metadataFactories == null ) 126 { 127 this.metadataFactories = new ArrayList<>(); 128 } 129 else 130 { 131 this.metadataFactories = metadataFactories; 132 } 133 return this; 134 } 135 136 public DefaultInstaller setSyncContextFactory( SyncContextFactory syncContextFactory ) 137 { 138 this.syncContextFactory = requireNonNull( syncContextFactory, "sync context factory cannot be null" ); 139 return this; 140 } 141 142 public InstallResult install( RepositorySystemSession session, InstallRequest request ) 143 throws InstallationException 144 { 145 requireNonNull( session, "session cannot be null" ); 146 requireNonNull( request, "request cannot be null" ); 147 try ( SyncContext syncContext = syncContextFactory.newInstance( session, false ) ) 148 { 149 return install( syncContext, session, request ); 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<>( request.getArtifacts() ); 163 164 IdentityHashMap<Metadata, Object> processedMetadata = new IdentityHashMap<>(); 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 ( ListIterator<Artifact> iterator = artifacts.listIterator(); iterator.hasNext(); ) 178 { 179 Artifact artifact = iterator.next(); 180 181 for ( MetadataGenerator generator : generators ) 182 { 183 artifact = generator.transformArtifact( artifact ); 184 } 185 186 iterator.set( 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<>(); 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() 243 .getTransformersForArtifact( artifact ); 244 if ( fileTransformers.isEmpty() ) 245 { 246 install( session, trace, artifact, lrm, srcFile, null ); 247 } 248 else 249 { 250 for ( FileTransformer fileTransformer : fileTransformers ) 251 { 252 install( session, trace, artifact, lrm, srcFile, fileTransformer ); 253 } 254 } 255 } 256 257 private void install( RepositorySystemSession session, RequestTrace trace, Artifact artifact, 258 LocalRepositoryManager lrm, File srcFile, FileTransformer fileTransformer ) 259 throws InstallationException 260 { 261 final Artifact targetArtifact; 262 if ( fileTransformer != null ) 263 { 264 targetArtifact = fileTransformer.transformArtifact( artifact ); 265 } 266 else 267 { 268 targetArtifact = artifact; 269 } 270 271 File dstFile = new File( lrm.getRepository().getBasedir(), lrm.getPathForLocalArtifact( targetArtifact ) ); 272 273 artifactInstalling( session, trace, targetArtifact, dstFile ); 274 275 Exception exception = null; 276 try 277 { 278 if ( dstFile.equals( srcFile ) ) 279 { 280 throw new IllegalStateException( "cannot install " + dstFile + " to same path" ); 281 } 282 283 boolean copy = 284 "pom".equals( targetArtifact.getExtension() ) || srcFile.lastModified() != dstFile.lastModified() 285 || srcFile.length() != dstFile.length() || !srcFile.exists(); 286 287 if ( !copy ) 288 { 289 LOGGER.debug( "Skipped re-installing {} to {}, seems unchanged", srcFile, dstFile ); 290 } 291 else if ( fileTransformer != null ) 292 { 293 try ( InputStream is = fileTransformer.transformData( srcFile ) ) 294 { 295 fileProcessor.write( dstFile, is ); 296 dstFile.setLastModified( srcFile.lastModified() ); 297 } 298 } 299 else 300 { 301 fileProcessor.copy( srcFile, dstFile ); 302 dstFile.setLastModified( srcFile.lastModified() ); 303 } 304 305 lrm.add( session, new LocalArtifactRegistration( targetArtifact ) ); 306 } 307 catch ( Exception e ) 308 { 309 exception = e; 310 throw new InstallationException( "Failed to install artifact " + targetArtifact + ": " + e.getMessage(), 311 e ); 312 } 313 finally 314 { 315 artifactInstalled( session, trace, targetArtifact, dstFile, exception ); 316 } 317 } 318 319 private void install( RepositorySystemSession session, RequestTrace trace, Metadata metadata ) 320 throws InstallationException 321 { 322 LocalRepositoryManager lrm = session.getLocalRepositoryManager(); 323 324 File dstFile = new File( lrm.getRepository().getBasedir(), lrm.getPathForLocalMetadata( metadata ) ); 325 326 metadataInstalling( session, trace, metadata, dstFile ); 327 328 Exception exception = null; 329 try 330 { 331 if ( metadata instanceof MergeableMetadata ) 332 { 333 ( (MergeableMetadata) metadata ).merge( dstFile, dstFile ); 334 } 335 else 336 { 337 if ( dstFile.equals( metadata.getFile() ) ) 338 { 339 throw new IllegalStateException( "cannot install " + dstFile + " to same path" ); 340 } 341 fileProcessor.copy( metadata.getFile(), dstFile ); 342 } 343 344 lrm.add( session, new LocalMetadataRegistration( metadata ) ); 345 } 346 catch ( Exception e ) 347 { 348 exception = e; 349 throw new InstallationException( "Failed to install metadata " + metadata + ": " + e.getMessage(), e ); 350 } 351 finally 352 { 353 metadataInstalled( session, trace, metadata, dstFile, exception ); 354 } 355 } 356 357 private void artifactInstalling( RepositorySystemSession session, RequestTrace trace, Artifact artifact, 358 File dstFile ) 359 { 360 RepositoryEvent.Builder event = new RepositoryEvent.Builder( session, EventType.ARTIFACT_INSTALLING ); 361 event.setTrace( trace ); 362 event.setArtifact( artifact ); 363 event.setRepository( session.getLocalRepositoryManager().getRepository() ); 364 event.setFile( dstFile ); 365 366 repositoryEventDispatcher.dispatch( event.build() ); 367 } 368 369 private void artifactInstalled( RepositorySystemSession session, RequestTrace trace, Artifact artifact, 370 File dstFile, Exception exception ) 371 { 372 RepositoryEvent.Builder event = new RepositoryEvent.Builder( session, EventType.ARTIFACT_INSTALLED ); 373 event.setTrace( trace ); 374 event.setArtifact( artifact ); 375 event.setRepository( session.getLocalRepositoryManager().getRepository() ); 376 event.setFile( dstFile ); 377 event.setException( exception ); 378 379 repositoryEventDispatcher.dispatch( event.build() ); 380 } 381 382 private void metadataInstalling( RepositorySystemSession session, RequestTrace trace, Metadata metadata, 383 File dstFile ) 384 { 385 RepositoryEvent.Builder event = new RepositoryEvent.Builder( session, EventType.METADATA_INSTALLING ); 386 event.setTrace( trace ); 387 event.setMetadata( metadata ); 388 event.setRepository( session.getLocalRepositoryManager().getRepository() ); 389 event.setFile( dstFile ); 390 391 repositoryEventDispatcher.dispatch( event.build() ); 392 } 393 394 private void metadataInstalled( RepositorySystemSession session, RequestTrace trace, Metadata metadata, 395 File dstFile, Exception exception ) 396 { 397 RepositoryEvent.Builder event = new RepositoryEvent.Builder( session, EventType.METADATA_INSTALLED ); 398 event.setTrace( trace ); 399 event.setMetadata( metadata ); 400 event.setRepository( session.getLocalRepositoryManager().getRepository() ); 401 event.setFile( dstFile ); 402 event.setException( exception ); 403 404 repositoryEventDispatcher.dispatch( event.build() ); 405 } 406 407}