[MANT-41] mvn ant:ant fails with NPE when maven-javadoc-plugin custom tag is specified in pom.xml
git-svn-id: https://svn.apache.org/repos/asf/maven/plugins/trunk@663768 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/it/javadoc-it/pom.xml b/src/it/javadoc-it/pom.xml
new file mode 100644
index 0000000..7996857
--- /dev/null
+++ b/src/it/javadoc-it/pom.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.apache.maven.plugins.maven-ant-plugin.it</groupId>
+ <artifactId>javadoc-it</artifactId>
+ <version>1.0-SNAPSHOT</version>
+
+ <build>
+ <finalName>${project.artifactId}</finalName>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-ant-plugin</artifactId>
+ <version>@pom.version@</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-clean-plugin</artifactId>
+ <version>2.2</version>
+ <configuration>
+ <filesets>
+ <fileset>
+ <directory>${basedir}</directory>
+ <includes>
+ <include>build.xml</include>
+ <include>maven-build.*</include>
+ </includes>
+ </fileset>
+ </filesets>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <reporting>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <version>2.4</version>
+ <configuration>
+ <tags>
+ <tag>
+ <name>requirement</name>
+ <placement>a</placement>
+ <head>Software Requirement:</head>
+ </tag>
+ </tags>
+ </configuration>
+ </plugin>
+ </plugins>
+ </reporting>
+
+ <properties>
+ <build.compiler>extJavac</build.compiler>
+ </properties>
+
+</project>
diff --git a/src/it/javadoc-it/src/main/java/Main.java b/src/it/javadoc-it/src/main/java/Main.java
new file mode 100644
index 0000000..27ccb83
--- /dev/null
+++ b/src/it/javadoc-it/src/main/java/Main.java
@@ -0,0 +1,3 @@
+public class Main
+{
+}
diff --git a/src/main/java/org/apache/maven/plugin/ant/AntBuildWriterUtil.java b/src/main/java/org/apache/maven/plugin/ant/AntBuildWriterUtil.java
index 8e25c4b..b0aa3c7 100644
--- a/src/main/java/org/apache/maven/plugin/ant/AntBuildWriterUtil.java
+++ b/src/main/java/org/apache/maven/plugin/ant/AntBuildWriterUtil.java
@@ -39,7 +39,6 @@
import org.apache.maven.project.MavenProject;
import org.apache.maven.wagon.PathUtils;
import org.apache.xpath.XPathAPI;
-import org.apache.xpath.objects.XObject;
import org.codehaus.plexus.util.StringUtils;
import org.codehaus.plexus.util.xml.XMLWriter;
import org.codehaus.plexus.util.xml.Xpp3Dom;
@@ -535,10 +534,11 @@
{
for ( int i = 0; i < tags.length; i++ )
{
+ Map props = (Map) tags[i].get( "tag" );
writer.startElement( "tag" );
- writer.addAttribute( "name", (String) tags[i].get( "name" ) );
- addWrapAttribute( writer, "javadoc", "scope", (String) tags[i].get( "placement" ), 4 );
- addWrapAttribute( writer, "javadoc", "description", (String) tags[i].get( "head" ), 4 );
+ 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
}
}
@@ -1131,98 +1131,103 @@
Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder()
.parse( new ByteArrayInputStream( pluginConf.toString().getBytes( "UTF-8" ) ) );
- XObject obj = XPathAPI.eval( doc, "//configuration/" + optionName );
-
- NodeList nodeList = obj.nodelist();
- if ( nodeList.getLength() > 0 && isList( nodeList.item( 0 ) ) )
+ NodeList nodeList = XPathAPI.eval( doc, "//configuration/" + optionName ).nodelist();
+ if ( nodeList.getLength() > 0 )
{
- /*
- * <optionNames>
- * <optionName>
- * <param1>value1</param1>
- * <param2>value2</param2>
- * </optionName>
- * </optionNames>
- */
- Map options = new HashMap();
+ Node optionNode = nodeList.item( 0 );
- List optionNames = new ArrayList();
- NodeList childs = nodeList.item( 0 ).getChildNodes();
- for ( int i = 0; i < childs.getLength(); i++ )
+ if ( isList( optionNode ) )
{
- if ( childs.item( i ).getNodeType() == Node.ELEMENT_NODE )
- {
- Map option = new HashMap();
+ /*
+ * <optionNames>
+ * <optionName>
+ * <param1>value1</param1>
+ * <param2>value2</param2>
+ * </optionName>
+ * </optionNames>
+ */
+ Map options = new HashMap();
- obj = XPathAPI.eval( doc, "//configuration/" + childs.item( i ).getNodeName() );
-
- if ( StringUtils.isNotEmpty( obj.toString() ) )
- {
- Map properties = new HashMap();
- NodeList childs2 = childs.item( i ).getChildNodes();
- if ( childs2.getLength() > 0 )
- {
- for ( int j = 0; j < childs2.getLength(); j++ )
- {
- if ( childs2.item( j ).getNodeType() == Node.ELEMENT_NODE )
- {
- properties.put( childs2.item( j ).getNodeName(), childs2.item( j )
- .getFirstChild().getNodeValue() );
- }
- }
- option.put( childs.item( i ).getNodeName(), properties );
- }
- }
- else
- {
- option.put( childs.item( i ).getNodeName(), childs.item( i ).getFirstChild()
- .getNodeValue() );
- }
-
- optionNames.add( option );
- }
- }
-
- options.put( optionName, optionNames.toArray( new Map[0] ) );
-
- return options;
- }
-
- /*
- * <optionName>
- * <param1>value1</param1>
- * <param2>value2</param2>
- * </optionName>
- */
- if ( StringUtils.isNotEmpty( obj.toString() ) )
- {
- Map option = new HashMap();
-
- NodeList childs = nodeList.item( 0 ).getChildNodes();
- if ( childs.getLength() > 1 )
- {
- Map parameters = new HashMap();
-
+ List optionNames = new ArrayList();
+ NodeList childs = optionNode.getChildNodes();
for ( int i = 0; i < childs.getLength(); i++ )
{
- if ( childs.item( i ).getNodeType() == Node.ELEMENT_NODE )
+ Node child = childs.item( i );
+ if ( child.getNodeType() == Node.ELEMENT_NODE )
{
- parameters.put( childs.item( i ).getNodeName(), childs.item( i ).getFirstChild()
- .getNodeValue() );
+ Map option = new HashMap();
+
+ if ( isElementContent( child ) )
+ {
+ Map properties = new HashMap();
+ 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 );
}
}
- option.put( optionName, parameters );
+ options.put( optionName, optionNames.toArray( new Map[0] ) );
+
+ 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>
*/
- option.put( optionName, obj.toString() );
- }
+ Map option = new HashMap();
- return option;
+ option.put( optionName, getTextContent( optionNode ) );
+
+ return option;
+ }
}
}
catch ( Exception e )
@@ -1286,7 +1291,7 @@
* </options>
* </pre>
*
- * @param node a given node
+ * @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 )
@@ -1296,13 +1301,13 @@
return false;
}
- NodeList childs = node.getChildNodes();
+ NodeList children = node.getChildNodes();
boolean isList = false;
String lastNodeName = null;
- for ( int i = 0; i < childs.getLength(); i++ )
+ for ( int i = 0; i < children.getLength(); i++ )
{
- Node child = childs.item( i );
+ Node child = children.item( i );
if ( child.getNodeType() == Node.ELEMENT_NODE )
{
isList = isList || ( child.getNodeName().equals( lastNodeName ) );
@@ -1318,6 +1323,54 @@
}
/**
+ * 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 )
+ {
+ StringBuffer buffer = new StringBuffer();
+ 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:
*
* <pre>
diff --git a/src/test/java/org/apache/maven/plugin/ant/AntBuildWriterUtilTest.java b/src/test/java/org/apache/maven/plugin/ant/AntBuildWriterUtilTest.java
index 8f5663f..e1b7cb7 100644
--- a/src/test/java/org/apache/maven/plugin/ant/AntBuildWriterUtilTest.java
+++ b/src/test/java/org/apache/maven/plugin/ant/AntBuildWriterUtilTest.java
@@ -21,6 +21,7 @@
import java.io.File;
import java.io.StringWriter;
+import java.util.Map;
import org.apache.maven.embedder.MavenEmbedder;
import org.apache.maven.embedder.MavenEmbedderConsoleLogger;
@@ -164,6 +165,16 @@
assertNotNull( AntBuildWriterUtil.getMavenJavadocPluginOptions( project, "docletArtifacts", null ) );
assertEquals( AntBuildWriterUtil.getMavenJavadocPluginOptions( project, "docletArtifacts", null ).length, 2 );
+ Map[] options = AntBuildWriterUtil.getMavenJavadocPluginOptions( project, "tags", null );
+ assertNotNull( options );
+ assertEquals( options.length, 1 );
+ assertEquals( 1, options[0].size() );
+ Map properties = (Map) options[0].get( "tag" );
+ assertNotNull( properties );
+ assertEquals( "requirement", properties.get( "name" ) );
+ assertEquals( "a", properties.get( "placement" ) );
+ assertEquals( "Software Requirement:", properties.get( "head" ) );
+
maven.stop();
}
diff --git a/src/test/resources/unit/ant-javadoc-test/pom.xml b/src/test/resources/unit/ant-javadoc-test/pom.xml
index c37f71f..17199d7 100644
--- a/src/test/resources/unit/ant-javadoc-test/pom.xml
+++ b/src/test/resources/unit/ant-javadoc-test/pom.xml
@@ -111,7 +111,13 @@
<version>4.5</version>
</docletArtifact>
</docletArtifacts>
-
+ <tags>
+ <tag>
+ <name>requirement</name>
+ <placement>a</placement>
+ <head>Software Requirement:</head>
+ </tag>
+ </tags>
</configuration>
</plugin>
</plugins>