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