]> source.dussan.org Git - archiva.git/blob
6db1e6f29955aead32de4fd2f9aa38ec149c79e4
[archiva.git] /
1 package org.apache.archiva.rest.services;
2
3 /*
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
11  *
12  *   http://www.apache.org/licenses/LICENSE-2.0
13  *
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
19  * under the License.
20  */
21
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;
69
70 import javax.inject.Inject;
71 import javax.inject.Named;
72 import java.io.File;
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;
81
82 /**
83  * @author Olivier Lamy
84  * @since 1.4-M1
85  */
86 @Service( "repositoriesService#rest" )
87 public class DefaultRepositoriesService
88     extends AbstractRestService
89     implements RepositoriesService
90 {
91     private Logger log = LoggerFactory.getLogger( getClass( ) );
92
93     @Inject
94     @Named( value = "archivaTaskScheduler#repository" )
95     private RepositoryArchivaTaskScheduler repositoryTaskScheduler;
96
97     @Inject
98     @Named( value = "taskExecutor#indexing" )
99     private ArchivaIndexingTaskExecutor archivaIndexingTaskExecutor;
100
101     @Inject
102     private ManagedRepositoryAdmin managedRepositoryAdmin;
103
104     @Inject
105     private PlexusSisuBridge plexusSisuBridge;
106
107     @Inject
108     private MavenIndexerUtils mavenIndexerUtils;
109
110     @Inject
111     private SecuritySystem securitySystem;
112
113     @Inject
114     private RepositoryContentFactory repositoryFactory;
115
116     @Inject
117     private ArchivaAdministration archivaAdministration;
118
119     @Inject
120     @Named( value = "archivaTaskScheduler#repository" )
121     private ArchivaTaskScheduler scheduler;
122
123     @Inject
124     private DownloadRemoteIndexScheduler downloadRemoteIndexScheduler;
125
126     private ChecksumAlgorithm[] algorithms = new ChecksumAlgorithm[]{ ChecksumAlgorithm.SHA1, ChecksumAlgorithm.MD5 };
127
128     public Boolean scanRepository( String repositoryId, boolean fullScan )
129     {
130         if ( repositoryTaskScheduler.isProcessingRepositoryTask( repositoryId ) )
131         {
132             log.info( "scanning of repository with id {} already scheduled", repositoryId );
133             return Boolean.FALSE;
134         }
135         RepositoryTask task = new RepositoryTask( );
136         task.setRepositoryId( repositoryId );
137         task.setScanAll( fullScan );
138         try
139         {
140             repositoryTaskScheduler.queueTask( task );
141         }
142         catch ( TaskQueueException e )
143         {
144             log.error( "failed to schedule scanning of repo with id {}", repositoryId, e );
145             return false;
146         }
147         return true;
148     }
149
150     public Boolean alreadyScanning( String repositoryId )
151     {
152         return repositoryTaskScheduler.isProcessingRepositoryTask( repositoryId );
153     }
154
155     public Boolean removeScanningTaskFromQueue( String repositoryId )
156     {
157         RepositoryTask task = new RepositoryTask( );
158         task.setRepositoryId( repositoryId );
159         try
160         {
161             return repositoryTaskScheduler.unQueueTask( task );
162         }
163         catch ( TaskQueueException e )
164         {
165             log.error( "failed to unschedule scanning of repo with id {}", repositoryId, e );
166             return false;
167         }
168     }
169
170     public Boolean scanRepositoryNow( String repositoryId, boolean fullScan )
171         throws ArchivaRestServiceException
172     {
173
174         try
175         {
176             ManagedRepository repository = managedRepositoryAdmin.getManagedRepository( repositoryId );
177
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 );
184
185             task.setExecuteOnEntireRepo( true );
186             task.setOnlyUpdate( false );
187
188             archivaIndexingTaskExecutor.executeTask( task );
189             return Boolean.TRUE;
190         }
191         catch ( Exception e )
192         {
193             log.error( e.getMessage( ), e );
194             throw new ArchivaRestServiceException( e.getMessage( ) );
195         }
196     }
197
198     public Boolean scheduleDownloadRemoteIndex( String repositoryId, boolean now, boolean fullDownload )
199         throws ArchivaRestServiceException
200     {
201         try
202         {
203             downloadRemoteIndexScheduler.scheduleDownloadRemote( repositoryId, now, fullDownload );
204         }
205         catch ( DownloadRemoteIndexException e )
206         {
207             log.error( e.getMessage( ), e );
208             throw new ArchivaRestServiceException( e.getMessage( ) );
209         }
210         return Boolean.TRUE;
211     }
212
213     public Boolean copyArtifact( ArtifactTransferRequest artifactTransferRequest )
214         throws ArchivaRestServiceException
215     {
216         // check parameters
217         String userName = getAuditInformation( ).getUser( ).getUsername( );
218         if ( StringUtils.isBlank( userName ) )
219         {
220             throw new ArchivaRestServiceException( "copyArtifact call: userName not found" );
221         }
222
223         if ( StringUtils.isBlank( artifactTransferRequest.getRepositoryId( ) ) )
224         {
225             throw new ArchivaRestServiceException( "copyArtifact call: sourceRepositoryId cannot be null" );
226         }
227
228         if ( StringUtils.isBlank( artifactTransferRequest.getTargetRepositoryId( ) ) )
229         {
230             throw new ArchivaRestServiceException( "copyArtifact call: targetRepositoryId cannot be null" );
231         }
232
233         ManagedRepository source = null;
234         try
235         {
236             source = managedRepositoryAdmin.getManagedRepository( artifactTransferRequest.getRepositoryId( ) );
237         }
238         catch ( RepositoryAdminException e )
239         {
240             throw new ArchivaRestServiceException( e.getMessage( ) );
241         }
242
243         if ( source == null )
244         {
245             throw new ArchivaRestServiceException(
246                 "cannot find repository with id " + artifactTransferRequest.getRepositoryId( ) );
247         }
248
249         ManagedRepository target = null;
250         try
251         {
252             target = managedRepositoryAdmin.getManagedRepository( artifactTransferRequest.getTargetRepositoryId( ) );
253         }
254         catch ( RepositoryAdminException e )
255         {
256             throw new ArchivaRestServiceException( e.getMessage( ) );
257         }
258
259         if ( target == null )
260         {
261             throw new ArchivaRestServiceException(
262                 "cannot find repository with id " + artifactTransferRequest.getTargetRepositoryId( ) );
263         }
264
265         if ( StringUtils.isBlank( artifactTransferRequest.getGroupId( ) ) )
266         {
267             throw new ArchivaRestServiceException( "groupId is mandatory" );
268         }
269
270         if ( StringUtils.isBlank( artifactTransferRequest.getArtifactId( ) ) )
271         {
272             throw new ArchivaRestServiceException( "artifactId is mandatory" );
273         }
274
275         if ( StringUtils.isBlank( artifactTransferRequest.getVersion( ) ) )
276         {
277             throw new ArchivaRestServiceException( "version is mandatory" );
278         }
279
280         if ( VersionUtil.isSnapshot( artifactTransferRequest.getVersion( ) ) )
281         {
282             throw new ArchivaRestServiceException( "copy of SNAPSHOT not supported" );
283         }
284
285         // end check parameters
286
287         User user = null;
288         try
289         {
290             user = securitySystem.getUserManager( ).findUser( userName );
291         }
292         catch ( UserNotFoundException e )
293         {
294             throw new ArchivaRestServiceException( "user " + userName + " not found" );
295         }
296
297         // check karma on source : read
298         AuthenticationResult authn = new AuthenticationResult( true, userName, null );
299         SecuritySession securitySession = new DefaultSecuritySession( authn, user );
300         try
301         {
302             boolean authz =
303                 securitySystem.isAuthorized( securitySession, ArchivaRoleConstants.OPERATION_REPOSITORY_ACCESS,
304                                              artifactTransferRequest.getRepositoryId( ) );
305             if ( !authz )
306             {
307                 throw new ArchivaRestServiceException(
308                     "not authorized to access repo:" + artifactTransferRequest.getRepositoryId( ) );
309             }
310         }
311         catch ( AuthorizationException e )
312         {
313             log.error( "error reading permission: " + e.getMessage( ), e );
314             throw new ArchivaRestServiceException( e.getMessage( ) );
315         }
316
317         // check karma on target: write
318         try
319         {
320             boolean authz =
321                 securitySystem.isAuthorized( securitySession, ArchivaRoleConstants.OPERATION_REPOSITORY_UPLOAD,
322                                              artifactTransferRequest.getTargetRepositoryId( ) );
323             if ( !authz )
324             {
325                 throw new ArchivaRestServiceException(
326                     "not authorized to write to repo:" + artifactTransferRequest.getTargetRepositoryId( ) );
327             }
328         }
329         catch ( AuthorizationException e )
330         {
331             log.error( "error reading permission: " + e.getMessage( ), e );
332             throw new ArchivaRestServiceException( e.getMessage( ) );
333         }
334
335         // sounds good we can continue !
336
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 );
344
345         try
346         {
347
348             ManagedRepositoryContent sourceRepository =
349                 repositoryFactory.getManagedRepositoryContent( artifactTransferRequest.getRepositoryId( ) );
350
351             String artifactSourcePath = sourceRepository.toPath( artifactReference );
352
353             if ( StringUtils.isEmpty( artifactSourcePath ) )
354             {
355                 log.error( "cannot find artifact " + artifactTransferRequest.toString( ) );
356                 throw new ArchivaRestServiceException( "cannot find artifact " + artifactTransferRequest.toString( ) );
357             }
358
359             File artifactFile = new File( source.getLocation( ), artifactSourcePath );
360
361             if ( !artifactFile.exists( ) )
362             {
363                 log.error( "cannot find artifact " + artifactTransferRequest.toString( ) );
364                 throw new ArchivaRestServiceException( "cannot find artifact " + artifactTransferRequest.toString( ) );
365             }
366
367             ManagedRepositoryContent targetRepository =
368                 repositoryFactory.getManagedRepositoryContent( artifactTransferRequest.getTargetRepositoryId( ) );
369
370             String artifactPath = targetRepository.toPath( artifactReference );
371
372             int lastIndex = artifactPath.lastIndexOf( '/' );
373
374             String path = artifactPath.substring( 0, lastIndex );
375             File targetPath = new File( target.getLocation( ), path );
376
377             Date lastUpdatedTimestamp = Calendar.getInstance( ).getTime( );
378             int newBuildNumber = 1;
379             String timestamp = null;
380
381             File versionMetadataFile = new File( targetPath, MetadataTools.MAVEN_METADATA );
382             ArchivaRepositoryMetadata versionMetadata = getMetadata( versionMetadataFile );
383
384             if ( !targetPath.exists( ) )
385             {
386                 targetPath.mkdirs( );
387             }
388
389             String filename = artifactPath.substring( lastIndex + 1 );
390
391             // FIXME some dupe with uploadaction
392
393             boolean fixChecksums =
394                 !( archivaAdministration.getKnownContentConsumers( ).contains( "create-missing-checksums" ) );
395
396             File targetFile = new File( targetPath, filename );
397             if ( targetFile.exists( ) && target.isBlockRedeployments( ) )
398             {
399                 throw new ArchivaRestServiceException(
400                     "artifact already exists in target repo: " + artifactTransferRequest.getTargetRepositoryId( )
401                         + " and redeployment blocked" );
402             }
403             else
404             {
405                 copyFile( artifactFile, targetPath, filename, fixChecksums );
406                 queueRepositoryTask( target.getId( ), targetFile );
407             }
408
409             // copy source pom to target repo
410             String pomFilename = filename;
411             if ( StringUtils.isNotBlank( artifactTransferRequest.getClassifier( ) ) )
412             {
413                 pomFilename = StringUtils.remove( pomFilename, "-" + artifactTransferRequest.getClassifier( ) );
414             }
415             pomFilename = FilenameUtils.removeExtension( pomFilename ) + ".pom";
416
417             File pomFile = new File(
418                 new File( source.getLocation( ), artifactSourcePath.substring( 0, artifactPath.lastIndexOf( '/' ) ) ),
419                 pomFilename );
420
421             if ( pomFile != null && pomFile.length( ) > 0 )
422             {
423                 copyFile( pomFile, targetPath, pomFilename, fixChecksums );
424                 queueRepositoryTask( target.getId( ), new File( targetPath, pomFilename ) );
425
426
427             }
428
429             // explicitly update only if metadata-updater consumer is not enabled!
430             if ( !archivaAdministration.getKnownContentConsumers( ).contains( "metadata-updater" ) )
431             {
432                 updateProjectMetadata( targetPath.getAbsolutePath( ), lastUpdatedTimestamp, timestamp, newBuildNumber,
433                                        fixChecksums, artifactTransferRequest );
434
435
436             }
437
438             String msg =
439                 "Artifact \'" + artifactTransferRequest.getGroupId( ) + ":" + artifactTransferRequest.getArtifactId( )
440                     + ":" + artifactTransferRequest.getVersion( ) + "\' was successfully deployed to repository \'"
441                     + artifactTransferRequest.getTargetRepositoryId( ) + "\'";
442
443         }
444         catch ( RepositoryException e )
445         {
446             log.error( "RepositoryException: " + e.getMessage( ), e );
447             throw new ArchivaRestServiceException( e.getMessage( ) );
448         }
449         catch ( RepositoryAdminException e )
450         {
451             log.error( "RepositoryAdminException: " + e.getMessage( ), e );
452             throw new ArchivaRestServiceException( e.getMessage( ) );
453         }
454         catch ( IOException e )
455         {
456             log.error( "IOException: " + e.getMessage( ), e );
457             throw new ArchivaRestServiceException( e.getMessage( ) );
458         }
459         return true;
460     }
461
462     //FIXME some duplicate with UploadAction 
463
464     private void queueRepositoryTask( String repositoryId, File localFile )
465     {
466         RepositoryTask task = new RepositoryTask( );
467         task.setRepositoryId( repositoryId );
468         task.setResourceFile( localFile );
469         task.setUpdateRelatedArtifacts( true );
470         //task.setScanAll( true );
471
472         try
473         {
474             scheduler.queueTask( task );
475         }
476         catch ( TaskQueueException e )
477         {
478             log.error( "Unable to queue repository task to execute consumers on resource file ['" + localFile.getName( )
479                            + "']." );
480         }
481     }
482
483     private ArchivaRepositoryMetadata getMetadata( File metadataFile )
484         throws RepositoryMetadataException
485     {
486         ArchivaRepositoryMetadata metadata = new ArchivaRepositoryMetadata( );
487         if ( metadataFile.exists( ) )
488         {
489             metadata = RepositoryMetadataReader.read( metadataFile );
490         }
491         return metadata;
492     }
493
494     private void copyFile( File sourceFile, File targetPath, String targetFilename, boolean fixChecksums )
495         throws IOException
496     {
497         FileOutputStream out = new FileOutputStream( new File( targetPath, targetFilename ) );
498         FileInputStream input = new FileInputStream( sourceFile );
499
500         try
501         {
502             IOUtils.copy( input, out );
503         }
504         finally
505         {
506             out.close( );
507             input.close( );
508         }
509
510         if ( fixChecksums )
511         {
512             fixChecksums( new File( targetPath, targetFilename ) );
513         }
514     }
515
516     private void fixChecksums( File file )
517     {
518         ChecksummedFile checksum = new ChecksummedFile( file );
519         checksum.fixChecksums( algorithms );
520     }
521
522     private void updateProjectMetadata( String targetPath, Date lastUpdatedTimestamp, String timestamp, int buildNumber,
523                                         boolean fixChecksums, ArtifactTransferRequest artifactTransferRequest )
524         throws RepositoryMetadataException
525     {
526         List<String> availableVersions = new ArrayList<String>( );
527         String latestVersion = artifactTransferRequest.getVersion( );
528
529         File projectDir = new File( targetPath ).getParentFile( );
530         File projectMetadataFile = new File( projectDir, MetadataTools.MAVEN_METADATA );
531
532         ArchivaRepositoryMetadata projectMetadata = getMetadata( projectMetadataFile );
533
534         if ( projectMetadataFile.exists( ) )
535         {
536             availableVersions = projectMetadata.getAvailableVersions( );
537
538             Collections.sort( availableVersions, VersionComparator.getInstance( ) );
539
540             if ( !availableVersions.contains( artifactTransferRequest.getVersion( ) ) )
541             {
542                 availableVersions.add( artifactTransferRequest.getVersion( ) );
543             }
544
545             latestVersion = availableVersions.get( availableVersions.size( ) - 1 );
546         }
547         else
548         {
549             availableVersions.add( artifactTransferRequest.getVersion( ) );
550
551             projectMetadata.setGroupId( artifactTransferRequest.getGroupId( ) );
552             projectMetadata.setArtifactId( artifactTransferRequest.getArtifactId( ) );
553         }
554
555         if ( projectMetadata.getGroupId( ) == null )
556         {
557             projectMetadata.setGroupId( artifactTransferRequest.getGroupId( ) );
558         }
559
560         if ( projectMetadata.getArtifactId( ) == null )
561         {
562             projectMetadata.setArtifactId( artifactTransferRequest.getArtifactId( ) );
563         }
564
565         projectMetadata.setLatestVersion( latestVersion );
566         projectMetadata.setLastUpdatedTimestamp( lastUpdatedTimestamp );
567         projectMetadata.setAvailableVersions( availableVersions );
568
569         if ( !VersionUtil.isSnapshot( artifactTransferRequest.getVersion( ) ) )
570         {
571             projectMetadata.setReleasedVersion( latestVersion );
572         }
573
574         RepositoryMetadataWriter.write( projectMetadata, projectMetadataFile );
575
576         if ( fixChecksums )
577         {
578             fixChecksums( projectMetadataFile );
579         }
580     }
581 }
582
583