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]