dev@javaserverfaces.java.net

[REVIEW] Proposed fix for issue 197

From: Ryan Lubke <Ryan.Lubke_at_Sun.COM>
Date: Tue, 15 Nov 2005 07:40:22 -0800

https://javaserverfaces.dev.java.net/issues/show_bug.cgi?id=197

Instead of producing an error message like:

Parse Error at line 2 column 59: cvc-elt.1: Cannot find the declaration of
element 'faces-config'.

Register a custom ErrorHandler implementation to rethrow
the exception passed to the ErrorHandler.error() callback.
This triggers the message in ConfigureListener so the user
can have feedback on which file is causing the problem.

Which will result in:

Can't parse configuration file: /some/dir/faces-config.xml: Error at line
2 column 59: Cannot find the declaration of element 'faces-config'.
                  

SECTION: Modified Files
----------------------------
M jsf-ri/src/com/sun/faces/config/ConfigureListener.java
 - update parse() method to include line and column
   information
 - update returned error message

M jsf-ri/src/javax/faces/Messages.properties
M jsf-ri/src/javax/faces/Messages_de.properties
M jsf-ri/src/javax/faces/Messages_en.properties
M jsf-ri/src/javax/faces/Messages_es.properties
M jsf-ri/src/javax/faces/Messages_fr.properties
 - updated messages

M jsf-ri/systest-per-webapp/build-tests.xml
 - commented out view-expired systest. Need to work on connection
   reset issue.

M jsf-tools/src/com/sun/faces/config/DigesterFactory.java
  - Add custom error handler that throws exception passed
    to error and fatalError callbacks.
 - Set digester logger to NoOpLog to reduce the number
   of duplicated messages their default logging produces.


SECTION: Diffs
----------------------------
Index: jsf-ri/src/com/sun/faces/config/ConfigureListener.java
===================================================================
RCS file:
/cvs/javaserverfaces-sources/jsf-ri/src/com/sun/faces/config/ConfigureListener.java,v
retrieving revision 1.54
diff -u -r1.54 ConfigureListener.java
--- jsf-ri/src/com/sun/faces/config/ConfigureListener.java 25 Oct
2005 20:39:55 -0000 1.54
+++ jsf-ri/src/com/sun/faces/config/ConfigureListener.java 15 Nov
2005 15:30:57 -0000
@@ -105,6 +105,7 @@
 import org.xml.sax.Attributes;
 import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
 import org.xml.sax.helpers.DefaultHandler;
 
 import java.util.logging.Logger;
@@ -1554,24 +1555,34 @@
             conn.setUseCaches(false);
             stream = conn.getInputStream();
             source = new InputSource(url.toExternalForm());
- source.setByteStream(stream);
+ source.setSystemId(url.toExternalForm());
+ source.setByteStream(stream);
             digester.clear();
             digester.push(fcb);
- digester.parse(source);
+ digester.parse(source);
         } catch (Exception e) {
+ int ln = -1;
+ int cn = -1;
+ if (e instanceof SAXParseException) {
+ SAXParseException spe = (SAXParseException) e;
+ ln = spe.getLineNumber();
+ cn = spe.getColumnNumber();
+ }
             String message = null;
             try {
                 message = Util.getExceptionMessageString
                     (Util.CANT_PARSE_FILE_ERROR_MESSAGE_ID,
- new Object[]{url.toExternalForm()});
+ new Object[]{url.toExternalForm(),
+ ln,
+ cn,
+ e.getMessage()});
             } catch (Exception ee) {
- message = "Can't parse configuration file:" +
- url.toExternalForm();
+ message = "Can't parse configuration file: "
+ + url.toExternalForm() + ": Error at line "
+ + ln + " column " + cn
+ + ": " + e.getMessage();
             }
