Author: khmarbaise
Date: Mon Sep 12 11:22:29 2016
New Revision: 1760333
URL: http://svn.apache.org/viewvc?rev=1760333&view=rev
Log:
[MSHARED-593] Add interface to install a Maven Project
Added:
maven/shared/trunk/maven-artifact-transfer/src/main/java/org/apache/maven/shared/project/install/
maven/shared/trunk/maven-artifact-transfer/src/main/java/org/apache/maven/shared/project/install/ProjectInstaller.java
maven/shared/trunk/maven-artifact-transfer/src/main/java/org/apache/maven/shared/project/install/ProjectInstallerRequest.java
maven/shared/trunk/maven-artifact-transfer/src/main/java/org/apache/maven/shared/project/install/internal/
maven/shared/trunk/maven-artifact-transfer/src/main/java/org/apache/maven/shared/project/install/internal/DefaultProjectInstaller.java
maven/shared/trunk/maven-artifact-transfer/src/main/java/org/apache/maven/shared/project/install/internal/DualDigester.java
Modified:
maven/shared/trunk/maven-artifact-transfer/pom.xml
Modified: maven/shared/trunk/maven-artifact-transfer/pom.xml
URL:
http://svn.apache.org/viewvc/maven/shared/trunk/maven-artifact-transfer/pom.xml?rev=1760333&r1=1760332&r2=1760333&view=diff
==============================================================================
--- maven/shared/trunk/maven-artifact-transfer/pom.xml (original)
+++ maven/shared/trunk/maven-artifact-transfer/pom.xml Mon Sep 12
11:22:29 2016
@@ -168,6 +168,17 @@
<artifactId>maven-common-artifact-filters</artifactId>
<version>3.0.0</version>
</dependency>
+ <dependency>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-utils</artifactId>
+ <version>3.0.24</version>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-codec</groupId>
+ <artifactId>commons-codec</artifactId>
+ <version>1.6</version>
+ </dependency>
<!-- Maven 3.0.x -->
<dependency>
Added:
maven/shared/trunk/maven-artifact-transfer/src/main/java/org/apache/maven/shared/project/install/ProjectInstaller.java
URL:
http://svn.apache.org/viewvc/maven/shared/trunk/maven-artifact-transfer/src/main/java/org/apache/maven/shared/project/install/ProjectInstaller.java?rev=1760333&view=auto
==============================================================================
---
maven/shared/trunk/maven-artifact-transfer/src/main/java/org/apache/maven/shared/project/install/ProjectInstaller.java
(added)
+++
maven/shared/trunk/maven-artifact-transfer/src/main/java/org/apache/maven/shared/project/install/ProjectInstaller.java
Mon Sep 12 11:22:29 2016
@@ -0,0 +1,49 @@
+package org.apache.maven.shared.project.install;
+
+/*
+ * 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.IOException;
+
+import org.apache.maven.artifact.repository.ArtifactRepository;
+import org.apache.maven.project.ProjectBuildingRequest;
+import
org.apache.maven.shared.artifact.install.ArtifactInstallerException;
+
+/**
+ * This defines the interface to install a single Maven Project.
+ *
+ * @author Karl Heinz Marbaise <a
href="mailto:khmarba...@apache.org">khmarba...@apache.org</a>
+ */
+public interface ProjectInstaller
+{
+ /**
+ * This will install a single project which may contain several
artifacts. Those artifacts will be installed into
+ * the appropriate repository.
+ *
+ * @param projectBuildingRequest {@link ProjectBuildingRequest}
+ * @param projectInstallerRequest {@link ProjectInstallerRequest}
+ * @param artifactRepository {@link ArtifactRepository}
+ * @throws IOException In case of problem to install project.
+ * @throws ArtifactInstallerException In case of problems to
install artifacts.
+ */
+ void installProject( ProjectBuildingRequest projectBuildingRequest,
ProjectInstallerRequest projectInstallerRequest,
+ ArtifactRepository artifactRepository )
+ throws IOException, ArtifactInstallerException;
+
+}
Added:
maven/shared/trunk/maven-artifact-transfer/src/main/java/org/apache/maven/shared/project/install/ProjectInstallerRequest.java
URL:
http://svn.apache.org/viewvc/maven/shared/trunk/maven-artifact-transfer/src/main/java/org/apache/maven/shared/project/install/ProjectInstallerRequest.java?rev=1760333&view=auto
==============================================================================
---
maven/shared/trunk/maven-artifact-transfer/src/main/java/org/apache/maven/shared/project/install/ProjectInstallerRequest.java
(added)
+++
maven/shared/trunk/maven-artifact-transfer/src/main/java/org/apache/maven/shared/project/install/ProjectInstallerRequest.java
Mon Sep 12 11:22:29 2016
@@ -0,0 +1,90 @@
+package org.apache.maven.shared.project.install;
+
+/*
+ * 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 org.apache.maven.project.MavenProject;
+
+/**
+ * @author Robert Scholte
+ */
+public class ProjectInstallerRequest
+{
+ // From AbstractInstallMojo
+
+ private boolean createChecksum;
+
+ private boolean updateReleaseInfo;
+
+ // From InstallMojo
+
+ private MavenProject project;
+
+ /**
+ * @return the createChecksum
+ */
+ public boolean isCreateChecksum()
+ {
+ return createChecksum;
+ }
+
+ /**
+ * @param createChecksum the createChecksum to set
+ */
+ public ProjectInstallerRequest setCreateChecksum( boolean
createChecksum )
+ {
+ this.createChecksum = createChecksum;
+ return this;
+ }
+
+ /**
+ * @return the updateReleaseInfo
+ */
+ public boolean isUpdateReleaseInfo()
+ {
+ return updateReleaseInfo;
+ }
+
+ /**
+ * @param updateReleaseInfo the updateReleaseInfo to set
+ */
+ public ProjectInstallerRequest setUpdateReleaseInfo( boolean
updateReleaseInfo )
+ {
+ this.updateReleaseInfo = updateReleaseInfo;
+ return this;
+ }
+
+ /**
+ * @return the project
+ */
+ public MavenProject getProject()
+ {
+ return project;
+ }
+
+ /**
+ * @param project the project to set
+ */
+ public ProjectInstallerRequest setProject( MavenProject project )
+ {
+ this.project = project;
+ return this;
+ }
+
+}
Added:
maven/shared/trunk/maven-artifact-transfer/src/main/java/org/apache/maven/shared/project/install/internal/DefaultProjectInstaller.java
URL:
http://svn.apache.org/viewvc/maven/shared/trunk/maven-artifact-transfer/src/main/java/org/apache/maven/shared/project/install/internal/DefaultProjectInstaller.java?rev=1760333&view=auto
==============================================================================
---
maven/shared/trunk/maven-artifact-transfer/src/main/java/org/apache/maven/shared/project/install/internal/DefaultProjectInstaller.java
(added)
+++
maven/shared/trunk/maven-artifact-transfer/src/main/java/org/apache/maven/shared/project/install/internal/DefaultProjectInstaller.java
Mon Sep 12 11:22:29 2016
@@ -0,0 +1,275 @@
+package org.apache.maven.shared.project.install.internal;
+
+/*
+ * 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.IOException;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.metadata.ArtifactMetadata;
+import org.apache.maven.artifact.repository.ArtifactRepository;
+import org.apache.maven.project.MavenProject;
+import org.apache.maven.project.ProjectBuildingRequest;
+import org.apache.maven.project.artifact.ProjectArtifact;
+import org.apache.maven.project.artifact.ProjectArtifactMetadata;
+import org.apache.maven.shared.artifact.install.ArtifactInstaller;
+import
org.apache.maven.shared.artifact.install.ArtifactInstallerException;
+import org.apache.maven.shared.project.install.ProjectInstaller;
+import org.apache.maven.shared.project.install.ProjectInstallerRequest;
+import org.apache.maven.shared.repository.RepositoryManager;
+import org.codehaus.plexus.component.annotations.Component;
+import org.codehaus.plexus.util.FileUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This will install a whole project into the appropriate repository.
+ *
+ * @author Karl Heinz Marbaise <a
href="mailto:khmarba...@apache.org">khmarba...@apache.org</a>
+ */
+@Component( role = ProjectInstaller.class )
+public class DefaultProjectInstaller
+ implements ProjectInstaller
+{
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(
DefaultProjectInstaller.class );
+
+ @Inject
+ private ArtifactInstaller installer;
+
+ @Inject
+ private RepositoryManager repositoryManager;
+
+ private final DualDigester digester = new DualDigester();
+
+ public void installProject( ProjectBuildingRequest buildingRequest,
ProjectInstallerRequest request,
+ ArtifactRepository artifactRepository )
+ throws IOException, ArtifactInstallerException
+ {
+
+ MavenProject project = request.getProject();
+ boolean createChecksum = request.isCreateChecksum();
+ boolean updateReleaseInfo = request.isUpdateReleaseInfo();
+
+ Artifact artifact = project.getArtifact();
+ String packaging = project.getPackaging();
+ File pomFile = project.getFile();
+
+ List<Artifact> attachedArtifacts =
project.getAttachedArtifacts();
+
+ // TODO: push into transformation
+ boolean isPomArtifact = "pom".equals( packaging );
+
+ ProjectArtifactMetadata metadata;
+
+ if ( updateReleaseInfo )
+ {
+ artifact.setRelease( true );
+ }
+
+ Collection<File> metadataFiles = new LinkedHashSet<File>();
+
+ if ( isPomArtifact )
+ {
+ // installer.install( pomFile, artifact, localRepository );
+ installer.install( buildingRequest,
Collections.<Artifact>singletonList( new ProjectArtifact( project ) ) );
+ installChecksums( buildingRequest, artifactRepository,
artifact, createChecksum );
+ addMetaDataFilesForArtifact( artifactRepository, artifact,
metadataFiles, createChecksum );
+ }
+ else
+ {
+ metadata = new ProjectArtifactMetadata( artifact, pomFile );
+ artifact.addMetadata( metadata );
+
+ File file = artifact.getFile();
+
+ // Here, we have a temporary solution to MINSTALL-3
(isDirectory() is true if it went through compile
+ // but not package). We are designing in a proper solution
for Maven 2.1
+ if ( file != null && file.isFile() )
+ {
+ installer.install( buildingRequest,
Collections.<Artifact>singletonList( artifact ) );
+ installChecksums( buildingRequest, artifactRepository,
artifact, createChecksum );
+ addMetaDataFilesForArtifact( artifactRepository,
artifact, metadataFiles, createChecksum );
+ }
+ else if ( !attachedArtifacts.isEmpty() )
+ {
+ throw new IllegalArgumentException( "The packaging
plugin for this project did not assign "
+ + "a main file to the project but it has
attachments. Change packaging to 'pom'." );
+ }
+ else
+ {
+ // CHECKSTYLE_OFF: LineLength
+ throw new IllegalArgumentException( "The packaging for
this project did not assign a file to the build artifact" );
+ // CHECKSTYLE_ON: LineLength
+ }
+ }
+
+ for ( Artifact attached : attachedArtifacts )
+ {
+ // installer.install( attached.getFile(), attached,
localRepository );
+ installer.install( buildingRequest,
Collections.singletonList( attached ) );
+ installChecksums( buildingRequest, artifactRepository,
attached, createChecksum );
+ addMetaDataFilesForArtifact( artifactRepository, attached,
metadataFiles, createChecksum );
+ }
+
+ installChecksums( metadataFiles );
+ }
+
+ /**
+ * Installs the checksums for the specified artifact if this has
been enabled in the plugin configuration. This
+ * method creates checksums for files that have already been
installed to the local repo to account for on-the-fly
+ * generated/updated files. For example, in Maven 2.0.4- the
<code>ProjectArtifactMetadata</code> did not install
+ * the original POM file (cf. MNG-2820). While the plugin currently
requires Maven 2.0.6, we continue to hash the
+ * installed POM for robustness with regard to future changes like
re-introducing some kind of POM filtering.
+ *
+ * @param artifact The artifact for which to create checksums, must
not be <code>null</code>.
+ * @param createChecksum {@code true} if checksum should be
created, otherwise {@code false}.
+ * @throws IOException If the checksums could not be installed.
+ */
+ private void installChecksums( ProjectBuildingRequest
buildingRequest, ArtifactRepository artifactRepository,
+ Artifact artifact, boolean
createChecksum )
+ throws IOException
+ {
+ if ( !createChecksum )
+ {
+ return;
+ }
+
+ File artifactFile = getLocalRepoFile( buildingRequest,
artifactRepository, artifact );
+ installChecksums( artifactFile );
+ }
+
+ // CHECKSTYLE_OFF: LineLength
+ protected void addMetaDataFilesForArtifact( ArtifactRepository
artifactRepository, Artifact artifact,
+ Collection<File>
targetMetadataFiles, boolean createChecksum )
+ // CHECKSTYLE_ON: LineLength
+ {
+ if ( !createChecksum )
+ {
+ return;
+ }
+
+ Collection<ArtifactMetadata> metadatas =
artifact.getMetadataList();
+ if ( metadatas != null )
+ {
+ for ( ArtifactMetadata metadata : metadatas )
+ {
+ File metadataFile = getLocalRepoFile(
artifactRepository, metadata );
+ targetMetadataFiles.add( metadataFile );
+ }
+ }
+ }
+
+ /**
+ * Installs the checksums for the specified metadata files.
+ *
+ * @param metadataFiles The collection of metadata files to install
checksums for, must not be <code>null</code>.
+ * @throws IOException If the checksums could not be installed.
+ */
+ protected void installChecksums( Collection<File> metadataFiles )
+ throws IOException
+ {
+ for ( File metadataFile : metadataFiles )
+ {
+ installChecksums( metadataFile );
+ }
+ }
+
+ /**
+ * Installs the checksums for the specified file (if it exists).
+ *
+ * @param installedFile The path to the already installed file in
the local repo for which to generate checksums,
+ * must not be <code>null</code>.
+ * @throws IOException In case of errors. Could not install
checksums.
+ */
+ private void installChecksums( File installedFile )
+ throws IOException
+ {
+ boolean signatureFile = installedFile.getName().endsWith(
".asc" );
+ if ( installedFile.isFile() && !signatureFile )
+ {
+ LOGGER.debug( "Calculating checksums for " + installedFile
);
+ digester.calculate( installedFile );
+ installChecksum( installedFile, ".md5", digester.getMd5() );
+ installChecksum( installedFile, ".sha1", digester.getSha1()
);
+ }
+ }
+
+ /**
+ * Installs a checksum for the specified file.
+ *
+ * @param installedFile The base path from which the path to the
checksum files is derived by appending the given
+ * file extension, must not be <code>null</code>.
+ * @param ext The file extension (including the leading dot) to use
for the checksum file, must not be
+ * <code>null</code>.
+ * @param checksum the checksum to write
+ * @throws IOException If the checksum could not be installed.
+ */
+ private void installChecksum( File installedFile, String ext,
String checksum )
+ throws IOException
+ {
+ File checksumFile = new File( installedFile.getAbsolutePath() +
ext );
+ LOGGER.debug( "Installing checksum to " + checksumFile );
+ try
+ {
+ // noinspection ResultOfMethodCallIgnored
+ checksumFile.getParentFile().mkdirs();
+ FileUtils.fileWrite( checksumFile.getAbsolutePath(),
"UTF-8", checksum );
+ }
+ catch ( IOException e )
+ {
+ throw new IOException( "Failed to install checksum to " +
checksumFile, e );
+ }
+ }
+
+ /**
+ * Gets the path of the specified artifact within the local
repository. Note that the returned path need not exist
+ * (yet).
+ *
+ * @param artifact The artifact whose local repo path should be
determined, must not be <code>null</code>.
+ * @return The absolute path to the artifact when installed, never
<code>null</code>.
+ */
+ private File getLocalRepoFile( ProjectBuildingRequest
buildingRequest, ArtifactRepository artifactRepository,
+ Artifact artifact )
+ {
+ String path = repositoryManager.getPathForLocalArtifact(
buildingRequest, artifact );
+ return new File( artifactRepository.getBasedir(), path );
+ }
+
+ /**
+ * Gets the path of the specified artifact metadata within the
local repository. Note that the returned path need
+ * not exist (yet).
+ *
+ * @param metadata The artifact metadata whose local repo path
should be determined, must not be <code>null</code>.
+ * @return The absolute path to the artifact metadata when
installed, never <code>null</code>.
+ */
+ private File getLocalRepoFile( ArtifactRepository
artifactRepository, ArtifactMetadata metadata )
+ {
+ String path = artifactRepository.pathOfLocalRepositoryMetadata(
metadata, artifactRepository );
+ return new File( artifactRepository.getBasedir(), path );
+ }
+
+}
Added:
maven/shared/trunk/maven-artifact-transfer/src/main/java/org/apache/maven/shared/project/install/internal/DualDigester.java
URL:
http://svn.apache.org/viewvc/maven/shared/trunk/maven-artifact-transfer/src/main/java/org/apache/maven/shared/project/install/internal/DualDigester.java?rev=1760333&view=auto
==============================================================================
---
maven/shared/trunk/maven-artifact-transfer/src/main/java/org/apache/maven/shared/project/install/internal/DualDigester.java
(added)
+++
maven/shared/trunk/maven-artifact-transfer/src/main/java/org/apache/maven/shared/project/install/internal/DualDigester.java
Mon Sep 12 11:22:29 2016
@@ -0,0 +1,112 @@
+package org.apache.maven.shared.project.install.internal;
+
+/*
+ * 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.IOException;
+import java.io.InputStream;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+import org.apache.commons.codec.binary.Hex;
+import org.codehaus.plexus.util.IOUtil;
+
+
+/**
+ * Calculates md5 and sha1 digest.
+ * <p/>
+ * Todo: Consider using a thread to calculate one of the digests when
the files are large; it's fairly slow !
+ *
+ * @author Kristian Rosenvold
+ */
+public class DualDigester
+{
+ private final MessageDigest md5 = getDigester( "MD5" );
+
+ private final MessageDigest sh1 = getDigester( "SHA-1" );
+
+ private static final int BUFSIZE = 65536 * 2;
+
+ private final byte[] buffer = new byte[BUFSIZE];
+
+ static MessageDigest getDigester( String algorithm )
+ {
+ try
+ {
+ return MessageDigest.getInstance( algorithm );
+ }
+ catch ( NoSuchAlgorithmException e )
+ {
+ throw new RuntimeException( "Unable to initialize digest "
+ algorithm + " : " + e.getMessage() );
+ }
+ }
+
+ public void calculate( File file ) throws IOException
+ {
+ FileInputStream fis = null;
+
+ try
+ {
+ fis = new FileInputStream( file );
+ calculate( fis );
+ fis.close();
+ fis = null;
+ }
+ catch ( IOException e )
+ {
+ throw new IOException( "Failed to calculate digest checksum
for " + file, e );
+ }
+ finally
+ {
+ IOUtil.close( fis );
+ }
+ }
+
+ void calculate( InputStream stream )
+ throws IOException
+ {
+ md5.reset();
+ sh1.reset();
+ update( stream );
+ }
+
+ public String getMd5()
+ {
+ return Hex.encodeHexString( md5.digest() );
+ }
+
+ public String getSha1()
+ {
+ return Hex.encodeHexString( sh1.digest() );
+ }
+
+ private void update( InputStream is )
+ throws IOException
+ {
+ int size = is.read( buffer, 0, BUFSIZE );
+ while ( size >= 0 )
+ {
+ md5.update( buffer, 0, size );
+ sh1.update( buffer, 0, size );
+ size = is.read( buffer, 0, BUFSIZE );
+ }
+ }
+}