1 package org.apache.maven.archiva.web.action;
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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
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;
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;
58 import com.opensymphony.xwork.ActionContext;
59 import com.opensymphony.xwork.Preparable;
60 import com.opensymphony.xwork.Validateable;
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.
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"
70 public class UploadAction
71 extends PlexusActionSupport
72 implements Validateable, Preparable
77 private RepositoryContentConsumers consumers;
80 * The groupId of the artifact to be deployed.
82 private String groupId;
85 * The artifactId of the artifact to be deployed.
87 private String artifactId;
90 * The version of the artifact to be deployed.
92 private String version;
95 * The packaging of the artifact to be deployed.
97 private String packaging;
100 * The classifier of the artifact to be deployed.
102 private String classifier;
105 * The temporary file representing the artifact to be deployed.
107 private File artifactFile;
110 * The content type of the artifact to be deployed.
112 private String artifactContentType;
115 * The original filename of the uploaded artifact file.
117 private String artifactFilename;
120 * The temporary file representing the pom to be deployed alongside the artifact.
122 private File pomFile;
125 * The content type of the pom file.
127 private String pomContentType;
130 * The original filename of the uploaded pom file.
132 private String pomFilename;
135 * The repository where the artifact is to be deployed.
137 private String repositoryId;
140 * Flag whether to generate a pom for the artifact or not.
142 private boolean generatePom;
145 * List of managed repositories to deploy to.
147 private List<String> managedRepoIdList;
150 * @plexus.requirement
152 private UserRepositories userRepositories;
155 * @plexus.requirement role-hint="default"
157 private ArchivaConfiguration configuration;
160 * @plexus.requirement
162 private RepositoryContentFactory repositoryFactory;
164 private ChecksumAlgorithm[] algorithms = new ChecksumAlgorithm[] { ChecksumAlgorithm.SHA1, ChecksumAlgorithm.MD5 };
166 private ProjectModelWriter pomWriter = new ProjectModel400Writer();
168 public void setArtifact( File file )
170 this.artifactFile = file;
173 public void setArtifactContentType( String contentType )
175 this.artifactContentType = contentType;
178 public void setArtifactFileName( String filename )
180 this.artifactFilename = filename;
183 public void setPom( File file )
188 public void setPomContentType( String contentType )
190 this.pomContentType = contentType;
193 public void setPomFileName( String filename )
195 this.pomFilename = filename;
198 public String getGroupId()
203 public void setGroupId( String groupId )
205 this.groupId = groupId;
208 public String getArtifactId()
213 public void setArtifactId( String artifactId )
215 this.artifactId = artifactId;
218 public String getVersion()
223 public void setVersion( String version )
225 this.version = version;
228 public String getPackaging()
233 public void setPackaging( String packaging )
235 this.packaging = packaging;
238 public String getClassifier()
243 public void setClassifier( String classifier )
245 this.classifier = classifier;
248 public String getRepositoryId()
253 public void setRepositoryId( String repositoryId )
255 this.repositoryId = repositoryId;
258 public boolean isGeneratePom()
263 public void setGeneratePom( boolean generatePom )
265 this.generatePom = generatePom;
268 public List<String> getManagedRepoIdList()
270 return managedRepoIdList;
273 public void setManagedRepoIdList( List<String> managedRepoIdList )
275 this.managedRepoIdList = managedRepoIdList;
278 public void prepare()
281 new ArrayList<String>( configuration.getConfiguration().getManagedRepositoriesAsMap().keySet() );
284 public String input()
291 // reset the fields so the form is clear when
292 // the action returns to the jsp page
299 artifactContentType = "";
300 artifactFilename = "";
308 public String doUpload()
312 ManagedRepositoryConfiguration repoConfig =
313 configuration.getConfiguration().findManagedRepositoryById( repositoryId );
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 );
322 ManagedRepositoryContent repository = repositoryFactory.getManagedRepositoryContent( repositoryId );
324 String artifactPath = repository.toPath( artifactReference );
326 int lastIndex = artifactPath.lastIndexOf( '/' );
328 File targetPath = new File( repoConfig.getLocation(), artifactPath.substring( 0, lastIndex ) );
330 if ( !targetPath.exists() )
337 copyFile( artifactFile, targetPath, artifactPath.substring( lastIndex + 1 ) );
338 consumers.executeConsumers( repoConfig, repository.toFile( artifactReference ) );
340 catch ( IOException ie )
342 addActionError( "Error encountered while uploading file: " + ie.getMessage() );
350 File generatedPomFile = createPom( targetPath, artifactPath.substring( lastIndex + 1 ) );
351 consumers.executeConsumers( repoConfig, generatedPomFile );
353 catch ( IOException ie )
355 addActionError( "Error encountered while writing pom file: " + ie.getMessage() );
358 catch ( ProjectModelException pe )
360 addActionError( "Error encountered while generating pom file: " + pe.getMessage() );
365 if ( pomFile != null && pomFile.length() > 0 )
370 String targetFilename = artifactPath.substring( lastIndex + 1 ).replaceAll( packaging, "pom" );
371 copyFile( pomFile, targetPath, targetFilename );
372 consumers.executeConsumers( repoConfig, new File( targetPath, targetFilename ) );
374 catch ( IOException ie )
376 addActionError( "Error encountered while uploading pom file: " + ie.getMessage() );
382 updateMetadata( getMetadata( targetPath.getAbsolutePath() ) );
384 String msg = "Artifact \'" + groupId + ":" + artifactId + ":" + version +
385 "\' was successfully deployed to repository \'" + repositoryId + "\'";
387 //TODO: MRM-810 (this writes to archiva.log, should be audit.log)
388 getLogger().info( msg + " by " + getPrincipal() );
390 addActionMessage( msg );
395 catch ( RepositoryNotFoundException re )
397 addActionError( "Target repository cannot be found: " + re.getMessage() );
400 catch ( RepositoryException rep )
402 addActionError( "Repository exception: " + rep.getMessage() );
407 private String getPrincipal()
409 return ArchivaXworkUser.getActivePrincipal( ActionContext.getContext().getSession() );
412 private void copyFile( File sourceFile, File targetPath, String targetFilename )
415 FileOutputStream out = new FileOutputStream( new File( targetPath, targetFilename ) );
419 FileInputStream input = new FileInputStream( sourceFile );
421 while ( ( i = input.read() ) != -1 )
433 private File createPom( File targetPath, String filename )
434 throws IOException, ProjectModelException
436 ArchivaProjectModel projectModel = new ArchivaProjectModel();
437 projectModel.setGroupId( groupId );
438 projectModel.setArtifactId( artifactId );
439 projectModel.setVersion( version );
440 projectModel.setPackaging( packaging );
442 File pomFile = new File( targetPath, filename.replaceAll( packaging, "pom" ) );
444 pomWriter.write( projectModel, pomFile );
449 private File getMetadata( String targetPath )
451 String artifactPath = targetPath.substring( 0, targetPath.lastIndexOf( '/' ) );
453 return new File( artifactPath, MetadataTools.MAVEN_METADATA );
457 * Update artifact level metadata. If it does not exist, create the metadata.
459 * @param metadataFile
461 private void updateMetadata( File metadataFile )
462 throws RepositoryMetadataException
464 List<String> availableVersions = new ArrayList<String>();
465 ArchivaRepositoryMetadata metadata = new ArchivaRepositoryMetadata();
467 if ( metadataFile.exists() )
469 metadata = RepositoryMetadataReader.read( metadataFile );
470 availableVersions = metadata.getAvailableVersions();
472 Collections.sort( availableVersions, VersionComparator.getInstance() );
474 if ( !availableVersions.contains( version ) )
476 availableVersions.add( version );
479 String latestVersion = availableVersions.get( availableVersions.size() - 1 );
480 metadata.setLatestVersion( latestVersion );
481 metadata.setAvailableVersions( availableVersions );
482 metadata.setLastUpdatedTimestamp( Calendar.getInstance().getTime() );
484 if ( !VersionUtil.isSnapshot( version ) )
486 metadata.setReleasedVersion( latestVersion );
491 availableVersions.add( version );
493 metadata.setGroupId( groupId );
494 metadata.setArtifactId( artifactId );
495 metadata.setLatestVersion( version );
496 metadata.setLastUpdatedTimestamp( Calendar.getInstance().getTime() );
497 metadata.setAvailableVersions( availableVersions );
499 if ( !VersionUtil.isSnapshot( version ) )
501 metadata.setReleasedVersion( version );
505 RepositoryMetadataWriter.write( metadata, metadataFile );
506 ChecksummedFile checksum = new ChecksummedFile( metadataFile );
507 checksum.fixChecksums( algorithms );
510 public void validate()
514 // is this enough check for the repository permission?
515 if ( !userRepositories.isAuthorizedToUploadArtifacts( getPrincipal(), repositoryId ) )
517 addActionError( "User is not authorized to upload in repository " + repositoryId );
520 if ( artifactFile == null || artifactFile.length() == 0 )
522 addActionError( "Please add a file to upload." );
525 if ( !VersionUtil.isVersion( version ) )
527 addActionError( "Invalid version." );
530 catch ( PrincipalNotFoundException pe )
532 addActionError( pe.getMessage() );
534 catch ( ArchivaSecurityException ae )
536 addActionError( ae.getMessage() );