Author: mrdon
Date: Sat Mar 19 17:36:59 2005
New Revision: 158266

URL: http://svn.apache.org/viewcvs?view=rev&rev=158266
Log:
Fixed processing of config files to use common method that supports multiple
instances of a file name within the classpath.  This allows a given module, 
for example, to have multiple jars, each having a META-INF/struts-config.xml,
to define their mappings.  This also ensures the processing of chain and
module config files will be consistent.

PR: 28051

Modified:
    struts/core/trunk/src/share/org/apache/struts/action/ActionServlet.java
    struts/core/trunk/src/test/org/apache/struts/action/TestActionServlet.java

Modified: 
struts/core/trunk/src/share/org/apache/struts/action/ActionServlet.java
URL: 
http://svn.apache.org/viewcvs/struts/core/trunk/src/share/org/apache/struts/action/ActionServlet.java?view=diff&r1=158265&r2=158266
==============================================================================
--- struts/core/trunk/src/share/org/apache/struts/action/ActionServlet.java 
(original)
+++ struts/core/trunk/src/share/org/apache/struts/action/ActionServlet.java Sat 
Mar 19 17:36:59 2005
@@ -25,6 +25,7 @@
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.ArrayList;
+import java.util.List;
 import java.util.Enumeration;
 import java.util.Iterator;
 import java.util.MissingResourceException;
@@ -673,26 +674,14 @@
         // Configure the Digester instance we will use
         Digester digester = initConfigDigester();
 
