[MCHANGES-354] The plugin should fail to execute if the changes.xml file cannot be parsed
 Submitted by: Gabor Szabo
 Patch applied without changes.


git-svn-id: https://svn.apache.org/repos/asf/maven/plugins/trunk@1685874 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/main/java/org/apache/maven/plugin/changes/ChangesXML.java b/src/main/java/org/apache/maven/plugin/changes/ChangesXML.java
index 337e65d..308bfc3 100644
--- a/src/main/java/org/apache/maven/plugin/changes/ChangesXML.java
+++ b/src/main/java/org/apache/maven/plugin/changes/ChangesXML.java
@@ -19,11 +19,6 @@
  * under the License.
  */
 
-import java.io.File;
-import java.io.FileInputStream;
-import java.util.Collections;
-import java.util.List;
-
 import org.apache.maven.plugin.logging.Log;
 import org.apache.maven.plugins.changes.model.Body;
 import org.apache.maven.plugins.changes.model.ChangesDocument;
@@ -31,6 +26,11 @@
 import org.apache.maven.plugins.changes.model.io.xpp3.ChangesXpp3Reader;
 import org.codehaus.plexus.util.IOUtil;
 
+import java.io.File;
+import java.io.FileInputStream;
+import java.util.Collections;
+import java.util.List;
+
 /**
  * A facade for a changes.xml file.
  *
@@ -39,17 +39,28 @@
 public class ChangesXML
 {
 
+    /** The list of releases in the changes.xml file. */
     private List releaseList;
 
+    /** The author in the changes.xml file. */
     private String author;
 
+    /** The title of the changes.xml file. */
     private String title;
 
+    /** The e-mail address of the author in the changes.xml file. */
     private String authorEmail;
 
+    /** The changes.xml document. */
     private ChangesDocument changesDocument;
 
-    public ChangesXML( File xmlPath, Log log )
+    /**
+     * Constructor that sets the changes.xml file and the logger.
+     * @param xmlPath the changes.xml file
+     * @param log the logger
+     * @throws ChangesXMLRuntimeException if there was a fatal error while parsing the changes.xml file
+     */
+    public ChangesXML( File xmlPath, Log log ) throws ChangesXMLRuntimeException
     {
 
         if ( xmlPath == null || !xmlPath.exists() )
@@ -98,8 +109,8 @@
         }
         catch ( Throwable e )
         {
-            // FIXME throw an Exception ?
             log.error( "An error occurred when parsing the changes.xml file: ", e );
+            throw new ChangesXMLRuntimeException( "An error occurred when parsing the changes.xml file", e );
         }
         finally
         {
@@ -107,46 +118,82 @@
         }
     }
 
+    /**
+     * Sets the {@link ChangesXML#author} attribute.
+     * @param author the new value of the {@link ChangesXML#author} attribute
+     */
     public void setAuthor( String author )
     {
         this.author = author;
     }
 
+    /**
+     * Returns the current value of the author attribute.
+     * @return the current value of the author attribute
+     */
     public String getAuthor()
     {
         return author;
     }
 
+    /**
+     * Sets the {@link ChangesXML#releaseList} attribute.
+     * @param releaseList the new value of the {@link ChangesXML#releaseList} attribute
+     */
     public void setReleaseList( List releaseList )
     {
         this.releaseList = releaseList;
     }
 
+    /**
+     * Returns the current value of the {@link ChangesXML#releaseList} attribute.
+     * @return the current value of the {@link ChangesXML#releaseList} attribute
+     */
     public List getReleaseList()
     {
         return releaseList == null ? Collections.EMPTY_LIST : releaseList;
     }
 
+    /**
+     * Sets the {@link ChangesXML#title} attribute.
+     * @param title the new value of the {@link ChangesXML#title} attribute
+     */
     public void setTitle( String title )
     {
         this.title = title;
     }
 
+    /**
+     * Returns the current value of the {@link ChangesXML#title} attribute.
+     * @return the current value of the {@link ChangesXML#title} attribute
+     */
     public String getTitle()
     {
         return title;
     }
 
+    /**
+     Returns the current value of the {@link ChangesXML#changesDocument} attribute.
+     * @return the current value of the {@link ChangesXML#changesDocument} attribute
+     */
     public ChangesDocument getChangesDocument()
     {
         return changesDocument;
     }
 
+    /**
+     * Returns the current value of the {@link ChangesXML#authorEmail} attribute.
+     * @return the current value of the {@link ChangesXML#authorEmail} attribute
+     */
     public String getAuthorEmail()
     {
         return authorEmail;
     }
 
