blob: d51031454a76ebcdfe4f3ad061ed317453a531e0 [file] [log] [blame]
/*
* 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.
*/
package org.apache.maven.plugin.testing;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.HashSet;
import java.util.Set;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.DefaultArtifact;
import org.apache.maven.artifact.handler.ArtifactHandler;
import org.apache.maven.artifact.versioning.VersionRange;
import org.apache.maven.plugin.testing.stubs.DefaultArtifactHandlerStub;
import org.codehaus.plexus.archiver.Archiver;
import org.codehaus.plexus.archiver.ArchiverException;
import org.codehaus.plexus.archiver.manager.ArchiverManager;
import org.codehaus.plexus.archiver.manager.NoSuchArchiverException;
import org.codehaus.plexus.archiver.war.WarArchiver;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.ReflectionUtils;
import org.codehaus.plexus.util.StringUtils;
/**
* This class creates artifacts to be used for testing purposes. It can optionally create actual files on the local disk
* for things like copying. It can create these files as archives with named files inside to be used for testing things
* like unpack. Also provided are some utility methods to quickly get a set of artifacts distinguished by various things
* like group,artifact,type,scope, etc It was originally developed for the dependency plugin, but can be useful in other
* plugins that need to simulate artifacts for unit tests.
*
* @author <a href="mailto:brianf@apache.org">Brian Fox</a>
*/
public class ArtifactStubFactory {
private File workingDir;
private boolean createFiles;
private File srcFile;
private boolean createUnpackableFile;
private ArchiverManager archiverManager;
/**
* Default constructor. This should be used only if real files aren't needed...just the artifact objects
*/
public ArtifactStubFactory() {
this.workingDir = null;
this.createFiles = false;
}
/**
* This constructor is to be used if files are needed and to set a working dir
*
* @param workingDir
* @param createFiles
*/
public ArtifactStubFactory(File workingDir, boolean createFiles) {
this.workingDir = new File(workingDir, "localTestRepo");
this.createFiles = createFiles;
}
/**
* If set, the file will be created as a zip/jar/war with a file inside that can be checked to exist after
* unpacking.
*
* @param archiverManager
*/
public void setUnpackableFile(ArchiverManager archiverManager) {
this.createUnpackableFile = true;
this.archiverManager = archiverManager;
}
/**
* @param groupId
* @param artifactId
* @param version
* @return a <code>DefaultArtifact</code> instance for the given parameters
* @throws IOException if any
* @see #createArtifact(String, String, String, String, String, String)
*/
public Artifact createArtifact(String groupId, String artifactId, String version) throws IOException {
return createArtifact(groupId, artifactId, version, Artifact.SCOPE_COMPILE, "jar", "");
}
/**
* @param groupId
* @param artifactId
* @param version
* @param scope
* @return a <code>DefaultArtifact</code> instance for the given parameters
* @throws IOException if any
* @see #createArtifact(String, String, String, String, String, String)
*/
public Artifact createArtifact(String groupId, String artifactId, String version, String scope) throws IOException {
return createArtifact(groupId, artifactId, version, scope, "jar", "");
}
/**
* @param groupId
* @param artifactId
* @param version
* @param scope
* @param type
* @param classifier
* @return a <code>DefaultArtifact</code> instance for the given parameters
* @throws IOException if any
* @see #createArtifact(String, String, VersionRange, String, String, String, boolean)
*/
public Artifact createArtifact(
String groupId, String artifactId, String version, String scope, String type, String classifier)
throws IOException {
VersionRange vr = VersionRange.createFromVersion(version);
return createArtifact(groupId, artifactId, vr, scope, type, classifier, false);
}
/**
* @param groupId not null
* @param artifactId not null
* @param versionRange not null
* @param scope not null
* @param type not null
* @param classifier
* @param optional not null
* @return a <code>DefaultArtifact</code> instance
* @throws IOException if any
*/
public Artifact createArtifact(
String groupId,
String artifactId,
VersionRange versionRange,
String scope,
String type,
String classifier,
boolean optional)
throws IOException {
ArtifactHandler ah = new DefaultArtifactHandlerStub(type, classifier);
Artifact artifact =
new DefaultArtifact(groupId, artifactId, versionRange, scope, type, classifier, ah, optional);
// i have no idea why this needs to be done manually when isSnapshot is able to figure it out.
artifact.setRelease(!artifact.isSnapshot());
if (createFiles) {
setArtifactFile(artifact, this.workingDir, this.srcFile, this.createUnpackableFile);
}
return artifact;
}
/**
* Creates a new empty file and attaches it to the artifact.
*
* @param artifact to attach the file to.
* @param workingDir where to locate the new file
* @throws IOException
*/
public void setArtifactFile(Artifact artifact, File workingDir) throws IOException {
setArtifactFile(artifact, workingDir, null, false);
}
/**
* Copyies the srcFile to the workingDir and then attaches it to the artifact. If srcFile is null, a new empty file
* will be created.
*
* @param artifact to attach
* @param workingDir where to copy the srcFile.
* @param srcFile file to be attached.
* @throws IOException
*/
public void setArtifactFile(Artifact artifact, File workingDir, File srcFile) throws IOException {
setArtifactFile(artifact, workingDir, srcFile, false);
}
/**
* Creates an unpackable file (zip,jar etc) containing an empty file.
*
* @param artifact to attach
* @param workingDir where to create the file.
* @throws IOException
*/
public void setUnpackableArtifactFile(Artifact artifact, File workingDir) throws IOException {
setArtifactFile(artifact, workingDir, null, true);
}
/**
* Creates an unpackable file (zip,jar etc) containing the srcFile. If srcFile is null, a new empty file will be
* created.
*
* @param artifact to attach
* @param workingDir where to create the file.
* @param srcFile
* @throws IOException if any
*/
public void setUnpackableArtifactFile(Artifact artifact, File workingDir, File srcFile) throws IOException {
setArtifactFile(artifact, workingDir, srcFile, true);
}
/**
* Creates a file that can be copied or unpacked based on the passed in artifact
*
* @param artifact
* @param workingDir
* @param srcFile
* @param createUnpackableFile
* @throws IOException if any
*/
private void setArtifactFile(Artifact artifact, File workingDir, File srcFile, boolean createUnpackableFile)
throws IOException {
if (workingDir == null) {
throw new IllegalArgumentException("The workingDir must be set.");
}
String fileName = getFormattedFileName(artifact, false);
File theFile = new File(workingDir, fileName);
theFile.getParentFile().mkdirs();
if (srcFile == null) {
theFile.createNewFile();
} else if (createUnpackableFile) {
try {
createUnpackableFile(artifact, theFile);
} catch (NoSuchArchiverException e) {
throw new IOException("NoSuchArchiverException: " + e.getMessage());
} catch (ArchiverException e) {
throw new IOException("ArchiverException: " + e.getMessage());
}
} else {
FileUtils.copyFile(srcFile, theFile);
}
artifact.setFile(theFile);
}
/**
* @param artifact
* @return
*/
public static String getUnpackableFileName(Artifact artifact) {
return "" + artifact.getGroupId() + "-" + artifact.getArtifactId() + "-" + artifact.getVersion() + "-"
+ artifact.getClassifier() + "-" + artifact.getType() + ".txt";
}
/**
* @param artifact
* @param destFile
* @throws NoSuchArchiverException
* @throws ArchiverException if any
* @throws IOException if any
*/
public void createUnpackableFile(Artifact artifact, File destFile)
throws NoSuchArchiverException, ArchiverException, IOException {
Archiver archiver = archiverManager.getArchiver(destFile);
archiver.setDestFile(destFile);
archiver.addFile(srcFile, getUnpackableFileName(artifact));
if (archiver instanceof WarArchiver) {
WarArchiver war = (WarArchiver) archiver;
war.setExpectWebXml(false);
}
archiver.createArchive();
}
/**
* @return a <code>DefaultArtifact</code> instance for <code>testGroupId:release:jar:1.0</code>
* @throws IOException if any
*/
public Artifact getReleaseArtifact() throws IOException {
return createArtifact("testGroupId", "release", "1.0");
}
/**
* @return a default <code>DefaultArtifact</code> instance for <code>testGroupId:snapshot:jar:2.0-SNAPSHOT</code>
* @throws IOException if any
*/
public Artifact getSnapshotArtifact() throws IOException {
return createArtifact("testGroupId", "snapshot", "2.0-SNAPSHOT");
}
/**
* @return a default set of release and snapshot <code>DefaultArtifact</code>, i.e.:
* <code>testGroupId:snapshot:jar:2.0-SNAPSHOT, testGroupId:release:jar:1.0</code>
* @throws IOException if any
* @see #getReleaseArtifact()
* @see #getSnapshotArtifact()
*/
public Set<Artifact> getReleaseAndSnapshotArtifacts() throws IOException {
Set<Artifact> set = new HashSet<>();
set.add(getReleaseArtifact());
set.add(getSnapshotArtifact());
return set;
}
/**
* @return a default set of <code>DefaultArtifact</code>, i.e.:
* <code>g:provided:jar:1.0, g:compile:jar:1.0, g:system:jar:1.0, g:test:jar:1.0, g:runtime:jar:1.0</code>
* @throws IOException if any
*/
public Set<Artifact> getScopedArtifacts() throws IOException {
Set<Artifact> set = new HashSet<>();
set.add(createArtifact("g", "compile", "1.0", Artifact.SCOPE_COMPILE));
set.add(createArtifact("g", "provided", "1.0", Artifact.SCOPE_PROVIDED));
set.add(createArtifact("g", "test", "1.0", Artifact.SCOPE_TEST));
set.add(createArtifact("g", "runtime", "1.0", Artifact.SCOPE_RUNTIME));
set.add(createArtifact("g", "system", "1.0", Artifact.SCOPE_SYSTEM));
return set;
}
/**
* @return a set of <code>DefaultArtifact</code>, i.e.:
* <code>g:d:zip:1.0, g:a:war:1.0, g:b:jar:1.0, g:c:sources:1.0, g:e:rar:1.0</code>
* @throws IOException if any
*/
public Set<Artifact> getTypedArtifacts() throws IOException {
Set<Artifact> set = new HashSet<>();
set.add(createArtifact("g", "a", "1.0", Artifact.SCOPE_COMPILE, "war", null));
set.add(createArtifact("g", "b", "1.0", Artifact.SCOPE_COMPILE, "jar", null));
set.add(createArtifact("g", "c", "1.0", Artifact.SCOPE_COMPILE, "sources", null));
set.add(createArtifact("g", "d", "1.0", Artifact.SCOPE_COMPILE, "zip", null));
set.add(createArtifact("g", "e", "1.0", Artifact.SCOPE_COMPILE, "rar", null));
return set;
}
/**
* @return a set of <code>DefaultArtifact</code>, i.e.:
* <code>g:c:jar:three:1.0, g:b:jar:two:1.0, g:d:jar:four:1.0, g:a:jar:one:1.0</code>
* @throws IOException if any
*/
public Set<Artifact> getClassifiedArtifacts() throws IOException {
Set<Artifact> set = new HashSet<>();
set.add(createArtifact("g", "a", "1.0", Artifact.SCOPE_COMPILE, "jar", "one"));
set.add(createArtifact("g", "b", "1.0", Artifact.SCOPE_COMPILE, "jar", "two"));
set.add(createArtifact("g", "c", "1.0", Artifact.SCOPE_COMPILE, "jar", "three"));
set.add(createArtifact("g", "d", "1.0", Artifact.SCOPE_COMPILE, "jar", "four"));
return set;
}
/**
* @return a set of <code>DefaultArtifact</code>, i.e.:
* <code>g:d:zip:1.0, g:a:war:1.0, g:b:jar:1.0, g:e:rar:1.0</code>
* @throws IOException if any
*/
public Set<Artifact> getTypedArchiveArtifacts() throws IOException {
Set<Artifact> set = new HashSet<>();
set.add(createArtifact("g", "a", "1.0", Artifact.SCOPE_COMPILE, "war", null));
set.add(createArtifact("g", "b", "1.0", Artifact.SCOPE_COMPILE, "jar", null));
set.add(createArtifact("g", "d", "1.0", Artifact.SCOPE_COMPILE, "zip", null));
set.add(createArtifact("g", "e", "1.0", Artifact.SCOPE_COMPILE, "rar", null));
return set;
}
/**
* @return a set of <code>DefaultArtifact</code>, i.e.:
* <code>g:one:jar:a:1.0, g:two:jar:a:1.0, g:four:jar:a:1.0, g:three:jar:a:1.0</code>
* @throws IOException if any
*/
public Set<Artifact> getArtifactArtifacts() throws IOException {
Set<Artifact> set = new HashSet<>();
set.add(createArtifact("g", "one", "1.0", Artifact.SCOPE_COMPILE, "jar", "a"));
set.add(createArtifact("g", "two", "1.0", Artifact.SCOPE_COMPILE, "jar", "a"));
set.add(createArtifact("g", "three", "1.0", Artifact.SCOPE_COMPILE, "jar", "a"));
set.add(createArtifact("g", "four", "1.0", Artifact.SCOPE_COMPILE, "jar", "a"));
return set;
}
/**
* @return a set of <code>DefaultArtifact</code>, i.e.:
* <code>one:group-one:jar:a:1.0, three:group-three:jar:a:1.0, four:group-four:jar:a:1.0,
* two:group-two:jar:a:1.0</code>
* @throws IOException if any
*/
public Set<Artifact> getGroupIdArtifacts() throws IOException {
Set<Artifact> set = new HashSet<>();
set.add(createArtifact("one", "group-one", "1.0", Artifact.SCOPE_COMPILE, "jar", "a"));
set.add(createArtifact("two", "group-two", "1.0", Artifact.SCOPE_COMPILE, "jar", "a"));
set.add(createArtifact("three", "group-three", "1.0", Artifact.SCOPE_COMPILE, "jar", "a"));
set.add(createArtifact("four", "group-four", "1.0", Artifact.SCOPE_COMPILE, "jar", "a"));
return set;
}
/**
* @return a set of <code>DefaultArtifact</code>
* @throws IOException if any
* @see #getTypedArtifacts()
* @see #getScopedArtifacts()
* @see #getReleaseAndSnapshotArtifacts()
*/
public Set<Artifact> getMixedArtifacts() throws IOException {
Set<Artifact> set = new HashSet<>();
set.addAll(getTypedArtifacts());
set.addAll(getScopedArtifacts());
set.addAll(getReleaseAndSnapshotArtifacts());
return set;
}
/**
* @return Returns the createFiles.
*/
public boolean isCreateFiles() {
return this.createFiles;
}
/**
* @param createFiles The createFiles to set.
*/
public void setCreateFiles(boolean createFiles) {
this.createFiles = createFiles;
}
/**
* @return Returns the workingDir.
*/
public File getWorkingDir() {
return this.workingDir;
}
/**
* @param workingDir The workingDir to set.
*/
public void setWorkingDir(File workingDir) {
this.workingDir = workingDir;
}
/**
* @return Returns the srcFile.
*/
public File getSrcFile() {
return this.srcFile;
}
/**
* @param srcFile The srcFile to set.
*/
public void setSrcFile(File srcFile) {
this.srcFile = srcFile;
}
/**
* Convenience method to set values to variables in objects that don't have setters
*
* @param object
* @param variable
* @param value
* @throws IllegalAccessException
*/
public static void setVariableValueToObject(Object object, String variable, Object value)
throws IllegalAccessException {
Field field = ReflectionUtils.getFieldByNameIncludingSuperclasses(variable, object.getClass());
field.setAccessible(true);
field.set(object, value);
}
/**
* Builds the file name. If removeVersion is set, then the file name must be reconstructed from the artifactId,
* Classifier (if used) and Type. Otherwise, this method returns the artifact file name.
*
* @param artifact File to be formatted.
* @param removeVersion Specifies if the version should be removed from the file name.
* @return Formatted file name in the format artifactId-[version]-[classifier].[type]
*/
public static String getFormattedFileName(Artifact artifact, boolean removeVersion) {
String destFileName = null;
// if there is a file and we aren't stripping the version, just get the
// name directly
if (artifact.getFile() != null && !removeVersion) {
destFileName = artifact.getFile().getName();
} else
// if offline
{
String versionString = null;
if (!removeVersion) {
versionString = "-" + artifact.getVersion();
} else {
versionString = "";
}
String classifierString = "";
if (StringUtils.isNotEmpty(artifact.getClassifier())) {
classifierString = "-" + artifact.getClassifier();
}
destFileName = artifact.getArtifactId() + versionString + classifierString + "."
+ artifact.getArtifactHandler().getExtension();
}
return destFileName;
}
}