Author: gvanmatre
Date: Thu Sep 1 22:14:12 2005
New Revision: 266287
URL: http://svn.apache.org/viewcvs?rev=266287&view=rev
Log:
Added automatic reloading of the Clay configuration files if modified.
Added:
struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/beans/ConfigDefinitionsWatchdogFilter.java
Modified:
struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/ClayConfigureListener.java
struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/ClayXmlParser.java
struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/Globals.java
struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/beans/ComponentConfigBean.java
struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/beans/ConfigBean.java
struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/beans/ConfigBeanFactory.java
struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/beans/TemplateConfigBean.java
struts/shale/trunk/clay-plugin/src/test/org/apache/shale/clay/config/ConfigTestCase.java
struts/shale/trunk/clay-plugin/src/test/org/apache/shale/clay/parser/ParserTestCase.java
Modified:
struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/ClayConfigureListener.java
URL:
http://svn.apache.org/viewcvs/struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/ClayConfigureListener.java?rev=266287&r1=266286&r2=266287&view=diff
==============================================================================
---
struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/ClayConfigureListener.java
(original)
+++
struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/ClayConfigureListener.java
Thu Sep 1 22:14:12 2005
@@ -72,39 +72,16 @@
try {
- ClayXmlParser parser = new ClayXmlParser();
- // grab the default config file
- StringBuffer configFiles = new StringBuffer(
- Globals.DEFAULT_CLAY_CONFIG_FILE);
-
- // a comma delimited value list of config files
- String param = event.getServletContext().getInitParameter(
- Globals.CLAY_CONFIG_FILES);
-
- if (param != null && param.trim().length() > 0)
- configFiles.append(", ").append(param);
-
+ // load xml config
ConfigBean config = new ComponentConfigBean();
- config.init(event.getServletContext());
-
- parser.setConfig((ComponentConfigBean) config);
- // materialize into an object graph
- parser.load(configFiles.toString());
-
+ config.init(event.getServletContext());
ConfigBeanFactory.register(config);
- parser = null;
- param = null;
- configFiles = null;
-
// load template config
- config = new TemplateConfigBean();
-
+ config = new TemplateConfigBean();
config.init(event.getServletContext());
ConfigBeanFactory.register(config);
-
-
-
+
} catch (RuntimeException e) {
log.error(messages.getMessage("config.load.error"), e);
throw e;
Modified:
struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/ClayXmlParser.java
URL:
http://svn.apache.org/viewcvs/struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/ClayXmlParser.java?rev=266287&r1=266286&r2=266287&view=diff
==============================================================================
---
struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/ClayXmlParser.java
(original)
+++
struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/ClayXmlParser.java
Thu Sep 1 22:14:12 2005
@@ -19,16 +19,16 @@
package org.apache.shale.clay.config;
import java.io.IOException;
+import java.io.InputStream;
import java.net.URL;
-import java.util.StringTokenizer;
import org.apache.commons.digester.Digester;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.shale.clay.config.beans.ComponentConfigBean;
+import org.apache.shale.util.Messages;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
-import org.apache.shale.util.Messages;
/**
@@ -95,61 +95,37 @@
new String[] {"-//Apache Software Foundation//DTD Shale Clay
View//EN", "/org/apache/shale/clay/config/resources/clay-config_1_0.dtd"}};
- /**
- * <p>Loads a single configuration file adding the bound objects to
the config [EMAIL PROTECTED] ComponentConfigBean}.
- * This method will be called for each file specified in the comma
delimited list.<p>
- *
- * @param configFile <code>String</code> a file path relative to the
context root.
- *
- */
- protected void loadConfigFile(String configFile) {
-
- if (log.isInfoEnabled())
- log.info(messages.getMessage("parser.load.file", new Object[]
{ configFile }));
-
- if (digester == null) {
- digester = new Digester();
- digester.setLogger(log);
- digester.setValidating(true);
- digester.setUseContextClassLoader(true);
-
- // Register our local copy of the DTDs that we can find
- for (int i = 0; i < registrations.length; i++) {
- URL url = this.getClass().getResource(((String[])
registrations[i])[1]);
- if (url != null) {
- digester.register(((String[])
registrations[i])[0], url.toString());
- }
- }
-
- configureRules();
- digester.push(config);
- } else {
- digester.clear();
- digester.push(config);
- }
- InputSource in = null;
- if (configFile.startsWith("META-INF")) {
-
- ClassLoader classloader =
Thread.currentThread().getContextClassLoader();
- if(classloader == null)
- classloader = this.getClass().getClassLoader();
-
- in = new
InputSource(classloader.getResourceAsStream(configFile));
- } else
- in = new
InputSource(config.getServletContext().getResourceAsStream(configFile));
- try {
- digester.parse(in);
- } catch (IOException e) {
- log.error(messages.getMessage("parser.load.error", new
Object[] {configFile}), e);
- } catch (SAXException e) {
- log.error(messages.getMessage("parser.load.error", new
Object[] {configFile}), e);
+ public void loadConfigFile(InputStream inputStream) throws IOException,
SAXException {
+
+
+ if (digester == null) {
+ digester = new Digester();
+ digester.setLogger(log);
+ digester.setValidating(true);
+ digester.setUseContextClassLoader(true);
+
+ // Register our local copy of the DTDs that we can find
+ for (int i = 0; i < registrations.length; i++) {
+ URL url = this.getClass().getResource(((String[])
registrations[i])[1]);
+ if (url != null) {
+ digester.register(((String[]) registrations[i])[0],
url.toString());
}
-
- in = null;
-
+ }
+
+ configureRules();
+ digester.push(config);
+ } else {
+ digester.clear();
+ digester.push(config);
}
+ InputSource inputSource = new InputSource(inputStream);
+ digester.parse(inputSource);
+ inputSource = null;
+
+ }
+
/**
* <p>This method is called once to register the object binding rules
with
* the <code>Digester</code> instance.
@@ -229,34 +205,6 @@
}
- /**
- * <p>Called to load a comma delimited value list of XML configuration
files.
- * The list passed a a parameter will be tokenized and loaded
individually by
- * calling the <code>loadConfigFile</code> method.
- *</p>
- *
- * @param configFiles <code>String</code> comma delimited list of
files to load.
- */
- public void load(String configFiles) {
-
- StringTokenizer tokenizer = new StringTokenizer(configFiles, ", ");
- while (tokenizer.hasMoreTokens()) {
- StringBuffer configFile = new
StringBuffer(tokenizer.nextToken().trim());
- if (configFile.toString().endsWith(".xml")) {
- for (int i = configFile.length() - 5; i > 0; i--) {
- if (configFile.charAt(i) == '.')
- configFile.setCharAt(i, '/');
- }
- }
-
- loadConfigFile(configFile.toString());
-
- configFile = null;
- }
- tokenizer = null;
-
- config.resolveInheritance();
-
- }
+
}
Modified:
struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/Globals.java
URL:
http://svn.apache.org/viewcvs/struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/Globals.java?rev=266287&r1=266286&r2=266287&view=diff
==============================================================================
---
struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/Globals.java
(original)
+++
struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/Globals.java
Thu Sep 1 22:14:12 2005
@@ -50,6 +50,18 @@
* </p>
*/
public static final String CLAY_TEMPLATE_SUFFIX = "clay-template-suffix";
+
+ /**
+ * <p>The name of the initialization parameter defined in the
+ * web deployment descriptor that's value will determine if the
+ * configuration files defined by <code>CLAY_CONFIG_FILES</code>
+ * will be watched for changes. The default value is <code>true</code>
+ * meaning that the config files will be automatically reloaded if
+ * a change occures.
+ * </p>
+ */
+ public static final String AUTO_RELOAD_CLAY_FILES =
"auto-reload-clay-files";
+
/**
* <p>The default template suffix identifier if one is not specified
@@ -63,7 +75,7 @@
*</p>
*/
public static final String DEFAULT_CLAY_CONFIG_FILE =
"META-INF/view-config.xml";
-
+
/**
* <p>The literal string used to identify that a clay subtree should be
* built at runtime. This value "RUNTIME" will be placed in the jsfid
@@ -157,28 +169,28 @@
* as method binding events.</p
*/
public static final String[] METHOD_ATTRIBUTES = { "converter",
- "validator", "valueChangeListener", "action", "actionListener" };
-
- /**
- * <p>A constants array of attribute names used by the faces
components
- * to define additional behavior using a value binding
expression.</b>
- */
- public static final String[] VALUE_ATTRIBUTES = { "value", "for",
- "immediate", "rendered", "required", "disabledClass",
- "enabledClass" };
-
- /**
- * <p>A constants array of component attributes that are
HTML related. This
- * list is used by the abstract [EMAIL PROTECTED]
org.apache.shale.clay.parser.builder.Builder}
- * to override component attributes defined in the view
XML files.
- * </p>
- */
- public static final String[] HTML_ATTRIBUTES = {
"accesskey", "dir",
- "disabled", "lang", "onblur", "onchange",
"onclick", "ondblclick",
- "onfocus", "onkeydown", "onkeypress", "onkeyup",
"onmousedown",
- "onmousemove", "onmouseout", "onmouseover",
"onmouseup",
- "onselect", "readonly", "size", "style",
"styleClass", "tabindex",
- "title", };
-
-
+ "validator", "valueChangeListener", "action", "actionListener" };
+
+ /**
+ * <p>A constants array of attribute names used by the faces components
+ * to define additional behavior using a value binding expression.</b>
+ */
+ public static final String[] VALUE_ATTRIBUTES = { "value", "for",
+ "immediate", "rendered", "required", "disabledClass",
+ "enabledClass" };
+
+ /**
+ * <p>A constants array of component attributes that are HTML related. This
+ * list is used by the abstract [EMAIL PROTECTED]
org.apache.shale.clay.parser.builder.Builder}
+ * to override component attributes defined in the view XML files.
+ * </p>
+ */
+ public static final String[] HTML_ATTRIBUTES = { "accesskey", "dir",
+ "disabled", "lang", "onblur", "onchange", "onclick", "ondblclick",
+ "onfocus", "onkeydown", "onkeypress", "onkeyup", "onmousedown",
+ "onmousemove", "onmouseout", "onmouseover", "onmouseup",
+ "onselect", "readonly", "size", "style", "styleClass", "tabindex",
+ "title", };
+
+
}
Modified:
struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/beans/ComponentConfigBean.java
URL:
http://svn.apache.org/viewcvs/struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/beans/ComponentConfigBean.java?rev=266287&r1=266286&r2=266287&view=diff
==============================================================================
---
struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/beans/ComponentConfigBean.java
(original)
+++
struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/beans/ComponentConfigBean.java
Thu Sep 1 22:14:12 2005
@@ -18,9 +18,17 @@
package org.apache.shale.clay.config.beans;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.ArrayList;
+import java.util.Enumeration;
import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import java.util.Stack;
+import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.TreeSet;
@@ -28,8 +36,10 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.shale.clay.config.ClayXmlParser;
import org.apache.shale.clay.config.Globals;
import org.apache.shale.util.Messages;
+import org.xml.sax.SAXException;
/**
* <p>This class is kind of the metadata object pool for configuration data
@@ -45,8 +55,31 @@
log = LogFactory.getLog(ComponentConfigBean.class);
}
+ /**
+ * <p>Uses the digester to load the configuration files
+ * into a object graph cached in <code>displayElements</code>.
+ * </p>
+ */
+ protected ClayXmlParser parser = null;
/**
+ * <p>This parameter is initialized from the <code>init</code>
+ * method from the <code>auto-reload-clay-files</code> init
+ * parameter in the web.xml. The default value is <code>true</code>
+ * which will trigger reloading the files when a change has occurred.
+ * </p>
+ */
+ private boolean isWatchDogOn = true;
+
+
+ /**
+ * <p>Watches the configuration files looking for changes. The
configuration
+ * files are defined by the [EMAIL PROTECTED] ConfigBean.ConfigDefinition}
top level
+ * interface.</p>
+ */
+ protected WatchDog watchDog = null;
+
+ /**
* <p>
* Message resources for this class.
* </p>
@@ -81,8 +114,104 @@
suffix = Globals.CLAY_DEFAULT_TEMPLATE_SUFFIX;
}
+ String autoReloadClayFiles = (String)
context.getInitParameter(Globals.AUTO_RELOAD_CLAY_FILES);
+ if (autoReloadClayFiles != null) {
+ try {
+ isWatchDogOn = Boolean.parseBoolean(autoReloadClayFiles);
+ } catch (RuntimeException e) {
+ }
+
+ }
+
+ //loads the config files
+ loadConfigFiles();
}
+
+ /**
+ * <p>Loads the [EMAIL PROTECTED] org.apache.shale.clay.component.Clay}
configration files
+ * into the <code>displayElements</code> Map. The files are defined by
the
+ * <code>clay-template-suffix</code> initialization parameter in the web
deployment
+ * descriptor. The default configuration file "META-INF/view-config.xml"
is always
+ * loaded from the shale-clay java archive.</p>
+ */
+ protected void loadConfigFiles() {
+
+ parser = new ClayXmlParser();
+ parser.setConfig(this);
+
+ // grab the default config file
+ StringBuffer configFiles = new StringBuffer(
+ Globals.DEFAULT_CLAY_CONFIG_FILE);
+
+ // a comma delimited value list of config files
+ String param = context.getInitParameter(Globals.CLAY_CONFIG_FILES);
+
+ // add the default config file
+ if (param != null && param.trim().length() > 0)
+ configFiles.append(", ").append(param);
+
+ // pass the config bean to the parser
+ parser.setConfig((ComponentConfigBean) this);
+
+ // create the watch dog with a list of config files to look for changes
+ watchDog = new WatchDog(getConfigDefinitions(configFiles.toString()));
+ // loads the config files
+ watchDog.refresh();
+
+ param = null;
+ configFiles = null;
+
+ }
+
+ /**
+ * <p>Passed a comma delimited list of configuration files, this method
returns
+ * an array of [EMAIL PROTECTED] ConfigBean.ConfigDefinition} defining the
files.</p>
+ */
+ protected ConfigBean.ConfigDefinition[] getConfigDefinitions(String
configFiles) {
+
+ List urls = new ArrayList();
+
+ ClassLoader classloader =
Thread.currentThread().getContextClassLoader();
+ if(classloader == null)
+ classloader = this.getClass().getClassLoader();
+
+ // convert a tokenized list of configuration files into an array of
urls
+ StringTokenizer tokenizer = new StringTokenizer(configFiles, ", ");
+ while (tokenizer.hasMoreTokens()) {
+ StringBuffer configFile = new
StringBuffer(tokenizer.nextToken().trim());
+ if (configFile.toString().endsWith(".xml")) {
+ for (int i = configFile.length() - 5; i > 0; i--) {
+ if (configFile.charAt(i) == '.')
+ configFile.setCharAt(i, '/');
+ }
+ }
+
+ try {
+ if (configFile.toString().startsWith("META-INF/")) {
+ for (Enumeration ui =
classloader.getResources(configFile.toString()); ui.hasMoreElements();
urls.add(ui.nextElement()));
+ } else {
+ urls.add(context.getResource(configFile.toString()));
+ }
+ } catch (IOException e) {
+ log.error(e);
+ }
+
+ configFile = null;
+ }
+ tokenizer = null;
+ classloader = null;
+
+
+ ConfigBean.ConfigDefinition[] configDefs = new
ConfigBean.ConfigDefinition[urls.size()];
+
+ for (int i = 0; i < urls.size(); i++) {
+ configDefs[i] = new XmlConfigDef((URL) urls.get(i));
+ }
+
+ return configDefs;
+ }
+
/**
* <p>Returns the web container ServletContext</p>
*/
@@ -108,7 +237,11 @@
* </p>
*/
public ComponentBean getElement(String jsfid) {
- return (ComponentBean) displayElements.get(jsfid);
+ ComponentBean element = null;
+ synchronized (displayElements) {
+ element = (ComponentBean) displayElements.get(jsfid);
+ }
+ return element;
}
/**
@@ -212,50 +345,54 @@
*/
public void assignParent(ComponentBean b) {
- if (b instanceof InnerComponentBean) {
+ synchronized (displayElements) {
- // these elements are like inner classes
- // set the extends to the element so the
- // parent can be generically resolved
- if (b.getJsfid() != null) {
- b.setExtends(b.getJsfid());
+ if (b instanceof InnerComponentBean) {
+
+ // these elements are like inner classes
+ // set the extends to the element so the
+ // parent can be generically resolved
+ if (b.getJsfid() != null) {
+ b.setExtends(b.getJsfid());
+ }
}
- }
-
- // look for a meta inheritance property
- if (b.getExtends() != null) {
- // assign the parent to a top-level display element
- b.setIsAParent(
- (ComponentBean) displayElements.get(b.getExtends()));
+ // look for a meta inheritance property
+ if (b.getExtends() != null) {
+
+ // assign the parent to a top-level display element
+ b.setIsAParent(
+ (ComponentBean) displayElements.get(b.getExtends()));
+ }
+
+ // resolve inheritance of nested components
+ Iterator ci = b.getChildrenIterator();
+ while (ci.hasNext())
+ assignParent((ComponentBean) ci.next());
+
+ // resolve inheritance of converter
+ if (b.getConverter() != null)
+ assignParent(((ComponentBean) b).getConverter());
+
+ // resolve inheritance of validators
+ Iterator vi = b.getValidatorIterator();
+ while (vi.hasNext())
+ assignParent((ComponentBean) vi.next());
+
+ // resolve inheritance of value change listeners
+ vi = b.getValueChangeListenerIterator();
+ while (vi.hasNext())
+ assignParent((ComponentBean) vi.next());
+ vi = null;
+
+ // resolve inheritance of action listeners
+ vi = b.getActionListenerIterator();
+ while (vi.hasNext())
+ assignParent((ComponentBean) vi.next());
+ vi = null;
+
}
- // resolve inheritance of nested components
- Iterator ci = b.getChildrenIterator();
- while (ci.hasNext())
- assignParent((ComponentBean) ci.next());
-
- // resolve inheritance of converter
- if (b.getConverter() != null)
- assignParent(((ComponentBean) b).getConverter());
-
- // resolve inheritance of validators
- Iterator vi = b.getValidatorIterator();
- while (vi.hasNext())
- assignParent((ComponentBean) vi.next());
-
- // resolve inheritance of value change listeners
- vi = b.getValueChangeListenerIterator();
- while (vi.hasNext())
- assignParent((ComponentBean) vi.next());
- vi = null;
-
- // resolve inheritance of action listeners
- vi = b.getActionListenerIterator();
- while (vi.hasNext())
- assignParent((ComponentBean) vi.next());
- vi = null;
-
}
/**
@@ -659,12 +796,8 @@
}
- /**
- * <p>The destroy method is invoked to clean up resources. By
- * dereferencing the complex graph of display elements
- * </p>
- */
- public void destroy() {
+
+ protected void clear() {
Iterator di = displayElements.entrySet().iterator();
while (di.hasNext()) {
Map.Entry e = (Map.Entry) di.next();
@@ -680,8 +813,26 @@
}
di = null;
+ displayElements.clear();
+ }
+
+ /**
+ * <p>The destroy method is invoked to clean up resources. By
+ * dereferencing the complex graph of display elements
+ * </p>
+ */
+ public void destroy() {
+ clear();
context = null;
+ if (parser != null)
+ parser.setConfig(null);
+ parser = null;
+
+ if (watchDog != null)
+ watchDog.destroy();
+ watchDog = null;
+
}
/**
@@ -721,7 +872,213 @@
return 0;
}
+ /**
+ * <p>This class defines a single configration file that is watched for
+ * changes. In addition to the <code>URL</code> passed to the overloaded
+ * constructor, the <code>lastModifed</code> date is kept as a state
+ * variable.</p>
+ */
+ protected class XmlConfigDef implements ConfigBean.ConfigDefinition {
+ /**
+ * <p>The location of the config file.</p>
+ */
+ URL configUrl = null;
+
+ /**
+ * <p>Date the last time the file was modified as a
<code>long</code>.</p>
+ */
+ long lastModified = 0;
+
+ /**
+ * <p>Overloaded constructor that requires the target config
<code>URL</code>.
+ */
+ public XmlConfigDef(URL configUrl) {
+ this.configUrl = configUrl;
+ }
+
+ /**
+ * <p>Returns the target configuration file url.</p>
+ */
+ public URL getConfigUrl() {
+ return configUrl;
+ }
+
+ /**
+ * <p>Returns the last time the target configuration file was
modified.</p>
+ */
+ public long getLastModified() {
+ return lastModified;
+ }
+
+ /**
+ * <p>Sets the last time the target configuration file was
modified.</p>
+ */
+ public void setLastModified(long lastModified) {
+ this.lastModified = lastModified;
+ }
+ }
+
+ /**
+ * <p>This inner class watches for changes in a array of [EMAIL PROTECTED]
ConfigBean.ConfigDefinition}'s.
+ * This collection defines the configuration files that the [EMAIL
PROTECTED] org.apache.shale.clay.component.Clay}
+ * component uses.</p>
+ */
+ protected class WatchDog {
+
+ /**
+ * <p>Array of config file definitions.</p>
+ */
+ private ConfigBean.ConfigDefinition[] configDefs = null;
+
+ /**
+ * <p>Array of connections used to determine that the file has
changed.</p>
+ */
+ private URLConnection[] connections = null;
+
+ /**
+ * <p>Overloaded constructor that is passed the configuration file
+ * definitions as a parameter.</p>
+ */
+ public WatchDog(ConfigBean.ConfigDefinition[] configDefs) {
+ this.configDefs = configDefs;
+ }
+
+ /**
+ * <p>This method is invoked to dereference the private
+ * array of config file definitions.</p>
+ */
+ public void destroy() {
+ close();
+ for (int i = 0; i < configDefs.length; i++)
+ configDefs[i] = null;
+
+ configDefs = null;
+ }
+
+ /**
+ * <p>Loads an array of <code>URLConnection</code> corresponding to
the
+ * <code>configDefs</code>'s.</p>
+ */
+ private void open() {
+
+ if (connections != null)
+ close();
+
+ connections = new URLConnection[configDefs.length];
+ for (int i = 0; i < configDefs.length; i++) {
+
+ try {
+ connections[i] = configDefs[i].getConfigUrl()
+ .openConnection();
+ } catch (IOException e) {
+ log.error(messages.getMessage("parser.load.error",
+ new Object[] { configDefs[i].getConfigUrl()
+ .getPath() }), e);
+ }
+ }
+ }
+
+ /**
+ * <p>Performs some extra cleanup on the open array of
+ * <code>connections</code>.</p>
+ */
+ private void close() {
+ if (connections == null)
+ return;
+
+ for (int i = 0; i < connections.length; i++)
+ connections[i] = null;
+
+ connections = null;
+ }
+
+ /**
+ * <p>Iterates over the open <code>connections</code> looking
+ * for files that have changed. A <code>true</code> value is
+ * returned if one of the <code>configDefs</code> has been
+ * modified since last loaded.</p>
+ */
+ private boolean isDirty() {
+ for (int i = 0; i < configDefs.length; i++) {
+ if (configDefs[i].getLastModified() < connections[i]
+ .getLastModified())
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * <p>This method is the watch dog timmer. It's invoked to determine
+ * if any of the files have changed since the last time they were
loaded.
+ * If a change has occured on any of the <code>configDefs</code>, all
the
+ * files are reloaded and the last modified date is reset in the
+ * [EMAIL PROTECTED] ConfigBean.ConfigDefinition}.
+ * </p>
+ */
+ public void refresh() {
+
+ int i = 0;
+ try {
+ open();
+ if (isDirty()) {
+ clear();
+ for (i = 0; i < configDefs.length; i++) {
+
+ if (log.isInfoEnabled())
+ log.info(messages.getMessage("parser.load.file",
+ new Object[] { configDefs[i].getConfigUrl()
+ .getPath() }));
+
+ InputStream in = null;
+ try {
+
+ configDefs[i].setLastModified(connections[i]
+ .getLastModified());
+ in = connections[i].getInputStream();
+ parser.loadConfigFile(in);
+
+ } catch (IOException e) {
+ log.error(messages.getMessage("parser.load.error",
+ new Object[] { configDefs[i].getConfigUrl()
+ .getPath() }), e);
+ } catch (SAXException e) {
+ log.error(messages.getMessage("parser.load.error",
+ new Object[] { configDefs[i].getConfigUrl()
+ .getPath() }), e);
+ } finally {
+ if (in != null) {
+ try {
+ in.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+ }
+
+ resolveInheritance();
+ }
+ } finally {
+ close();
+ }
+ }
+
+ }
-
+ /**
+ * <p>This method should be called from key points in the application to
invoke
+ * automatic reloading of the configuration files if they have been
modified since
+ * last reloaded.</p>
+ */
+ public void refresh() {
+
+ // is auto watch turned off
+ if (!ComponentConfigBean.this.isWatchDogOn || watchDog == null)
+ return;
+
+ synchronized (displayElements) {
+ watchDog.refresh();
+ }
+ }
+
}
Modified:
struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/beans/ConfigBean.java
URL:
http://svn.apache.org/viewcvs/struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/beans/ConfigBean.java?rev=266287&r1=266286&r2=266287&view=diff
==============================================================================
---
struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/beans/ConfigBean.java
(original)
+++
struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/beans/ConfigBean.java
Thu Sep 1 22:14:12 2005
@@ -19,6 +19,8 @@
package org.apache.shale.clay.config.beans;
+import java.net.URL;
+
import javax.servlet.ServletContext;
/**
@@ -28,6 +30,25 @@
*/
public interface ConfigBean extends Comparable {
+ /**
+ * <p>Top-level interface that defines a single configuration
+ * file entry.<p>
+ */
+ interface ConfigDefinition {
+ /**
+ * <p>Returns the URL of the config file.</p>
+ */
+ public URL getConfigUrl();
+ /**
+ * <p>Returns the last modified date of the config file.</p>
+ */
+ public long getLastModified();
+ /**
+ * </p>Sets the last modified date of the config file.</p>
+ */
+ public void setLastModified(long lastModified);
+ }
+
/**
* <p>Factory method that returns a [EMAIL PROTECTED] ComponentBean}
* using an identifier.
@@ -78,5 +99,11 @@
*/
public void assignParent(ComponentBean b);
-
+ /**
+ * <p>This method should be called from key points in the application to
invoke
+ * automatic reloading of the configuration files if they have been
modified since
+ * last reloaded.</p>
+ */
+ public void refresh();
+
}
Modified:
struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/beans/ConfigBeanFactory.java
URL:
http://svn.apache.org/viewcvs/struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/beans/ConfigBeanFactory.java?rev=266287&r1=266286&r2=266287&view=diff
==============================================================================
---
struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/beans/ConfigBeanFactory.java
(original)
+++
struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/beans/ConfigBeanFactory.java
Thu Sep 1 22:14:12 2005
@@ -60,8 +60,7 @@
break;
}
}
-
-
+
return config;
}
@@ -80,5 +79,20 @@
}
configBeans.clear();
}
+
+ /**
+ * <p>This method should be called from key points in the application to
invoke
+ * automatic reloading of the configuration files if they have been
modified since
+ * last reloaded.</p>
+ */
+ public static void refresh() {
+ Iterator ci = configBeans.iterator();
+ ConfigBean config = null;
+ while (ci.hasNext()) {
+ config = (ConfigBean) ci.next();
+ config.refresh();
+ }
+ }
+
}
Added:
struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/beans/ConfigDefinitionsWatchdogFilter.java
URL:
http://svn.apache.org/viewcvs/struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/beans/ConfigDefinitionsWatchdogFilter.java?rev=266287&view=auto
==============================================================================
---
struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/beans/ConfigDefinitionsWatchdogFilter.java
(added)
+++
struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/beans/ConfigDefinitionsWatchdogFilter.java
Thu Sep 1 22:14:12 2005
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Id$
+ */
+
+package org.apache.shale.clay.config.beans;
+
+import org.apache.shale.application.AbstractRegExpFilter;
+import org.apache.shale.faces.ShaleWebContext;
+
+public class ConfigDefinitionsWatchdogFilter extends AbstractRegExpFilter {
+
+ /**
+ * <p>Return the servlet path (if any) concatenated with the path info
+ * (if any) for this request.</p>
+ *
+ * @param context <code>Context</code> for the current request
+ */
+ protected String value(ShaleWebContext context) {
+
+ String servletPath = context.getRequest().getServletPath();
+ if (servletPath == null) {
+ servletPath = "";
+ }
+ String pathInfo = context.getRequest().getPathInfo();
+ if (pathInfo == null) {
+ pathInfo = "";
+ }
+ return servletPath + pathInfo;
+
+ }
+
+ /**
+ * <p>Override the base implementation to ignore this condition.</p>
+ *
+ * @param context <code>Context</code> for the current request
+ */
+ protected void reject(ShaleWebContext context) throws Exception {
+ }
+
+ /**
+ * <p>Trigger reloading of the [EMAIL PROTECTED]
org.apache.shale.clay.component.Clay}'s
+ * xml configuration files if the <code>auto-reload-clay-files</code> init
+ * parameter is set to <code>true</code> in the web.xml.</p>
+ *
+ * @param context <code>Context</code> for the current request
+ */
+ protected void accept(ShaleWebContext context) throws Exception {
+ ConfigBeanFactory.refresh();
+ }
+
+
+
+}
Modified:
struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/beans/TemplateConfigBean.java
URL:
http://svn.apache.org/viewcvs/struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/beans/TemplateConfigBean.java?rev=266287&r1=266286&r2=266287&view=diff
==============================================================================
---
struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/beans/TemplateConfigBean.java
(original)
+++
struts/shale/trunk/clay-plugin/src/java/org/apache/shale/clay/config/beans/TemplateConfigBean.java
Thu Sep 1 22:14:12 2005
@@ -152,6 +152,13 @@
public boolean validMoniker(String id) {
return id.endsWith(suffix);
}
-
+
+ /**
+ * <p>Override this method to suppress loading configuration files. This
+ * [EMAIL PROTECTED] ConfigBean} doesn't need the cached graph of
components. It's
+ * purpose is to load [EMAIL PROTECTED] ElementBean}'s from a HTML
document.
+ * </p>
+ */
+ protected void loadConfigFiles() {}
}
Modified:
struts/shale/trunk/clay-plugin/src/test/org/apache/shale/clay/config/ConfigTestCase.java
URL:
http://svn.apache.org/viewcvs/struts/shale/trunk/clay-plugin/src/test/org/apache/shale/clay/config/ConfigTestCase.java?rev=266287&r1=266286&r2=266287&view=diff
==============================================================================
---
struts/shale/trunk/clay-plugin/src/test/org/apache/shale/clay/config/ConfigTestCase.java
(original)
+++
struts/shale/trunk/clay-plugin/src/test/org/apache/shale/clay/config/ConfigTestCase.java
Thu Sep 1 22:14:12 2005
@@ -167,10 +167,8 @@
protected void loadConfigFile(String configFiles) {
// this would be done in the ClayConfigureListener
- ClayXmlParser parser = new ClayXmlParser();
- parser.setConfig((ComponentConfigBean) standardConfigBean);
-
- parser.load(configFiles);
+ servletContext.addInitParameter(Globals.CLAY_CONFIG_FILES,
configFiles);
+ standardConfigBean.init(servletContext);
}
public void testLoadConfigFile() {
Modified:
struts/shale/trunk/clay-plugin/src/test/org/apache/shale/clay/parser/ParserTestCase.java
URL:
http://svn.apache.org/viewcvs/struts/shale/trunk/clay-plugin/src/test/org/apache/shale/clay/parser/ParserTestCase.java?rev=266287&r1=266286&r2=266287&view=diff
==============================================================================
---
struts/shale/trunk/clay-plugin/src/test/org/apache/shale/clay/parser/ParserTestCase.java
(original)
+++
struts/shale/trunk/clay-plugin/src/test/org/apache/shale/clay/parser/ParserTestCase.java
Thu Sep 1 22:14:12 2005
@@ -244,7 +244,7 @@
List nodes = p.parse(doc);
assertTrue("Failed unmatched non-optional ending tag test", false);
} catch (Exception e) {
- assertTrue("Failed unmatched non-optional ending tag test",
e.getMessage().startsWith("Unmatched ending non-option token"));
+ assertTrue("Failed unmatched non-optional ending tag test",
e.getMessage().startsWith("Unmatched ending non-optional token"));
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]