123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637 |
- package org.apache.maven.archiva.web.action;
-
- /*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.text.DateFormat;
- import java.text.SimpleDateFormat;
- import java.util.ArrayList;
- import java.util.Calendar;
- import java.util.Date;
- import java.util.Collections;
- import java.util.List;
- import java.util.TimeZone;
-
- import org.apache.archiva.checksum.ChecksumAlgorithm;
- import org.apache.archiva.checksum.ChecksummedFile;
- import org.apache.maven.archiva.common.utils.VersionComparator;
- import org.apache.maven.archiva.common.utils.VersionUtil;
- import org.apache.maven.archiva.configuration.ArchivaConfiguration;
- import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration;
- import org.apache.maven.archiva.model.ArchivaProjectModel;
- import org.apache.maven.archiva.model.ArchivaRepositoryMetadata;
- import org.apache.maven.archiva.model.ArtifactReference;
- import org.apache.maven.archiva.model.SnapshotVersion;
- import org.apache.maven.archiva.repository.ManagedRepositoryContent;
- import org.apache.maven.archiva.repository.RepositoryContentFactory;
- import org.apache.maven.archiva.repository.RepositoryException;
- import org.apache.maven.archiva.repository.RepositoryNotFoundException;
- import org.apache.maven.archiva.repository.scanner.RepositoryContentConsumers;
- import org.apache.maven.archiva.repository.audit.AuditEvent;
- import org.apache.maven.archiva.repository.audit.AuditListener;
- import org.apache.maven.archiva.repository.audit.Auditable;
- import org.apache.maven.archiva.repository.metadata.MetadataTools;
- import org.apache.maven.archiva.repository.metadata.RepositoryMetadataException;
- import org.apache.maven.archiva.repository.metadata.RepositoryMetadataReader;
- import org.apache.maven.archiva.repository.metadata.RepositoryMetadataWriter;
- import org.apache.maven.archiva.repository.project.ProjectModelException;
- import org.apache.maven.archiva.repository.project.ProjectModelWriter;
- import org.apache.maven.archiva.repository.project.writers.ProjectModel400Writer;
- import org.apache.maven.archiva.security.ArchivaSecurityException;
- import org.apache.maven.archiva.security.PrincipalNotFoundException;
- import org.apache.maven.archiva.security.UserRepositories;
- import org.apache.maven.archiva.security.ArchivaXworkUser;
-
- import org.apache.struts2.ServletActionContext;
- import com.opensymphony.xwork2.ActionContext;
- import com.opensymphony.xwork2.Preparable;
- import com.opensymphony.xwork2.Validateable;
- import org.apache.commons.io.FilenameUtils;
- import org.apache.commons.lang.StringUtils;
-
- /**
- * Upload an artifact using Jakarta file upload in webwork. If set by the user a pom will also be generated. Metadata
- * will also be updated if one exists, otherwise it would be created.
- *
- * @author <a href="mailto:wsmoak@apache.org">Wendy Smoak</a>
- * @author <a href="mailto:oching@apache.org">Maria Odea Ching</a>
- * @plexus.component role="com.opensymphony.xwork2.Action" role-hint="uploadAction"
- */
- public class UploadAction
- extends PlexusActionSupport
- implements Validateable, Preparable, Auditable
- {
- /**
- * @plexus.requirement
- */
- private RepositoryContentConsumers consumers;
-
- /**
- * @plexus.requirement
- */
- private ArchivaXworkUser archivaXworkUser;
-
- /**
- * The groupId of the artifact to be deployed.
- */
- private String groupId;
-
- /**
- * The artifactId of the artifact to be deployed.
- */
- private String artifactId;
-
- /**
- * The version of the artifact to be deployed.
- */
- private String version;
-
- /**
- * The packaging of the artifact to be deployed.
- */
- private String packaging;
-
- /**
- * The classifier of the artifact to be deployed.
- */
- private String classifier;
-
- /**
- * The temporary file representing the artifact to be deployed.
- */
- private File artifactFile;
-
- /**
- * The content type of the artifact to be deployed.
- */
- private String artifactContentType;
-
- /**
- * The original filename of the uploaded artifact file.
- */
- private String artifactFilename;
-
- /**
- * The temporary file representing the pom to be deployed alongside the artifact.
- */
- private File pomFile;
-
- /**
- * The content type of the pom file.
- */
- private String pomContentType;
-
- /**
- * The original filename of the uploaded pom file.
- */
- private String pomFilename;
-
- /**
- * The repository where the artifact is to be deployed.
- */
- private String repositoryId;
-
- /**
- * Flag whether to generate a pom for the artifact or not.
- */
- private boolean generatePom;
-
- /**
- * List of managed repositories to deploy to.
- */
- private List<String> managedRepoIdList;
-
- /**
- * @plexus.requirement
- */
- private UserRepositories userRepositories;
-
- /**
- * @plexus.requirement role-hint="default"
- */
- private ArchivaConfiguration configuration;
-
- /**
- * @plexus.requirement
- */
- private RepositoryContentFactory repositoryFactory;
-
- /**
- * @plexus.requirement role="org.apache.maven.archiva.repository.audit.AuditListener"
- */
- private List<AuditListener> auditListeners = new ArrayList<AuditListener>();
-
- private ChecksumAlgorithm[] algorithms = new ChecksumAlgorithm[] { ChecksumAlgorithm.SHA1, ChecksumAlgorithm.MD5 };
-
- private ProjectModelWriter pomWriter = new ProjectModel400Writer();
-
- public void setArtifact( File file )
- {
- this.artifactFile = file;
- }
-
- public void setArtifactContentType( String contentType )
- {
- this.artifactContentType = contentType;
- }
-
- public void setArtifactFileName( String filename )
- {
- this.artifactFilename = filename;
- }
-
- public void setPom( File file )
- {
- this.pomFile = file;
- }
-
- public void setPomContentType( String contentType )
- {
- this.pomContentType = contentType;
- }
-
- public void setPomFileName( String filename )
- {
- this.pomFilename = filename;
- }
-
- public String getGroupId()
- {
- return groupId;
- }
-
- public void setGroupId( String groupId )
- {
- this.groupId = groupId;
- }
-
- public String getArtifactId()
- {
- return artifactId;
- }
-
- public void setArtifactId( String artifactId )
- {
- this.artifactId = artifactId;
- }
-
- public String getVersion()
- {
- return version;
- }
-
- public void setVersion( String version )
- {
- this.version = version;
- }
-
- public String getPackaging()
- {
- return packaging;
- }
-
- public void setPackaging( String packaging )
- {
- this.packaging = packaging;
- }
-
- public String getClassifier()
- {
- return classifier;
- }
-
- public void setClassifier( String classifier )
- {
- this.classifier = classifier;
- }
-
- public String getRepositoryId()
- {
- return repositoryId;
- }
-
- public void setRepositoryId( String repositoryId )
- {
- this.repositoryId = repositoryId;
- }
-
- public boolean isGeneratePom()
- {
- return generatePom;
- }
-
- public void setGeneratePom( boolean generatePom )
- {
- this.generatePom = generatePom;
- }
-
- public List<String> getManagedRepoIdList()
- {
- return managedRepoIdList;
- }
-
- public void setManagedRepoIdList( List<String> managedRepoIdList )
- {
- this.managedRepoIdList = managedRepoIdList;
- }
-
- public void prepare()
- {
- managedRepoIdList =
- new ArrayList<String>( configuration.getConfiguration().getManagedRepositoriesAsMap().keySet() );
- }
-
- public String input()
- {
- return INPUT;
- }
-
- private void reset()
- {
- // reset the fields so the form is clear when
- // the action returns to the jsp page
- groupId = "";
- artifactId = "";
- version = "";
- packaging = "";
- classifier = "";
- artifactFile = null;
- artifactContentType = "";
- artifactFilename = "";
- pomFile = null;
- pomContentType = "";
- pomFilename = "";
- repositoryId = "";
- generatePom = false;
- }
-
- public String doUpload()
- {
- try
- {
- ManagedRepositoryConfiguration repoConfig =
- configuration.getConfiguration().findManagedRepositoryById( repositoryId );
-
- ArtifactReference artifactReference = new ArtifactReference();
- artifactReference.setArtifactId( artifactId );
- artifactReference.setGroupId( groupId );
- artifactReference.setVersion( version );
- artifactReference.setClassifier( classifier );
- artifactReference.setType( packaging );
-
- ManagedRepositoryContent repository = repositoryFactory.getManagedRepositoryContent( repositoryId );
-
- String artifactPath = repository.toPath( artifactReference );
-
- int lastIndex = artifactPath.lastIndexOf( '/' );
-
- File targetPath = new File( repoConfig.getLocation(), artifactPath.substring( 0, lastIndex ) );
-
- Date lastUpdatedTimestamp = Calendar.getInstance().getTime();
- int newBuildNumber = -1;
- String timestamp = null;
-
- File metadataFile = getMetadata( targetPath.getAbsolutePath() );
- ArchivaRepositoryMetadata metadata = getMetadata( metadataFile );
-
- if (VersionUtil.isSnapshot(version))
- {
- TimeZone timezone = TimeZone.getTimeZone( "UTC" );
- DateFormat fmt = new SimpleDateFormat( "yyyyMMdd.HHmmss" );
- fmt.setTimeZone( timezone );
- timestamp = fmt.format( lastUpdatedTimestamp );
- if ( metadata.getSnapshotVersion() != null )
- {
- newBuildNumber = metadata.getSnapshotVersion().getBuildNumber() + 1;
- }
- else
- {
- metadata.setSnapshotVersion( new SnapshotVersion() );
- newBuildNumber = 1;
- }
- }
-
- if ( !targetPath.exists() )
- {
- targetPath.mkdirs();
- }
-
- String filename = artifactPath.substring( lastIndex + 1 );
- if ( VersionUtil.isSnapshot( version ) )
- {
- filename = filename.replaceAll( "SNAPSHOT", timestamp + "-" + newBuildNumber );
- }
-
- try
- {
- copyFile( artifactFile, targetPath, filename );
- consumers.executeConsumers( repoConfig, repository.toFile( artifactReference ) );
- }
- catch ( IOException ie )
- {
- addActionError( "Error encountered while uploading file: " + ie.getMessage() );
- return ERROR;
- }
-
- String pomFilename = filename;
- if( classifier != null && !"".equals( classifier ) )
- {
- pomFilename = StringUtils.remove( pomFilename, "-" + classifier );
- }
- pomFilename = FilenameUtils.removeExtension( pomFilename ) + ".pom";
-
- if ( generatePom )
- {
- try
- {
- File generatedPomFile = createPom( targetPath, pomFilename );
- consumers.executeConsumers( repoConfig, generatedPomFile );
- }
- catch ( IOException ie )
- {
- addActionError( "Error encountered while writing pom file: " + ie.getMessage() );
- return ERROR;
- }
- catch ( ProjectModelException pe )
- {
- addActionError( "Error encountered while generating pom file: " + pe.getMessage() );
- return ERROR;
- }
- }
-
- if ( pomFile != null && pomFile.length() > 0 )
- {
- try
- {
- copyFile( pomFile, targetPath, pomFilename );
- consumers.executeConsumers( repoConfig, new File( targetPath, pomFilename ) );
- }
- catch ( IOException ie )
- {
- addActionError( "Error encountered while uploading pom file: " + ie.getMessage() );
- return ERROR;
- }
-
- }
-
- updateMetadata( metadata, metadataFile, lastUpdatedTimestamp, timestamp, newBuildNumber );
-
- String msg = "Artifact \'" + groupId + ":" + artifactId + ":" + version +
- "\' was successfully deployed to repository \'" + repositoryId + "\'";
-
- triggerAuditEvent( getPrincipal(), repositoryId, groupId + ":" + artifactId + ":" + version, AuditEvent.UPLOAD_FILE );
-
- addActionMessage( msg );
-
- reset();
- return SUCCESS;
- }
- catch ( RepositoryNotFoundException re )
- {
- addActionError( "Target repository cannot be found: " + re.getMessage() );
- return ERROR;
- }
- catch ( RepositoryException rep )
- {
- addActionError( "Repository exception: " + rep.getMessage() );
- return ERROR;
- }
- }
-
- private String getPrincipal()
- {
- return archivaXworkUser.getActivePrincipal( ActionContext.getContext().getSession() );
- }
-
- private void copyFile( File sourceFile, File targetPath, String targetFilename )
- throws IOException
- {
- FileOutputStream out = new FileOutputStream( new File( targetPath, targetFilename ) );
-
- try
- {
- FileInputStream input = new FileInputStream( sourceFile );
- int i = 0;
- while ( ( i = input.read() ) != -1 )
- {
- out.write( i );
- }
- out.flush();
- }
- finally
- {
- out.close();
- }
- }
-
- private File createPom( File targetPath, String filename )
- throws IOException, ProjectModelException
- {
- ArchivaProjectModel projectModel = new ArchivaProjectModel();
- projectModel.setGroupId( groupId );
- projectModel.setArtifactId( artifactId );
- projectModel.setVersion( version );
- projectModel.setPackaging( packaging );
-
- File pomFile = new File( targetPath, filename);
- pomWriter.write( projectModel, pomFile );
-
- return pomFile;
- }
-
- private File getMetadata( String targetPath )
- {
- String artifactPath = targetPath.substring( 0, targetPath.lastIndexOf( File.separatorChar ) );
-
- return new File( artifactPath, MetadataTools.MAVEN_METADATA );
- }
-
- private ArchivaRepositoryMetadata getMetadata( File metadataFile )
- throws RepositoryMetadataException
- {
- ArchivaRepositoryMetadata metadata = new ArchivaRepositoryMetadata();
- if ( metadataFile.exists() )
- {
- metadata = RepositoryMetadataReader.read( metadataFile );
- }
- return metadata;
- }
-
- /**
- * Update artifact level metadata. If it does not exist, create the metadata.
- *
- * @param metadata
- */
- private void updateMetadata( ArchivaRepositoryMetadata metadata, File metadataFile, Date lastUpdatedTimestamp,
- String timestamp, int buildNumber )
- throws RepositoryMetadataException
- {
- List<String> availableVersions = new ArrayList<String>();
- String latestVersion = version;
-
- if ( metadataFile.exists() )
- {
- availableVersions = metadata.getAvailableVersions();
-
- Collections.sort( availableVersions, VersionComparator.getInstance() );
-
- if ( !availableVersions.contains( version ) )
- {
- availableVersions.add( version );
- }
-
- latestVersion = availableVersions.get( availableVersions.size() - 1 );
- }
- else
- {
- availableVersions.add( version );
-
- metadata.setGroupId( groupId );
- metadata.setArtifactId( artifactId );
- }
-
- if ( metadata.getGroupId() == null )
- {
- metadata.setGroupId( groupId );
- }
- if ( metadata.getArtifactId() == null )
- {
- metadata.setArtifactId( artifactId );
- }
-
- metadata.setLatestVersion( latestVersion );
- metadata.setLastUpdatedTimestamp( lastUpdatedTimestamp );
- metadata.setAvailableVersions( availableVersions );
-
- if ( !VersionUtil.isSnapshot( version ) )
- {
- metadata.setReleasedVersion( latestVersion );
- }
- else
- {
- metadata.getSnapshotVersion().setBuildNumber( buildNumber );
-
- metadata.getSnapshotVersion().setTimestamp( timestamp );
- }
-
- RepositoryMetadataWriter.write( metadata, metadataFile );
- ChecksummedFile checksum = new ChecksummedFile( metadataFile );
- checksum.fixChecksums( algorithms );
- }
-
- public void validate()
- {
- try
- {
- // is this enough check for the repository permission?
- if ( !userRepositories.isAuthorizedToUploadArtifacts( getPrincipal(), repositoryId ) )
- {
- addActionError( "User is not authorized to upload in repository " + repositoryId );
- }
-
- if ( artifactFile == null || artifactFile.length() == 0 )
- {
- addActionError( "Please add a file to upload." );
- }
-
- if ( !VersionUtil.isVersion( version ) )
- {
- addActionError( "Invalid version." );
- }
- }
- catch ( PrincipalNotFoundException pe )
- {
- addActionError( pe.getMessage() );
- }
- catch ( ArchivaSecurityException ae )
- {
- addActionError( ae.getMessage() );
- }
- }
-
- public void addAuditListener( AuditListener listener )
- {
- this.auditListeners.add( listener );
- }
-
- public void clearAuditListeners()
- {
- this.auditListeners.clear();
- }
-
- public void removeAuditListener( AuditListener listener )
- {
- this.auditListeners.remove( listener );
- }
-
- private void triggerAuditEvent( String user, String repositoryId, String resource, String action )
- {
- AuditEvent event = new AuditEvent( repositoryId, user, resource, action );
- event.setRemoteIP( ServletActionContext.getRequest().getRemoteAddr() );
-
- for ( AuditListener listener : auditListeners )
- {
- listener.auditEvent( event );
- }
- }
- }
|