]> source.dussan.org Git - archiva.git/blob
2f958a32c210259a3a7259c12d0931493302060a
[archiva.git] /
1 package org.apache.maven.archiva.web.action;
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 java.io.File;
23 import java.io.FileInputStream;
24 import java.io.FileOutputStream;
25 import java.io.IOException;
26 import java.util.ArrayList;
27 import java.util.Calendar;
28 import java.util.Collections;
29 import java.util.List;
30
31 import org.apache.archiva.checksum.ChecksumAlgorithm;
32 import org.apache.archiva.checksum.ChecksummedFile;
33 import org.apache.maven.archiva.common.utils.VersionComparator;
34 import org.apache.maven.archiva.common.utils.VersionUtil;
35 import org.apache.maven.archiva.configuration.ArchivaConfiguration;
36 import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration;
37 import org.apache.maven.archiva.model.ArchivaProjectModel;
38 import org.apache.maven.archiva.model.ArchivaRepositoryMetadata;
39 import org.apache.maven.archiva.model.ArtifactReference;
40 import org.apache.maven.archiva.repository.ManagedRepositoryContent;
41 import org.apache.maven.archiva.repository.RepositoryContentFactory;
42 import org.apache.maven.archiva.repository.RepositoryException;
43 import org.apache.maven.archiva.repository.RepositoryNotFoundException;
44 import org.apache.maven.archiva.repository.scanner.RepositoryContentConsumers;
45 import org.apache.maven.archiva.repository.metadata.MetadataTools;
46 import org.apache.maven.archiva.repository.metadata.RepositoryMetadataException;
47 import org.apache.maven.archiva.repository.metadata.RepositoryMetadataReader;
48 import org.apache.maven.archiva.repository.metadata.RepositoryMetadataWriter;
49 import org.apache.maven.archiva.repository.project.ProjectModelException;
50 import org.apache.maven.archiva.repository.project.ProjectModelWriter;
51 import org.apache.maven.archiva.repository.project.writers.ProjectModel400Writer;
52 import org.apache.maven.archiva.security.ArchivaSecurityException;
53 import org.apache.maven.archiva.security.PrincipalNotFoundException;
54 import org.apache.maven.archiva.security.UserRepositories;
55 import org.apache.maven.archiva.security.ArchivaXworkUser;
56 import org.codehaus.plexus.xwork.action.PlexusActionSupport;
57
58 import com.opensymphony.xwork.ActionContext;
59 import com.opensymphony.xwork.Preparable;
60 import com.opensymphony.xwork.Validateable;
61
62 /**
63  * Upload an artifact using Jakarta file upload in webwork. If set by the user a pom will also be generated. Metadata
64  * will also be updated if one exists, otherwise it would be created.
65  * 
66  * @author <a href="mailto:wsmoak@apache.org">Wendy Smoak</a>
67  * @author <a href="mailto:oching@apache.org">Maria Odea Ching</a>
68  * @plexus.component role="com.opensymphony.xwork.Action" role-hint="uploadAction"
69  */
70 public class UploadAction
71     extends PlexusActionSupport
72     implements Validateable, Preparable
73 {
74     /**
75       * @plexus.requirement
76       */
77      private RepositoryContentConsumers consumers;
78     
79     /**
80      * The groupId of the artifact to be deployed.
81      */
82     private String groupId;
83
84     /**
85      * The artifactId of the artifact to be deployed.
86      */
87     private String artifactId;
88
89     /**
90      * The version of the artifact to be deployed.
91      */
92     private String version;
93
94     /**
95      * The packaging of the artifact to be deployed.
96      */
97     private String packaging;
98
99     /**
100      * The classifier of the artifact to be deployed.
101      */
102     private String classifier;
103
104     /**
105      * The temporary file representing the artifact to be deployed.
106      */
107     private File artifactFile;
108
109     /**
110      * The content type of the artifact to be deployed.
111      */
112     private String artifactContentType;
113
114     /**
115      * The original filename of the uploaded artifact file.
116      */
117     private String artifactFilename;
118
119     /**
120      * The temporary file representing the pom to be deployed alongside the artifact.
121      */
122     private File pomFile;
123
124     /**
125      * The content type of the pom file.
126      */
127     private String pomContentType;
128
129     /**
130      * The original filename of the uploaded pom file.
131      */
132     private String pomFilename;
133
134     /**
135      * The repository where the artifact is to be deployed.
136      */
137     private String repositoryId;
138
139     /**
140      * Flag whether to generate a pom for the artifact or not.
141      */
142     private boolean generatePom;
143
144     /**
145      * List of managed repositories to deploy to.
146      */
147     private List<String> managedRepoIdList;
148
149     /**
150      * @plexus.requirement
151      */
152     private UserRepositories userRepositories;
153
154     /**
155      * @plexus.requirement role-hint="default"
156      */
157     private ArchivaConfiguration configuration;
158
159     /**
160      * @plexus.requirement
161      */
162     private RepositoryContentFactory repositoryFactory;
163     
164     private ChecksumAlgorithm[] algorithms = new ChecksumAlgorithm[] { ChecksumAlgorithm.SHA1, ChecksumAlgorithm.MD5 };
165
166     private ProjectModelWriter pomWriter = new ProjectModel400Writer();
167     
168     public void setArtifact( File file )
169     {
170         this.artifactFile = file;
171     }
172
173     public void setArtifactContentType( String contentType )
174     {
175         this.artifactContentType = contentType;
176     }
177
178     public void setArtifactFileName( String filename )
179     {
180         this.artifactFilename = filename;
181     }
182
183     public void setPom( File file )
184     {
185         this.pomFile = file;
186     }
187
188     public void setPomContentType( String contentType )
189     {
190         this.pomContentType = contentType;
191     }
192
193     public void setPomFileName( String filename )
194     {
195         this.pomFilename = filename;
196     }
197
198     public String getGroupId()
199     {
200         return groupId;
201     }
202
203     public void setGroupId( String groupId )
204     {
205         this.groupId = groupId;
206     }
207
208     public String getArtifactId()
209     {
210         return artifactId;
211     }
212
213     public void setArtifactId( String artifactId )
214     {
215         this.artifactId = artifactId;
216     }
217
218     public String getVersion()
219     {
220         return version;
221     }
222
223     public void setVersion( String version )
224     {
225         this.version = version;
226     }
227
228     public String getPackaging()
229     {
230         return packaging;
231     }
232
233     public void setPackaging( String packaging )
234     {
235         this.packaging = packaging;
236     }
237
238     public String getClassifier()
239     {
240         return classifier;
241     }
242
243     public void setClassifier( String classifier )
244     {
245         this.classifier = classifier;
246     }
247
248     public String getRepositoryId()
249     {
250         return repositoryId;
251     }
252
253     public void setRepositoryId( String repositoryId )
254     {
255         this.repositoryId = repositoryId;
256     }
257
258     public boolean isGeneratePom()
259     {
260         return generatePom;
261     }
262
263     public void setGeneratePom( boolean generatePom )
264     {
265         this.generatePom = generatePom;
266     }
267
268     public List<String> getManagedRepoIdList()
269     {
270         return managedRepoIdList;
271     }
272
273     public void setManagedRepoIdList( List<String> managedRepoIdList )
274     {
275         this.managedRepoIdList = managedRepoIdList;
276     }
277
278     public void prepare()
279     {
280         managedRepoIdList =
281             new ArrayList<String>( configuration.getConfiguration().getManagedRepositoriesAsMap().keySet() );
282     }
283
284     public String input()
285     {
286         return INPUT;
287     }
288
289     public String doUpload()
290     {
291         try
292         {
293             ManagedRepositoryConfiguration repoConfig =
294                 configuration.getConfiguration().findManagedRepositoryById( repositoryId );
295
296             ArtifactReference artifactReference = new ArtifactReference();
297             artifactReference.setArtifactId( artifactId );
298             artifactReference.setGroupId( groupId );
299             artifactReference.setVersion( version );
300             artifactReference.setClassifier( classifier );
301             artifactReference.setType( packaging );
302
303             ManagedRepositoryContent repository = repositoryFactory.getManagedRepositoryContent( repositoryId );
304
305             String artifactPath = repository.toPath( artifactReference );
306
307             int lastIndex = artifactPath.lastIndexOf( '/' );
308
309             File targetPath = new File( repoConfig.getLocation(), artifactPath.substring( 0, lastIndex ) );
310
311             if ( !targetPath.exists() )
312             {
313                 targetPath.mkdirs();
314             }
315
316             try
317             {
318                 copyFile( artifactFile, targetPath, artifactPath.substring( lastIndex + 1 ) );
319             }
320             catch ( IOException ie )
321             {
322                 addActionError( "Error encountered while uploading file: " + ie.getMessage() );
323                 return ERROR;
324             }
325
326             if ( generatePom )
327             {
328                 try
329                 {
330                     createPom( targetPath, artifactPath.substring( lastIndex + 1 ) );
331                 }
332                 catch ( IOException ie )
333                 {
334                     addActionError( "Error encountered while writing pom file: " + ie.getMessage() );
335                     return ERROR;
336                 }
337                 catch ( ProjectModelException pe )
338                 {
339                     addActionError( "Error encountered while generating pom file: " + pe.getMessage() );
340                     return ERROR;
341                 }
342             }
343             
344             if ( pomFile != null && pomFile.length() > 0 ) 
345             {
346                 
347                 try
348                 {
349                     String targetFilename = artifactPath.substring( lastIndex + 1 ).replaceAll( packaging, "pom" );
350                     copyFile( pomFile, targetPath, targetFilename );
351                 }
352                 catch ( IOException ie )
353                 {
354                     addActionError( "Error encountered while uploading pom file: " + ie.getMessage() );
355                     return ERROR;
356                 }
357                 
358             }
359
360             updateMetadata( getMetadata( targetPath.getAbsolutePath() ) );
361
362             String msg = "Artifact \'" + groupId + ":" + artifactId + ":" + version +
363                 "\' was successfully deployed to repository \'" + repositoryId + "\'";
364
365             //TODO: MRM-810 (this writes to archiva.log, should be audit.log)
366             getLogger().info( msg + " by " + getPrincipal() );
367
368             //TODO: MRM-785 (success message does not display on web page)
369             addActionMessage( msg );
370
371             consumers.executeConsumers( repoConfig, repository.toFile( artifactReference ) );
372             
373             return SUCCESS;
374         }
375         catch ( RepositoryNotFoundException re )
376         {
377             addActionError( "Target repository cannot be found: " + re.getMessage() );
378             return ERROR;
379         }
380         catch ( RepositoryException rep )
381         {
382             addActionError( "Repository exception: " + rep.getMessage() );
383             return ERROR;
384         }
385     }
386
387     private String getPrincipal()
388     {
389         return ArchivaXworkUser.getActivePrincipal( ActionContext.getContext().getSession() );
390     }
391
392     private void copyFile( File sourceFile, File targetPath, String targetFilename )
393         throws IOException
394     {
395         FileOutputStream out = new FileOutputStream( new File( targetPath, targetFilename ) );
396
397         try
398         {
399             FileInputStream input = new FileInputStream( sourceFile );
400             int i = 0;
401             while ( ( i = input.read() ) != -1 )
402             {
403                 out.write( i );
404             }
405             out.flush();
406         }
407         finally
408         {
409             out.close();
410         }
411     }
412
413     private void createPom( File targetPath, String filename )
414         throws IOException, ProjectModelException
415     {
416         ArchivaProjectModel projectModel = new ArchivaProjectModel();
417         projectModel.setGroupId( groupId );
418         projectModel.setArtifactId( artifactId );
419         projectModel.setVersion( version );
420         projectModel.setPackaging( packaging );
421
422         File pomFile = new File( targetPath, filename.replaceAll( packaging, "pom" ) );
423
424         pomWriter.write( projectModel, pomFile );
425     }
426
427     private File getMetadata( String targetPath )
428     {
429         String artifactPath = targetPath.substring( 0, targetPath.lastIndexOf( '/' ) );
430
431         return new File( artifactPath, MetadataTools.MAVEN_METADATA );
432     }
433
434     /**
435      * Update artifact level metadata. If it does not exist, create the metadata.
436      * 
437      * @param metadataFile
438      */
439     private void updateMetadata( File metadataFile )
440         throws RepositoryMetadataException
441     {
442         List<String> availableVersions = new ArrayList<String>();
443         ArchivaRepositoryMetadata metadata = new ArchivaRepositoryMetadata();
444
445         if ( metadataFile.exists() )
446         {
447             metadata = RepositoryMetadataReader.read( metadataFile );
448             availableVersions = metadata.getAvailableVersions();
449
450             Collections.sort( availableVersions, VersionComparator.getInstance() );
451
452             if ( !availableVersions.contains( version ) )
453             {
454                 availableVersions.add( version );
455             }
456
457             String latestVersion = availableVersions.get( availableVersions.size() - 1 );
458             metadata.setLatestVersion( latestVersion );
459             metadata.setAvailableVersions( availableVersions );
460             metadata.setLastUpdatedTimestamp( Calendar.getInstance().getTime() );
461
462             if ( !VersionUtil.isSnapshot( version ) )
463             {
464                 metadata.setReleasedVersion( latestVersion );
465             }
466         }
467         else
468         {
469             availableVersions.add( version );
470
471             metadata.setGroupId( groupId );
472             metadata.setArtifactId( artifactId );
473             metadata.setLatestVersion( version );
474             metadata.setLastUpdatedTimestamp( Calendar.getInstance().getTime() );
475             metadata.setAvailableVersions( availableVersions );
476
477             if ( !VersionUtil.isSnapshot( version ) )
478             {
479                 metadata.setReleasedVersion( version );
480             }
481         }
482
483         RepositoryMetadataWriter.write( metadata, metadataFile );
484         ChecksummedFile checksum = new ChecksummedFile( metadataFile );
485         checksum.fixChecksums( algorithms );
486     }
487     
488     public void validate()
489     {
490         try
491         {
492             // is this enough check for the repository permission?
493             if ( !userRepositories.isAuthorizedToUploadArtifacts( getPrincipal(), repositoryId ) )
494             {
495                 addActionError( "User is not authorized to upload in repository " + repositoryId );
496             }
497
498             if ( artifactFile == null || artifactFile.length() == 0 )
499             {
500                 addActionError( "Please add a file to upload." );
501             }
502             
503             if ( !VersionUtil.isVersion( version ) )
504             {
505                 addActionError( "Invalid version." );
506             }            
507         }
508         catch ( PrincipalNotFoundException pe )
509         {
510             addActionError( pe.getMessage() );
511         }
512         catch ( ArchivaSecurityException ae )
513         {
514             addActionError( ae.getMessage() );
515         }
516     }
517 }