struts-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From gvanma...@apache.org
Subject svn commit: r266287 - in /struts/shale/trunk/clay-plugin/src: java/org/apache/shale/clay/config/ java/org/apache/shale/clay/config/beans/ test/org/apache/shale/clay/config/ test/org/apache/shale/clay/parser/
Date Fri, 02 Sep 2005 05:14:26 GMT
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
{@link 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 {@link 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 {@link 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 {@link 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 {@link 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 {@link 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 {@link ConfigBean.ConfigDefinition}'s.
+     * This collection defines the configuration files that the {@link 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
+         * {@link 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 {@link 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 {@link 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
+     * {@link ConfigBean} doesn't need the cached graph of components.  It's 
+     * purpose is to load {@link 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: dev-unsubscribe@struts.apache.org
For additional commands, e-mail: dev-help@struts.apache.org


Mime
View raw message