1 package org.apache.archiva.rest.services;
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
22 import org.apache.archiva.admin.model.RepositoryAdminException;
23 import org.apache.archiva.admin.model.admin.ArchivaAdministration;
24 import org.apache.archiva.admin.model.beans.ManagedRepository;
25 import org.apache.archiva.admin.model.managed.ManagedRepositoryAdmin;
26 import org.apache.archiva.checksum.ChecksumAlgorithm;
27 import org.apache.archiva.checksum.ChecksummedFile;
28 import org.apache.archiva.common.plexusbridge.MavenIndexerUtils;
29 import org.apache.archiva.common.plexusbridge.PlexusSisuBridge;
30 import org.apache.archiva.common.utils.VersionComparator;
31 import org.apache.archiva.common.utils.VersionUtil;
32 import org.apache.archiva.model.ArchivaRepositoryMetadata;
33 import org.apache.archiva.model.ArtifactReference;
34 import org.apache.archiva.repository.ManagedRepositoryContent;
35 import org.apache.archiva.repository.RepositoryContentFactory;
36 import org.apache.archiva.repository.RepositoryException;
37 import org.apache.archiva.repository.metadata.MetadataTools;
38 import org.apache.archiva.repository.metadata.RepositoryMetadataException;
39 import org.apache.archiva.repository.metadata.RepositoryMetadataReader;
40 import org.apache.archiva.repository.metadata.RepositoryMetadataWriter;
41 import org.apache.archiva.rest.api.model.ArtifactTransferRequest;
42 import org.apache.archiva.rest.api.services.ArchivaRestServiceException;
43 import org.apache.archiva.rest.api.services.RepositoriesService;
44 import org.apache.archiva.scheduler.ArchivaTaskScheduler;
45 import org.apache.archiva.scheduler.indexing.ArchivaIndexingTaskExecutor;
46 import org.apache.archiva.scheduler.indexing.ArtifactIndexingTask;
47 import org.apache.archiva.scheduler.indexing.DownloadRemoteIndexException;
48 import org.apache.archiva.scheduler.indexing.DownloadRemoteIndexScheduler;
49 import org.apache.archiva.scheduler.repository.RepositoryArchivaTaskScheduler;
50 import org.apache.archiva.scheduler.repository.RepositoryTask;
51 import org.apache.archiva.security.common.ArchivaRoleConstants;
52 import org.apache.commons.io.FilenameUtils;
53 import org.apache.commons.io.IOUtils;
54 import org.apache.commons.lang.StringUtils;
55 import org.apache.maven.index.NexusIndexer;
56 import org.apache.maven.index.context.IndexCreator;
57 import org.apache.maven.index.context.IndexingContext;
58 import org.codehaus.plexus.redback.authentication.AuthenticationResult;
59 import org.codehaus.plexus.redback.authorization.AuthorizationException;
60 import org.codehaus.plexus.redback.system.DefaultSecuritySession;
61 import org.codehaus.plexus.redback.system.SecuritySession;
62 import org.codehaus.plexus.redback.system.SecuritySystem;
63 import org.codehaus.plexus.redback.users.User;
64 import org.codehaus.plexus.redback.users.UserNotFoundException;
65 import org.codehaus.plexus.taskqueue.TaskQueueException;
66 import org.slf4j.Logger;
67 import org.slf4j.LoggerFactory;
68 import org.springframework.stereotype.Service;
70 import javax.inject.Inject;
71 import javax.inject.Named;
73 import java.io.FileInputStream;
74 import java.io.FileOutputStream;
75 import java.io.IOException;
76 import java.util.ArrayList;
77 import java.util.Calendar;
78 import java.util.Collections;
79 import java.util.Date;
80 import java.util.List;
83 * @author Olivier Lamy
86 @Service( "repositoriesService#rest" )
87 public class DefaultRepositoriesService
88 extends AbstractRestService
89 implements RepositoriesService
91 private Logger log = LoggerFactory.getLogger( getClass( ) );
94 @Named( value = "archivaTaskScheduler#repository" )
95 private RepositoryArchivaTaskScheduler repositoryTaskScheduler;
98 @Named( value = "taskExecutor#indexing" )
99 private ArchivaIndexingTaskExecutor archivaIndexingTaskExecutor;
102 private ManagedRepositoryAdmin managedRepositoryAdmin;
105 private PlexusSisuBridge plexusSisuBridge;
108 private MavenIndexerUtils mavenIndexerUtils;
111 private SecuritySystem securitySystem;
114 private RepositoryContentFactory repositoryFactory;
117 private ArchivaAdministration archivaAdministration;
120 @Named( value = "archivaTaskScheduler#repository" )
121 private ArchivaTaskScheduler scheduler;
124 private DownloadRemoteIndexScheduler downloadRemoteIndexScheduler;
126 private ChecksumAlgorithm[] algorithms = new ChecksumAlgorithm[]{ ChecksumAlgorithm.SHA1, ChecksumAlgorithm.MD5 };
128 public Boolean scanRepository( String repositoryId, boolean fullScan )
130 if ( repositoryTaskScheduler.isProcessingRepositoryTask( repositoryId ) )
132 log.info( "scanning of repository with id {} already scheduled", repositoryId );
133 return Boolean.FALSE;
135 RepositoryTask task = new RepositoryTask( );
136 task.setRepositoryId( repositoryId );
137 task.setScanAll( fullScan );
140 repositoryTaskScheduler.queueTask( task );
142 catch ( TaskQueueException e )
144 log.error( "failed to schedule scanning of repo with id {}", repositoryId, e );
150 public Boolean alreadyScanning( String repositoryId )
152 return repositoryTaskScheduler.isProcessingRepositoryTask( repositoryId );
155 public Boolean removeScanningTaskFromQueue( String repositoryId )
157 RepositoryTask task = new RepositoryTask( );
158 task.setRepositoryId( repositoryId );
161 return repositoryTaskScheduler.unQueueTask( task );
163 catch ( TaskQueueException e )
165 log.error( "failed to unschedule scanning of repo with id {}", repositoryId, e );
170 public Boolean scanRepositoryNow( String repositoryId, boolean fullScan )
171 throws ArchivaRestServiceException
176 ManagedRepository repository = managedRepositoryAdmin.getManagedRepository( repositoryId );
178 IndexingContext context =
179 ArtifactIndexingTask.createContext( repository, plexusSisuBridge.lookup( NexusIndexer.class ),
180 new ArrayList<IndexCreator>(
181 mavenIndexerUtils.getAllIndexCreators( ) ) );
182 ArtifactIndexingTask task =
183 new ArtifactIndexingTask( repository, null, ArtifactIndexingTask.Action.FINISH, context );
185 task.setExecuteOnEntireRepo( true );
186 task.setOnlyUpdate( false );
188 archivaIndexingTaskExecutor.executeTask( task );
191 catch ( Exception e )
193 log.error( e.getMessage( ), e );
194 throw new ArchivaRestServiceException( e.getMessage( ) );
198 public Boolean scheduleDownloadRemoteIndex( String repositoryId, boolean now, boolean fullDownload )
199 throws ArchivaRestServiceException
203 downloadRemoteIndexScheduler.scheduleDownloadRemote( repositoryId, now, fullDownload );
205 catch ( DownloadRemoteIndexException e )
207 log.error( e.getMessage( ), e );
208 throw new ArchivaRestServiceException( e.getMessage( ) );
213 public Boolean copyArtifact( ArtifactTransferRequest artifactTransferRequest )
214 throws ArchivaRestServiceException
217 String userName = getAuditInformation( ).getUser( ).getUsername( );
218 if ( StringUtils.isBlank( userName ) )
220 throw new ArchivaRestServiceException( "copyArtifact call: userName not found" );
223 if ( StringUtils.isBlank( artifactTransferRequest.getRepositoryId( ) ) )
225 throw new ArchivaRestServiceException( "copyArtifact call: sourceRepositoryId cannot be null" );
228 if ( StringUtils.isBlank( artifactTransferRequest.getTargetRepositoryId( ) ) )
230 throw new ArchivaRestServiceException( "copyArtifact call: targetRepositoryId cannot be null" );
233 ManagedRepository source = null;
236 source = managedRepositoryAdmin.getManagedRepository( artifactTransferRequest.getRepositoryId( ) );
238 catch ( RepositoryAdminException e )
240 throw new ArchivaRestServiceException( e.getMessage( ) );
243 if ( source == null )
245 throw new ArchivaRestServiceException(
246 "cannot find repository with id " + artifactTransferRequest.getRepositoryId( ) );
249 ManagedRepository target = null;
252 target = managedRepositoryAdmin.getManagedRepository( artifactTransferRequest.getTargetRepositoryId( ) );
254 catch ( RepositoryAdminException e )
256 throw new ArchivaRestServiceException( e.getMessage( ) );
259 if ( target == null )
261 throw new ArchivaRestServiceException(
262 "cannot find repository with id " + artifactTransferRequest.getTargetRepositoryId( ) );
265 if ( StringUtils.isBlank( artifactTransferRequest.getGroupId( ) ) )
267 throw new ArchivaRestServiceException( "groupId is mandatory" );
270 if ( StringUtils.isBlank( artifactTransferRequest.getArtifactId( ) ) )
272 throw new ArchivaRestServiceException( "artifactId is mandatory" );
275 if ( StringUtils.isBlank( artifactTransferRequest.getVersion( ) ) )
277 throw new ArchivaRestServiceException( "version is mandatory" );
280 if ( VersionUtil.isSnapshot( artifactTransferRequest.getVersion( ) ) )
282 throw new ArchivaRestServiceException( "copy of SNAPSHOT not supported" );
285 // end check parameters
290 user = securitySystem.getUserManager( ).findUser( userName );
292 catch ( UserNotFoundException e )
294 throw new ArchivaRestServiceException( "user " + userName + " not found" );
297 // check karma on source : read
298 AuthenticationResult authn = new AuthenticationResult( true, userName, null );
299 SecuritySession securitySession = new DefaultSecuritySession( authn, user );
303 securitySystem.isAuthorized( securitySession, ArchivaRoleConstants.OPERATION_REPOSITORY_ACCESS,
304 artifactTransferRequest.getRepositoryId( ) );
307 throw new ArchivaRestServiceException(
308 "not authorized to access repo:" + artifactTransferRequest.getRepositoryId( ) );
311 catch ( AuthorizationException e )
313 log.error( "error reading permission: " + e.getMessage( ), e );
314 throw new ArchivaRestServiceException( e.getMessage( ) );
317 // check karma on target: write
321 securitySystem.isAuthorized( securitySession, ArchivaRoleConstants.OPERATION_REPOSITORY_UPLOAD,
322 artifactTransferRequest.getTargetRepositoryId( ) );
325 throw new ArchivaRestServiceException(
326 "not authorized to write to repo:" + artifactTransferRequest.getTargetRepositoryId( ) );
329 catch ( AuthorizationException e )
331 log.error( "error reading permission: " + e.getMessage( ), e );
332 throw new ArchivaRestServiceException( e.getMessage( ) );
335 // sounds good we can continue !
337 ArtifactReference artifactReference = new ArtifactReference( );
338 artifactReference.setArtifactId( artifactTransferRequest.getArtifactId( ) );
339 artifactReference.setGroupId( artifactTransferRequest.getGroupId( ) );
340 artifactReference.setVersion( artifactTransferRequest.getVersion( ) );
341 artifactReference.setClassifier( artifactTransferRequest.getClassifier( ) );
342 String packaging = StringUtils.trim( artifactTransferRequest.getPackaging( ) );
343 artifactReference.setType( StringUtils.isEmpty( packaging ) ? "jar" : packaging );
348 ManagedRepositoryContent sourceRepository =
349 repositoryFactory.getManagedRepositoryContent( artifactTransferRequest.getRepositoryId( ) );
351 String artifactSourcePath = sourceRepository.toPath( artifactReference );
353 if ( StringUtils.isEmpty( artifactSourcePath ) )
355 log.error( "cannot find artifact " + artifactTransferRequest.toString( ) );
356 throw new ArchivaRestServiceException( "cannot find artifact " + artifactTransferRequest.toString( ) );
359 File artifactFile = new File( source.getLocation( ), artifactSourcePath );
361 if ( !artifactFile.exists( ) )
363 log.error( "cannot find artifact " + artifactTransferRequest.toString( ) );
364 throw new ArchivaRestServiceException( "cannot find artifact " + artifactTransferRequest.toString( ) );
367 ManagedRepositoryContent targetRepository =
368 repositoryFactory.getManagedRepositoryContent( artifactTransferRequest.getTargetRepositoryId( ) );
370 String artifactPath = targetRepository.toPath( artifactReference );
372 int lastIndex = artifactPath.lastIndexOf( '/' );
374 String path = artifactPath.substring( 0, lastIndex );
375 File targetPath = new File( target.getLocation( ), path );
377 Date lastUpdatedTimestamp = Calendar.getInstance( ).getTime( );
378 int newBuildNumber = 1;
379 String timestamp = null;
381 File versionMetadataFile = new File( targetPath, MetadataTools.MAVEN_METADATA );
382 ArchivaRepositoryMetadata versionMetadata = getMetadata( versionMetadataFile );
384 if ( !targetPath.exists( ) )
386 targetPath.mkdirs( );
389 String filename = artifactPath.substring( lastIndex + 1 );
391 // FIXME some dupe with uploadaction
393 boolean fixChecksums =
394 !( archivaAdministration.getKnownContentConsumers( ).contains( "create-missing-checksums" ) );
396 File targetFile = new File( targetPath, filename );
397 if ( targetFile.exists( ) && target.isBlockRedeployments( ) )
399 throw new ArchivaRestServiceException(
400 "artifact already exists in target repo: " + artifactTransferRequest.getTargetRepositoryId( )
401 + " and redeployment blocked" );
405 copyFile( artifactFile, targetPath, filename, fixChecksums );
406 queueRepositoryTask( target.getId( ), targetFile );
409 // copy source pom to target repo
410 String pomFilename = filename;
411 if ( StringUtils.isNotBlank( artifactTransferRequest.getClassifier( ) ) )
413 pomFilename = StringUtils.remove( pomFilename, "-" + artifactTransferRequest.getClassifier( ) );
415 pomFilename = FilenameUtils.removeExtension( pomFilename ) + ".pom";
417 File pomFile = new File(
418 new File( source.getLocation( ), artifactSourcePath.substring( 0, artifactPath.lastIndexOf( '/' ) ) ),
421 if ( pomFile != null && pomFile.length( ) > 0 )
423 copyFile( pomFile, targetPath, pomFilename, fixChecksums );
424 queueRepositoryTask( target.getId( ), new File( targetPath, pomFilename ) );
429 // explicitly update only if metadata-updater consumer is not enabled!
430 if ( !archivaAdministration.getKnownContentConsumers( ).contains( "metadata-updater" ) )
432 updateProjectMetadata( targetPath.getAbsolutePath( ), lastUpdatedTimestamp, timestamp, newBuildNumber,
433 fixChecksums, artifactTransferRequest );
439 "Artifact \'" + artifactTransferRequest.getGroupId( ) + ":" + artifactTransferRequest.getArtifactId( )
440 + ":" + artifactTransferRequest.getVersion( ) + "\' was successfully deployed to repository \'"
441 + artifactTransferRequest.getTargetRepositoryId( ) + "\'";
444 catch ( RepositoryException e )
446 log.error( "RepositoryException: " + e.getMessage( ), e );
447 throw new ArchivaRestServiceException( e.getMessage( ) );
449 catch ( RepositoryAdminException e )
451 log.error( "RepositoryAdminException: " + e.getMessage( ), e );
452 throw new ArchivaRestServiceException( e.getMessage( ) );
454 catch ( IOException e )
456 log.error( "IOException: " + e.getMessage( ), e );
457 throw new ArchivaRestServiceException( e.getMessage( ) );
462 //FIXME some duplicate with UploadAction
464 private void queueRepositoryTask( String repositoryId, File localFile )
466 RepositoryTask task = new RepositoryTask( );
467 task.setRepositoryId( repositoryId );
468 task.setResourceFile( localFile );
469 task.setUpdateRelatedArtifacts( true );
470 //task.setScanAll( true );
474 scheduler.queueTask( task );
476 catch ( TaskQueueException e )
478 log.error( "Unable to queue repository task to execute consumers on resource file ['" + localFile.getName( )
483 private ArchivaRepositoryMetadata getMetadata( File metadataFile )
484 throws RepositoryMetadataException
486 ArchivaRepositoryMetadata metadata = new ArchivaRepositoryMetadata( );
487 if ( metadataFile.exists( ) )
489 metadata = RepositoryMetadataReader.read( metadataFile );
494 private void copyFile( File sourceFile, File targetPath, String targetFilename, boolean fixChecksums )
497 FileOutputStream out = new FileOutputStream( new File( targetPath, targetFilename ) );
498 FileInputStream input = new FileInputStream( sourceFile );
502 IOUtils.copy( input, out );
512 fixChecksums( new File( targetPath, targetFilename ) );
516 private void fixChecksums( File file )
518 ChecksummedFile checksum = new ChecksummedFile( file );
519 checksum.fixChecksums( algorithms );
522 private void updateProjectMetadata( String targetPath, Date lastUpdatedTimestamp, String timestamp, int buildNumber,
523 boolean fixChecksums, ArtifactTransferRequest artifactTransferRequest )
524 throws RepositoryMetadataException
526 List<String> availableVersions = new ArrayList<String>( );
527 String latestVersion = artifactTransferRequest.getVersion( );
529 File projectDir = new File( targetPath ).getParentFile( );
530 File projectMetadataFile = new File( projectDir, MetadataTools.MAVEN_METADATA );
532 ArchivaRepositoryMetadata projectMetadata = getMetadata( projectMetadataFile );
534 if ( projectMetadataFile.exists( ) )
536 availableVersions = projectMetadata.getAvailableVersions( );
538 Collections.sort( availableVersions, VersionComparator.getInstance( ) );
540 if ( !availableVersions.contains( artifactTransferRequest.getVersion( ) ) )
542 availableVersions.add( artifactTransferRequest.getVersion( ) );
545 latestVersion = availableVersions.get( availableVersions.size( ) - 1 );
549 availableVersions.add( artifactTransferRequest.getVersion( ) );
551 projectMetadata.setGroupId( artifactTransferRequest.getGroupId( ) );
552 projectMetadata.setArtifactId( artifactTransferRequest.getArtifactId( ) );
555 if ( projectMetadata.getGroupId( ) == null )
557 projectMetadata.setGroupId( artifactTransferRequest.getGroupId( ) );
560 if ( projectMetadata.getArtifactId( ) == null )
562 projectMetadata.setArtifactId( artifactTransferRequest.getArtifactId( ) );
565 projectMetadata.setLatestVersion( latestVersion );
566 projectMetadata.setLastUpdatedTimestamp( lastUpdatedTimestamp );
567 projectMetadata.setAvailableVersions( availableVersions );
569 if ( !VersionUtil.isSnapshot( artifactTransferRequest.getVersion( ) ) )
571 projectMetadata.setReleasedVersion( latestVersion );
574 RepositoryMetadataWriter.write( projectMetadata, projectMetadataFile );
578 fixChecksums( projectMetadataFile );