Commits

Anonymous committed 0e93f37

XW-85: Invalid configuration files were not throwing errors. Configuration file parsing is now using validation. ConfigurationException now extends XworkException, which is a RuntimeException.

git-svn-id: http://svn.opensymphony.com/svn/xwork/trunk@39e221344d-f017-0410-9bd5-d282ab1896d7

Comments (0)

Files changed (9)

src/java/com/opensymphony/xwork/XworkException.java

+package com.opensymphony.xwork;
+
+/**
+ * XworkException
+ * @author Jason Carreira
+ * Created Sep 7, 2003 12:15:03 AM
+ */
+public class XworkException extends RuntimeException {
+    Throwable throwable;
+
+    /**
+     * Constructs a <code>XworkException</code> with no detail  message.
+     */
+    public XworkException() {
+    }
+
+    /**
+     * Constructs a <code>XworkException</code> with the specified
+     * detail message.
+     *
+     * @param   s   the detail message.
+     */
+    public XworkException(String s) {
+        super(s);
+    }
+
+    /**
+     * Constructs a <code>XworkException</code> with no detail  message.
+     */
+    public XworkException(Throwable cause) {
+        this.throwable = cause;
+    }
+
+    /**
+     * Constructs a <code>XworkException</code> with the specified
+     * detail message.
+     *
+     * @param   s   the detail message.
+     */
+    public XworkException(String s, Throwable cause) {
+        super(s);
+        this.throwable = cause;
+    }
+
+    public Throwable getThrowable() {
+        return throwable;
+    }
+
+    /**
+     * Returns a short description of this throwable object.
+     * If this <code>Throwable</code> object was
+     * {@link #Throwable(String) created} with an error message string,
+     * then the result is the concatenation of three strings:
+     * <ul>
+     * <li>The name of the actual class of this object
+     * <li>": " (a colon and a space)
+     * <li>The result of the {@link #getMessage} method for this object
+     * </ul>
+     * If this <code>Throwable</code> object was {@link #Throwable() created}
+     * with no error message string, then the name of the actual class of
+     * this object is returned.
+     *
+     * @return  a string representation of this <code>Throwable</code>.
+     */
+    public String toString() {
+        if (throwable == null) {
+            return super.toString();
+        }
+
+        return super.toString() + " with nested exception " + throwable.toString();
+    }
+}

src/java/com/opensymphony/xwork/config/Configuration.java

 
     void addPackageConfig(String name, PackageConfig packageConfig);
 
+    /**
+     * @throws ConfigurationException
+     */
     void buildRuntimeConfiguration() throws ConfigurationException;
 
     /**
      */
     void destroy();
 
+    /**
+     * @throws ConfigurationException
+     */
     void reload() throws ConfigurationException;
 
     void removePackageConfig(String name);

src/java/com/opensymphony/xwork/config/ConfigurationException.java

  */
 package com.opensymphony.xwork.config;
 
+import com.opensymphony.xwork.XworkException;
+
 
 /**
  * ConfigurationException
  * @author Jason Carreira
  * Created Feb 24, 2003 8:15:08 AM
  */
-public class ConfigurationException extends Exception {
-    //~ Instance fields ////////////////////////////////////////////////////////
-
-    private Throwable throwable;
-
-    //~ Constructors ///////////////////////////////////////////////////////////
-
+public class ConfigurationException extends XworkException {
     /**
-     * Constructs an <code>Exception</code> with no specified detail message.
+     * Constructs a <code>ConfigurationException</code> with no detail  message.
      */
     public ConfigurationException() {
     }
 
     /**
-     * Constructs an <code>Exception</code> with the specified detail message.
+     * Constructs a <code>ConfigurationException</code> with the specified
+     * detail message.
      *
      * @param   s   the detail message.
      */
     }
 
     /**
-     * Constructs an <code>Exception</code> with no specified detail message.
+     * Constructs a <code>ConfigurationException</code> with no detail  message.
      */
-    public ConfigurationException(Throwable throwable) {
-        this.throwable = throwable;
+    public ConfigurationException(Throwable cause) {
+        super(cause);
     }
 
     /**
-     * Constructs an <code>Exception</code> with the specified detail message.
+     * Constructs a <code>ConfigurationException</code> with the specified
+     * detail message.
      *
      * @param   s   the detail message.
      */
-    public ConfigurationException(String s, Throwable throwable) {
-        super(s);
-        this.throwable = throwable;
-    }
-
-    //~ Methods ////////////////////////////////////////////////////////////////
-
-    public void setThrowable(Throwable throwable) {
-        this.throwable = throwable;
-    }
-
-    public Throwable getThrowable() {
-        return throwable;
-    }
-
-    public String toString() {
-        if (throwable == null) {
-            return super.toString();
-        }
-
-        return super.toString() + " with nested exception " + throwable;
+    public ConfigurationException(String s, Throwable cause) {
+        super(s, cause);
     }
 }

src/java/com/opensymphony/xwork/config/ConfigurationManager.java

                 }
             }
 
