webwork/src/main/webwork/config AbstractConfiguration.java,NONE,1.1 ConfigurationInterface.java,NONE,1.1 CachingConfiguration.java,1.1,1.2 Configuration.java,1.12,1.13 DefaultConfiguration.java,1.13,1.14 DelegatingConfiguration.java,1.7,1.8 PropertiesConfiguration.java,1.9,1.10 XMLActionConfiguration.java,1.18,1.19
[email protected] Sun, 16 Jan 2005 21:10:41 -0800
| Newsgroups | gmane.comp.java.open-symphony.cvs |
|---|---|
| Message-ID | <[email protected]> |
Update of /cvsroot/opensymphony/webwork/src/main/webwork/config
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv27114/src/main/webwork/config
Modified Files:
CachingConfiguration.java Configuration.java
DefaultConfiguration.java DelegatingConfiguration.java
PropertiesConfiguration.java XMLActionConfiguration.java
Added Files:
AbstractConfiguration.java ConfigurationInterface.java
Log Message:
Allow pluggable configurations for webwork.
You can now specify your own configuration objects in
webwork.properties.
Introduced the (badly named) ConfigurationInterface object, which all
configurations have to implement.
Split out the XML reading from the XML configuration object, so that it
can be reused from other configuration objects.
Fixes WW-722
--- NEW FILE: AbstractConfiguration.java ---
package webwork.config;
import java.util.Iterator;
public class AbstractConfiguration implements ConfigurationInterface
{
/**
* Get a named setting.
*
* @throws IllegalArgumentException if there is no configuration parameter with the given name.
*/
public Object getImpl(String aName)
throws IllegalArgumentException
{
return null;
}
/**
* Set a named setting
*/
public void setImpl(String aName, Object aValue)
throws IllegalArgumentException, UnsupportedOperationException
{
throw new UnsupportedOperationException("This configuration does not support updating a setting");
}
/**
* List setting names
*/
public Iterator listImpl()
{
throw new UnsupportedOperationException("This configuration does not support listing the settings");
}
}
--- NEW FILE: ConfigurationInterface.java ---
package webwork.config;
import java.util.Iterator;
/**
* This is named this ugly name because the Configuration object couldn't be renamed (it would break anyone
* who uses it in their code).
*/
public interface ConfigurationInterface
{
Object getImpl(String aName) throws IllegalArgumentException;
void setImpl(String aName, Object aValue) throws IllegalArgumentException, UnsupportedOperationException;
Iterator listImpl();
}
Index: CachingConfiguration.java
===================================================================
RCS file: /cvsroot/opensymphony/webwork/src/main/webwork/config/CachingConfiguration.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- CachingConfiguration.java 5 Nov 2003 10:18:37 -0000 1.1
+++ CachingConfiguration.java 17 Jan 2005 05:10:37 -0000 1.2
@@ -11,7 +11,7 @@
import java.util.HashMap;
/**
- * This is a caching implementation of Configuration.
+ * This is a caching implementation of ConfigurationInterface.
* This class can be used instead of the DefaultConfiguration to
* make your configuration lookups more efficient.
* At startup it iterates through all the configuration settings
@@ -20,8 +20,7 @@
* @author Dick Zetterberg ([email protected])
* @version $Revision$
*/
-public class CachingConfiguration
- extends DefaultConfiguration
+public class CachingConfiguration extends DefaultConfiguration
{
// Attributes ----------------------------------------------------
protected Map configurationMap;
@@ -37,7 +36,7 @@
/**
* Create and return a Map with configuration key/values
*/
- protected Map getConfigurationMap(Configuration configObject)
+ protected Map getConfigurationMap(ConfigurationInterface configObject)
{
// Get an iterator for the configObject
Iterator it = configObject.listImpl();
@@ -46,7 +45,7 @@
{
String key = (String) it.next();
// Get the value for the key
- Object value = configObject.get(key);
+ Object value = configObject.getImpl(key);
// Put the key and value in the Map
configMap.put(key, value);
}
Index: Configuration.java
===================================================================
RCS file: /cvsroot/opensymphony/webwork/src/main/webwork/config/Configuration.java,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- Configuration.java 24 Jun 2003 04:24:35 -0000 1.12
+++ Configuration.java 17 Jan 2005 05:10:37 -0000 1.13
@@ -12,27 +12,30 @@
import java.util.Locale;
import java.util.StringTokenizer;
-import webwork.config.DefaultConfiguration;
import webwork.util.ClassLoaderUtils;
/**
* Access to WebWork configuration. Use the constants to access defined configuration settings.
- *
+ * <p>
* The implementation is pluggable. The default implementation is to use the properties file
- * "webwork.properties", which must be in classpath. To install a new implementation subclass this
- * class and call setConfiguration() with it.
+ * "webwork.properties", which must be in classpath. To install a new implementation implement
+ * {@link ConfigurationInterface} and call setConfiguration() with it.
*
* @author Rickard Ãberg ([email protected])
* @version $Revision$
*
*/
-public abstract class Configuration
+public final class Configuration
{
// Static --------------------------------------------------------
- static Configuration configurationImpl;
- static Configuration defaultImpl;
+ static ConfigurationInterface configurationImpl;
+ static ConfigurationInterface defaultImpl;
static Locale locale; // Cached locale
+ private Configuration()
+ {
+ }
+
/**
* Get a named setting.
*/
@@ -49,8 +52,8 @@
public static String getString(String aName)
throws IllegalArgumentException
{
- String val = get(aName).toString();
- return val;
+ final Object o = get(aName);
+ return o == null ? aName : o.toString();
}
/**
@@ -100,7 +103,7 @@
/**
* Get the current configuration implementation.
*/
- public static Configuration getConfiguration()
+ public static ConfigurationInterface getConfiguration()
{
return configurationImpl == null ? getDefaultConfiguration() : configurationImpl;
}
@@ -108,7 +111,7 @@
/**
* Set the current configuration implementation. Can only be called once.
*/
- public static void setConfiguration(Configuration aConfig)
+ public static void setConfiguration(ConfigurationInterface aConfig)
throws IllegalStateException
{
if (configurationImpl != null)
@@ -118,35 +121,7 @@
locale = null; // Reset cached locale
}
- /**
- * Get a named setting.
- *
- * @throws IllegalArgumentException if there is no configuration parameter with the given name.
- */
- public Object getImpl(String aName)
- throws IllegalArgumentException
- {
- return null;
- }
-
- /**
- * Set a named setting
- */
- public void setImpl(String aName, Object aValue)
- throws IllegalArgumentException, UnsupportedOperationException
- {
- throw new UnsupportedOperationException("This configuration does not support updating a setting");
- }
-
- /**
- * List setting names
- */
- public Iterator listImpl()
- {
- throw new UnsupportedOperationException("This configuration does not support listing the settings");
- }
-
- private static Configuration getDefaultConfiguration()
+ private static ConfigurationInterface getDefaultConfiguration()
{
if (defaultImpl == null)
{
@@ -161,7 +136,7 @@
{
try
{
- defaultImpl = (Configuration)ClassLoaderUtils.loadClass(className, Configuration.class).newInstance();
+ defaultImpl = (ConfigurationInterface)ClassLoaderUtils.loadClass(className, ConfigurationInterface.class).newInstance();
} catch (Exception e)
{
LogFactory.getLog(Configuration.class).error("Could not instantiate configuration", e);
Index: DefaultConfiguration.java
===================================================================
RCS file: /cvsroot/opensymphony/webwork/src/main/webwork/config/DefaultConfiguration.java,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- DefaultConfiguration.java 14 Oct 2004 00:38:08 -0000 1.13
+++ DefaultConfiguration.java 17 Jan 2005 05:10:37 -0000 1.14
@@ -11,19 +11,21 @@
import java.util.ArrayList;
import java.util.Iterator;
import java.util.StringTokenizer;
+import java.util.List;
+
+import webwork.util.ClassLoaderUtils;
/**
* Default implementation of configuration. Creates and delegates to other configurations.
*
- * @author Rickard Öberg ([email protected])
+ * @author Rickard Åberg ([email protected])
* @version $Revision$
*
*/
-public class DefaultConfiguration
- extends Configuration
+public class DefaultConfiguration extends AbstractConfiguration
{
// Attributes ----------------------------------------------------
- Configuration config;
+ ConfigurationInterface config;
// Constructors --------------------------------------------------
public DefaultConfiguration()
@@ -46,8 +48,8 @@
LogFactory.getLog(this.getClass()).error("Could not find webwork/default.properties", e);
}
- Configuration[] configList = new Configuration[list.size()];
- config = new DelegatingConfiguration((Configuration[])list.toArray(configList));
+ ConfigurationInterface[] configList = new ConfigurationInterface[list.size()];
+ config = new DelegatingConfiguration((ConfigurationInterface[])list.toArray(configList));
// List of configurations to delegate to
list = new ArrayList();
@@ -68,8 +70,8 @@
//reset the delegating config in case we have added some
//additional configurations that override webwork.configuration.xml
- configList = new Configuration[list.size()];
- config = new DelegatingConfiguration((Configuration[])list.toArray(configList));
+ configList = new ConfigurationInterface[list.size()];
+ config = new DelegatingConfiguration((ConfigurationInterface[])list.toArray(configList));
// Add list of XML action configurations
configFiles = new StringTokenizer((String)config.getImpl("webwork.configuration.xml"), ",");
@@ -88,8 +90,44 @@
}
}
- configList = new Configuration[list.size()];
- config = new DelegatingConfiguration((Configuration[])list.toArray(configList));
+ List configurationObjects = new ArrayList();
+ try
+ {
+ configFiles = new StringTokenizer((String)config.getImpl("webwork.configuration.class"), ",");
+ while (configFiles.hasMoreTokens())
+ {
+ String name = configFiles.nextToken();
+ try
+ {
+ final Class configurationClass = ClassLoaderUtils.loadClass(name, ConfigurationInterface.class);
+ if (configurationClass == null)
+ {
+ LogFactory.getLog(this.getClass()).warn("Could not find configuration class '" + configurationClass + "' in classpath");
+ }
+ else if (!ConfigurationInterface.class.isAssignableFrom(configurationClass))
+ {
+ LogFactory.getLog(this.getClass()).warn("ConfigurationInterface class '" + configurationClass + "' is not of type 'ConfigurationInterface'");
+ }
+ else
+ {
+ configurationObjects.add(configurationClass.newInstance());
+ }
+ }catch (Exception e)
+ {
+ LogFactory.getLog(this.getClass()).error("Skipping configuration for class '" + name + "'", e);
+ }
+ }
+ }
+ catch (IllegalArgumentException e)
+ {
+ //this means that it could not find any property 'webwork.configuration.class'
+ }
+
+ //the new configuration objects should be added at the start of the list, so that they can override any other properties
+ list.addAll(0, configurationObjects);
+
+ configList = new ConfigurationInterface[list.size()];
+ config = new DelegatingConfiguration((ConfigurationInterface[])list.toArray(configList));
}
/**
Index: DelegatingConfiguration.java
===================================================================
RCS file: /cvsroot/opensymphony/webwork/src/main/webwork/config/DelegatingConfiguration.java,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- DelegatingConfiguration.java 11 Mar 2002 09:02:34 -0000 1.7
+++ DelegatingConfiguration.java 17 Jan 2005 05:10:37 -0000 1.8
@@ -12,18 +12,18 @@
/**
* Delegating implementation of configuration. Delegates to a list of other configurations.
*
- * @author Rickard Öberg ([email protected])
+ * @author Rickard Åberg ([email protected])
* @version $Revision$
*
*/
public class DelegatingConfiguration
- extends Configuration
+ extends AbstractConfiguration
{
// Attributes ----------------------------------------------------
- Configuration[] configList;
+ ConfigurationInterface[] configList;
// Constructors --------------------------------------------------
- public DelegatingConfiguration(Configuration[] aConfigList)
+ public DelegatingConfiguration(ConfigurationInterface[] aConfigList)
{
configList = aConfigList;
}
Index: PropertiesConfiguration.java
===================================================================
RCS file: /cvsroot/opensymphony/webwork/src/main/webwork/config/PropertiesConfiguration.java,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- PropertiesConfiguration.java 24 Jun 2003 04:24:35 -0000 1.9
+++ PropertiesConfiguration.java 17 Jan 2005 05:10:37 -0000 1.10
@@ -22,7 +22,7 @@
*
*/
public class PropertiesConfiguration
- extends Configuration
+ extends AbstractConfiguration
{
// Attributes ----------------------------------------------------
Properties settings;
Index: XMLActionConfiguration.java
===================================================================
RCS file: /cvsroot/opensymphony/webwork/src/main/webwork/config/XMLActionConfiguration.java,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -d -r1.18 -r1.19
--- XMLActionConfiguration.java 9 Aug 2004 03:57:05 -0000 1.18
+++ XMLActionConfiguration.java 17 Jan 2005 05:10:37 -0000 1.19
@@ -6,26 +6,21 @@
*/
package webwork.config;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.NodeList;
-import org.w3c.dom.Node;
-import org.w3c.dom.Text;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.w3c.dom.DOMException;
-import org.apache.commons.logging.*;
+import org.w3c.dom.Document;
import org.xml.sax.SAXException;
+import webwork.config.util.XMLConfigurationReader;
+import webwork.util.ClassLoaderUtils;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
-import java.io.IOException;
import java.io.File;
-import java.net.URL;
+import java.io.IOException;
import java.net.MalformedURLException;
+import java.net.URL;
import java.util.Iterator;
-import java.util.HashMap;
-import java.util.Map;
-
-import webwork.util.ClassLoaderUtils;
/**
* Access view configuration from an XML file.
@@ -36,18 +31,10 @@
*
*/
public class XMLActionConfiguration
- extends Configuration
+ extends AbstractConfiguration
{
// Attributes ----------------------------------------------------
- /**
- * This stores the mapping from URL -> action. It looks through the (xml) configuration file and
- * adds all the commands, aliases, and views.
- * <p>
- * One caveat - if you are using an extension aside from '.action', the views will be added with
- * '.action' here, and then replaced on retrieval. This is to warn off a recursive dependency that
- * I haven't had a chance to look at yet.
- */
- Map actionMappings = null;
+ private XMLConfigurationReader configurationReader;
Log log = LogFactory.getLog(getClass());
private File file;
private long lastModified;
@@ -59,7 +46,7 @@
URL fileUrl = ClassLoaderUtils.getResource(aName+".xml", XMLActionConfiguration.class);
if (fileUrl == null)
throw new IllegalArgumentException("No such XML resource:"+aName+".xml");
- actionMappings = getMappingsFromResource(fileUrl);
+ configurationReader = getMappingsFromResource(fileUrl);
file = new File(fileUrl.getFile());
if(!file.exists() || !file.canRead())
{
@@ -69,9 +56,8 @@
lastModified = file.lastModified();
}
- private Map getMappingsFromResource(URL url)
+ protected XMLConfigurationReader getMappingsFromResource(URL url)
{
- Map actionMap = new HashMap();
try
{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
@@ -81,120 +67,8 @@
log.debug("Found XML view configuration "+url);
- // Get list of actions
- NodeList actions = document.getElementsByTagName("action");
-
- // Build list of views
- int length = actions.getLength();
- for (int i = 0; i < length; i++)
- {
- Element action = (Element)actions.item(i);
- String actionName = action.getAttribute("name");
- String actionAlias = action.getAttribute("alias");
-
- // Build views for this action
- {
- NodeList views = action.getElementsByTagName("view");
- for (int j = 0; j < views.getLength(); j++)
- {
- Element view = (Element)views.item(j);
-
- // This is to avoid listing "view" elements
- // that are associated with the commands
- // of this action
- if (!view.getParentNode().equals(action))
- break;
-
- // View mappings for this action
- NodeList viewMapping = view.getChildNodes();
- StringBuffer mapping = new StringBuffer();
- for (int k = 0; k < viewMapping.getLength(); k++)
- {
- Node mappingNode = viewMapping.item(k);
- if (mappingNode instanceof Text)
- {
- mapping.append(mappingNode.getNodeValue());
- }
- }
-
- String actionViewName;
- if ("".equals(actionAlias))
- {
- if(!"".equals(actionName))
- {
- actionViewName = actionName+"."+view.getAttribute("name");
- }
- else
- {
- actionViewName = view.getAttribute("name");
- }
- }
- else
- {
- actionViewName = actionAlias+"."+view.getAttribute("name");
- log.debug("Adding action alias "+actionAlias+"="+actionName);
- actionMap.put(actionAlias+".action",
- actionName);
- }
-
- String actionViewMapping = mapping.toString().trim();
- log.debug("Adding view mapping "+actionViewName+"="+actionViewMapping);
- actionMap.put(actionViewName, actionViewMapping);
- }
- }
-
- // Commands
- NodeList commands = action.getElementsByTagName("command");
- for (int j = 0; j < commands.getLength(); j++)
- {
- Element command = (Element)commands.item(j);
- String commandName = command.getAttribute("name");
- String commandAlias = command.getAttribute("alias");
-
- if (!commandAlias.equals(""))
- {
- log.debug("Adding command alias "+commandAlias+"="+actionName+"!"+commandName);
- actionMap.put(commandAlias+".action",
- actionName+"!"+commandName);
- }
-
- // Build views for this action
- NodeList views = command.getElementsByTagName("view");
- for (int k = 0; k < views.getLength(); k++)
- {
- Element view = (Element)views.item(k);
-
- // View mappings for this action
- NodeList viewMapping = view.getChildNodes();
- StringBuffer mapping = new StringBuffer();
- for (int l = 0; l < viewMapping.getLength(); l++)
- {
- Node mappingNode = viewMapping.item(l);
- if (mappingNode instanceof Text)
- {
- mapping.append(mappingNode.getNodeValue());
- }
- }
-
- String commandViewName;
- if (commandAlias.equals(""))
- {
- if (actionAlias.equals(""))
- commandViewName = actionName+"!"+commandName+"."+view.getAttribute("name");
- else
- commandViewName = actionAlias+"!"+commandName+"."+view.getAttribute("name");
- }
- else
- {
- commandViewName = commandAlias+"."+view.getAttribute("name");
- }
+ return new XMLConfigurationReader(document.getDocumentElement());
- String commandViewMapping = mapping.toString().trim();
- log.debug("Adding command view mapping "+commandViewName+"="+commandViewMapping);
- actionMap.put(commandViewName, commandViewMapping);
- }
- }
- }
} catch (SAXException e)
{
log.error("SAX exception", e);
@@ -212,10 +86,10 @@
log.error("DOM exception", e);
throw new IllegalArgumentException("Could not load XML action configuration");
}
- return actionMap;
}
- /**
+
+ /**
* Get a named setting. Note extension is stripped and replaced with extension defined
* in property file. This is done here because of the recursive dependency if the constructor
* called Configuration.getString("webwork.action.extension").
@@ -241,8 +115,7 @@
log.debug("Reloading " + file);
try
{
- Map newMappings = getMappingsFromResource(file.toURL());
- actionMappings = newMappings;
+ configurationReader = getMappingsFromResource(file.toURL());
}
catch(MalformedURLException e)
{
@@ -250,46 +123,13 @@
log.error("Something horrible happened", e);
}
}
- String mappingName = replaceExtension(aName);
- Object mapping = actionMappings.get(mappingName);
+ Object mapping = configurationReader.getActionMapping(aName);
if (mapping == null)
- throw new IllegalArgumentException("No such view mapping:"+mappingName);
+ throw new IllegalArgumentException("No such view mapping:"+aName);
return mapping;
}
- /**
- * As the actions are stored in the action mapping with a '.action' extension, we need to map the current
- * request to that '.action' mapping.
- * <p>
- * So an action 'ABC.jspa' would be lookup up in the map at 'ABC.action'.
- * <p>
- * The extension used is retrieved from the configuration using key 'webwork.action.extension'
- * @param actionName The original action (url) to be mapped, including an extension (if any).
- * @return The action name used in actionMappings - ie with a '.action' extension.
- */
- private String replaceExtension(String actionName){
- String ext = "." + Configuration.getString("webwork.action.extension");
-
- //replace all custom extensions with .action to retrieve view mapping from cache
- if (actionName != null && !".action".equals(ext))
- {
- // try to find another extension
- if (actionName.endsWith(ext))
- actionName = actionName.substring(0, actionName.lastIndexOf(ext)) + ".action";
-
- // otherwise look for something like .jspa? in the view mapping and replace
- // with .action?
- int idx = actionName.indexOf(ext + "?");
-
- if (idx > 0)
- {
- actionName = actionName.substring(0, idx) + ".action?" + actionName.substring(idx + ext.length() + 1);
- }
- }
-
- return actionName;
- }
public void setImpl(String aName, Object aValue)
{
@@ -298,6 +138,6 @@
public Iterator listImpl()
{
- return actionMappings.keySet().iterator();
+ return configurationReader.getActionMappingNames().iterator();
}
}
-------------------------------------------------------
The SF.Net email is sponsored by: Beat the post-holiday blues
Get a FREE limited edition SourceForge.net t-shirt from ThinkGeek.
It's fun and FREE -- well, almost....http://www.thinkgeek.com/sfshirt