]> source.dussan.org Git - archiva.git/blob
5e1c69ac94a284ad64298a324b96cbe36d4f29a2
[archiva.git] /
1 package org.apache.archiva.web.api;
2 /*
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  */
20
21 import com.google.common.base.Predicate;
22 import com.google.common.collect.Iterables;
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.checksum.ChecksumAlgorithm;
28 import org.apache.archiva.checksum.ChecksummedFile;
29 import org.apache.archiva.common.utils.VersionComparator;
30 import org.apache.archiva.common.utils.VersionUtil;
31 import org.apache.archiva.maven2.metadata.MavenMetadataReader;
32 import org.apache.archiva.metadata.model.facets.AuditEvent;
33 import org.apache.archiva.model.ArchivaRepositoryMetadata;
34 import org.apache.archiva.model.ArtifactReference;
35 import org.apache.archiva.model.SnapshotVersion;
36 import org.apache.archiva.redback.components.taskqueue.TaskQueueException;
37 import org.apache.archiva.repository.ManagedRepositoryContent;
38 import org.apache.archiva.repository.RepositoryContentFactory;
39 import org.apache.archiva.repository.RepositoryException;
40 import org.apache.archiva.repository.RepositoryNotFoundException;
41 import org.apache.archiva.repository.metadata.MetadataTools;
42 import org.apache.archiva.repository.metadata.RepositoryMetadataException;
43 import org.apache.archiva.repository.metadata.RepositoryMetadataWriter;
44 import org.apache.archiva.rest.api.services.ArchivaRestServiceException;
45 import org.apache.archiva.rest.services.AbstractRestService;
46 import org.apache.archiva.scheduler.ArchivaTaskScheduler;
47 import org.apache.archiva.scheduler.repository.model.RepositoryTask;
48 import org.apache.archiva.web.model.FileMetadata;
49 import org.apache.archiva.xml.XMLException;
50 import org.apache.commons.io.FilenameUtils;
51 import org.apache.commons.io.IOUtils;
52 import org.apache.commons.lang.BooleanUtils;
53 import org.apache.commons.lang.StringUtils;
54 import org.apache.commons.lang.SystemUtils;
55 import org.apache.cxf.jaxrs.ext.multipart.Attachment;
56 import org.apache.cxf.jaxrs.ext.multipart.MultipartBody;
57 import org.apache.maven.model.Model;
58 import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
59 import org.slf4j.Logger;
60 import org.slf4j.LoggerFactory;
61 import org.springframework.stereotype.Service;
62
63 import javax.inject.Inject;
64 import javax.inject.Named;
65 import javax.servlet.http.HttpServletRequest;
66 import javax.ws.rs.core.Context;
67 import javax.ws.rs.core.Response;
68 import java.io.FileOutputStream;
69 import java.io.FileWriter;
70 import java.io.IOException;
71 import java.nio.file.Files;
72 import java.nio.file.Path;
73 import java.nio.file.Paths;
74 import java.nio.file.StandardCopyOption;
75 import java.text.DateFormat;
76 import java.text.SimpleDateFormat;
77 import java.util.ArrayList;
78 import java.util.Arrays;
79 import java.util.Calendar;
80 import java.util.Collections;
81 import java.util.Date;
82 import java.util.Iterator;
83 import java.util.List;
84 import java.util.TimeZone;
85 import java.util.concurrent.CopyOnWriteArrayList;
86
87 /**
88  * @author Olivier Lamy
89  */
90 @Service("fileUploadService#rest")
91 public class DefaultFileUploadService
92     extends AbstractRestService
93     implements FileUploadService
94 {
95     private Logger log = LoggerFactory.getLogger( getClass() );
96
97     @Context
98     private HttpServletRequest httpServletRequest;
99
100     @Inject
101     private ManagedRepositoryAdmin managedRepositoryAdmin;
102
103     @Inject
104     private RepositoryContentFactory repositoryFactory;
105
106     @Inject
107     private ArchivaAdministration archivaAdministration;
108
109     private List<ChecksumAlgorithm> algorithms = Arrays.asList( ChecksumAlgorithm.SHA1, ChecksumAlgorithm.MD5 );
110
111     @Inject
112     @Named(value = "archivaTaskScheduler#repository")
113     private ArchivaTaskScheduler scheduler;
114
115     private String getStringValue( MultipartBody multipartBody, String attachmentId )
116         throws IOException
117     {
118         Attachment attachment = multipartBody.getAttachment( attachmentId );
119         return attachment == null ? "" : IOUtils.toString( attachment.getDataHandler().getInputStream() );
120     }
121
122     @Override
123     public FileMetadata post( MultipartBody multipartBody )
124         throws ArchivaRestServiceException
125     {
126
127         try
128         {
129
130             String classifier = getStringValue( multipartBody, "classifier" );
131             String packaging = getStringValue( multipartBody, "packaging" );
132             // skygo: http header form pomFile was once sending 1 for true and void for false
133             // leading to permanent false value for pomFile if using toBoolean(); use , "1", ""
134             boolean pomFile = BooleanUtils.toBoolean( getStringValue( multipartBody, "pomFile" ) );
135
136             Attachment file = multipartBody.getAttachment( "files[]" );
137
138             //Content-Disposition: form-data; name="files[]"; filename="org.apache.karaf.features.command-2.2.2.jar"
139             String fileName = file.getContentDisposition().getParameter( "filename" );
140
141             Path tmpFile = Files.createTempFile( "upload-artifact", ".tmp" );
142             tmpFile.toFile().deleteOnExit();
143             IOUtils.copy( file.getDataHandler().getInputStream(), new FileOutputStream( tmpFile.toFile() ) );
144             FileMetadata fileMetadata = new FileMetadata( fileName, Files.size(tmpFile), "theurl" );
145             fileMetadata.setServerFileName( tmpFile.toString() );
146             fileMetadata.setClassifier( classifier );
147             fileMetadata.setDeleteUrl( tmpFile.getFileName().toString() );
148             fileMetadata.setPomFile( pomFile );
149             fileMetadata.setPackaging( packaging );
150
151             log.info( "uploading file: {}", fileMetadata );
152
153             List<FileMetadata> fileMetadatas = getSessionFilesList();
154
155             fileMetadatas.add( fileMetadata );
156
157             return fileMetadata;
158         }
159         catch ( IOException e )
160         {
161             throw new ArchivaRestServiceException( e.getMessage(),
162                                                    Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
163         }
164
165     }
166
167     /**
168      * FIXME must be per session synchronized not globally
169      *
170      * @return
171      */
172     protected synchronized List<FileMetadata> getSessionFilesList()
173     {
174         List<FileMetadata> fileMetadatas =
175             (List<FileMetadata>) httpServletRequest.getSession().getAttribute( FILES_SESSION_KEY );
176         if ( fileMetadatas == null )
177         {
178             fileMetadatas = new CopyOnWriteArrayList<>();
179             httpServletRequest.getSession().setAttribute( FILES_SESSION_KEY, fileMetadatas );
180         }
181         return fileMetadatas;
182     }
183
184     @Override
185     public Boolean deleteFile( String fileName )
186         throws ArchivaRestServiceException
187     {
188         Path file = SystemUtils.getJavaIoTmpDir().toPath().resolve( fileName );
189         log.debug( "delete file:{},exists:{}", file, Files.exists(file) );
190         boolean removed = getSessionFileMetadatas().remove( new FileMetadata( fileName ) );
191         // try with full name as ui only know the file name
192         if ( !removed )
193         {
194             /* unused */ getSessionFileMetadatas().remove( new FileMetadata( file.toString() ) );
195         }
196         try
197         {
198             Files.deleteIfExists( file );
199         }
200         catch ( IOException e )
201         {
202             log.error("Could not delete file {}: {}", file, e.getMessage(), e);
203         }
204         return Boolean.FALSE;
205     }
206
207     @Override
208     public Boolean clearUploadedFiles()
209         throws ArchivaRestServiceException
210     {
211         List<FileMetadata> fileMetadatas = new ArrayList( getSessionFileMetadatas() );
212         for ( FileMetadata fileMetadata : fileMetadatas )
213         {
214             deleteFile( Paths.get( fileMetadata.getServerFileName() ).toString() );
215         }
216         getSessionFileMetadatas().clear();
217         return Boolean.TRUE;
218     }
219
220     @Override
221     public List<FileMetadata> getSessionFileMetadatas()
222         throws ArchivaRestServiceException
223     {
224         List<FileMetadata> fileMetadatas =
225             (List<FileMetadata>) httpServletRequest.getSession().getAttribute( FILES_SESSION_KEY );
226
227         return fileMetadatas == null ? Collections.<FileMetadata>emptyList() : fileMetadatas;
228     }
229
230     @Override
231     public Boolean save( String repositoryId, String groupId, String artifactId, String version, String packaging,
232                          boolean generatePom )
233         throws ArchivaRestServiceException
234     {
235         repositoryId = StringUtils.trim( repositoryId );
236         groupId = StringUtils.trim( groupId );
237         artifactId = StringUtils.trim( artifactId );
238         version = StringUtils.trim( version );
239         packaging = StringUtils.trim( packaging );
240
241         List<FileMetadata> fileMetadatas = getSessionFilesList();
242         if ( fileMetadatas == null || fileMetadatas.isEmpty() )
243         {
244             return Boolean.FALSE;
245         }
246
247         try
248         {
249             ManagedRepository managedRepository = managedRepositoryAdmin.getManagedRepository( repositoryId );
250
251             if ( managedRepository == null )
252             {
253                 // TODO i18n ?
254                 throw new ArchivaRestServiceException( "Cannot find managed repository with id " + repositoryId,
255                                                        Response.Status.BAD_REQUEST.getStatusCode(), null );
256             }
257
258             if ( VersionUtil.isSnapshot( version ) && !managedRepository.isSnapshots() )
259             {
260                 // TODO i18n ?
261                 throw new ArchivaRestServiceException(
262                     "Managed repository with id " + repositoryId + " do not accept snapshots",
263                     Response.Status.BAD_REQUEST.getStatusCode(), null );
264             }
265         }
266         catch ( RepositoryAdminException e )
267         {
268             throw new ArchivaRestServiceException( e.getMessage(),
269                                                    Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
270         }
271
272         // get from the session file with groupId/artifactId
273
274         Iterable<FileMetadata> filesToAdd = Iterables.filter( fileMetadatas, new Predicate<FileMetadata>()
275         {
276             public boolean apply( FileMetadata fileMetadata )
277             {
278                 return fileMetadata != null && !fileMetadata.isPomFile();
279             }
280         } );
281         Iterator<FileMetadata> iterator = filesToAdd.iterator();
282         boolean pomGenerated = false;
283         while ( iterator.hasNext() )
284         {
285             FileMetadata fileMetadata = iterator.next();
286             log.debug( "fileToAdd: {}", fileMetadata );
287             saveFile( repositoryId, fileMetadata, generatePom && !pomGenerated, groupId, artifactId, version,
288                       packaging );
289             pomGenerated = true;
290             deleteFile( fileMetadata.getServerFileName() );
291         }
292
293         filesToAdd = Iterables.filter( fileMetadatas, new Predicate<FileMetadata>()
294         {
295             @Override
296             public boolean apply( FileMetadata fileMetadata )
297             {
298                 return fileMetadata != null && fileMetadata.isPomFile();
299             }
300         } );
301
302         iterator = filesToAdd.iterator();
303         while ( iterator.hasNext() )
304         {
305             FileMetadata fileMetadata = iterator.next();
306             log.debug( "fileToAdd: {}", fileMetadata );
307             savePomFile( repositoryId, fileMetadata, groupId, artifactId, version, packaging );
308             deleteFile( fileMetadata.getServerFileName() );
309         }
310
311         return Boolean.TRUE;
312     }
313
314     protected void savePomFile( String repositoryId, FileMetadata fileMetadata, String groupId, String artifactId,
315                                 String version, String packaging )
316         throws ArchivaRestServiceException
317     {
318
319         try
320         {
321             boolean fixChecksums =
322                 !( archivaAdministration.getKnownContentConsumers().contains( "create-missing-checksums" ) );
323
324             ManagedRepository repoConfig = managedRepositoryAdmin.getManagedRepository( repositoryId );
325
326             ArtifactReference artifactReference = new ArtifactReference();
327             artifactReference.setArtifactId( artifactId );
328             artifactReference.setGroupId( groupId );
329             artifactReference.setVersion( version );
330             artifactReference.setClassifier( fileMetadata.getClassifier() );
331             artifactReference.setType( packaging );
332
333             ManagedRepositoryContent repository = repositoryFactory.getManagedRepositoryContent( repositoryId );
334
335             String artifactPath = repository.toPath( artifactReference );
336
337             int lastIndex = artifactPath.lastIndexOf( '/' );
338
339             String path = artifactPath.substring( 0, lastIndex );
340             Path targetPath = Paths.get( repoConfig.getLocation(), path );
341
342             String pomFilename = artifactPath.substring( lastIndex + 1 );
343             if ( StringUtils.isNotEmpty( fileMetadata.getClassifier() ) )
344             {
345                 pomFilename = StringUtils.remove( pomFilename, "-" + fileMetadata.getClassifier() );
346             }
347             pomFilename = FilenameUtils.removeExtension( pomFilename ) + ".pom";
348
349             copyFile( Paths.get( fileMetadata.getServerFileName() ), targetPath, pomFilename, fixChecksums );
350             triggerAuditEvent( repoConfig.getId(), path + "/" + pomFilename, AuditEvent.UPLOAD_FILE );
351             queueRepositoryTask( repoConfig.getId(), targetPath.resolve(pomFilename ) );
352         }
353         catch ( IOException ie )
354         {
355             throw new ArchivaRestServiceException( "Error encountered while uploading pom file: " + ie.getMessage(),
356                                                    Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), ie );
357         }
358         catch ( RepositoryException rep )
359         {
360             throw new ArchivaRestServiceException( "Repository exception: " + rep.getMessage(),
361                                                    Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), rep );
362         }
363         catch ( RepositoryAdminException e )
364         {
365             throw new ArchivaRestServiceException( "RepositoryAdmin exception: " + e.getMessage(),
366                                                    Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
367         }
368     }
369
370     protected void saveFile( String repositoryId, FileMetadata fileMetadata, boolean generatePom, String groupId,
371                              String artifactId, String version, String packaging )
372         throws ArchivaRestServiceException
373     {
374         try
375         {
376
377             ManagedRepository repoConfig = managedRepositoryAdmin.getManagedRepository( repositoryId );
378
379             ArtifactReference artifactReference = new ArtifactReference();
380             artifactReference.setArtifactId( artifactId );
381             artifactReference.setGroupId( groupId );
382             artifactReference.setVersion( version );
383             artifactReference.setClassifier( fileMetadata.getClassifier() );
384             artifactReference.setType(
385                 StringUtils.isEmpty( fileMetadata.getPackaging() ) ? packaging : fileMetadata.getPackaging() );
386
387             ManagedRepositoryContent repository = repositoryFactory.getManagedRepositoryContent( repositoryId );
388
389             String artifactPath = repository.toPath( artifactReference );
390
391             int lastIndex = artifactPath.lastIndexOf( '/' );
392
393             String path = artifactPath.substring( 0, lastIndex );
394             Path targetPath = Paths.get( repoConfig.getLocation(), path );
395
396             log.debug( "artifactPath: {} found targetPath: {}", artifactPath, targetPath );
397
398             Date lastUpdatedTimestamp = Calendar.getInstance().getTime();
399             int newBuildNumber = -1;
400             String timestamp = null;
401
402             Path versionMetadataFile = targetPath.resolve( MetadataTools.MAVEN_METADATA );
403             ArchivaRepositoryMetadata versionMetadata = getMetadata( versionMetadataFile );
404
405             if ( VersionUtil.isSnapshot( version ) )
406             {
407                 TimeZone timezone = TimeZone.getTimeZone( "UTC" );
408                 DateFormat fmt = new SimpleDateFormat( "yyyyMMdd.HHmmss" );
409                 fmt.setTimeZone( timezone );
410                 timestamp = fmt.format( lastUpdatedTimestamp );
411                 if ( versionMetadata.getSnapshotVersion() != null )
412                 {
413                     newBuildNumber = versionMetadata.getSnapshotVersion().getBuildNumber() + 1;
414                 }
415                 else
416                 {
417                     newBuildNumber = 1;
418                 }
419             }
420
421             if ( !Files.exists(targetPath) )
422             {
423                 Files.createDirectories( targetPath );
424             }
425
426             String filename = artifactPath.substring( lastIndex + 1 );
427             if ( VersionUtil.isSnapshot( version ) )
428             {
429                 filename = filename.replaceAll( VersionUtil.SNAPSHOT, timestamp + "-" + newBuildNumber );
430             }
431
432             boolean fixChecksums =
433                 !( archivaAdministration.getKnownContentConsumers().contains( "create-missing-checksums" ) );
434
435             try
436             {
437                 Path targetFile = targetPath.resolve( filename );
438                 if ( Files.exists(targetFile) && !VersionUtil.isSnapshot( version ) && repoConfig.isBlockRedeployments() )
439                 {
440                     throw new ArchivaRestServiceException(
441                         "Overwriting released artifacts in repository '" + repoConfig.getId() + "' is not allowed.",
442                         Response.Status.BAD_REQUEST.getStatusCode(), null );
443                 }
444                 else
445                 {
446                     copyFile( Paths.get( fileMetadata.getServerFileName() ), targetPath, filename, fixChecksums );
447                     triggerAuditEvent( repository.getId(), path + "/" + filename, AuditEvent.UPLOAD_FILE );
448                     queueRepositoryTask( repository.getId(), targetFile );
449                 }
450             }
451             catch ( IOException ie )
452             {
453                 log.error( "IOException copying file: {}", ie.getMessage(), ie );
454                 throw new ArchivaRestServiceException(
455                     "Overwriting released artifacts in repository '" + repoConfig.getId() + "' is not allowed.",
456                     Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), ie );
457             }
458
459             if ( generatePom )
460             {
461                 String pomFilename = filename;
462                 if ( StringUtils.isNotEmpty( fileMetadata.getClassifier() ) )
463                 {
464                     pomFilename = StringUtils.remove( pomFilename, "-" + fileMetadata.getClassifier() );
465                 }
466                 pomFilename = FilenameUtils.removeExtension( pomFilename ) + ".pom";
467
468                 try
469                 {
470                     Path generatedPomFile =
471                         createPom( targetPath, pomFilename, fileMetadata, groupId, artifactId, version, packaging );
472                     triggerAuditEvent( repoConfig.getId(), path + "/" + pomFilename, AuditEvent.UPLOAD_FILE );
473                     if ( fixChecksums )
474                     {
475                         fixChecksums( generatedPomFile );
476                     }
477                     queueRepositoryTask( repoConfig.getId(), generatedPomFile );
478                 }
479                 catch ( IOException ie )
480                 {
481                     throw new ArchivaRestServiceException(
482                         "Error encountered while writing pom file: " + ie.getMessage(),
483                         Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), ie );
484                 }
485             }
486
487             // explicitly update only if metadata-updater consumer is not enabled!
488             if ( !archivaAdministration.getKnownContentConsumers().contains( "metadata-updater" ) )
489             {
490                 updateProjectMetadata( targetPath.toAbsolutePath().toString(), lastUpdatedTimestamp, timestamp, newBuildNumber,
491                                        fixChecksums, fileMetadata, groupId, artifactId, version, packaging );
492
493                 if ( VersionUtil.isSnapshot( version ) )
494                 {
495                     updateVersionMetadata( versionMetadata, versionMetadataFile, lastUpdatedTimestamp, timestamp,
496                                            newBuildNumber, fixChecksums, fileMetadata, groupId, artifactId, version,
497                                            packaging );
498                 }
499             }
500         }
501         catch ( RepositoryNotFoundException re )
502         {
503             throw new ArchivaRestServiceException( "Target repository cannot be found: " + re.getMessage(),
504                                                    Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), re );
505         }
506         catch ( RepositoryException rep )
507         {
508             throw new ArchivaRestServiceException( "Repository exception: " + rep.getMessage(),
509                                                    Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), rep );
510         }
511         catch ( RepositoryAdminException e )
512         {
513             throw new ArchivaRestServiceException( "RepositoryAdmin exception: " + e.getMessage(),
514                                                    Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
515         }
516         catch ( IOException e )
517         {
518             throw new ArchivaRestServiceException("Repository exception "+ e.getMessage(),
519                 Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e);
520         }
521     }
522
523     private ArchivaRepositoryMetadata getMetadata( Path metadataFile )
524         throws RepositoryMetadataException
525     {
526         ArchivaRepositoryMetadata metadata = new ArchivaRepositoryMetadata();
527         if ( Files.exists(metadataFile) )
528         {
529             try
530             {
531                 metadata = MavenMetadataReader.read( metadataFile );
532             }
533             catch ( XMLException e )
534             {
535                 throw new RepositoryMetadataException( e.getMessage(), e );
536             }
537         }
538         return metadata;
539     }
540
541     private Path createPom( Path targetPath, String filename, FileMetadata fileMetadata, String groupId,
542                             String artifactId, String version, String packaging )
543         throws IOException
544     {
545         Model projectModel = new Model();
546         projectModel.setModelVersion( "4.0.0" );
547         projectModel.setGroupId( groupId );
548         projectModel.setArtifactId( artifactId );
549         projectModel.setVersion( version );
550         projectModel.setPackaging( packaging );
551
552         Path pomFile = targetPath.resolve( filename );
553         MavenXpp3Writer writer = new MavenXpp3Writer();
554
555         try (FileWriter w = new FileWriter( pomFile.toFile() ))
556         {
557             writer.write( w, projectModel );
558         }
559
560         return pomFile;
561     }
562
563     private void fixChecksums( Path file )
564     {
565         ChecksummedFile checksum = new ChecksummedFile( file );
566         checksum.fixChecksums( algorithms );
567     }
568
569     private void queueRepositoryTask( String repositoryId, Path localFile )
570     {
571         RepositoryTask task = new RepositoryTask();
572         task.setRepositoryId( repositoryId );
573         task.setResourceFile( localFile );
574         task.setUpdateRelatedArtifacts( true );
575         task.setScanAll( false );
576
577         try
578         {
579             scheduler.queueTask( task );
580         }
581         catch ( TaskQueueException e )
582         {
583             log.error( "Unable to queue repository task to execute consumers on resource file ['{}"
584                            + "'].", localFile.getFileName() );
585         }
586     }
587
588     private void copyFile( Path sourceFile, Path targetPath, String targetFilename, boolean fixChecksums )
589         throws IOException
590     {
591
592         Files.copy( sourceFile, targetPath.resolve( targetFilename ), StandardCopyOption.REPLACE_EXISTING,
593                     StandardCopyOption.COPY_ATTRIBUTES );
594
595         if ( fixChecksums )
596         {
597             fixChecksums( targetPath.resolve( targetFilename ) );
598         }
599     }
600
601     /**
602      * Update artifact level metadata. If it does not exist, create the metadata and fix checksums if necessary.
603      */
604     private void updateProjectMetadata( String targetPath, Date lastUpdatedTimestamp, String timestamp, int buildNumber,
605                                         boolean fixChecksums, FileMetadata fileMetadata, String groupId,
606                                         String artifactId, String version, String packaging )
607         throws RepositoryMetadataException
608     {
609         List<String> availableVersions = new ArrayList<>();
610         String latestVersion = version;
611
612         Path projectDir = Paths.get(targetPath).getParent();
613         Path projectMetadataFile = projectDir.resolve( MetadataTools.MAVEN_METADATA );
614
615         ArchivaRepositoryMetadata projectMetadata = getMetadata( projectMetadataFile );
616
617         if ( Files.exists(projectMetadataFile) )
618         {
619             availableVersions = projectMetadata.getAvailableVersions();
620
621             Collections.sort( availableVersions, VersionComparator.getInstance() );
622
623             if ( !availableVersions.contains( version ) )
624             {
625                 availableVersions.add( version );
626             }
627
628             latestVersion = availableVersions.get( availableVersions.size() - 1 );
629         }
630         else
631         {
632             availableVersions.add( version );
633
634             projectMetadata.setGroupId( groupId );
635             projectMetadata.setArtifactId( artifactId );
636         }
637
638         if ( projectMetadata.getGroupId() == null )
639         {
640             projectMetadata.setGroupId( groupId );
641         }
642
643         if ( projectMetadata.getArtifactId() == null )
644         {
645             projectMetadata.setArtifactId( artifactId );
646         }
647
648         projectMetadata.setLatestVersion( latestVersion );
649         projectMetadata.setLastUpdatedTimestamp( lastUpdatedTimestamp );
650         projectMetadata.setAvailableVersions( availableVersions );
651
652         if ( !VersionUtil.isSnapshot( version ) )
653         {
654             projectMetadata.setReleasedVersion( latestVersion );
655         }
656
657         RepositoryMetadataWriter.write( projectMetadata, projectMetadataFile );
658
659         if ( fixChecksums )
660         {
661             fixChecksums( projectMetadataFile );
662         }
663     }
664
665     /**
666      * Update version level metadata for snapshot artifacts. If it does not exist, create the metadata and fix checksums
667      * if necessary.
668      */
669     private void updateVersionMetadata( ArchivaRepositoryMetadata metadata, Path metadataFile,
670                                         Date lastUpdatedTimestamp, String timestamp, int buildNumber,
671                                         boolean fixChecksums, FileMetadata fileMetadata, String groupId,
672                                         String artifactId, String version, String packaging )
673         throws RepositoryMetadataException
674     {
675         if ( !Files.exists(metadataFile) )
676         {
677             metadata.setGroupId( groupId );
678             metadata.setArtifactId( artifactId );
679             metadata.setVersion( version );
680         }
681
682         if ( metadata.getSnapshotVersion() == null )
683         {
684             metadata.setSnapshotVersion( new SnapshotVersion() );
685         }
686
687         metadata.getSnapshotVersion().setBuildNumber( buildNumber );
688         metadata.getSnapshotVersion().setTimestamp( timestamp );
689         metadata.setLastUpdatedTimestamp( lastUpdatedTimestamp );
690
691         RepositoryMetadataWriter.write( metadata, metadataFile );
692
693         if ( fixChecksums )
694         {
695             fixChecksums( metadataFile );
696         }
697     }
698
699
700 }