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]