-        // Process each specified resource path
-        while (paths.length() > 0) {
+        List urls = splitAndResolvePaths(paths);
+        URL url = null;
+        for (Iterator i = urls.iterator(); i.hasNext(); ) {
+            url = (URL)i.next();
             digester.push(config);
-            String path = null;
-            int comma = paths.indexOf(',');
-            if (comma >= 0) {
-                path = paths.substring(0, comma).trim();
-                paths = paths.substring(comma + 1);
-            } else {
-                path = paths.trim();
-                paths = "";
-            }
-
-            if (path.length() < 1) {
-                break;
-            }
-
-            this.parseModuleConfigFile(digester, path);
+            this.parseModuleConfigFile(digester, url);
         }
-
+        
         getServletContext().setAttribute(
             Globals.MODULE_KEY + config.getPrefix(),
             config);
@@ -718,37 +707,51 @@
      *
      * @throws UnavailableException if file cannot be read or parsed
      * @since Struts 1.2
+     * @deprecated use parseModuleConfigFile(Digester digester, URL url) 
+     * instead
      */
     protected void parseModuleConfigFile(Digester digester, String path)
         throws UnavailableException {
 
-        InputStream input = null;
         try {
-            URL url = getServletContext().getResource(path);
-
-            // If the config isn't in the servlet context, try the class loader
-            // which allows the config files to be stored in a jar
-            if (url == null) {
-                url = getClass().getResource(path);
-            }
-            
-            if (url == null) {
-                String msg = internal.getMessage("configMissing", path);
-                log.error(msg);
-                throw new UnavailableException(msg);
+            List paths = splitAndResolvePaths(path);
+            if (paths.size() > 0) {
+                // Get first path as was the old behavior
+                URL url = (URL)paths.get(0);
+                parseModuleConfigFile(digester, url);
+            } else {
+                throw new UnavailableException("Cannot locate path "+path);
             }
-           
+        } catch (UnavailableException ex) {
+            throw ex;
+        } catch (ServletException ex) {
+            handleConfigException(path, ex);
+        }
+    }
+    
+    /**
+     * <p>Parses one module config file.</p>
+     *
+     * @param digester Digester instance that does the parsing
+     * @param url The url to the config file to parse.
+     *
+     * @throws UnavailableException if file cannot be read or parsed
+     * @since Struts 1.3
+     */
+    protected void parseModuleConfigFile(Digester digester, URL url)
+        throws UnavailableException {
+
+        InputStream input = null;
+        try {
             InputSource is = new InputSource(url.toExternalForm());
             input = url.openStream();
             is.setByteStream(input);
             digester.parse(is);
 
-        } catch (MalformedURLException e) {
-            handleConfigException(path, e);
         } catch (IOException e) {
-            handleConfigException(path, e);
+            handleConfigException(url.toString(), e);
         } catch (SAXException e) {
-            handleConfigException(path, e);
+            handleConfigException(url.toString(), e);
         } finally {
             if (input != null) {
                 try {
@@ -1020,56 +1023,14 @@
             if (value != null) {
                 chainConfig = value;
             }
-         
-            ClassLoader loader =
-                Thread.currentThread().getContextClassLoader();
-            if (loader == null) {    
-                loader = this.getClass().getClassLoader();
-            }
- 
-            URL resource = null;
-            String path = null;
-            int comma = 0;
-            ConfigParser parser = new ConfigParser();
             
-            // Process each specified resource path
-            while (chainConfig.length() > 0) {
-                path = null;
-                comma = chainConfig.indexOf(',');
-                if (comma >= 0) {
-                    path = chainConfig.substring(0, comma).trim();
-                    chainConfig = chainConfig.substring(comma + 1);
-                } else {
-                    path = chainConfig.trim();
-                    chainConfig = "";
-                }
-    
-                if (path.length() < 1) {
-                    break;
-                }
-   
-                if (path.charAt(0) == '/') {
-                    resource = getServletContext().getResource(path);
-                }
-
-                if (resource == null) {
-                    if (log.isDebugEnabled()) {
-                        log.debug("Unable to locate "+path+" in the servlet "
-                                + "context, trying classloader.");
-                    }
-                    resource = loader.getResource(path);
-                }
-
-                
-                
-                if (resource == null) {
-                    // TODO: this should be pulled from internal resources
-                    throw new ServletException("Unable to locate chain 
"+path+" but is "+getClass().getClassLoader().getResource(path));
-                } else {
-                    log.info("Loading chain catalog from "+resource);
-                    parser.parse(resource);
-                }
-                resource = null;
+            ConfigParser parser = new ConfigParser();
+            List urls = splitAndResolvePaths(chainConfig);
+            URL resource = null;
+            for (Iterator i = urls.iterator(); i.hasNext(); ) {
+                resource = (URL)i.next();
+                log.info("Loading chain catalog from "+resource);
+                parser.parse(resource);
             }
         } catch (Exception e) {
             log.error("Exception loading resources", e);
@@ -1197,6 +1158,74 @@
             getServletContext().setAttribute(Globals.SERVLET_KEY, 
servletMapping);
         }
 
+    }
+    
+    /**
+     *  Takes a comma-delimited string and splits it into paths, then resolves
+     *  those paths using the ServletContext and appropriate ClassLoader.  When
+     *  loading from the classloader, multiple resources per path are supported
+     *  to support, for example, multiple jars containing the same named config
+     *  file.
+     *
+     * @param paths A comma-delimited string of paths
+     * @return A list of resolved URL's for all found resources
+     *
+     * @exception ServletException if a servlet exception is thrown
+     */
+    protected List splitAndResolvePaths(String paths) throws ServletException {
+        ClassLoader loader = Thread.currentThread().getContextClassLoader();
+        if (loader == null) {    
+            loader = this.getClass().getClassLoader();
+        }
+        ArrayList resolvedUrls = new ArrayList();
+        
+        URL resource = null;
+        String path = null;
+        try {
+            // Process each specified resource path
+            while (paths.length() > 0) {
+                int comma = paths.indexOf(',');
+                if (comma >= 0) {
+                    path = paths.substring(0, comma).trim();
+                    paths = paths.substring(comma + 1);
+                } else {
+                    path = paths.trim();
+                    paths = "";
+                }
+    
+                if (path.length() < 1) {
+                    break;
+                }
+                
+                if (path.charAt(0) == '/') {
+                    resource = getServletContext().getResource(path);
+                }
+    
+                if (resource == null) {
+                    if (log.isDebugEnabled()) {
+                        log.debug("Unable to locate "+path+" in the servlet "
+                                + "context, trying classloader.");
+                    }
+                    Enumeration e = loader.getResources(path);
+                    if (!e.hasMoreElements()) {
+                        String msg = internal.getMessage("configMissing", 
path);
+                        log.error(msg);
+                        throw new UnavailableException(msg);
+                    } else {
+                        while (e.hasMoreElements()) {
+                            resolvedUrls.add(e.nextElement());
+                        }
+                    }
+                } else {
+                    resolvedUrls.add(resource);
+                }
+            }
+        } catch (MalformedURLException e) {
+            handleConfigException(path, e);
+        } catch (IOException e) {
+            handleConfigException(path, e);
+        }
+        return resolvedUrls;
     }
 
 

Modified: 
struts/core/trunk/src/test/org/apache/struts/action/TestActionServlet.java
URL: 
http://svn.apache.org/viewcvs/struts/core/trunk/src/test/org/apache/struts/action/TestActionServlet.java?view=diff&r1=158265&r2=158266
==============================================================================
--- struts/core/trunk/src/test/org/apache/struts/action/TestActionServlet.java 
(original)
+++ struts/core/trunk/src/test/org/apache/struts/action/TestActionServlet.java 
Sat Mar 19 17:36:59 2005
@@ -23,6 +23,8 @@
 import junit.framework.TestCase;
 import junit.framework.TestSuite;
 
+import java.util.List;
+
 import org.apache.struts.util.MessageResources;
 
 /**
@@ -87,7 +89,32 @@
 
     }
 
-
+    /** 
+     *  Test class loader resolution and splitting.  
+     */
+    public void testSplitAndResolvePaths() throws Exception {
+        ActionServlet servlet = new ActionServlet();
+        List list = 
servlet.splitAndResolvePaths("org/apache/struts/config/struts-config.xml");
+        assertNotNull(list);
+        assertTrue("List size should be 1", list.size() == 1);
+        
+        list = 
servlet.splitAndResolvePaths("org/apache/struts/config/struts-config.xml, "   
+            + "org/apache/struts/config/struts-config-1.1.xml");
+        assertNotNull(list);
+        assertTrue("List size should be 2, was "+list.size(), list.size() == 
2);
+        
+        list = servlet.splitAndResolvePaths("META-INF/MANIFEST.MF");
+        assertNotNull(list);
+        assertTrue("Number of manifests should be more than 5, was 
"+list.size(), list.size() > 5);
+        
+        // test invalid path
+        try {
+            list = 
servlet.splitAndResolvePaths("org/apache/struts/config/struts-asdfasdfconfig.xml");
+            fail("Should have thrown an exception on bad path");
+        } catch (NullPointerException ex) {
+            // correct behavior since internal error resources aren't loaded
+        }
+    }
 
     //----- Test initApplication() method 
--------------------------------------
 



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to