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