- if (logger.isLoggable(Level.WARNING)) {
- logger.log(Level.WARNING, message, e);
- }
- throw new FacesException(message, e);
+ throw new FacesException(message);
         } finally {
             if (stream != null) {
                 try {
Index: jsf-ri/src/javax/faces/Messages.properties
===================================================================
RCS file:
/cvs/javaserverfaces-sources/jsf-ri/src/javax/faces/Messages.properties,v
retrieving revision 1.33
diff -u -r1.33 Messages.properties
--- jsf-ri/src/javax/faces/Messages.properties 2 Nov 2005 17:47:26
-0000 1.33
+++ jsf-ri/src/javax/faces/Messages.properties 15 Nov 2005 15:30:57 -0000
@@ -110,7 +110,7 @@
 com.sun.faces.CANT_CREATE_LIFECYCLE_ERROR=Can''t create Lifecycle for
id: ''{0}''.
 com.sun.faces.CANT_INSTANTIATE_CLASS=Can''t instantiate class: ''{0}''.
 com.sun.faces.CANT_INTROSPECT_CLASS=Can''t introspect class: ''{0}''
-com.sun.faces.CANT_PARSE_FILE=Can''t parse file: ''{0}''.
+com.sun.faces.CANT_PARSE_FILE=Can''t parse file: ''{0}'': Error at line
{1} column {2}: {3}.
 com.sun.faces.CHILD_NOT_OF_EXPECTED_TYPE="Expected a child component
type of ''{0}'' for component type ''{1}({2})''.
 com.sun.faces.COMPONENT_NOT_FOUND_ERROR=Component Not Found for
identifier: ''{0}''.
 com.sun.faces.COMPONENT_NOT_FOUND_IN_VIEW_WARNING=Unable to find
component with ID ''{0}'' in view.
Index: jsf-ri/src/javax/faces/Messages_de.properties
===================================================================
RCS file:
/cvs/javaserverfaces-sources/jsf-ri/src/javax/faces/Messages_de.properties,v
retrieving revision 1.29
diff -u -r1.29 Messages_de.properties
--- jsf-ri/src/javax/faces/Messages_de.properties 2 Nov 2005 17:47:26
-0000 1.29
+++ jsf-ri/src/javax/faces/Messages_de.properties 15 Nov 2005
15:30:57 -0000
@@ -111,7 +111,7 @@
 com.sun.faces.ILLEGAL_MODEL_REFERENCE=Illegal Model Reference in this
context for expression ''{0}''.
 com.sun.faces.ATTRIBUTE_NOT_SUPORTED=Attribute ''{0}'' not supported
for component type ''{1}''.
 com.sun.faces.FILE_NOT_FOUND=File ''{0}'' nicht gefunden
-com.sun.faces.CANT_PARSE_FILE=Can''t parse file: ''{0}''.
+com.sun.faces.CANT_PARSE_FILE=Can''t parse file: ''{0}'': Error at line
{1} column {2}: {3}.
 com.sun.faces.CANT_INSTANTIATE_CLASS=Can''t instantiate class: ''{0}''.
 com.sun.faces.ILLEGAL_CHARACTERS_ERROR=Characters not allowed.
 com.sun.faces.NOT_NESTED_IN_FACES_TAG_ERROR=Not nested in a FacesTag
Error for tag with handler class: ''{0}''.
Index: jsf-ri/src/javax/faces/Messages_en.properties
===================================================================
RCS file:
/cvs/javaserverfaces-sources/jsf-ri/src/javax/faces/Messages_en.properties,v
retrieving revision 1.2
diff -u -r1.2 Messages_en.properties
--- jsf-ri/src/javax/faces/Messages_en.properties 2 Nov 2005 17:47:27
-0000 1.2
+++ jsf-ri/src/javax/faces/Messages_en.properties 15 Nov 2005
15:30:57 -0000
@@ -110,7 +110,7 @@
 com.sun.faces.CANT_CREATE_LIFECYCLE_ERROR=Can''t create Lifecycle for
id: ''{0}''.
 com.sun.faces.CANT_INSTANTIATE_CLASS=Can''t instantiate class: ''{0}''.
 com.sun.faces.CANT_INTROSPECT_CLASS=Can''t introspect class: ''{0}''
-com.sun.faces.CANT_PARSE_FILE=Can''t parse file: ''{0}''.
+com.sun.faces.CANT_PARSE_FILE=Can''t parse file: ''{0}'': Error at line
{1} column {2}: {3}.
 com.sun.faces.CHILD_NOT_OF_EXPECTED_TYPE="Expected a child component
type of ''{0}'' for component type ''{1}({2})''.
 com.sun.faces.COMPONENT_NOT_FOUND_ERROR=Component Not Found for
identifier: ''{0}''.
 com.sun.faces.COMPONENT_NOT_FOUND_IN_VIEW_WARNING=Unable to find
component with ID ''{0}'' in view.
Index: jsf-ri/src/javax/faces/Messages_es.properties
===================================================================
RCS file:
/cvs/javaserverfaces-sources/jsf-ri/src/javax/faces/Messages_es.properties,v
retrieving revision 1.29
diff -u -r1.29 Messages_es.properties
--- jsf-ri/src/javax/faces/Messages_es.properties 2 Nov 2005 17:47:27
-0000 1.29
+++ jsf-ri/src/javax/faces/Messages_es.properties 15 Nov 2005
15:30:57 -0000
@@ -111,7 +111,7 @@
 com.sun.faces.ILLEGAL_MODEL_REFERENCE=Ilegal Referencia de Modelo:
Expresi\u00f3n de ModelReference ''{0}'' en esto contexto es ilegal.
 com.sun.faces.ATTRIBUTE_NOT_SUPORTED=Atributo ''{0}'' no es apoyado
para el tipo de componente ''{1}''.
 com.sun.faces.FILE_NOT_FOUND=File ''{0}'' no encontrado.
-com.sun.faces.CANT_PARSE_FILE=Can''t parse file: ''{0}''.
+com.sun.faces.CANT_PARSE_FILE=Can''t parse file: ''{0}'': Error at line
{1} column {2}: {3}.
 com.sun.faces.CANT_INSTANTIATE_CLASS=Can''t instantiate class: ''{0}''.
 com.sun.faces.ILLEGAL_CHARACTERS_ERROR=Characters not allowed.
 com.sun.faces.NOT_NESTED_IN_FACES_TAG_ERROR=Not nested in a FacesTag
Error for tag with handler class: ''{0}''.
Index: jsf-ri/src/javax/faces/Messages_fr.properties
===================================================================
RCS file:
/cvs/javaserverfaces-sources/jsf-ri/src/javax/faces/Messages_fr.properties,v
retrieving revision 1.28
diff -u -r1.28 Messages_fr.properties
--- jsf-ri/src/javax/faces/Messages_fr.properties 2 Nov 2005 17:47:27
-0000 1.28
+++ jsf-ri/src/javax/faces/Messages_fr.properties 15 Nov 2005
15:30:57 -0000
@@ -110,7 +110,7 @@
 com.sun.faces.ILLEGAL_MODEL_REFERENCE=L''expression ''{0}'' du
mod\u00e9le de r\u00e9f\u00e9rence est ill\u00e9gale dans ce contexte.
 com.sun.faces.ATTRIBUTE_NOT_SUPORTED=L''attribut ''{0}'' n''est pas
support\u00e9 pour la composante de type ''{1}''.
 com.sun.faces.FILE_NOT_FOUND=File ''{0}'' ne peut ''tre trouv\u00e9e.
-com.sun.faces.CANT_PARSE_FILE=Can''t parse file: ''{0}''.
+com.sun.faces.CANT_PARSE_FILE=Can''t parse file: ''{0}'': Error at line
{1} column {2}: {3}.
 com.sun.faces.CANT_INSTANTIATE_CLASS=Can''t instantiate class: ''{0}''.
 com.sun.faces.ILLEGAL_CHARACTERS_ERROR=Characters not allowed.
 com.sun.faces.NOT_NESTED_IN_FACES_TAG_ERROR=Not nested in a FacesTag
Error for tag with handler class: ''{0}''.
Index: jsf-ri/systest-per-webapp/build-tests.xml
===================================================================
RCS file:
/cvs/javaserverfaces-sources/jsf-ri/systest-per-webapp/build-tests.xml,v
retrieving revision 1.18
diff -u -r1.18 build-tests.xml
--- jsf-ri/systest-per-webapp/build-tests.xml 10 Nov 2005 19:06:53
-0000 1.18
+++ jsf-ri/systest-per-webapp/build-tests.xml 15 Nov 2005 15:30:57 -0000
@@ -139,7 +139,8 @@
       <param name="testcase"
value="com/sun/faces/systest/ReplaceLifecycleTestCase.class"/>
 
     </antcall>
-
+ <!-- Comment out until connection reset can be consistently
+ eliminated
     <antcall target="test.webapp">
       <param name="webapp.build.home"
              value="${basedir}/view-expired/build" />
@@ -149,8 +150,7 @@
              value="${basedir}/view-expired/src/java" />
       <param name="context.path" value="/jsf-view-expired"/>
       <param name="testcase"
value="com/sun/faces/systest/ViewExpiredExceptionTestCase.class"/>
-
- </antcall>
+ </antcall> -->
 
 <!-- PENDING: return to running
     <antcall target="test.webapp">
Index: jsf-tools/src/com/sun/faces/config/DigesterFactory.java
===================================================================
RCS file:
/cvs/javaserverfaces-sources/jsf-tools/src/com/sun/faces/config/DigesterFactory.java,v
retrieving revision 1.7
diff -u -r1.7 DigesterFactory.java
--- jsf-tools/src/com/sun/faces/config/DigesterFactory.java 22 Aug
2005 22:12:15 -0000 1.7
+++ jsf-tools/src/com/sun/faces/config/DigesterFactory.java 15 Nov
2005 15:30:57 -0000
@@ -30,20 +30,24 @@
 
 package com.sun.faces.config;
 
-import com.sun.faces.util.ToolsUtil;
+import javax.xml.parsers.ParserConfigurationException;
+
+import java.net.URL;
+import java.util.HashMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
 import org.apache.commons.digester.Digester;
+import org.apache.commons.logging.impl.NoOpLog;
+import org.xml.sax.ErrorHandler;
 import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
 import org.xml.sax.SAXNotRecognizedException;
 import org.xml.sax.SAXNotSupportedException;
+import org.xml.sax.SAXParseException;
 import org.xml.sax.helpers.DefaultHandler;
 
-import javax.xml.parsers.ParserConfigurationException;
-
-import java.net.URL;
-import java.util.HashMap;
-import java.util.logging.Level;
-import java.util.logging.Logger;
+import com.sun.faces.util.ToolsUtil;
 
 /**
  * <p>A simple factory to hide <code>Digester</code> configuration
@@ -81,6 +85,11 @@
     private static final JsfEntityResolver RESOLVER = new
JsfEntityResolver();
 
     /**
+ * <p>Custom <code>ErrorHandler</code>.</p>
+ */
+ private static final JsfErrorHandler ERROR_HANDLER = new
JsfErrorHandler();
+
+ /**
      * <p>Indicates whether or not document validation is
      * requested or not.</p>
      */
@@ -164,6 +173,9 @@
         digester.setNamespaceAware(true);
         digester.setUseContextClassLoader(true);
         digester.setEntityResolver(RESOLVER);
+ digester.setErrorHandler(ERROR_HANDLER);
+ // disable digester log messages
+ digester.setLogger(new NoOpLog());
 
         if (validating) {
 
@@ -370,5 +382,19 @@
         } // END resolveEntity
 
     } // END JsfEntityResolver
+
+ private static class JsfErrorHandler implements ErrorHandler {
+ public void warning(SAXParseException exception) throws
SAXException {
+ // do nothing
+ }
+
+ public void error(SAXParseException exception) throws
SAXException {
+ throw exception;
+ }
+
+ public void fatalError(SAXParseException exception) throws
SAXException {
+ throw exception;
+ }
+ }
 
 }