-            // @todo if a configure does need to be reloaded, it seems reasonable to limit the reload to only that which needs it
             if (reload) {
-                try {
-                    configurationInstance.reload();
-                } catch (ConfigurationException e) {
-                    LOG.error("Caught an exception while reloading the Configuration.", e);
-                }
+                configurationInstance.reload();
             }
         }
     }

src/java/com/opensymphony/xwork/config/providers/InterceptorBuilder.java

     * @throws com.opensymphony.xwork.config.ConfigurationException
     */
     public static Interceptor buildInterceptor(Class interceptorClass, Map params) throws ConfigurationException {
+        String message;
         try {
             Interceptor interceptor = (Interceptor) interceptorClass.newInstance();
             OgnlUtil.setProperties(params, interceptor);
 
             return interceptor;
         } catch (InstantiationException e) {
-            LOG.error("Unable to instantiate an instance of Interceptor class [" + interceptorClass.getName() + "].");
+            message = "Unable to instantiate an instance of Interceptor class [" + interceptorClass.getName() + "].";
         } catch (IllegalAccessException e) {
-            LOG.error("IllegalAccessException while attempting to instantiate an instance of Interceptor class [" + interceptorClass.getName() + "].");
+            message = "IllegalAccessException while attempting to instantiate an instance of Interceptor class [" + interceptorClass.getName() + "].";
         } catch (ClassCastException e) {
-            LOG.error("Class [" + interceptorClass.getName() + "] does not implement com.opensymphony.xwork.interceptor.Interceptor");
+            message = "Class [" + interceptorClass.getName() + "] does not implement com.opensymphony.xwork.interceptor.Interceptor";
         } catch (Exception e) {
             throw new ConfigurationException("Caught Exception while registering Interceptor class " + interceptorClass.getName(), e);
         }
-
-        return null;
+        throw new ConfigurationException(message);
     }
 
     /**
 
                 result.addAll(stackConfig.getInterceptors());
             } else {
-                LOG.error("Got unexpected type for interceptor " + refName);
+                LOG.error("Got unexpected type for interceptor " + refName + ". Got " + referencedConfig);
             }
         }
 

src/java/com/opensymphony/xwork/config/providers/XmlConfigurationProvider.java

 import com.opensymphony.util.ClassLoaderUtil;
 import com.opensymphony.util.FileManager;
 import com.opensymphony.util.TextUtils;
-
 import com.opensymphony.xwork.config.Configuration;
 import com.opensymphony.xwork.config.ConfigurationException;
 import com.opensymphony.xwork.config.ConfigurationProvider;
 import com.opensymphony.xwork.config.entities.PackageConfig;
 import com.opensymphony.xwork.config.entities.ResultConfig;
 import com.opensymphony.xwork.config.entities.ResultTypeConfig;
-
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
-
 import org.xml.sax.EntityResolver;
 import org.xml.sax.ErrorHandler;
 import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
 import org.xml.sax.SAXParseException;
 
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
 import java.io.IOException;
 import java.io.InputStream;
-
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-
 
 /**
  * Looks in the classpath for "xwork.xml" and uses it for the XWork configuration.
     public void destroy() {
     }
 
-    public void init(Configuration configuration) throws ConfigurationException {
+    public void init(Configuration configuration) {
         this.configuration = configuration;
         includedFileNames.clear();
 
         DocumentBuilder db;
 
         try {
-            db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+            dbf.setValidating(true);
+            dbf.setNamespaceAware(true);
+
+            DocumentBuilder builder = dbf.newDocumentBuilder();
             db.setEntityResolver(new EntityResolver() {
                     public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
                         if ("-//OpenSymphony Group//XWork 1.0//EN".equals(publicId)) {
                 });
             db.setErrorHandler(new ErrorHandler() {
                     public void warning(SAXParseException exception) throws SAXException {
-                        LOG.warn(exception.getMessage() + " at (" + exception.getLineNumber() + ":" + exception.getColumnNumber() + ")");
                     }
 
                     public void error(SAXParseException exception) throws SAXException {
                         LOG.error(exception.getMessage() + " at (" + exception.getLineNumber() + ":" + exception.getColumnNumber() + ")");
+                        throw exception;
                     }
 
                     public void fatalError(SAXParseException exception) throws SAXException {
                         LOG.fatal(exception.getMessage() + " at (" + exception.getLineNumber() + ":" + exception.getColumnNumber() + ")");
+                        throw exception;
                     }
                 });
             loadConfigurationFile(configFileName, db);
         } catch (Exception e) {
-            LOG.fatal("Could not load XWork configuration file, failing", e);
-
-            return;
+            LOG.fatal("Could not load XWork configuration file, failing");
+            throw new ConfigurationException("Error loading configuration file " + configFileName, e);
         }
     }
 
     //            addPackage(packageElement);
     //        }
     //    }
-    private void loadConfigurationFile(String fileName, DocumentBuilder db) throws Exception {
+    private void loadConfigurationFile(String fileName, DocumentBuilder db) {
         Document doc = null;
         InputStream is = null;
 
 
             doc = db.parse(is);
         } catch (Exception e) {
-            LOG.error("Caught exception while loading file " + fileName, e);
+            final String s = "Caught exception while loading file " + fileName;
+            LOG.error(s, e);
+            throw new ConfigurationException(s,e);
         } finally {
             if (is != null) {
                 try {

src/test/com/opensymphony/xwork/ActionNestingTest.java

         /**
         * Initializes the configuration object.
         */
