All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.kuali.maven.mojo.AntMojo Maven / Gradle / Ivy

/**
 * Copyright 2004-2011 The Kuali Foundation
 *
 * Licensed under the Educational Community 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.opensource.org/licenses/ecl2.php
 *
 * 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.kuali.maven.mojo;

/*
 * 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.io.LineNumberReader;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.DependencyResolutionRequiredException;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.MavenProjectHelper;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.BuildLogger;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.ProjectHelper;
import org.apache.tools.ant.taskdefs.Typedef;
import org.apache.tools.ant.types.Path;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.IOUtil;
import org.codehaus.plexus.util.ReaderFactory;
import org.codehaus.plexus.util.StringUtils;
import org.kuali.maven.common.AntMavenUtils;
import org.kuali.maven.common.ResourceUtils;

/**
 * 

* Maven Ant Mojo. Allows Maven to invoke a target inside an Ant build file. The build file can be located on the file system, the ant-maven-plugin * classpath, or any resource URL that Spring 3.0 can understand. *

* *

* By default, this mojo makes the following available to Ant build files as both properties and references: *

* * maven.compile.classpath=The classpath Maven is using for compilation
* maven.runtime.classpath=The classpath Maven is using at runtime
* maven.test.classpath=The classpath Maven is using for testing
* maven.plugin.classpath=The classpath for the ant-maven-plugin * * *

* These are available as Ant references: *

* * maven.project=MavenProject
* maven.project.helper=MavenProjectHelper
* maven.local.repository=ArtifactRepository
* * @goal run * @threadSafe * @requiresDependencyResolution test */ public class AntMojo extends AbstractMojo { ResourceUtils resourceUtils = new ResourceUtils(); AntMavenUtils antMvnUtils = new AntMavenUtils(); private static final String FS = System.getProperty("file.separator"); public static final String ANT_DIR = "ant"; public static final String ANT_BUILD_DIR = "target" + FS + ANT_DIR; /** * The refid used to store the Maven project object in the Ant build. */ public static final String DEFAULT_MAVEN_PROJECT_REFID = "maven.project"; /** * The refid used to store the Maven project helper object in the Ant build. */ public static final String DEFAULT_MAVEN_PROJECT_HELPER_REFID = "maven.project.helper"; /** * The refid used to store the Maven local repository object in the Ant build. */ public static final String DEFAULT_MAVEN_LOCAL_REPOSITORY_REFID = "maven.local.repository"; /** * The default target name. */ public static final String DEFAULT_ANT_TARGET_NAME = "main"; /** * The default encoding to use for the generated Ant build. */ public static final String UTF_8 = "UTF-8"; public static final String XML_HEADER = "\n"; /** * The path to The XML file containing the definition of the Maven tasks. */ public static final String ANTLIB = "org/apache/maven/ant/tasks/antlib.xml"; /** * The URI which defines the built in Ant tasks */ public static final String TASK_URI = "antlib:org.apache.maven.ant.tasks"; /** * The Maven project object * * @parameter expression="${project}" * @readonly */ private MavenProject project; /** * The Maven project helper object * * @component */ private MavenProjectHelper projectHelper; /** * The plugin dependencies. * * @parameter expression="${plugin.artifacts}" * @required * @readonly */ private List pluginArtifacts; /** * The local Maven repository * * @parameter expression="${localRepository}" * @readonly */ protected ArtifactRepository localRepository; /** * String to prepend to project and dependency property names. * * @parameter expression="${ant.propertyPrefix}" default-value="" */ private String propertyPrefix = ""; /** * The xml tag prefix to use for the built in Ant tasks. This prefix needs to be prepended to each task referenced. For example, a prefix of "mvn" * means that the attachartifact task is referenced by "<mvn:attachartifact>" The default value of an empty string means that no prefix is used * for the tasks. * * @parameter expression="${ant.customTaskPrefix}" default-value="" */ private String customTaskPrefix = ""; /** * Specifies whether the Antrun execution should be skipped. * * @parameter expression="${ant.skip}" default-value="false" */ private boolean skip; /** * Specifies whether the Ant properties should be propagated to the Maven properties. * * @parameter expression="${ant.exportAntProperties}" default-value="false" */ private boolean exportAntProperties; /** * Specifies whether a failure in the ant build leads to a failure of the Maven build. * * If this value is 'false', the Maven build will proceed even if the ant build fails. If it is 'true', then the Maven build fails if the ant build * fails. * * @parameter expression="${ant.failOnError}" default-value="true" */ private boolean failOnError; /** * The build file to use. This supports Spring 3.0 resource URL expressions eg "classpath:build.xml" or "http://myurl/build.xml". The ant-maven-plugin * classpath is what is searched when using the "classpath:" notation * * @parameter expression="${ant.file}" default-value="build.xml" * @required */ private String file; /** * The target inside the build file to invoke. If not provided, the default target from the specified build file will be executed * * @parameter expression="${ant.target}" */ private String target; /** * Filename to redirect the ant output to. This is relative to the base directory of the current project * * @parameter expression="${ant.output}" */ private String output; /** * If true, pass all Maven properties to Ant * * @parameter expression="${ant.inheritAll}" default-value="true" */ private String inheritAll; /** * If true, pass Maven object references to Ant (MavenProject, MavenProjectHelper, ArtifactRepository - for the local repo) * * @parameter expression="${ant.inheritRefs}" default-value="true" */ private String inheritRefs; /** * If they give us "http://myurl/mybuild.xml", this gets set to "mybuild.xml" by the handleAntFile() method */ private String antFilename; /** * If they give us "http://myurl/mybuild.xml" this gets set to "target/ant/mybuild.xml" by the handleAntFile() method */ private String relativeLocalFilename; /** * */ @Override public void execute() throws MojoExecutionException { // Might be skipping this execution if (isSkip()) { return; } // The currently executing project MavenProject mavenProject = getMavenProject(); try { // Setup the build file handleAntfile(); // Initialize an Ant project Project antProject = getAntProject(); // Create the Ant equivalents of important Maven classpath's Map pathRefs = antMvnUtils.getPathRefs(antProject, mavenProject, pluginArtifacts); // Collect some Maven objects Map mavenRefs = getMavenRefs(mavenProject); // Add both as references to the Ant project antMvnUtils.addRefs(antProject, pathRefs); antMvnUtils.addRefs(antProject, mavenRefs); // Add the Maven classpath's as simple properties (for convenience) antMvnUtils.setPathProperties(antProject, pathRefs); // Initialize Maven ant tasks initMavenTasks(antProject); // Ant project needs actual properties vs. using expression evaluator when calling an external build file. antMvnUtils.copyProperties(mavenProject, antProject, propertyPrefix, getLog(), localRepository); // Execute the target from our wrapper. This calls the target from the build file they supplied getLog().info("Executing tasks"); antProject.executeTarget(DEFAULT_ANT_TARGET_NAME); getLog().info("Executed tasks"); // Copy properties from Ant back to Maven (if needed) if (exportAntProperties) { antMvnUtils.copyProperties(antProject, mavenProject, getLog()); } } catch (DependencyResolutionRequiredException e) { throw new MojoExecutionException("DependencyResolutionRequiredException: " + e.getMessage(), e); } catch (BuildException e) { handleBuildException(e); } catch (Throwable e) { throw new MojoExecutionException("Error executing ant tasks: " + e.getMessage(), e); } } /** * Determine if mojo execution should be skipped */ protected boolean isSkip() { if (skip) { getLog().info("Skipping Ant execution"); return true; } return false; } /** * Create a wrapper build file that calls into the build file they supplied us with. Initialize an Ant project from the wrapper file. */ public Project getAntProject() throws IOException { Project antProject = new Project(); File antBuildFile = createBuildWrapper(); ProjectHelper.configureProject(antProject, antBuildFile); antProject.init(); // Setup logging BuildLogger antLogger = antMvnUtils.getBuildLogger(getLog()); antProject.addBuildListener(antLogger); return antProject; } /** * Collect Maven model objects, the currently executing project, the project helper, and the local repository */ protected Map getMavenRefs(MavenProject mavenProject) { Map mavenRefs = new HashMap(); mavenRefs.put(DEFAULT_MAVEN_PROJECT_REFID, getMavenProject()); mavenRefs.put(DEFAULT_MAVEN_PROJECT_HELPER_REFID, projectHelper); mavenRefs.put(DEFAULT_MAVEN_LOCAL_REPOSITORY_REFID, localRepository); return mavenRefs; } /** * There was an Ant build exception */ protected void handleBuildException(BuildException e) throws MojoExecutionException { StringBuffer sb = new StringBuffer(); sb.append("An Ant BuildException has occured: " + e.getMessage()); String fragment = findFragment(e); if (fragment != null) { sb.append("\n").append(fragment); } if (!failOnError) { getLog().info(sb.toString(), e); return; // do not register roots. } else { throw new MojoExecutionException(sb.toString(), e); } } /** * Get the current Maven project * * @return current Maven project */ public MavenProject getMavenProject() { return this.project; } public void initMavenTasks(Project antProject) { getLog().debug("Initialize Maven Ant Tasks"); Typedef typedef = new Typedef(); typedef.setProject(antProject); typedef.setResource(ANTLIB); if (!customTaskPrefix.equals("")) { typedef.setURI(TASK_URI); } typedef.execute(); } /** * Default XML that wraps the build file they supplied us with */ protected String getDefaultXML(AntTaskPojo atp) throws IOException { StringBuilder sb = new StringBuilder(); sb.append(XML_HEADER); sb.append(getProjectOpen()); sb.append(" \n"); sb.append(" " + getXML(atp) + "\n"); sb.append(" \n"); sb.append("\n"); return sb.toString(); } /** * Write the ant target and surrounding tags to a temporary file */ protected File createBuildWrapper() throws IOException { AntTaskPojo atp = getAntTaskPojo(); String xml = getDefaultXML(atp); File buildFile = new File(ANT_BUILD_DIR + FS + antFilename); buildFile.getParentFile().mkdirs(); FileUtils.fileWrite(buildFile.getAbsolutePath(), UTF_8, xml); return buildFile; } /** * Copy the build file to a local temp directory and preserve some information about the filename */ protected void handleAntfile() throws IOException { String filename = resourceUtils.getFilename(file); // The fileName should probably use the plugin executionId instead of target if (!StringUtils.isBlank(target)) { filename = target + "-" + filename; } antFilename = filename; relativeLocalFilename = ANT_BUILD_DIR + FS + "local-" + antFilename; File localFile = new File(relativeLocalFilename); resourceUtils.copy(file, localFile.getAbsolutePath()); } /** * Aggregate some of the Maven configuration into a pojo */ protected AntTaskPojo getAntTaskPojo() { AntTaskPojo pojo = new AntTaskPojo(); pojo.setAntfile(relativeLocalFilename); pojo.setTarget(target); pojo.setOutput(output); pojo.setInheritAll(Boolean.parseBoolean(inheritAll)); pojo.setInheritRefs(Boolean.parseBoolean(inheritRefs)); return pojo; } /** * XML for the Ant project tag */ protected String getProjectOpen() { StringBuilder sb = new StringBuilder(); sb.append(""); sb.append("\n"); return sb.toString(); } /** * @param buildException * not null * @return the fragment XML part where the buildException occurs. */ protected String findFragment(BuildException buildException) { if (buildException == null || buildException.getLocation() == null || buildException.getLocation().getFileName() == null) { return null; } File antFile = new File(buildException.getLocation().getFileName()); if (!antFile.exists()) { return null; } LineNumberReader reader = null; try { reader = new LineNumberReader(ReaderFactory.newXmlReader(antFile)); String line = ""; while ((line = reader.readLine()) != null) { if (reader.getLineNumber() == buildException.getLocation().getLineNumber()) { return "around Ant part ..." + line.trim() + "... @ " + buildException.getLocation().getLineNumber() + ":" + buildException.getLocation().getColumnNumber() + " in " + antFile.getAbsolutePath(); } } } catch (Exception e) { getLog().debug(e.getMessage(), e); return null; } finally { IOUtil.close(reader); } return null; } /** * Convert an AntTaskPojo into XML * * http://ant.apache.org/manual/Tasks/ant.html */ protected String getXML(AntTaskPojo atp) { StringBuilder sb = new StringBuilder(); sb.append(""); return sb.toString(); } /** * Return XML for an attribute */ protected String attr(String name, String value) { if (StringUtils.isEmpty(value)) { return ""; } else { return " " + name + "=\"" + value + "\""; } } public String getPropertyPrefix() { return propertyPrefix; } public void setPropertyPrefix(String propertyPrefix) { this.propertyPrefix = propertyPrefix; } public String getCustomTaskPrefix() { return customTaskPrefix; } public void setCustomTaskPrefix(String customTaskPrefix) { this.customTaskPrefix = customTaskPrefix; } public boolean isExportAntProperties() { return exportAntProperties; } public void setExportAntProperties(boolean exportAntProperties) { this.exportAntProperties = exportAntProperties; } public boolean isFailOnError() { return failOnError; } public void setFailOnError(boolean failOnError) { this.failOnError = failOnError; } public String getFile() { return file; } public void setFile(String file) { this.file = file; } public String getTarget() { return target; } public void setTarget(String target) { this.target = target; } public String getOutput() { return output; } public void setOutput(String output) { this.output = output; } public String getInheritAll() { return inheritAll; } public void setInheritAll(String inheritAll) { this.inheritAll = inheritAll; } public String getInheritRefs() { return inheritRefs; } public void setInheritRefs(String inheritRefs) { this.inheritRefs = inheritRefs; } public MavenProject getProject() { return project; } public MavenProjectHelper getProjectHelper() { return projectHelper; } public List getPluginArtifacts() { return pluginArtifacts; } public ArtifactRepository getLocalRepository() { return localRepository; } public String getAntFilename() { return antFilename; } public String getRelativeLocalFilename() { return relativeLocalFilename; } public void setSkip(boolean skip) { this.skip = skip; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy