]> source.dussan.org Git - archiva.git/blob
567c5c901f1f41945c3d5147d337ba16ab60e85a
[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     private void reset()
290     {
291         // reset the fields so the form is clear when 
292         // the action returns to the jsp page
293         groupId = "";
294         artifactId = "";
295         version = "";
296         packaging = "";
297         classifier = "";
298         artifactFile = null;
299         artifactContentType = "";
300         artifactFilename = "";
301         pomFile = null;
302         pomContentType = "";
303         pomFilename = "";
304         repositoryId = "";
305         generatePom = false;
306     }
307     
308     public String doUpload()
309     {
310         try
311         {
312             ManagedRepositoryConfiguration repoConfig =
313                 configuration.getConfiguration().findManagedRepositoryById( repositoryId );
314
315             ArtifactReference artifactReference = new ArtifactReference();
316             artifactReference.setArtifactId( artifactId );
317             artifactReference.setGroupId( groupId );
318             artifactReference.setVersion( version );
319             artifactReference.setClassifier( classifier );
320             artifactReference.setType( packaging );
321
322             ManagedRepositoryContent repository = repositoryFactory.getManagedRepositoryContent( repositoryId );
323
324             String artifactPath = repository.toPath( artifactReference );
325
326             int lastIndex = artifactPath.lastIndexOf( '/' );
327
328             File targetPath = new File( repoConfig.getLocation(), artifactPath.substring( 0, lastIndex ) );
329
330             if ( !targetPath.exists() )
331             {
332                 targetPath.mkdirs();
333             }
334
335             try
336             {
337                 copyFile( artifactFile, targetPath, artifactPath.substring( lastIndex + 1 ) );
338                 consumers.executeConsumers( repoConfig, repository.toFile( artifactReference ) );
339             }
340             catch ( IOException ie )
341             {
342                 addActionError( "Error encountered while uploading file: " + ie.getMessage() );
343                 return ERROR;
344             }
345
346             if ( generatePom )
347             {
348                 try
349                 {
350                     File generatedPomFile = createPom( targetPath, artifactPath.substring( lastIndex + 1 ) );
351                     consumers.executeConsumers( repoConfig, generatedPomFile );
352                 }
353                 catch ( IOException ie )
354                 {
355                     addActionError( "Error encountered while writing pom file: " + ie.getMessage() );
356                     return ERROR;
357                 }
358                 catch ( ProjectModelException pe )
359                 {
360                     addActionError( "Error encountered while generating pom file: " + pe.getMessage() );
361                     return ERROR;
362                 }
363             }
364             
365             if ( pomFile != null && pomFile.length() > 0 ) 
366             {
367                 
368                 try
369                 {
370                     String targetFilename = artifactPath.substring( lastIndex + 1 ).replaceAll( packaging, "pom" );
371                     copyFile( pomFile, targetPath, targetFilename );
372                     consumers.executeConsumers( repoConfig, new File( targetPath, targetFilename ) );
373                 }
374                 catch ( IOException ie )
375                 {
376                     addActionError( "Error encountered while uploading pom file: " + ie.getMessage() );
377                     return ERROR;
378                 }
379                 
380             }
381
382             updateMetadata( getMetadata( targetPath.getAbsolutePath() ) );
383
384             String msg = "Artifact \'" + groupId + ":" + artifactId + ":" + version +
385                 "\' was successfully deployed to repository \'" + repositoryId + "\'";
386
387             //TODO: MRM-810 (this writes to archiva.log, should be audit.log)
388             getLogger().info( msg + " by " + getPrincipal() );
389             
390             addActionMessage( msg );
391
392             reset();
393             return SUCCESS;
394         }
395         catch ( RepositoryNotFoundException re )
396         {
397             addActionError( "Target repository cannot be found: " + re.getMessage() );
398             return ERROR;
399         }
400         catch ( RepositoryException rep )
401         {
402             addActionError( "Repository exception: " + rep.getMessage() );
403             return ERROR;
404         }
405     }
406
407     private String getPrincipal()
408     {
409         return ArchivaXworkUser.getActivePrincipal( ActionContext.getContext().getSession() );
410     }
411
412     private void copyFile( File sourceFile, File targetPath, String targetFilename )
413         throws IOException
414     {
415         FileOutputStream out = new FileOutputStream( new File( targetPath, targetFilename ) );
416
417         try
418         {
419             FileInputStream input = new FileInputStream( sourceFile );
420             int i = 0;
421             while ( ( i = input.read() ) != -1 )
422             {
423                 out.write( i );
424             }
425             out.flush();
426         }
427         finally
428         {
429             out.close();
430         }
431     }
432
433     private File createPom( File targetPath, String filename )
434         throws IOException, ProjectModelException
435     {
436         ArchivaProjectModel projectModel = new ArchivaProjectModel();
437         projectModel.setGroupId( groupId );
438         projectModel.setArtifactId( artifactId );
439         projectModel.setVersion( version );
440         projectModel.setPackaging( packaging );
441
442         File pomFile = new File( targetPath, filename.replaceAll( packaging, "pom" ) );
443
444         pomWriter.write( projectModel, pomFile );
445
446         return pomFile;
447     }
448
449     private File getMetadata( String targetPath )
450     {
451         String artifactPath = targetPath.substring( 0, targetPath.lastIndexOf( '/' ) );
452
453         return new File( artifactPath, MetadataTools.MAVEN_METADATA );
454     }
455
456     /**
457      * Update artifact level metadata. If it does not exist, create the metadata.
458      * 
459      * @param metadataFile
460      */
461     private void updateMetadata( File metadataFile )
462         throws RepositoryMetadataException
463     {
464         List<String> availableVersions = new ArrayList<String>();
465         ArchivaRepositoryMetadata metadata = new ArchivaRepositoryMetadata();
466
467         if ( metadataFile.exists() )
468         {
469             metadata = RepositoryMetadataReader.read( metadataFile );
470             availableVersions = metadata.getAvailableVersions();
471
472             Collections.sort( availableVersions, VersionComparator.getInstance() );
473
474             if ( !availableVersions.contains( version ) )
475             {
476                 availableVersions.add( version );
477             }
478
479             String latestVersion = availableVersions.get( availableVersions.size() - 1 );
480             metadata.setLatestVersion( latestVersion );
481             metadata.setAvailableVersions( availableVersions );
482             metadata.setLastUpdatedTimestamp( Calendar.getInstance().getTime() );
483
484             if ( !VersionUtil.isSnapshot( version ) )
485             {
486                 metadata.setReleasedVersion( latestVersion );
487             }
488         }
489         else
490         {
491             availableVersions.add( version );
492
493             metadata.setGroupId( groupId );
494             metadata.setArtifactId( artifactId );
495             metadata.setLatestVersion( version );
496             metadata.setLastUpdatedTimestamp( Calendar.getInstance().getTime() );
497             metadata.setAvailableVersions( availableVersions );
498
499             if ( !VersionUtil.isSnapshot( version ) )
500             {
501                 metadata.setReleasedVersion( version );
502             }
503         }
504
505         RepositoryMetadataWriter.write( metadata, metadataFile );
506         ChecksummedFile checksum = new ChecksummedFile( metadataFile );
507         checksum.fixChecksums( algorithms );
508     }
509     
510     public void validate()
511     {
512         try
513         {
514             // is this enough check for the repository permission?
515             if ( !userRepositories.isAuthorizedToUploadArtifacts( getPrincipal(), repositoryId ) )
516             {
517                 addActionError( "User is not authorized to upload in repository " + repositoryId );
518             }
519
520             if ( artifactFile == null || artifactFile.length() == 0 )
521             {
522                 addActionError( "Please add a file to upload." );
523             }
524             
525             if ( !VersionUtil.isVersion( version ) )
526             {
527                 addActionError( "Invalid version." );
528             }            
529         }
530         catch ( PrincipalNotFoundException pe )
531         {
532             addActionError( pe.getMessage() );
533         }
534         catch ( ArchivaSecurityException ae )
535         {
536             addActionError( ae.getMessage() );
537         }
538     }
539 }