+    /**
+     * Sets the {@link ChangesXML#authorEmail} attribute.
+     * @param authorEmail the new value of the {@link ChangesXML#authorEmail} attribute
+     */
     public void setAuthorEmail( String authorEmail )
     {
         this.authorEmail = authorEmail;
diff --git a/src/main/java/org/apache/maven/plugin/changes/ChangesXMLRuntimeException.java b/src/main/java/org/apache/maven/plugin/changes/ChangesXMLRuntimeException.java
new file mode 100644
index 0000000..62ea50b
--- /dev/null
+++ b/src/main/java/org/apache/maven/plugin/changes/ChangesXMLRuntimeException.java
@@ -0,0 +1,55 @@
+package org.apache.maven.plugin.changes;
+
+/*
+ * 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.
+ */
+
+/**
+ * This is a runtime exception class that is thrown by the
+ * {@link ChangesXML#ChangesXML(java.io.File, org.apache.maven.plugin.logging.Log)} constructor if the given
+ * changes.xml file cannot be parsed, for example it is not well-formed or valid.
+ *
+ * @author <a href="mailto:szgabsz91@gmail.com">Gabor Szabo</a>
+ */
+public class ChangesXMLRuntimeException
+    extends RuntimeException
+{
+    /** The serialVersionUID **/
+    private static final long serialVersionUID = -8059557047280992301L;
+
+    /**
+     * Default constructor that sets the message.
+     *
+     * @param msg the exception message.
+     */
+    public ChangesXMLRuntimeException( String msg )
+    {
+        super( msg );
+    }
+
+    /**
+     * Constructor that sets the message and the cause of the exception.
+     *
+     * @param msg the exception message.
+     * @param cause the cause.
+     */
+    public ChangesXMLRuntimeException( String msg, Throwable cause )
+    {
+        super( msg, cause );
+    }
+}
diff --git a/src/test/java/org/apache/maven/plugin/changes/ChangesXMLTest.java b/src/test/java/org/apache/maven/plugin/changes/ChangesXMLTest.java
index 7c20ed2..978ddbc 100644
--- a/src/test/java/org/apache/maven/plugin/changes/ChangesXMLTest.java
+++ b/src/test/java/org/apache/maven/plugin/changes/ChangesXMLTest.java
@@ -19,17 +19,16 @@
  * under the License.
  */
 
-import java.io.File;
-import java.util.List;
-
 import org.apache.maven.plugin.logging.Log;
 import org.apache.maven.plugins.changes.model.Action;
-import org.apache.maven.plugins.changes.model.FixedIssue;
 import org.apache.maven.plugins.changes.model.Release;
 import org.codehaus.plexus.PlexusTestCase;
 import org.codehaus.plexus.logging.Logger;
 import org.codehaus.plexus.logging.console.ConsoleLogger;
 
+import java.io.File;
+import java.util.List;
+
 /**
  * @author Olivier Lamy
  * @since 27 juil. 2008
@@ -57,13 +56,11 @@
         public void debug( Throwable error )
         {
             consoleLogger.debug( error.getMessage() );
-
         }
 
         public void debug( CharSequence content, Throwable error )
         {
             consoleLogger.debug( error.getMessage(), error );
-
         }
 
         public void error( CharSequence content )
@@ -79,7 +76,6 @@
         public void error( CharSequence content, Throwable error )
         {
             consoleLogger.error( error.getMessage(), error );
-
         }
 
         public void info( CharSequence content )
@@ -125,13 +121,11 @@
         public void warn( Throwable error )
         {
             consoleLogger.warn( error.getMessage() );
-
         }
 
         public void warn( CharSequence content, Throwable error )
         {
             consoleLogger.warn( content.toString(), error );
-
         }
 
     }
@@ -146,16 +140,35 @@
 
         List releases = changesXML.getReleaseList();
         assertEquals( 2, releases.size() );
-        for (Object release1 : releases) {
+        for ( Object release1 : releases ) {
             Release release = (Release) release1;
-            if ("1.0".equals(release.getVersion())) {
-                Action action = release.getActions().get(0);
-                assertEquals(2, action.getFixedIssues().size());
-                assertEquals("JIRA-XXX", action.getFixedIssues().get(0).getIssue());
-                assertEquals("JIRA-YYY", action.getFixedIssues().get(1).getIssue());
-                assertEquals(2, action.getDueTos().size());
+            if ( "1.0".equals( release.getVersion() ) ) {
+                Action action = release.getActions().get( 0 );
+                assertEquals( 2, action.getFixedIssues().size() );
+                assertEquals( "JIRA-XXX", action.getFixedIssues().get( 0 ).getIssue() );
+                assertEquals( "JIRA-YYY", action.getFixedIssues().get( 1 ).getIssue() );
+                assertEquals( 2, action.getDueTos().size() );
             }
         }
     }
-    
+
+    public void testParseInvalidChangesFile()
+    {
+        File changesFile = new File( getBasedir() + "/src/test/unit/invalid-changes.xml" );
+
+        try
+        {
+            ChangesXML changesXML = new ChangesXML( changesFile, new MockLog() );
+            fail( "Should have thrown a ChangesXMLRuntimeException due to the invalid changes.xml file" );
+        }
+        catch ( ChangesXMLRuntimeException e )
+        {
+            assertEquals( "An error occurred when parsing the changes.xml file", e.getMessage() );
+        }
+        catch ( Throwable e )
+        {
+            fail( "Wrong type of Throwable object was thrown, expected ChangesXMLRuntimeException" );
+        }
+    }
+
 }
diff --git a/src/test/unit/invalid-changes.xml b/src/test/unit/invalid-changes.xml
new file mode 100644
index 0000000..1702fa8
--- /dev/null
+++ b/src/test/unit/invalid-changes.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+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.
+-->
+<document xmlns="http://maven.apache.org/changes/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xsi:schemaLocation="http://maven.apache.org/changes/1.0.0 http://maven.apache.org/xsd/changes-1.0.0.xsd">
+    <body>
+        <release version="1.0" date="2015-06-15">
+            <action dev="me" type="add">
+                This is my first & last addition.
+            </action>
+        </release>
+    </body>
+</document>