blob: 4820352e96b8854a146bae57bed805faf16d2327 [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.axis2.maven2.aar;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.util.DirectoryScanner;
import org.codehaus.plexus.util.FileUtils;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/** Abstract base class of all the mojos in the axis2-aar-maven-plugin. */
public abstract class AbstractAarMojo
extends AbstractMojo {
/**
* The projects base directory.
*
* @parameter property="project.basedir"
* @required
* @readonly
*/
protected File baseDir;
/**
* The maven project.
*
* @parameter property="project"
* @required
* @readonly
*/
protected MavenProject project;
/**
* The directory containing generated classes.
*
* @parameter default-value="${project.build.outputDirectory}"
* @required
*/
private File classesDirectory;
/**
* The directory where the aar is built.
*
* @parameter default-value="${project.build.directory}/aar"
* @required
*/
protected File aarDirectory;
/**
* The location of the services.xml file. If it is present in the META-INF directory in
* src/main/resources with that name then it will automatically be included. Otherwise this
* parameter must be set.
*
* @parameter default-value="src/main/resources/META-INF/services.xml"
*/
private File servicesXmlFile;
/**
* The location of the WSDL file, if any. By default, no WSDL file is added and it is assumed,
* that Axis 2 will automatically generate a WSDL file.
*
* @parameter
*/
private File wsdlFile;
/**
* Name, to which the wsdl file shall be mapped. By default, the name will be computed from the
* files path by removing the directory.
*
* @parameter default-value="service.wsdl"
*/
private String wsdlFileName;
/**
* Additional file sets, which are being added to the archive.
*
* @parameter
*/
private FileSet[] fileSets;
/**
* Whether the dependency jars should be included in the aar
*
* @parameter default-value="true"
*/
private boolean includeDependencies;
/**
* Builds the exploded AAR file.
*
* @throws MojoExecutionException
*/
protected void buildExplodedAar()
throws MojoExecutionException {
getLog().debug("Exploding aar...");
aarDirectory.mkdirs();
getLog().debug("Assembling aar " + project.getArtifactId() + " in " + aarDirectory);
try {
final File metaInfDir = new File(aarDirectory, "META-INF");
final File libDir = new File(aarDirectory, "lib");
final File servicesFileTarget = new File(metaInfDir, "services.xml");
boolean existsBeforeCopyingClasses = servicesFileTarget.exists();
String wsdlName = wsdlFileName;
if (wsdlName == null && wsdlFile != null) {
wsdlName = wsdlFile.getName();
}
File wsdlFileTarget = null;
if (wsdlFile != null) {
wsdlFileTarget = new File(metaInfDir, wsdlFileName);
}
boolean wsdlExistsBeforeCopyingClasses =
wsdlFileTarget == null ? false : wsdlFileTarget.exists();
if (classesDirectory.exists() && (!classesDirectory.equals(aarDirectory))) {
FileUtils.copyDirectoryStructure(classesDirectory, aarDirectory);
}
if (fileSets != null) {
for (int i = 0; i < fileSets.length; i++) {
FileSet fileSet = fileSets[i];
copyFileSet(fileSet, aarDirectory);
}
}
copyMetaInfFile(servicesXmlFile, servicesFileTarget, existsBeforeCopyingClasses,
"services.xml file");
copyMetaInfFile(wsdlFile, wsdlFileTarget, wsdlExistsBeforeCopyingClasses, "WSDL file");
if (includeDependencies) {
Set<Artifact> artifacts = project.getArtifacts();
List<String> duplicates = findDuplicates(artifacts);
for (Artifact artifact : artifacts) {
String targetFileName = getDefaultFinalName(artifact);
getLog().debug("Processing: " + targetFileName);
if (duplicates.contains(targetFileName)) {
getLog().debug("Duplicate found: " + targetFileName);
targetFileName = artifact.getGroupId() + "-"
+ targetFileName;
getLog().debug("Renamed to: " + targetFileName);
}
// TODO: utilise appropriate methods from project builder
ScopeArtifactFilter filter = new ScopeArtifactFilter(
Artifact.SCOPE_RUNTIME);
if (filter.include(artifact)) {
String type = artifact.getType();
if ("jar".equals(type)) {
copyFileIfModified(artifact.getFile(), new File(
libDir, targetFileName));
}
}
}
}
}
catch (IOException e) {
throw new MojoExecutionException("Could not explode aar...", e);
}
}
/**
* Searches a set of artifacts for duplicate filenames and returns a list of duplicates.
*
* @param artifacts set of artifacts
* @return List of duplicated artifacts
*/
private List<String> findDuplicates(Set<Artifact> artifacts) {
List<String> duplicates = new ArrayList<String>();
List<String> identifiers = new ArrayList<String>();
for (Artifact artifact : artifacts) {
String candidate = getDefaultFinalName(artifact);
if (identifiers.contains(candidate)) {
duplicates.add(candidate);
} else {
identifiers.add(candidate);
}
}
return duplicates;
}
/**
* Converts the filename of an artifact to artifactId-version.type format.
*
* @param artifact
* @return converted filename of the artifact
*/
private String getDefaultFinalName(Artifact artifact) {
return artifact.getArtifactId() + "-" + artifact.getVersion() + "." +
artifact.getArtifactHandler().getExtension();
}
/**
* Copy file from source to destination only if source timestamp is later than the destination
* timestamp. The directories up to <code>destination</code> will be created if they don't
* already exist. <code>destination</code> will be overwritten if it already exists.
*
* @param source An existing non-directory <code>File</code> to copy bytes from.
* @param destination A non-directory <code>File</code> to write bytes to (possibly
* overwriting).
* @throws IOException if <code>source</code> does not exist,
* <code>destination</code> cannot be written to, or an IO
* error occurs during copying.
* @throws java.io.FileNotFoundException if <code>destination</code> is a directory
* <p/>
* TO DO: Remove this method when Maven moves to
* plexus-utils version 1.4
*/
private void copyFileIfModified(File source, File destination)
throws IOException {
// TO DO: Remove this method and use the method in WarFileUtils when Maven 2 changes
// to plexus-utils 1.2.
if (destination.lastModified() < source.lastModified()) {
FileUtils.copyFile(source.getCanonicalFile(), destination);
// preserve timestamp
destination.setLastModified(source.lastModified());
}
}
private void copyFileSet(FileSet fileSet, File targetDirectory)
throws IOException {
File dir = fileSet.getDirectory();
if (dir == null) {
dir = baseDir;
}
File targetDir = targetDirectory;
if (fileSet.getOutputDirectory() != null) {
targetDir = new File(targetDir, fileSet.getOutputDirectory());
}
if (targetDir.equals(dir)) {
return;
}
DirectoryScanner ds = new DirectoryScanner();
ds.setBasedir(dir);
if (!fileSet.isSkipDefaultExcludes()) {
ds.addDefaultExcludes();
}
final String[] excludes = fileSet.getExcludes();
if (excludes != null) {
ds.setExcludes(excludes);
}
final String[] includes = fileSet.getIncludes();
if (includes != null) {
ds.setIncludes(includes);
}
ds.scan();
String[] files = ds.getIncludedFiles();
for (int i = 0; i < files.length; i++) {
File sourceFile = new File(dir, files[i]);
File targetFile = new File(targetDir, files[i]);
FileUtils.copyFile(sourceFile, targetFile);
}
}
private void copyMetaInfFile(final File pSource, final File pTarget,
final boolean pExistsBeforeCopying,
final String pDescription)
throws MojoExecutionException, IOException {
if (pSource != null && pTarget != null) {
if (!pSource.exists()) {
throw new MojoExecutionException(
"The configured " + pDescription + " could not be found at "
+ pSource);
}
if (!pExistsBeforeCopying && pTarget.exists()) {
getLog().warn("The configured " + pDescription +
" overwrites another file from the classpath.");
}
FileUtils.copyFile(pSource, pTarget);
}
}
}