-        public void init(Configuration configurationManager) throws ConfigurationException {
+        public void init(Configuration configurationManager) {
             PackageConfig packageContext = new PackageConfig();
             ActionConfig config = new ActionConfig(null, SimpleAction.class, null, null, null);
             packageContext.addActionConfig(SIMPLE_ACTION_NAME, config);

src/test/com/opensymphony/xwork/config/providers/XmlConfigurationProviderInvalidFileTest.java

+package com.opensymphony.xwork.config.providers;
+
+import com.opensymphony.xwork.config.ConfigurationProvider;
+import com.opensymphony.xwork.config.ConfigurationException;
+
+/**
+ * XmlConfigurationProviderInvalidFileTest
+ * @author Jason Carreira
+ * Created Sep 6, 2003 2:36:10 PM
+ */
+public class XmlConfigurationProviderInvalidFileTest extends ConfigurationTestBase {
+    public void testInvalidFileThrowsException() {
+        final String filename = "com/opensymphony/xwork/config/providers/xwork-test-invalid-file.xml";
+        ConfigurationProvider provider = buildConfigurationProvider(filename);
+        try {
+            provider.init(configuration);
+            fail();
+        } catch (ConfigurationException e) {
+            // this is what we expect
+        }
+    }
+}

src/test/com/opensymphony/xwork/config/providers/xwork-test-invalid-file.xml

+        <action name="Foo" class="com.opensymphony.xwork.SimpleAction">
+            <param name="foo">17</param>
+            <param name="bar">23</param>
+            <result name="success" type="chain">
+                <param name="actionName">Bar</param>
+            </result>
+            <interceptor-ref name="debugStack"/>
+            <interceptor-ref name="defaultStack"/>
+        </action>
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.