package eu.hats_project.build.maven.plugin;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.jar.JarFile;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.DefaultArtifact;
import org.apache.maven.artifact.factory.ArtifactFactory;
import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.resolver.ArtifactCollector;
import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
import org.apache.maven.artifact.resolver.ArtifactResolutionException;
import org.apache.maven.artifact.resolver.ArtifactResolver;
import org.apache.maven.artifact.resolver.filter.AndArtifactFilter;
import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter;
import org.apache.maven.model.Dependency;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.MavenProjectBuilder;
import org.apache.maven.project.ProjectBuildingException;
import org.apache.maven.project.artifact.InvalidDependencyVersionException;
import org.apache.maven.shared.dependency.tree.DependencyTreeBuilder;
abstract class AbstractABSMojo extends AbstractMojo {
public static final String[] ABS_EXTENSIONS = {".abs", ".mtvl"};
public static final String[] LEGAL_ABS = {".abs"};
public static final String ABS_GROUPID = "eu.hats-project";
public static final String ABS_FRONTEND_ARTIFACTID = "absfrontend";
public static final String MTVL_ARTIFACTID = "mTVL";
public static final String VERSION_ATTRIBUTE = "ABS-Package-Version";
/**
* @parameter expression="${abs.check.selection}" default-value=true
*/
protected boolean checkProductSelection;
/**
* @parameter expression="${abs.stdlib}" default-value=true
*/
protected boolean stdlib;
/**
* @parameter expression="${abs.verbose}" default-value=false
*/
protected boolean verbose;
/**
* @parameter expression="${abs.loctype}" default-value=false
*/
protected boolean loctype;
/**
* Product selection
* @parameter expression="${abs.product}"
*/
protected String productName;
/**
* The ABS source folder.
*
* @parameter expression="${abs.srcFolder}"
* default-value="${project.basedir}/src/main/abs"
* @required
*/
protected File absSrcFolder;
/**
* The ABS test source folder.
*
* @parameter expression="${abs.test.srcFolder}"
* default-value="${project.basedir}/src/test/abs/"
*/
protected File absTestSrcFolder;
/**
* @parameter expression="${project}"
* @required
* @readonly
*/
protected MavenProject project;
/**
* Used to look up Artifacts in the remote repository.
*
* @component
* @required
* @readonly
*/
protected ArtifactFactory factory;
/**
* Used to look up Artifacts in the remote repository.
*
* @component
* @required
* @readonly
*/
protected ArtifactResolver resolver;
/**
* Location of the local repository.
*
* @parameter expression="${localRepository}"
* @readonly
* @required
*/
protected ArtifactRepository localRepo;
/**
* List of Remote Repositories used by the resolver
*
* @parameter expression="${project.remoteArtifactRepositories}"
* @readonly
* @required
*/
protected List<?> remoteRepos;
/**
* Jvm Arguments.
*
* @parameter
*/
protected String[] jvmArgs;
/**
* compiler additionnals arguments
*
* @parameter
*/
protected String[] args;
/**
* Display the command line called ?
*
* @required
* @parameter expression="${displayCmd}" default-value="false"
*/
public boolean displayCmd;
/**
* Forks the execution into a separate process.
*
* @parameter default-value="true"
*/
protected boolean fork = true;
/**
* Force the use of an external ArgFile to run any forked process.
*
* @parameter default-value="false"
*/
protected boolean forceUseArgFile = false;
/**
* Artifact factory, needed to download source jars.
*
* @component
* @required
* @readonly
*/
protected MavenProjectBuilder mavenProjectBuilder;
/**
* The artifact metadata source to use.
*
* @component
* @required
* @readonly
*/
private ArtifactMetadataSource artifactMetadataSource;
/**
* The artifact collector to use.
*
* @component
* @required
* @readonly
*/
private ArtifactCollector artifactCollector;
/**
* The dependency tree builder to use.
*
* @component
* @required
* @readonly
*/
private DependencyTreeBuilder dependencyTreeBuilder;
/**
* ABS frontend jar
*/
protected File absfrontEnd;
public void execute() throws MojoExecutionException, MojoFailureException {
try {
absfrontEnd = new File(getToolClassPath(ABS_FRONTEND_ARTIFACTID));
doExecute();
} catch (MojoExecutionException exc) {
throw exc;
} catch (MojoFailureException exc) {
throw exc;
} catch (RuntimeException exc) {
throw exc;
} catch (Exception exc) {
throw new MojoExecutionException("wrap: " + exc, exc);
}
}
protected abstract void doExecute() throws Exception;
void setABSSrcFolder(File absSrcFolder) {
this.absSrcFolder = absSrcFolder;
}
/**
* This method resolves the dependency artifacts from the project.
*
* @param theProject
* The POM.
* @return resolved set of dependency artifacts.
*
* @throws ArtifactResolutionException
* @throws ArtifactNotFoundException
* @throws InvalidDependencyVersionException
*/
@SuppressWarnings("unchecked")
protected Set<Artifact> resolveDependencyArtifacts(MavenProject theProject) throws Exception {
AndArtifactFilter filter = new AndArtifactFilter();
filter.add(new ScopeArtifactFilter(Artifact.SCOPE_TEST));
filter.add(new ArtifactFilter() {
public boolean include(Artifact artifact) {
return !artifact.isOptional();
}
});
// TODO follow the dependenciesManagement and override rules
Set<Artifact> artifacts = theProject.createArtifacts(factory, Artifact.SCOPE_RUNTIME, filter);
for (Artifact artifact : artifacts) {
resolver.resolve(artifact, remoteRepos, localRepo);
}
return artifacts;
}
/**
* This method resolves all transitive dependencies of an artifact.
*
* @param artifact
* the artifact used to retrieve dependencies
*
* @return resolved set of dependencies
*
* @throws ArtifactResolutionException
* @throws ArtifactNotFoundException
* @throws ProjectBuildingException
* @throws InvalidDependencyVersionException
*/
protected Set<Artifact> resolveArtifactDependencies(Artifact artifact) throws Exception {
Artifact pomArtifact = factory.createArtifact(artifact.getGroupId(), artifact.getArtifactId(),
artifact.getVersion(), "", "pom");
MavenProject pomProject = mavenProjectBuilder.buildFromRepository(pomArtifact, remoteRepos, localRepo);
return resolveDependencyArtifacts(pomProject);
}
protected String getToolClassPath(String artifactId) throws Exception {
return getClasspath(ABS_GROUPID, artifactId, "1.0-SNAPSHOT");
}
protected String getClasspath(String groupId, String artifactId, String version) throws Exception {
return getClasspath(factory.createArtifactWithClassifier(groupId, artifactId, version, "jar", "jar-with-dependencies"));
}
protected String getClasspath(Artifact artifact) throws Exception {
resolver.resolve(artifact, remoteRepos, localRepo);
return artifact.getFile().getCanonicalPath();
}
@SuppressWarnings("unchecked")
protected List<Dependency> getDependencies() {
return project.getCompileDependencies();
}
protected List<String> getAbsDependencies() {
Set<File> absJars = new HashSet<File>();
for (Object a : project.getArtifacts()) {
if (a instanceof Artifact) {
absJars.add(((Artifact) a).getFile());
}
}
return getFileNames(absJars);
}
protected File getArtifact(String artifactId) {
for (Object o : project.getArtifacts()) {
if (o instanceof DefaultArtifact) {
DefaultArtifact a = (DefaultArtifact) o;
if (a.getArtifactId().equals(artifactId)) {
return a.getFile();
}
}
}
return null;
}
protected List<String> getFileNames(Collection<File> files) {
List<String> res = new ArrayList<String>(files.size());
for (File f : files) {
res.add(f.getAbsolutePath());
}
return res;
}
protected List<File> getAbsFiles(File dir) {
List<File> absFiles = new ArrayList<File>();
for (File f : dir.listFiles()) {
if (!f.isHidden() && f.canRead()) {
if (f.isDirectory()) {
absFiles.addAll(getAbsFiles(f));
} else {
String name = f.getName();
for (String ext : ABS_EXTENSIONS) {
if (name.endsWith(ext)) {
absFiles.add(f);
break;
}
}
}
}
}
return absFiles;
}
protected List<String> getABSArguments() throws Exception {
List<String> args = new ArrayList<String>();
args.addAll(getFileNames(getAbsFiles(absSrcFolder)));
for (String dep : getAbsDependencies()) {
if (isABSPackage(new File(dep))) {
args.add(dep);
}
}
return args;
}
protected boolean isABSPackage(File file) throws IOException {
return new JarFile(file).getManifest().getMainAttributes()
.getValue(VERSION_ATTRIBUTE) != null;
}
}