]> source.dussan.org Git - archiva.git/blob
89e5301539bcf153b377d8b8260e3e9369aa591d
[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.AuditInformation;
23 import org.apache.archiva.admin.model.RepositoryAdminException;
24 import org.apache.archiva.admin.model.admin.ArchivaAdministration;
25 import org.apache.archiva.admin.model.beans.ManagedRepository;
26 import org.apache.archiva.admin.model.managed.ManagedRepositoryAdmin;
27 import org.apache.archiva.audit.AuditEvent;
28 import org.apache.archiva.audit.AuditListener;
29 import org.apache.archiva.checksum.ChecksumAlgorithm;
30 import org.apache.archiva.checksum.ChecksummedFile;
31 import org.apache.archiva.common.plexusbridge.MavenIndexerUtils;
32 import org.apache.archiva.common.plexusbridge.PlexusSisuBridge;
33 import org.apache.archiva.common.utils.VersionComparator;
34 import org.apache.archiva.common.utils.VersionUtil;
35 import org.apache.archiva.metadata.model.ArtifactMetadata;
36 import org.apache.archiva.metadata.repository.MetadataRepository;
37 import org.apache.archiva.metadata.repository.MetadataRepositoryException;
38 import org.apache.archiva.metadata.repository.MetadataResolutionException;
39 import org.apache.archiva.metadata.repository.RepositorySession;
40 import org.apache.archiva.metadata.repository.RepositorySessionFactory;
41 import org.apache.archiva.model.ArchivaRepositoryMetadata;
42 import org.apache.archiva.model.ArtifactReference;
43 import org.apache.archiva.model.VersionedReference;
44 import org.apache.archiva.repository.ContentNotFoundException;
45 import org.apache.archiva.repository.ManagedRepositoryContent;
46 import org.apache.archiva.repository.RepositoryContentFactory;
47 import org.apache.archiva.repository.RepositoryException;
48 import org.apache.archiva.repository.RepositoryNotFoundException;
49 import org.apache.archiva.repository.events.RepositoryListener;
50 import org.apache.archiva.repository.metadata.MetadataTools;
51 import org.apache.archiva.repository.metadata.RepositoryMetadataException;
52 import org.apache.archiva.repository.metadata.RepositoryMetadataReader;
53 import org.apache.archiva.repository.metadata.RepositoryMetadataWriter;
54 import org.apache.archiva.rest.api.model.Artifact;
55 import org.apache.archiva.rest.api.model.ArtifactTransferRequest;
56 import org.apache.archiva.rest.api.services.ArchivaRestServiceException;
57 import org.apache.archiva.rest.api.services.RepositoriesService;
58 import org.apache.archiva.scheduler.ArchivaTaskScheduler;
59 import org.apache.archiva.scheduler.indexing.ArchivaIndexingTaskExecutor;
60 import org.apache.archiva.scheduler.indexing.ArtifactIndexingTask;
61 import org.apache.archiva.scheduler.indexing.DownloadRemoteIndexException;
62 import org.apache.archiva.scheduler.indexing.DownloadRemoteIndexScheduler;
63 import org.apache.archiva.scheduler.repository.RepositoryArchivaTaskScheduler;
64 import org.apache.archiva.scheduler.repository.RepositoryTask;
65 import org.apache.archiva.security.common.ArchivaRoleConstants;
66 import org.apache.commons.io.FilenameUtils;
67 import org.apache.commons.io.IOUtils;
68 import org.apache.commons.lang.StringUtils;
69 import org.apache.maven.index.context.IndexingContext;
70 import org.codehaus.plexus.redback.authentication.AuthenticationResult;
71 import org.codehaus.plexus.redback.authorization.AuthorizationException;
72 import org.codehaus.plexus.redback.system.DefaultSecuritySession;
73 import org.codehaus.plexus.redback.system.SecuritySession;
74 import org.codehaus.plexus.redback.system.SecuritySystem;
75 import org.codehaus.plexus.redback.users.User;
76 import org.codehaus.plexus.redback.users.UserNotFoundException;
77 import org.codehaus.plexus.taskqueue.TaskQueueException;
78 import org.slf4j.Logger;
79 import org.slf4j.LoggerFactory;
80 import org.springframework.stereotype.Service;
81
82 import javax.inject.Inject;
83 import javax.inject.Named;
84 import java.io.File;
85 import java.io.FileInputStream;
86 import java.io.FileOutputStream;
87 import java.io.IOException;
88 import java.text.DateFormat;
89 import java.text.SimpleDateFormat;
90 import java.util.ArrayList;
91 import java.util.Calendar;
92 import java.util.Collection;
93 import java.util.Collections;
94 import java.util.Date;
95 import java.util.List;
96 import java.util.TimeZone;
97
98 /**
99  * @author Olivier Lamy
100  * @since 1.4-M1
101  */
102 @Service( "repositoriesService#rest" )
103 public class DefaultRepositoriesService
104     extends AbstractRestService
105     implements RepositoriesService
106 {
107     private Logger log = LoggerFactory.getLogger( getClass() );
108
109     @Inject
110     @Named( value = "archivaTaskScheduler#repository" )
111     private RepositoryArchivaTaskScheduler repositoryTaskScheduler;
112
113     @Inject
114     @Named( value = "taskExecutor#indexing" )
115     private ArchivaIndexingTaskExecutor archivaIndexingTaskExecutor;
116
117     @Inject
118     private ManagedRepositoryAdmin managedRepositoryAdmin;
119
120     @Inject
121     private PlexusSisuBridge plexusSisuBridge;
122
123     @Inject
124     private MavenIndexerUtils mavenIndexerUtils;
125
126     @Inject
127     private SecuritySystem securitySystem;
128
129     @Inject
130     private RepositoryContentFactory repositoryFactory;
131
132     @Inject
133     private ArchivaAdministration archivaAdministration;
134
135     @Inject
136     @Named( value = "archivaTaskScheduler#repository" )
137     private ArchivaTaskScheduler scheduler;
138
139     @Inject
140     private DownloadRemoteIndexScheduler downloadRemoteIndexScheduler;
141
142     @Inject
143     @Named( value = "repositorySessionFactory" )
144     protected RepositorySessionFactory repositorySessionFactory;
145
146     @Inject
147     protected List<RepositoryListener> listeners = new ArrayList<RepositoryListener>();
148
149     private ChecksumAlgorithm[] algorithms = new ChecksumAlgorithm[]{ ChecksumAlgorithm.SHA1, ChecksumAlgorithm.MD5 };
150
151     public Boolean scanRepository( String repositoryId, boolean fullScan )
152     {
153         if ( repositoryTaskScheduler.isProcessingRepositoryTask( repositoryId ) )
154         {
155             log.info( "scanning of repository with id {} already scheduled", repositoryId );
156             return Boolean.FALSE;
157         }
158         RepositoryTask task = new RepositoryTask();
159         task.setRepositoryId( repositoryId );
160         task.setScanAll( fullScan );
161         try
162         {
163             repositoryTaskScheduler.queueTask( task );
164         }
165         catch ( TaskQueueException e )
166         {
167             log.error( "failed to schedule scanning of repo with id {}", repositoryId, e );
168             return false;
169         }
170         return true;
171     }
172
173     public Boolean alreadyScanning( String repositoryId )
174     {
175         return repositoryTaskScheduler.isProcessingRepositoryTask( repositoryId );
176     }
177
178     public Boolean removeScanningTaskFromQueue( String repositoryId )
179     {
180         RepositoryTask task = new RepositoryTask();
181         task.setRepositoryId( repositoryId );
182         try
183         {
184             return repositoryTaskScheduler.unQueueTask( task );
185         }
186         catch ( TaskQueueException e )
187         {
188             log.error( "failed to unschedule scanning of repo with id {}", repositoryId, e );
189             return false;
190         }
191     }
192
193     public Boolean scanRepositoryNow( String repositoryId, boolean fullScan )
194         throws ArchivaRestServiceException
195     {
196
197         try
198         {
199             ManagedRepository repository = managedRepositoryAdmin.getManagedRepository( repositoryId );
200
201             IndexingContext context = managedRepositoryAdmin.createIndexContext( repository );
202             ArtifactIndexingTask task =
203                 new ArtifactIndexingTask( repository, null, ArtifactIndexingTask.Action.FINISH, context );
204
205             task.setExecuteOnEntireRepo( true );
206             task.setOnlyUpdate( false );
207
208             archivaIndexingTaskExecutor.executeTask( task );
209             return Boolean.TRUE;
210         }
211         catch ( Exception e )
212         {
213             log.error( e.getMessage(), e );
214             throw new ArchivaRestServiceException( e.getMessage() );
215         }
216     }
217
218     public Boolean scheduleDownloadRemoteIndex( String repositoryId, boolean now, boolean fullDownload )
219         throws ArchivaRestServiceException
220     {
221         try
222         {
223             downloadRemoteIndexScheduler.scheduleDownloadRemote( repositoryId, now, fullDownload );
224         }
225         catch ( DownloadRemoteIndexException e )
226         {
227             log.error( e.getMessage(), e );
228             throw new ArchivaRestServiceException( e.getMessage() );
229         }
230         return Boolean.TRUE;
231     }
232
233     public Boolean copyArtifact( ArtifactTransferRequest artifactTransferRequest )
234         throws ArchivaRestServiceException
235     {
236         // check parameters
237         String userName = getAuditInformation().getUser().getUsername();
238         if ( StringUtils.isBlank( userName ) )
239         {
240             throw new ArchivaRestServiceException( "copyArtifact call: userName not found" );
241         }
242
243         if ( StringUtils.isBlank( artifactTransferRequest.getRepositoryId() ) )
244         {
245             throw new ArchivaRestServiceException( "copyArtifact call: sourceRepositoryId cannot be null" );
246         }
247
248         if ( StringUtils.isBlank( artifactTransferRequest.getTargetRepositoryId() ) )
249         {
250             throw new ArchivaRestServiceException( "copyArtifact call: targetRepositoryId cannot be null" );
251         }
252
253         ManagedRepository source = null;
254         try
255         {
256             source = managedRepositoryAdmin.getManagedRepository( artifactTransferRequest.getRepositoryId() );
257         }
258         catch ( RepositoryAdminException e )
259         {
260             throw new ArchivaRestServiceException( e.getMessage() );
261         }
262
263         if ( source == null )
264         {
265             throw new ArchivaRestServiceException(
266                 "cannot find repository with id " + artifactTransferRequest.getRepositoryId() );
267         }
268
269         ManagedRepository target = null;
270         try
271         {
272             target = managedRepositoryAdmin.getManagedRepository( artifactTransferRequest.getTargetRepositoryId() );
273         }
274         catch ( RepositoryAdminException e )
275         {
276             throw new ArchivaRestServiceException( e.getMessage() );
277         }
278
279         if ( target == null )
280         {
281             throw new ArchivaRestServiceException(
282                 "cannot find repository with id " + artifactTransferRequest.getTargetRepositoryId() );
283         }
284
285         if ( StringUtils.isBlank( artifactTransferRequest.getGroupId() ) )
286         {
287             throw new ArchivaRestServiceException( "groupId is mandatory" );
288         }
289
290         if ( StringUtils.isBlank( artifactTransferRequest.getArtifactId() ) )
291         {
292             throw new ArchivaRestServiceException( "artifactId is mandatory" );
293         }
294
295         if ( StringUtils.isBlank( artifactTransferRequest.getVersion() ) )
296         {
297             throw new ArchivaRestServiceException( "version is mandatory" );
298         }
299
300         if ( VersionUtil.isSnapshot( artifactTransferRequest.getVersion() ) )
301         {
302             throw new ArchivaRestServiceException( "copy of SNAPSHOT not supported" );
303         }
304
305         // end check parameters
306
307         User user = null;
308         try
309         {
310             user = securitySystem.getUserManager().findUser( userName );
311         }
312         catch ( UserNotFoundException e )
313         {
314             throw new ArchivaRestServiceException( "user " + userName + " not found" );
315         }
316
317         // check karma on source : read
318         AuthenticationResult authn = new AuthenticationResult( true, userName, null );
319         SecuritySession securitySession = new DefaultSecuritySession( authn, user );
320         try
321         {
322             boolean authz =
323                 securitySystem.isAuthorized( securitySession, ArchivaRoleConstants.OPERATION_REPOSITORY_ACCESS,
324                                              artifactTransferRequest.getRepositoryId() );
325             if ( !authz )
326             {
327                 throw new ArchivaRestServiceException(
328                     "not authorized to access repo:" + artifactTransferRequest.getRepositoryId() );
329             }
330         }
331         catch ( AuthorizationException e )
332         {
333             log.error( "error reading permission: " + e.getMessage(), e );
334             throw new ArchivaRestServiceException( e.getMessage() );
335         }
336
337         // check karma on target: write
338         try
339         {
340             boolean authz =
341                 securitySystem.isAuthorized( securitySession, ArchivaRoleConstants.OPERATION_REPOSITORY_UPLOAD,
342                                              artifactTransferRequest.getTargetRepositoryId() );
343             if ( !authz )
344             {
345                 throw new ArchivaRestServiceException(
346                     "not authorized to write to repo:" + artifactTransferRequest.getTargetRepositoryId() );
347             }
348         }
349         catch ( AuthorizationException e )
350         {
351             log.error( "error reading permission: " + e.getMessage(), e );
352             throw new ArchivaRestServiceException( e.getMessage() );
353         }
354
355         // sounds good we can continue !
356
357         ArtifactReference artifactReference = new ArtifactReference();
358         artifactReference.setArtifactId( artifactTransferRequest.getArtifactId() );
359         artifactReference.setGroupId( artifactTransferRequest.getGroupId() );
360         artifactReference.setVersion( artifactTransferRequest.getVersion() );
361         artifactReference.setClassifier( artifactTransferRequest.getClassifier() );
362         String packaging = StringUtils.trim( artifactTransferRequest.getPackaging() );
363         artifactReference.setType( StringUtils.isEmpty( packaging ) ? "jar" : packaging );
364
365         try
366         {
367
368             ManagedRepositoryContent sourceRepository =
369                 repositoryFactory.getManagedRepositoryContent( artifactTransferRequest.getRepositoryId() );
370
371             String artifactSourcePath = sourceRepository.toPath( artifactReference );
372
373             if ( StringUtils.isEmpty( artifactSourcePath ) )
374             {
375                 log.error( "cannot find artifact " + artifactTransferRequest.toString() );
376                 throw new ArchivaRestServiceException( "cannot find artifact " + artifactTransferRequest.toString() );
377             }
378
379             File artifactFile = new File( source.getLocation(), artifactSourcePath );
380
381             if ( !artifactFile.exists() )
382             {
383                 log.error( "cannot find artifact " + artifactTransferRequest.toString() );
384                 throw new ArchivaRestServiceException( "cannot find artifact " + artifactTransferRequest.toString() );
385             }
386
387             ManagedRepositoryContent targetRepository =
388                 repositoryFactory.getManagedRepositoryContent( artifactTransferRequest.getTargetRepositoryId() );
389
390             String artifactPath = targetRepository.toPath( artifactReference );
391
392             int lastIndex = artifactPath.lastIndexOf( '/' );
393
394             String path = artifactPath.substring( 0, lastIndex );
395             File targetPath = new File( target.getLocation(), path );
396
397             Date lastUpdatedTimestamp = Calendar.getInstance().getTime();
398             int newBuildNumber = 1;
399             String timestamp = null;
400
401             File versionMetadataFile = new File( targetPath, MetadataTools.MAVEN_METADATA );
402             ArchivaRepositoryMetadata versionMetadata = getMetadata( versionMetadataFile );
403
404             if ( !targetPath.exists() )
405             {
406                 targetPath.mkdirs();
407             }
408
409             String filename = artifactPath.substring( lastIndex + 1 );
410
411             // FIXME some dupe with uploadaction
412
413             boolean fixChecksums =
414                 !( archivaAdministration.getKnownContentConsumers().contains( "create-missing-checksums" ) );
415
416             File targetFile = new File( targetPath, filename );
417             if ( targetFile.exists() && target.isBlockRedeployments() )
418             {
419                 throw new ArchivaRestServiceException(
420                     "artifact already exists in target repo: " + artifactTransferRequest.getTargetRepositoryId()
421                         + " and redeployment blocked" );
422             }
423             else
424             {
425                 copyFile( artifactFile, targetPath, filename, fixChecksums );
426                 queueRepositoryTask( target.getId(), targetFile );
427             }
428
429             // copy source pom to target repo
430             String pomFilename = filename;
431             if ( StringUtils.isNotBlank( artifactTransferRequest.getClassifier() ) )
432             {
433                 pomFilename = StringUtils.remove( pomFilename, "-" + artifactTransferRequest.getClassifier() );
434             }
435             pomFilename = FilenameUtils.removeExtension( pomFilename ) + ".pom";
436
437             File pomFile = new File(
438                 new File( source.getLocation(), artifactSourcePath.substring( 0, artifactPath.lastIndexOf( '/' ) ) ),
439                 pomFilename );
440
441             if ( pomFile != null && pomFile.length() > 0 )
442             {
443                 copyFile( pomFile, targetPath, pomFilename, fixChecksums );
444                 queueRepositoryTask( target.getId(), new File( targetPath, pomFilename ) );
445
446
447             }
448
449             // explicitly update only if metadata-updater consumer is not enabled!
450             if ( !archivaAdministration.getKnownContentConsumers().contains( "metadata-updater" ) )
451             {
452                 updateProjectMetadata( targetPath.getAbsolutePath(), lastUpdatedTimestamp, timestamp, newBuildNumber,
453                                        fixChecksums, artifactTransferRequest );
454
455
456             }
457
458             String msg =
459                 "Artifact \'" + artifactTransferRequest.getGroupId() + ":" + artifactTransferRequest.getArtifactId()
460                     + ":" + artifactTransferRequest.getVersion() + "\' was successfully deployed to repository \'"
461                     + artifactTransferRequest.getTargetRepositoryId() + "\'";
462
463         }
464         catch ( RepositoryException e )
465         {
466             log.error( "RepositoryException: " + e.getMessage(), e );
467             throw new ArchivaRestServiceException( e.getMessage() );
468         }
469         catch ( RepositoryAdminException e )
470         {
471             log.error( "RepositoryAdminException: " + e.getMessage(), e );
472             throw new ArchivaRestServiceException( e.getMessage() );
473         }
474         catch ( IOException e )
475         {
476             log.error( "IOException: " + e.getMessage(), e );
477             throw new ArchivaRestServiceException( e.getMessage() );
478         }
479         return true;
480     }
481
482     //FIXME some duplicate with UploadAction 
483
484     private void queueRepositoryTask( String repositoryId, File localFile )
485     {
486         RepositoryTask task = new RepositoryTask();
487         task.setRepositoryId( repositoryId );
488         task.setResourceFile( localFile );
489         task.setUpdateRelatedArtifacts( true );
490         //task.setScanAll( true );
491
492         try
493         {
494             scheduler.queueTask( task );
495         }
496         catch ( TaskQueueException e )
497         {
498             log.error( "Unable to queue repository task to execute consumers on resource file ['" + localFile.getName()
499                            + "']." );
500         }
501     }
502
503     private ArchivaRepositoryMetadata getMetadata( File metadataFile )
504         throws RepositoryMetadataException
505     {
506         ArchivaRepositoryMetadata metadata = new ArchivaRepositoryMetadata();
507         if ( metadataFile.exists() )
508         {
509             metadata = RepositoryMetadataReader.read( metadataFile );
510         }
511         return metadata;
512     }
513
514     private File getMetadata( String targetPath )
515     {
516         String artifactPath = targetPath.substring( 0, targetPath.lastIndexOf( File.separatorChar ) );
517
518         return new File( artifactPath, MetadataTools.MAVEN_METADATA );
519     }
520
521     private void copyFile( File sourceFile, File targetPath, String targetFilename, boolean fixChecksums )
522         throws IOException
523     {
524         FileOutputStream out = new FileOutputStream( new File( targetPath, targetFilename ) );
525         FileInputStream input = new FileInputStream( sourceFile );
526
527         try
528         {
529             IOUtils.copy( input, out );
530         }
531         finally
532         {
533             out.close();
534             input.close();
535         }
536
537         if ( fixChecksums )
538         {
539             fixChecksums( new File( targetPath, targetFilename ) );
540         }
541     }
542
543     private void fixChecksums( File file )
544     {
545         ChecksummedFile checksum = new ChecksummedFile( file );
546         checksum.fixChecksums( algorithms );
547     }
548
549     private void updateProjectMetadata( String targetPath, Date lastUpdatedTimestamp, String timestamp, int buildNumber,
550                                         boolean fixChecksums, ArtifactTransferRequest artifactTransferRequest )
551         throws RepositoryMetadataException
552     {
553         List<String> availableVersions = new ArrayList<String>();
554         String latestVersion = artifactTransferRequest.getVersion();
555
556         File projectDir = new File( targetPath ).getParentFile();
557         File projectMetadataFile = new File( projectDir, MetadataTools.MAVEN_METADATA );
558
559         ArchivaRepositoryMetadata projectMetadata = getMetadata( projectMetadataFile );
560
561         if ( projectMetadataFile.exists() )
562         {
563             availableVersions = projectMetadata.getAvailableVersions();
564
565             Collections.sort( availableVersions, VersionComparator.getInstance() );
566
567             if ( !availableVersions.contains( artifactTransferRequest.getVersion() ) )
568             {
569                 availableVersions.add( artifactTransferRequest.getVersion() );
570             }
571
572             latestVersion = availableVersions.get( availableVersions.size() - 1 );
573         }
574         else
575         {
576             availableVersions.add( artifactTransferRequest.getVersion() );
577
578             projectMetadata.setGroupId( artifactTransferRequest.getGroupId() );
579             projectMetadata.setArtifactId( artifactTransferRequest.getArtifactId() );
580         }
581
582         if ( projectMetadata.getGroupId() == null )
583         {
584             projectMetadata.setGroupId( artifactTransferRequest.getGroupId() );
585         }
586
587         if ( projectMetadata.getArtifactId() == null )
588         {
589             projectMetadata.setArtifactId( artifactTransferRequest.getArtifactId() );
590         }
591
592         projectMetadata.setLatestVersion( latestVersion );
593         projectMetadata.setLastUpdatedTimestamp( lastUpdatedTimestamp );
594         projectMetadata.setAvailableVersions( availableVersions );
595
596         if ( !VersionUtil.isSnapshot( artifactTransferRequest.getVersion() ) )
597         {
598             projectMetadata.setReleasedVersion( latestVersion );
599         }
600
601         RepositoryMetadataWriter.write( projectMetadata, projectMetadataFile );
602
603         if ( fixChecksums )
604         {
605             fixChecksums( projectMetadataFile );
606         }
607     }
608
609
610     public Boolean deleteArtifact( Artifact artifact, String repositoryId )
611         throws ArchivaRestServiceException
612     {
613         String userName = getAuditInformation().getUser().getUsername();
614         if ( StringUtils.isBlank( userName ) )
615         {
616             // TODO use constants from a class instead of magic number
617             throw new ArchivaRestServiceException( "deleteArtifact call: userName not found", 403 );
618         }
619         if ( artifact == null )
620         {
621             throw new ArchivaRestServiceException( "artifact cannot be null", 400 );
622         }
623         if ( StringUtils.isEmpty( repositoryId ) )
624         {
625             throw new ArchivaRestServiceException( "repositoryId cannot be null", 400 );
626         }
627
628         // TODO more control on artifact fields
629
630         RepositorySession repositorySession = repositorySessionFactory.createSession();
631         try
632         {
633             Date lastUpdatedTimestamp = Calendar.getInstance().getTime();
634
635             TimeZone timezone = TimeZone.getTimeZone( "UTC" );
636             DateFormat fmt = new SimpleDateFormat( "yyyyMMdd.HHmmss" );
637             fmt.setTimeZone( timezone );
638             ManagedRepository repoConfig = managedRepositoryAdmin.getManagedRepository( repositoryId );
639
640             VersionedReference ref = new VersionedReference();
641             ref.setArtifactId( artifact.getArtifactId() );
642             ref.setGroupId( artifact.getGroupId() );
643             ref.setVersion( artifact.getVersion() );
644
645             ManagedRepositoryContent repository = repositoryFactory.getManagedRepositoryContent( repositoryId );
646
647             if ( StringUtils.isNotBlank( artifact.getClassifier() ) )
648             {
649                 if ( StringUtils.isBlank( artifact.getPackaging() ) )
650                 {
651                     throw new ArchivaRestServiceException( "You must configure a type/packaging when using classifier",
652                                                            400 );
653                 }
654                 ArtifactReference artifactReference = new ArtifactReference();
655                 artifactReference.setArtifactId( artifact.getArtifactId() );
656                 artifactReference.setGroupId( artifact.getGroupId() );
657                 artifactReference.setVersion( artifact.getVersion() );
658                 artifactReference.setClassifier( artifact.getClassifier() );
659                 artifactReference.setType( artifact.getPackaging() );
660                 repository.deleteArtifact( artifactReference );
661
662                 // TODO cleanup facet which contains classifier information
663                 return Boolean.TRUE;
664             }
665
666             String path = repository.toMetadataPath( ref );
667             int index = path.lastIndexOf( '/' );
668             path = path.substring( 0, index );
669             File targetPath = new File( repoConfig.getLocation(), path );
670
671             if ( !targetPath.exists() )
672             {
673                 throw new ContentNotFoundException(
674                     artifact.getGroupId() + ":" + artifact.getArtifactId() + ":" + artifact.getVersion() );
675             }
676
677             // TODO: this should be in the storage mechanism so that it is all tied together
678             // delete from file system
679             repository.deleteVersion( ref );
680
681             File metadataFile = getMetadata( targetPath.getAbsolutePath() );
682             ArchivaRepositoryMetadata metadata = getMetadata( metadataFile );
683
684             updateMetadata( metadata, metadataFile, lastUpdatedTimestamp, artifact );
685
686             MetadataRepository metadataRepository = repositorySession.getRepository();
687
688             Collection<ArtifactMetadata> artifacts =
689                 metadataRepository.getArtifacts( repositoryId, artifact.getGroupId(), artifact.getArtifactId(),
690                                                  artifact.getVersion() );
691
692             for ( ArtifactMetadata artifactMetadata : artifacts )
693             {
694                 // TODO: mismatch between artifact (snapshot) version and project (base) version here
695                 if ( artifact.getVersion().equals( artifact.getVersion() ) )
696                 {
697                     metadataRepository.removeArtifact( artifactMetadata.getRepositoryId(),
698                                                        artifactMetadata.getNamespace(), artifactMetadata.getProject(),
699                                                        artifact.getVersion(), artifactMetadata.getId() );
700
701                     // TODO: move into the metadata repository proper - need to differentiate attachment of
702                     //       repository metadata to an artifact
703                     for ( RepositoryListener listener : listeners )
704                     {
705                         listener.deleteArtifact( metadataRepository, repository.getId(),
706                                                  artifactMetadata.getNamespace(), artifactMetadata.getProject(),
707                                                  artifactMetadata.getVersion(), artifactMetadata.getId() );
708                     }
709
710                     triggerAuditEvent( repositoryId, path, AuditEvent.REMOVE_FILE );
711                 }
712             }
713             repositorySession.save();
714         }
715
716         catch ( ContentNotFoundException e )
717         {
718             throw new ArchivaRestServiceException( "Artifact does not exist: " + e.getMessage(), 400 );
719         }
720         catch ( RepositoryNotFoundException e )
721         {
722             throw new ArchivaRestServiceException( "Target repository cannot be found: " + e.getMessage(), 400 );
723         }
724         catch ( RepositoryException e )
725         {
726             throw new ArchivaRestServiceException( "Repository exception: " + e.getMessage(), 400 );
727         }
728         catch ( MetadataResolutionException e )
729         {
730             throw new ArchivaRestServiceException( "Repository exception: " + e.getMessage(), 400 );
731         }
732         catch ( MetadataRepositoryException e )
733         {
734             throw new ArchivaRestServiceException( "Repository exception: " + e.getMessage(), 400 );
735         }
736         catch ( RepositoryAdminException e )
737         {
738             throw new ArchivaRestServiceException( "RepositoryAdmin exception: " + e.getMessage(), 400 );
739         }
740         finally
741
742         {
743             repositorySession.close();
744         }
745         return Boolean.TRUE;
746     }
747
748
749     /**
750      * Update artifact level metadata. Creates one if metadata does not exist after artifact deletion.
751      *
752      * @param metadata
753      */
754     private void updateMetadata( ArchivaRepositoryMetadata metadata, File metadataFile, Date lastUpdatedTimestamp,
755                                  Artifact artifact )
756         throws RepositoryMetadataException
757     {
758         List<String> availableVersions = new ArrayList<String>();
759         String latestVersion = "";
760
761         if ( metadataFile.exists() )
762         {
763             if ( metadata.getAvailableVersions() != null )
764             {
765                 availableVersions = metadata.getAvailableVersions();
766
767                 if ( availableVersions.size() > 0 )
768                 {
769                     Collections.sort( availableVersions, VersionComparator.getInstance() );
770
771                     if ( availableVersions.contains( artifact.getVersion() ) )
772                     {
773                         availableVersions.remove( availableVersions.indexOf( artifact.getVersion() ) );
774                     }
775                     if ( availableVersions.size() > 0 )
776                     {
777                         latestVersion = availableVersions.get( availableVersions.size() - 1 );
778                     }
779                 }
780             }
781         }
782
783         if ( metadata.getGroupId() == null )
784         {
785             metadata.setGroupId( artifact.getGroupId() );
786         }
787         if ( metadata.getArtifactId() == null )
788         {
789             metadata.setArtifactId( artifact.getArtifactId() );
790         }
791
792         if ( !VersionUtil.isSnapshot( artifact.getVersion() ) )
793         {
794             if ( metadata.getReleasedVersion() != null && metadata.getReleasedVersion().equals(
795                 artifact.getVersion() ) )
796             {
797                 metadata.setReleasedVersion( latestVersion );
798             }
799         }
800
801         metadata.setLatestVersion( latestVersion );
802         metadata.setLastUpdatedTimestamp( lastUpdatedTimestamp );
803         metadata.setAvailableVersions( availableVersions );
804
805         RepositoryMetadataWriter.write( metadata, metadataFile );
806         ChecksummedFile checksum = new ChecksummedFile( metadataFile );
807         checksum.fixChecksums( algorithms );
808     }
809
810     protected void triggerAuditEvent( String repositoryId, String filePath, String action )
811     {
812         AuditEvent auditEvent = new AuditEvent();
813         auditEvent.setAction( action );
814         auditEvent.setRepositoryId( repositoryId );
815         auditEvent.setResource( filePath );
816         AuditInformation auditInformation = getAuditInformation();
817         auditEvent.setUserId( auditInformation.getUser() == null ? "" : auditInformation.getUser().getUsername() );
818         auditEvent.setRemoteIP( auditInformation.getRemoteAddr() );
819         for ( AuditListener auditListener : getAuditListeners() )
820         {
821             auditListener.auditEvent( auditEvent );
822         }
823     }
824 }
825
826