package org.apache.maven.plugin.ant; /* * 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.ByteArrayInputStream; import java.io.File; import java.io.IOException; import java.text.DateFormat; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import javax.xml.parsers.DocumentBuilderFactory; import org.apache.maven.artifact.Artifact; import org.apache.maven.model.Plugin; import org.apache.maven.model.ReportPlugin; import org.apache.maven.project.MavenProject; import org.apache.xpath.XPathAPI; import org.codehaus.plexus.util.PathTool; import org.codehaus.plexus.util.StringUtils; import org.codehaus.plexus.util.xml.XMLWriter; import org.codehaus.plexus.util.xml.XmlWriterUtil; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** * Utility class for the <code>AntBuildWriter</code> class. * * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a> * @version $Id$ */ public class AntBuildWriterUtil { /** * @param compileSourceRoots {@link List} * @return not null list */ public static List removeEmptyCompileSourceRoots( List compileSourceRoots ) { List newCompileSourceRootsList = new ArrayList(); if ( compileSourceRoots != null ) { // copy as I may be modifying it for ( Object compileSourceRoot : compileSourceRoots ) { String srcDir = (String) compileSourceRoot; if ( new File( srcDir ).exists() ) { newCompileSourceRootsList.add( srcDir ); } } } return newCompileSourceRootsList; } /** * Convenience method to write <code><include/></code> and <code><exclude/></code> * * @param writer not null * @param includes {@link List} * @param excludes {@link List} */ public static void writeIncludesExcludes( XMLWriter writer, List includes, List excludes ) { if ( includes != null ) { for ( Object include1 : includes ) { String include = (String) include1; writer.startElement( "include" ); writer.addAttribute( "name", include ); writer.endElement(); // include } } if ( excludes != null ) { for ( Object exclude1 : excludes ) { String exclude = (String) exclude1; writer.startElement( "exclude" ); writer.addAttribute( "name", exclude ); writer.endElement(); // exclude } } } /** * Write comments in the Ant build file header * * @param writer {@link XMLWriter} */ public static void writeHeader( XMLWriter writer ) { writeAntVersionHeader( writer ); XmlWriterUtil.writeCommentLineBreak( writer ); // CHECKSTYLE_OFF: MagicNumber XmlWriterUtil.writeComment( writer, StringUtils.repeat( "=", 21 ) + " - DO NOT EDIT THIS FILE! - " + StringUtils.repeat( "=", 21 ) ); // CHECKSTYLE_ON: MagicNumber XmlWriterUtil.writeCommentLineBreak( writer ); XmlWriterUtil.writeComment( writer, " " ); XmlWriterUtil.writeComment( writer, "Any modifications will be overwritten." ); XmlWriterUtil.writeComment( writer, " " ); DateFormat dateFormat = DateFormat.getDateTimeInstance( DateFormat.SHORT, DateFormat.SHORT, Locale.US ); XmlWriterUtil.writeComment( writer, "Generated by Maven Ant Plugin on " + dateFormat.format( new Date( System.currentTimeMillis() ) ) ); XmlWriterUtil.writeComment( writer, "See: http://maven.apache.org/plugins/maven-ant-plugin/" ); XmlWriterUtil.writeComment( writer, " " ); XmlWriterUtil.writeCommentLineBreak( writer ); XmlWriterUtil.writeLineBreak( writer ); } /** * Write comment for the Ant supported version * * @param writer the writer */ public static void writeAntVersionHeader( XMLWriter writer ) { XmlWriterUtil.writeCommentText( writer, "Ant build file (http://ant.apache.org/) for Ant 1.6.2 or above.", 0 ); } /** * Convenience method to write XML ant task * * @param writer not null * @param project not null * @param moduleSubPath not null * @param tasks not null */ public static void writeAntTask( XMLWriter writer, MavenProject project, String moduleSubPath, String tasks ) { writer.startElement( "ant" ); writer.addAttribute( "antfile", "build.xml" ); writer.addAttribute( "dir", toRelative( project.getBasedir(), moduleSubPath ) ); writer.addAttribute( "target", tasks ); writer.endElement(); // ant } /** * Convenience method to write XML Ant javadoc task * * @param writer not null * @param project not null * @param wrapper not null * @throws IOException if any */ public static void writeJavadocTask( XMLWriter writer, MavenProject project, ArtifactResolverWrapper wrapper ) throws IOException { List<String> sources = new ArrayList<String>(); for ( Object o : project.getCompileSourceRoots() ) { String source = (String) o; if ( new File( source ).exists() ) { sources.add( source ); } } // No sources if ( sources.size() == 0 ) { return; } writer.startElement( "javadoc" ); String sourcepath = getMavenJavadocPluginBasicOption( project, "sourcepath", null ); if ( sourcepath == null ) { StringBuilder sb = new StringBuilder(); String[] compileSourceRoots = sources.toArray( new String[sources.size()] ); for ( int i = 0; i < compileSourceRoots.length; i++ ) { sb.append( "${maven.build.srcDir." ).append( i ).append( "}" ); if ( i < ( compileSourceRoots.length - 1 ) ) { sb.append( File.pathSeparatorChar ); } } writer.addAttribute( "sourcepath", sb.toString() ); addWrapAttribute( writer, "javadoc", "packagenames", "*", 3 ); } else { writer.addAttribute( "sourcepath", sourcepath ); } addWrapAttribute( writer, "javadoc", "destdir", getMavenJavadocPluginBasicOption( project, "destdir", "${maven.reporting.outputDirectory}/apidocs" ), 3 ); addWrapAttribute( writer, "javadoc", "extdirs", getMavenJavadocPluginBasicOption( project, "extdirs", null ), 3 ); addWrapAttribute( writer, "javadoc", "overview", getMavenJavadocPluginBasicOption( project, "overview", null ), 3 ); addWrapAttribute( writer, "javadoc", "access", getMavenJavadocPluginBasicOption( project, "show", "protected" ), 3 ); addWrapAttribute( writer, "javadoc", "old", getMavenJavadocPluginBasicOption( project, "old", "false" ), 3 ); addWrapAttribute( writer, "javadoc", "verbose", getMavenJavadocPluginBasicOption( project, "verbose", "false" ), 3 ); addWrapAttribute( writer, "javadoc", "locale", getMavenJavadocPluginBasicOption( project, "locale", null ), 3 ); addWrapAttribute( writer, "javadoc", "encoding", getMavenJavadocPluginBasicOption( project, "encoding", null ), 3 ); addWrapAttribute( writer, "javadoc", "version", getMavenJavadocPluginBasicOption( project, "version", "true" ), 3 ); addWrapAttribute( writer, "javadoc", "use", getMavenJavadocPluginBasicOption( project, "use", "true" ), 3 ); addWrapAttribute( writer, "javadoc", "author", getMavenJavadocPluginBasicOption( project, "author", "true" ), 3 ); addWrapAttribute( writer, "javadoc", "splitindex", getMavenJavadocPluginBasicOption( project, "splitindex", "false" ), 3 ); addWrapAttribute( writer, "javadoc", "windowtitle", getMavenJavadocPluginBasicOption( project, "windowtitle", null ), 3 ); addWrapAttribute( writer, "javadoc", "nodeprecated", getMavenJavadocPluginBasicOption( project, "nodeprecated", "false" ), 3 ); addWrapAttribute( writer, "javadoc", "nodeprecatedlist", getMavenJavadocPluginBasicOption( project, "nodeprecatedlist", "false" ), 3 ); addWrapAttribute( writer, "javadoc", "notree", getMavenJavadocPluginBasicOption( project, "notree", "false" ), 3 ); addWrapAttribute( writer, "javadoc", "noindex", getMavenJavadocPluginBasicOption( project, "noindex", "false" ), 3 ); addWrapAttribute( writer, "javadoc", "nohelp", getMavenJavadocPluginBasicOption( project, "nohelp", "false" ), 3 ); addWrapAttribute( writer, "javadoc", "nonavbar", getMavenJavadocPluginBasicOption( project, "nonavbar", "false" ), 3 ); addWrapAttribute( writer, "javadoc", "serialwarn", getMavenJavadocPluginBasicOption( project, "serialwarn", "false" ), 3 ); addWrapAttribute( writer, "javadoc", "helpfile", getMavenJavadocPluginBasicOption( project, "helpfile", null ), 3 ); addWrapAttribute( writer, "javadoc", "stylesheetfile", getMavenJavadocPluginBasicOption( project, "stylesheetfile", null ), 3 ); addWrapAttribute( writer, "javadoc", "charset", getMavenJavadocPluginBasicOption( project, "charset", "ISO-8859-1" ), 3 ); addWrapAttribute( writer, "javadoc", "docencoding", getMavenJavadocPluginBasicOption( project, "docencoding", null ), 3 ); addWrapAttribute( writer, "javadoc", "excludepackagenames", getMavenJavadocPluginBasicOption( project, "excludepackagenames", null ), 3 ); addWrapAttribute( writer, "javadoc", "source", getMavenJavadocPluginBasicOption( project, "source", null ), 3 ); addWrapAttribute( writer, "javadoc", "linksource", getMavenJavadocPluginBasicOption( project, "linksource", "false" ), 3 ); addWrapAttribute( writer, "javadoc", "breakiterator", getMavenJavadocPluginBasicOption( project, "breakiterator", "false" ), 3 ); addWrapAttribute( writer, "javadoc", "noqualifier", getMavenJavadocPluginBasicOption( project, "noqualifier", null ), 3 ); // miscellaneous addWrapAttribute( writer, "javadoc", "maxmemory", getMavenJavadocPluginBasicOption( project, "maxmemory", null ), 3 ); addWrapAttribute( writer, "javadoc", "additionalparam", getMavenJavadocPluginBasicOption( project, "additionalparam", null ), 3 ); // Nested arg String doctitle = getMavenJavadocPluginBasicOption( project, "doctitle", null ); if ( doctitle != null ) { writer.startElement( "doctitle" ); writer.writeText( "<![CDATA[" + doctitle + "]]>" ); writer.endElement(); // doctitle } String header = getMavenJavadocPluginBasicOption( project, "header", null ); if ( header != null ) { writer.startElement( "header" ); writer.writeText( "<![CDATA[" + header + "]]>" ); writer.endElement(); // header } String footer = getMavenJavadocPluginBasicOption( project, "footer", null ); if ( footer != null ) { writer.startElement( "footer" ); writer.writeText( "<![CDATA[" + footer + "]]>" ); writer.endElement(); // footer } String bottom = getMavenJavadocPluginBasicOption( project, "bottom", null ); if ( bottom != null ) { writer.startElement( "bottom" ); writer.writeText( "<![CDATA[" + bottom + "]]>" ); writer.endElement(); // bottom } Map[] links = getMavenJavadocPluginOptions( project, "links", null ); if ( links != null ) { for ( Map link : links ) { writer.startElement( "link" ); writer.addAttribute( "href", (String) link.get( "link" ) ); writer.endElement(); // link } } Map[] offlineLinks = getMavenJavadocPluginOptions( project, "offlineLinks", null ); if ( offlineLinks != null ) { for ( Map offlineLink : offlineLinks ) { writer.startElement( "link" ); writer.addAttribute( "href", (String) offlineLink.get( "url" ) ); addWrapAttribute( writer, "javadoc", "offline", "true", 4 ); writer.endElement(); // link } } Map[] groups = getMavenJavadocPluginOptions( project, "groups", null ); if ( groups != null ) { for ( Map group1 : groups ) { Map group = (Map) group1.get( "group" ); writer.startElement( "group" ); writer.addAttribute( "title", (String) group.get( "title" ) ); addWrapAttribute( writer, "javadoc", "package", (String) group.get( "package" ), 4 ); writer.endElement(); // group } } // TODO Handle docletArtifacts String doclet = getMavenJavadocPluginBasicOption( project, "doclet", null ); if ( doclet != null ) { String docletpath = getMavenJavadocPluginBasicOption( project, "docletpath", null ); if ( StringUtils.isNotEmpty( docletpath ) ) { writer.startElement( "doclet" ); writer.addAttribute( "name", doclet ); addWrapAttribute( writer, "javadoc", "path", docletpath, 4 ); writer.endElement(); // doclet } else { Map docletArtifact = getMavenJavadocPluginOption( project, "docletArtifact", null ); String path = wrapper.getArtifactAbsolutePath( (String) docletArtifact.get( "groupId" ), (String) docletArtifact.get( "artifactId" ), (String) docletArtifact.get( "version" ) ); path = StringUtils.replace( path, wrapper.getLocalRepository().getBasedir(), "${maven.repo.local}" ); writer.startElement( "doclet" ); writer.addAttribute( "name", doclet ); addWrapAttribute( writer, "javadoc", "path", path, 4 ); writer.endElement(); // doclet } } // TODO Handle taglets String taglet = getMavenJavadocPluginBasicOption( project, "taglet", null ); if ( taglet != null ) { String tagletpath = getMavenJavadocPluginBasicOption( project, "tagletpath", null ); if ( StringUtils.isNotEmpty( tagletpath ) ) { writer.startElement( "taglet" ); writer.addAttribute( "name", taglet ); addWrapAttribute( writer, "javadoc", "path", tagletpath, 4 ); writer.endElement(); // taglet } else { Map tagletArtifact = getMavenJavadocPluginOption( project, "tagletArtifact", null ); String path = wrapper.getArtifactAbsolutePath( (String) tagletArtifact.get( "groupId" ), (String) tagletArtifact.get( "artifactId" ), (String) tagletArtifact.get( "version" ) ); path = StringUtils.replace( path, wrapper.getLocalRepository().getBasedir(), "${maven.repo.local}" ); writer.startElement( "taglet" ); writer.addAttribute( "name", taglet ); addWrapAttribute( writer, "javadoc", "path", path, 4 ); writer.endElement(); // taglet } } Map[] tags = getMavenJavadocPluginOptions( project, "tags", null ); if ( tags != null ) { for ( Map tag : tags ) { Map props = (Map) tag.get( "tag" ); writer.startElement( "tag" ); writer.addAttribute( "name", (String) props.get( "name" ) ); addWrapAttribute( writer, "javadoc", "scope", (String) props.get( "placement" ), 4 ); addWrapAttribute( writer, "javadoc", "description", (String) props.get( "head" ), 4 ); writer.endElement(); // tag } } writer.endElement(); // javadoc } /** * Convenience method to write XML Ant jar task * * @param writer not null * @param project not null * @throws IOException if any */ public static void writeJarTask( XMLWriter writer, MavenProject project ) throws IOException { writer.startElement( "jar" ); writer.addAttribute( "jarfile", "${maven.build.dir}/${maven.build.finalName}.jar" ); addWrapAttribute( writer, "jar", "compress", getMavenJarPluginBasicOption( project, "archive//compress", "true" ), 3 ); addWrapAttribute( writer, "jar", "index", getMavenJarPluginBasicOption( project, "archive//index", "false" ), 3 ); if ( getMavenJarPluginBasicOption( project, "archive//manifestFile", null ) != null ) { addWrapAttribute( writer, "jar", "manifest", getMavenJarPluginBasicOption( project, "archive//manifestFile", null ), 3 ); } addWrapAttribute( writer, "jar", "basedir", "${maven.build.outputDir}", 3 ); addWrapAttribute( writer, "jar", "excludes", "**/package.html", 3 ); if ( getMavenPluginOption( project, "maven-jar-plugin", "archive//manifest", null ) != null ) { writer.startElement( "manifest" ); writer.startElement( "attribute" ); writer.addAttribute( "name", "Main-Class" ); addWrapAttribute( writer, "attribute", "value", getMavenJarPluginBasicOption( project, "archive//manifest//mainClass", null ), 5 ); writer.endElement(); // attribute writer.endElement(); // manifest } writer.endElement(); // jar } /** * Convenience method to write XML Ant ear task * * @param writer not null * @param project not null * @param artifactResolverWrapper not null * @throws IOException if any */ public static void writeEarTask( XMLWriter writer, MavenProject project, ArtifactResolverWrapper artifactResolverWrapper ) throws IOException { writeCopyLib( writer, project, artifactResolverWrapper, "${maven.build.dir}/${maven.build.finalName}" ); writer.startElement( "ear" ); writer.addAttribute( "destfile", "${maven.build.dir}/${maven.build.finalName}.ear" ); addWrapAttribute( writer, "ear", "basedir", "${maven.build.dir}/${maven.build.finalName}", 3 ); addWrapAttribute( writer, "ear", "compress", getMavenEarPluginBasicOption( project, "archive//compress", "true" ), 3 ); addWrapAttribute( writer, "ear", "includes ", getMavenEarPluginBasicOption( project, "includes", null ), 3 ); addWrapAttribute( writer, "ear", "excludes", getMavenEarPluginBasicOption( project, "excludes", null ), 3 ); if ( getMavenEarPluginBasicOption( project, "applicationXml", null ) != null ) { addWrapAttribute( writer, "ear", "appxml", getMavenEarPluginBasicOption( project, "applicationXml", null ), 3 ); } else { // Generated appxml addWrapAttribute( writer, "ear", "appxml", "${maven.build.dir}/application.xml", 3 ); } if ( getMavenEarPluginBasicOption( project, "manifestFile", null ) != null ) { addWrapAttribute( writer, "ear", "manifest", getMavenEarPluginBasicOption( project, "manifestFile", null ), 3 ); } writer.endElement(); // ear } /** * Convenience method to write XML Ant war task * * @param writer not null * @param project not null * @param artifactResolverWrapper not null * @throws IOException if any */ public static void writeWarTask( XMLWriter writer, MavenProject project, ArtifactResolverWrapper artifactResolverWrapper ) throws IOException { String webXml = getMavenWarPluginBasicOption( project, "webXml", "${basedir}/src/main/webapp/WEB-INF/web.xml" ); if ( webXml.startsWith( "${basedir}/" ) ) { webXml = webXml.substring( "${basedir}/".length() ); } writeCopyLib( writer, project, artifactResolverWrapper, "${maven.build.dir}/${maven.build.finalName}/WEB-INF/lib" ); writer.startElement( "war" ); writer.addAttribute( "destfile", "${maven.build.dir}/${maven.build.finalName}.war" ); addWrapAttribute( writer, "war", "compress", getMavenWarPluginBasicOption( project, "archive//compress", "true" ), 3 ); addWrapAttribute( writer, "war", "webxml", webXml, 3 ); if ( getMavenWarPluginBasicOption( project, "manifestFile", null ) != null ) { addWrapAttribute( writer, "war", "manifest", getMavenWarPluginBasicOption( project, "manifestFile", null ), 3 ); } writer.startElement( "lib" ); writer.addAttribute( "dir", "${maven.build.dir}/${maven.build.finalName}/WEB-INF/lib" ); writer.endElement(); // lib writer.startElement( "classes" ); writer.addAttribute( "dir", "${maven.build.outputDir}" ); writer.endElement(); // classes writer.startElement( "fileset" ); writer.addAttribute( "dir", "src/main/webapp" ); addWrapAttribute( writer, "fileset", "excludes", "WEB-INF/web.xml", 4 ); writer.endElement(); // fileset writer.endElement(); // war } /** * Convenience method to wrap long element tags for a given attribute. * * @param writer not null * @param tag not null * @param name not null * @param value not null * @param indent positive value */ public static void addWrapAttribute( XMLWriter writer, String tag, String name, String value, int indent ) { if ( StringUtils.isEmpty( value ) ) { return; } if ( indent < 0 ) { writer.addAttribute( name, value ); } else { writer.addAttribute( "\n" + StringUtils.repeat( " ", ( StringUtils.isEmpty( tag ) ? 0 : tag.length() ) + indent * XmlWriterUtil.DEFAULT_INDENTATION_SIZE ) + name, value ); } } /** * @param mavenProject not null * @return true if project packaging equals <code>pom</code> */ public static boolean isPomPackaging( MavenProject mavenProject ) { return "pom".equals( mavenProject.getPackaging() ); } /** * @param mavenProject {@link MavenProject} * @return true if project packaging equals one of several packaging types * including <code>jar</code>, <code>maven-plugin</code>, <code>ejb</code>, or * <code>bundle</code> */ public static boolean isJarPackaging( MavenProject mavenProject ) { return "jar".equals( mavenProject.getPackaging() ) || isEjbPackaging( mavenProject ) || isMavenPluginPackaging( mavenProject ) || isBundlePackaging( mavenProject ); } /** * @param mavenProject {@link MavenProject} * @return true if project packaging equals <code>bundle</code> */ public static boolean isBundlePackaging( MavenProject mavenProject ) { return "bundle".equals( mavenProject.getPackaging() ); } /** * @param mavenProject {@link MavenProject} * @return true if project packaging equals <code>ejb</code> */ public static boolean isEjbPackaging( MavenProject mavenProject ) { return "ejb".equals( mavenProject.getPackaging() ); } /** * @param mavenProject {@link MavenProject} * @return true if project packaging equals <code>maven-plugin</code> */ public static boolean isMavenPluginPackaging( MavenProject mavenProject ) { return "maven-plugin".equals( mavenProject.getPackaging() ); } /** * @param mavenProject {@link MavenProject} * @return true if project packaging equals <code>ear</code> */ public static boolean isEarPackaging( MavenProject mavenProject ) { return "ear".equals( mavenProject.getPackaging() ); } /** * @param mavenProject {@link MavenProject} * @return true if project packaging equals <code>war</code> */ public static boolean isWarPackaging( MavenProject mavenProject ) { return "war".equals( mavenProject.getPackaging() ); } /** * Return the <code>optionName</code> value defined in a project for the "maven-compiler-plugin" plugin. * * @param project {@link MavenProject} not null. * @param optionName the option name wanted * @param defaultValue a default value * @return the value for the option name or the default value. Could be null if not found. * @throws IOException if any */ public static String getMavenCompilerPluginBasicOption( MavenProject project, String optionName, String defaultValue ) throws IOException { return getMavenPluginBasicOption( project, "maven-compiler-plugin", optionName, defaultValue ); } /** * Return the map of <code>optionName</code> value defined in a project for the "maven-compiler-plugin" plugin. * * @param project {@link MavenProject} not null. * @param optionName the option name wanted * @param defaultValue a default value * @return the map for the option name or the default value. Could be null if not found. * @throws IOException if any */ public static Map getMavenCompilerPluginOption( MavenProject project, String optionName, String defaultValue ) throws IOException { return getMavenPluginOption( project, "maven-compiler-plugin", optionName, defaultValue ); } /** * Return an array of map of <code>optionName</code> value defined in a project for the "maven-compiler-plugin" * plugin. * * @param project not null * @param optionName the option name wanted * @param defaultValue a default value * @return the array of option name or the default value. Could be null if not found. * @throws IOException if any */ public static Map[] getMavenCompilerPluginOptions( MavenProject project, String optionName, String defaultValue ) throws IOException { return getMavenPluginOptions( project, "maven-compiler-plugin", optionName, defaultValue ); } /** * Return the <code>optionName</code> value defined in a project for the "maven-surefire-plugin" plugin. * * @param project not null * @param optionName the option name wanted * @param defaultValue a default value * @return the value for the option name or the default value. Could be null if not found. * @throws IOException if any */ public static String getMavenSurefirePluginBasicOption( MavenProject project, String optionName, String defaultValue ) throws IOException { return getMavenPluginBasicOption( project, "maven-surefire-plugin", optionName, defaultValue ); } /** * Return the map of <code>optionName</code> value defined in a project for the "maven-surefire-plugin" plugin. * * @param project not null * @param optionName the option name wanted * @param defaultValue a default value * @return the map for the option name or the default value. Could be null if not found. * @throws IOException if any */ public static Map getMavenSurefirePluginOption( MavenProject project, String optionName, String defaultValue ) throws IOException { return getMavenPluginOption( project, "maven-surefire-plugin", optionName, defaultValue ); } /** * Return an array of map of <code>optionName</code> value defined in a project for the "maven-surefire-plugin" * plugin. * * @param project not null * @param optionName the option name wanted * @param defaultValue a default value * @return the array of option name or the default value. Could be null if not found. * @throws IOException if any */ public static Map[] getMavenSurefirePluginOptions( MavenProject project, String optionName, String defaultValue ) throws IOException { return getMavenPluginOptions( project, "maven-surefire-plugin", optionName, defaultValue ); } /** * Return the <code>optionName</code> value defined in a project for the "maven-javadoc-plugin" plugin. * * @param project not null * @param optionName the option name wanted * @param defaultValue a default value * @return the value for the option name or the default value. Could be null if not found. * @throws IOException if any */ public static String getMavenJavadocPluginBasicOption( MavenProject project, String optionName, String defaultValue ) throws IOException { return getMavenPluginBasicOption( project, "maven-javadoc-plugin", optionName, defaultValue ); } /** * Return a map of <code>optionName</code> value defined in a project for the "maven-javadoc-plugin" plugin. * * @param project not null * @param optionName the option name wanted * @param defaultValue a default value * @return the map for the option name or the default value. Could be null if not found. * @throws IOException if any */ public static Map getMavenJavadocPluginOption( MavenProject project, String optionName, String defaultValue ) throws IOException { return getMavenPluginOption( project, "maven-javadoc-plugin", optionName, defaultValue ); } /** * Return an array of map of <code>optionName</code> value defined in a project for the "maven-javadoc-plugin" * plugin. * * @param project not null * @param optionName the option name wanted * @param defaultValue a default value * @return an array of option name. Could be null if not found. * @throws IOException if any */ public static Map[] getMavenJavadocPluginOptions( MavenProject project, String optionName, String defaultValue ) throws IOException { return getMavenPluginOptions( project, "maven-javadoc-plugin", optionName, defaultValue ); } /** * Return the <code>optionName</code> value defined in a project for the "maven-jar-plugin" plugin. * * @param project not null * @param optionName the option name wanted * @param defaultValue a default value * @return the value for the option name or the default value. Could be null if not found. * @throws IOException if any */ public static String getMavenJarPluginBasicOption( MavenProject project, String optionName, String defaultValue ) throws IOException { return getMavenPluginBasicOption( project, "maven-jar-plugin", optionName, defaultValue ); } /** * Return the <code>optionName</code> value defined in a project for the "maven-ear-plugin" plugin. * * @param project not null * @param optionName the option name wanted * @param defaultValue a default value * @return the value for the option name or the default value. Could be null if not found. * @throws IOException if any */ public static String getMavenEarPluginBasicOption( MavenProject project, String optionName, String defaultValue ) throws IOException { return getMavenPluginBasicOption( project, "maven-ear-plugin", optionName, defaultValue ); } /** * Return the <code>optionName</code> value defined in a project for the "maven-war-plugin" plugin. * * @param project not null * @param optionName the option name wanted * @param defaultValue a default value * @return the value for the option name or the default value. Could be null if not found. * @throws IOException if any */ public static String getMavenWarPluginBasicOption( MavenProject project, String optionName, String defaultValue ) throws IOException { return getMavenPluginBasicOption( project, "maven-war-plugin", optionName, defaultValue ); } // ---------------------------------------------------------------------- // Convenience methods // ---------------------------------------------------------------------- /** * Return the value for the option <code>optionName</code> defined in a project with the given * <code>artifactId</code> plugin. * <br/> * Example: * <table> * <tr> * <td>Configuration</td> * <td>Result</td> * </tr> * <tr> * <td><pre><option>value</option></pre></td> * <td><pre>value</pre></td> * </tr> * </table> * * @param project not null * @param pluginArtifactId not null * @param optionName an <code>Xpath</code> expression from the plugin <code><configuration/></code> * @param defaultValue could be null * @return the value for the option name or null if not found * @throws IOException if any */ private static String getMavenPluginBasicOption( MavenProject project, String pluginArtifactId, String optionName, String defaultValue ) throws IOException { return (String) getMavenPluginConfigurationsImpl( project, pluginArtifactId, optionName, defaultValue ).get( optionName ); } /** * Return a Map for the option <code>optionName</code> defined in a project with the given * <code>artifactId</code> plugin. * <br/> * Example: * <table> * <tr> * <td>Configuration</td> * <td>Result</td> * </tr> * <tr> * <td><pre> * <option> * <param1>value1</param1> * <param2>value2</param2> * </option> * </pre></td> * <td><pre>{param1=value1, param2=value2}<pre></td> * </tr> * </table> * * @param project not null * @param pluginArtifactId not null * @param optionName an <code>Xpath</code> expression from the plugin <code><configuration/></code> * @param defaultValue could be null * @return the value for the option name or null if not found * @throws IOException if any */ private static Map getMavenPluginOption( MavenProject project, String pluginArtifactId, String optionName, String defaultValue ) throws IOException { return (Map) getMavenPluginConfigurationsImpl( project, pluginArtifactId, optionName, defaultValue ).get( optionName ); } /** * Return an array of Map for the option <code>optionName</code> defined in a project with the given * <code>artifactId</code> plugin. * <br/> * Example: * <table> * <tr> * <td>Configuration</td> * <td>Result</td> * </tr> * <tr> * <td><pre> * <options> * <option> * <param1>value1</param1> * <param2>value2</param2> * </option> * <option> * <param1>value1</param1> * <param2>value2</param2> * </option> * </options> * </pre></td> * <td><pre>[{option=[{param1=value1, param2=value2}]}, {option=[{param1=value1, param2=value2}]<pre></td> * </tr> * </table> * * @param project not null * @param pluginArtifactId not null * @param optionName an <code>Xpath</code> expression from the plugin <code><configuration/></code> * @param defaultValue could be null * @return the value for the option name or null if not found * @throws IOException if any */ private static Map[] getMavenPluginOptions( MavenProject project, String pluginArtifactId, String optionName, String defaultValue ) throws IOException { return (Map[]) getMavenPluginConfigurationsImpl( project, pluginArtifactId, optionName, defaultValue ).get( optionName ); } /** * Return a Map for the option <code>optionName</code> defined in a project with the given * <code>artifactId</code> plugin. * <br/> * Example: * <table> * <tr> * <td>Configuration</td> * <td>Result</td> * </tr> * <tr> * <td><pre><option>value</option></pre></td> * <td><pre>{option=value}</pre></td> * </tr> * <tr> * <td><pre> * <option> * <param1>value1</param1> * <param2>value2</param2> * </option> * </pre></td> * <td><pre>{option={param1=value1, param2=value2}}<pre></td> * </tr> * <tr> * <td><pre> * <options> * <option> * <param1>value1</param1> * <param2>value2</param2> * </option> * <option> * <param1>value1</param1> * <param2>value2</param2> * </option> * </options> * </pre></td> * <td><pre>{options=[{option=[{param1=value1, param2=value2}]}, {option=[{param1=value1, param2=value2}]}]<pre> * </td> * </tr> * </table> * * @param project not null * @param pluginArtifactId not null * @param optionName an <code>Xpath</code> expression from the plugin <code><configuration/></code> * @param defaultValue could be null * @return a map with the options found * @throws IOException if any */ private static Map getMavenPluginConfigurationsImpl( MavenProject project, String pluginArtifactId, String optionName, String defaultValue ) throws IOException { List plugins = new ArrayList(); for ( ReportPlugin reportPlugin1 : project.getModel().getReporting().getPlugins() ) { plugins.add( reportPlugin1 ); } for ( Plugin plugin1 : project.getModel().getBuild().getPlugins() ) { plugins.add( plugin1 ); } if ( project.getBuild().getPluginManagement() != null ) { for ( Plugin plugin : project.getBuild().getPluginManagement().getPlugins() ) { plugins.add( plugin ); } } for ( Object next : plugins ) { Object pluginConf = null; if ( next instanceof Plugin ) { Plugin plugin = (Plugin) next; // using out-of-box Maven plugins if ( !( ( plugin.getGroupId().equals( "org.apache.maven.plugins" ) ) && ( plugin.getArtifactId().equals( pluginArtifactId ) ) ) ) { continue; } pluginConf = plugin.getConfiguration(); } if ( next instanceof ReportPlugin ) { ReportPlugin reportPlugin = (ReportPlugin) next; // using out-of-box Maven plugins if ( !( ( reportPlugin.getGroupId().equals( "org.apache.maven.plugins" ) ) && ( reportPlugin.getArtifactId().equals( pluginArtifactId ) ) ) ) { continue; } pluginConf = reportPlugin.getConfiguration(); } if ( pluginConf == null ) { continue; } try { Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse( new ByteArrayInputStream( pluginConf.toString().getBytes( "UTF-8" ) ) ); NodeList nodeList = XPathAPI.eval( doc, "//configuration/" + optionName ).nodelist(); if ( nodeList.getLength() > 0 ) { Node optionNode = nodeList.item( 0 ); if ( isList( optionNode ) ) { /* * <optionNames> * <optionName> * <param1>value1</param1> * <param2>value2</param2> * </optionName> * </optionNames> */ Map options = new HashMap(); List optionNames = new ArrayList(); NodeList childs = optionNode.getChildNodes(); for ( int i = 0; i < childs.getLength(); i++ ) { Node child = childs.item( i ); if ( child.getNodeType() == Node.ELEMENT_NODE ) { Map<String, Object> option = new HashMap<String, Object>(); if ( isElementContent( child ) ) { Map<String, String> properties = new HashMap<String, String>(); NodeList childs2 = child.getChildNodes(); if ( childs2.getLength() > 0 ) { for ( int j = 0; j < childs2.getLength(); j++ ) { Node child2 = childs2.item( j ); if ( child2.getNodeType() == Node.ELEMENT_NODE ) { properties.put( child2.getNodeName(), getTextContent( child2 ) ); } } option.put( child.getNodeName(), properties ); } } else { option.put( child.getNodeName(), getTextContent( child ) ); } optionNames.add( option ); } } options.put( optionName, optionNames.toArray( new Map[optionNames.size()] ) ); return options; } if ( isElementContent( optionNode ) ) { /* * <optionName> * <param1>value1</param1> * <param2>value2</param2> * </optionName> */ Map option = new HashMap(); NodeList childs = optionNode.getChildNodes(); if ( childs.getLength() > 1 ) { Map parameters = new HashMap(); for ( int i = 0; i < childs.getLength(); i++ ) { Node child = childs.item( i ); if ( child.getNodeType() == Node.ELEMENT_NODE ) { parameters.put( child.getNodeName(), getTextContent( child ) ); } } option.put( optionName, parameters ); } return option; } else { /* * <optionName>value1</optionName> */ Map option = new HashMap(); option.put( optionName, getTextContent( optionNode ) ); return option; } } } catch ( Exception e ) { throw new IOException( "Exception occured: " + e.getMessage() ); } } Map properties = new HashMap(); properties.put( optionName, defaultValue ); return properties; } /** * Write copy tasks in an outputDir for EAR and WAR targets for project depencies without * <code>provided</code> or <code>test</code> as scope * * @param writer not null * @param project not null * @param artifactResolverWrapper not null * @param outputDir not null */ private static void writeCopyLib( XMLWriter writer, MavenProject project, ArtifactResolverWrapper artifactResolverWrapper, String outputDir ) { writer.startElement( "mkdir" ); writer.addAttribute( "dir", outputDir ); writer.endElement(); // mkdir if ( project.getArtifacts() != null ) { for ( Object o : project.getArtifacts() ) { Artifact artifact = (Artifact) o; if ( Artifact.SCOPE_COMPILE.equals( artifact.getScope() ) || Artifact.SCOPE_RUNTIME.equals( artifact.getScope() ) ) { String path = artifactResolverWrapper.getLocalArtifactPath( artifact ); if ( !new File( path ).isAbsolute() ) { path = "${maven.repo.local}/" + path; } writer.startElement( "copy" ); writer.addAttribute( "file", path ); addWrapAttribute( writer, "copy", "todir", outputDir, 3 ); writer.endElement(); // copy } } } } /** * Check if a given <code>node</code> is a list of nodes or not. * <br/> * For instance, the node <code>options</code> is a list of <code>option</code> in the following case: * <pre> * <options> * <option> * <param1>value1</param1> * <param2>value2</param2> * </option> * <option> * <param1>value1</param1> * <param2>value2</param2> * </option> * </options> * </pre> * * @param node a given node, may be <code>null</code>. * @return true if the node is a list, false otherwise. */ private static boolean isList( Node node ) { if ( node == null ) { return false; } NodeList children = node.getChildNodes(); boolean isList = false; String lastNodeName = null; for ( int i = 0; i < children.getLength(); i++ ) { Node child = children.item( i ); if ( child.getNodeType() == Node.ELEMENT_NODE ) { isList = isList || ( child.getNodeName().equals( lastNodeName ) ); lastNodeName = child.getNodeName(); } } if ( StringUtils.isNotEmpty( lastNodeName ) ) { isList = isList || lastNodeName.equals( getSingularForm( node.getNodeName() ) ); } return isList; } /** * Checks whether the specified node has element content or consists only of character data. * * @param node The node to test, may be <code>null</code>. * @return <code>true</code> if any child node is an element, <code>false</code> otherwise. */ private static boolean isElementContent( Node node ) { if ( node == null ) { return false; } NodeList children = node.getChildNodes(); for ( int i = 0; i < children.getLength(); i++ ) { Node child = children.item( i ); if ( child.getNodeType() == Node.ELEMENT_NODE ) { return true; } } return false; } /** * Gets the text content of the specified node. * * @param node The node whose text contents should be retrieved, may be <code>null</code>. * @return The text content of the node, can be empty but never <code>null</code>. */ private static String getTextContent( Node node ) { StringBuilder buffer = new StringBuilder(); if ( node != null ) { NodeList children = node.getChildNodes(); for ( int i = 0; i < children.getLength(); i++ ) { Node child = children.item( i ); if ( child.getNodeType() == Node.TEXT_NODE || child.getNodeType() == Node.CDATA_SECTION_NODE ) { buffer.append( child.getNodeValue() ); } } } return buffer.toString(); } /** * Gets the singular form of the specified (English) plural form. For example: * <p/> * <pre> * properties -> property * branches -> branch * reports -> report * </pre> * * @param pluralForm The plural form for which to derive the singular form, may be <code>null</code>. * @return The corresponding singular form or an empty string if the input string was not recognized as a plural * form. */ static String getSingularForm( String pluralForm ) { String singularForm = ""; if ( StringUtils.isNotEmpty( pluralForm ) ) { if ( pluralForm.endsWith( "ies" ) ) { singularForm = pluralForm.substring( 0, pluralForm.length() - 3 ) + 'y'; } else if ( pluralForm.endsWith( "ches" ) ) { singularForm = pluralForm.substring( 0, pluralForm.length() - 2 ); } else if ( pluralForm.endsWith( "s" ) && pluralForm.length() > 1 ) { singularForm = pluralForm.substring( 0, pluralForm.length() - 1 ); } } return singularForm; } /** * Relativizes the specified path against the given base directory (if possible). If the specified path is a * subdirectory of the base directory, the base directory prefix will be chopped off. If the specified path is equal * to the base directory, the path "." is returned. Otherwise, the path is returned as is. Examples: * <table border="1"> * <tr> * <td>basedir</td> * <td>path</td> * <td>result</td> * </tr> * <tr> * <td>/home</td> * <td>/home/dir</td> * <td>dir</td> * </tr> * <tr> * <td>/home</td> * <td>/home/dir/</td> * <td>dir/</td> * </tr> * <tr> * <td>/home</td> * <td>/home</td> * <td>.</td> * </tr> * <tr> * <td>/home</td> * <td>/home/</td> * <td>./</td> * </tr> * <tr> * <td>/home</td> * <td>dir</td> * <td>dir</td> * </tr> * </table> * The returned path will always use the forward slash ('/') as the file separator regardless of the current * platform. Also, the result path will have a trailing slash if the input path has a trailing file separator. * * @param basedir The base directory to relativize the path against, must not be <code>null</code>. * @param path The path to relativize, must not be <code>null</code>. * @return The relativized path, never <code>null</code>. */ static String toRelative( File basedir, String path ) { String result = null; if ( new File( path ).isAbsolute() ) { String pathNormalized = path.replace( '/', File.separatorChar ).replace( '\\', File.separatorChar ); result = PathTool.getRelativeFilePath( basedir.getAbsolutePath(), pathNormalized ); } if ( result == null ) { result = path; } result = result.replace( '\\', '/' ); if ( result.length() <= 0 || "/".equals( result ) ) { result = '.' + result; } return result; } }