commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From craig...@apache.org
Subject cvs commit: jakarta-commons/chain/src/java/org/apache/commons/chain/web ChainResources.java
Date Mon, 18 Oct 2004 01:07:42 GMT
craigmcc    2004/10/17 18:07:42

  Modified:    chain/src/java/org/apache/commons/chain CatalogFactory.java
               chain/src/java/org/apache/commons/chain/config
                        ConfigParser.java ConfigRuleSet.java
               chain/src/java/org/apache/commons/chain/impl
                        CatalogFactoryBase.java
               chain/src/java/org/apache/commons/chain/web
                        ChainResources.java
  Log:
  Make CatalogFactory an abstract class instead of an interface, and make
  the getInstance() and clear() methods static on this class.  This is
  necessary both to avoid applications having to reference CatalogFactoryBase,
  but also to ensure that the clear() method actually releases all references
  to the relevant class loader -- in the original scheme, we would still have
  been leaving garbage lying around.
  
  Refine ConfigRuleSet so that multiple <factory> elements with the same
  catalog name will cause the nested chain and command definitions to be
  merged, instead of replacing the entire catalog with only the contents
  of the last <factory> element.
  
  FIXME: Modify ConfigureListener and ConfigureServlet to use the new
  mechanisms that expect a <factory> element -- but find a backwards
  compatible way to continue supporting existing use cases.
  
  Revision  Changes    Path
  1.4       +86 -12    jakarta-commons/chain/src/java/org/apache/commons/chain/CatalogFactory.java
  
  Index: CatalogFactory.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/chain/src/java/org/apache/commons/chain/CatalogFactory.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- CatalogFactory.java	17 Oct 2004 01:53:53 -0000	1.3
  +++ CatalogFactory.java	18 Oct 2004 01:07:41 -0000	1.4
  @@ -15,7 +15,10 @@
    */
   package org.apache.commons.chain;
   
  +import java.util.HashMap;
   import java.util.Iterator;
  +import java.util.Map;
  +import org.apache.commons.chain.impl.CatalogFactoryBase;
   
   /**
    * <p>A {@link CatalogFactory} is a class used to store and retrieve
  @@ -27,15 +30,19 @@
    * @version $Revision$ $Date$
    */
   
  -public interface CatalogFactory {
  +public abstract class CatalogFactory {
  +
  +
  +    // --------------------------------------------------------- Public Methods
   
   
       /**
  -     * <p>Gets the default instance of Catalog associated with the factory.</p>
  +     * <p>Gets the default instance of Catalog associated with the factory
  +     * (if any); otherwise, return <code>null</code>.</p>
        *
        * @return the default Catalog instance
        */
  -    public Catalog getCatalog();
  +    public abstract Catalog getCatalog();
   
   
       /**
  @@ -43,16 +50,17 @@
        *
        * @param catalog the default Catalog instance
        */
  -    public void setCatalog(Catalog catalog);
  +    public abstract void setCatalog(Catalog catalog);
   
   
       /**
  -     * <p>Retrieves a Catalog instance by name.</p>
  +     * <p>Retrieves a Catalog instance by name (if any); otherwise
  +     * return <code>null</code>.</p>
        *
        * @param name the name of the Catalog to retrieve
        * @return the specified Catalog
        */
  -    public Catalog getCatalog(String name);
  +    public abstract Catalog getCatalog(String name);
   
   
       /**
  @@ -62,7 +70,7 @@
        * @param name the name of the Catalog to add
        * @param catalog the Catalog to add
        */
  -    public void addCatalog(String name, Catalog catalog);
  +    public abstract void addCatalog(String name, Catalog catalog);
   
   
       /**
  @@ -70,14 +78,80 @@
        * {@link Catalog}s known to this {@link CatalogFactory}.
        * If there are no known catalogs, an empty Iterator is returned.</p>
        */
  -    public Iterator getNames();
  +    public abstract Iterator getNames();
  +
  +
  +    // ------------------------------------------------------- Static Variables
  +    
  +
  +    /**
  +     * <p>The set of registered {@link CatalogFactory} instances,
  +     * keyed by the relevant class loader.</p>
  +     */
  +    private static Map factories = new HashMap();
  +
  +
  +    // -------------------------------------------------------- Static Methods
   
   
       /**
  -     * <p>Release all {@link Catalog}s currently registered with
  -     * this {@link CatalogFactory}.</p>
  +     * <p>Return the singleton {@link CatalogFactory} instance
  +     * for the relevant <code>ClassLoader</code>.  For applications
  +     * that use a thread context class loader (such as web applications
  +     * running inside a servet container), this will return a separate
  +     * instance for each application, even if this class is loaded from
  +     * a shared parent class loader.</p>
  +     * 
  +     * @return the per-application singleton instance of {@link CatalogFactory}
        */
  -    public void clear();
  +    public static CatalogFactory getInstance() {
  +
  +        CatalogFactory factory = null;
  +        ClassLoader cl = getClassLoader();
  +        synchronized (factories) {
  +            factory = (CatalogFactory) factories.get(cl);
  +            if (factory == null) {
  +                factory = new CatalogFactoryBase();
  +                factories.put(cl, factory);
  +            }
  +        }
  +        return factory;
  +        
  +    }
  +    
  +
  +    /**
  +     * <p>Clear all references to registered catalogs, as well as to the
  +     * relevant class loader.  This method should be called, for example,
  +     * when a web application utilizing this class is removed from
  +     * service, to allow for garbage collection.</p>
  +     */
  +    public static void clear() {
  +
  +        synchronized (factories) {
  +            factories.remove(getClassLoader());
  +        }
  +
  +    }
  +
  +
  +    // ------------------------------------------------------- Private Methods
  +
  +
  +    /**
  +     * <p>Return the relevant <code>ClassLoader</code> to use as a Map
key
  +     * for this request.  If there is a thread context class loader, return
  +     * that; otherwise, return the class loader that loaded this class.</p>
  +     */
  +    private static ClassLoader getClassLoader() {
  +
  +        ClassLoader cl = Thread.currentThread().getContextClassLoader();
  +        if (cl == null) {
  +            cl = CatalogFactory.class.getClassLoader();
  +        }
  +        return cl;
  +
  +    }
   
   
   }
  
  
  
  1.4       +34 -2     jakarta-commons/chain/src/java/org/apache/commons/chain/config/ConfigParser.java
  
  Index: ConfigParser.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/chain/src/java/org/apache/commons/chain/config/ConfigParser.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- ConfigParser.java	25 Feb 2004 00:01:06 -0000	1.3
  +++ ConfigParser.java	18 Oct 2004 01:07:41 -0000	1.4
  @@ -140,13 +140,18 @@
       /**
        * <p>Parse the XML document at the specified URL, using the configured
        * <code>RuleSet</code>, registering top level commands into the specified
  -     * {@link Catalog}.</p>
  +     * {@link Catalog}.  Use this method <strong>only</strong> if you have
  +     * <strong>NOT</strong> included any <code>factory</code> element
in your
  +     * configuration resource, and wish to supply the catalog explictly.</p>
        *
        * @param catalog {@link Catalog} into which configured chains are
        *  to be registered
        * @param url <code>URL</code> of the XML document to be parsed
        *
        * @exception Exception if a parsing error occurs
  +     *
  +     * @deprecated Use parse(URL) on a configuration resource with "factory"
  +     *  element(s) embedded
        */
       public void parse(Catalog catalog, URL url) throws Exception {
   
  @@ -154,6 +159,33 @@
           Digester digester = getDigester();
           digester.clear();
           digester.push(catalog);
  +
  +        // Prepare our InputSource
  +        InputSource source = new InputSource(url.toExternalForm());
  +        source.setByteStream(url.openStream());
  +
  +        // Parse the configuration document
  +        digester.parse(source);
  +
  +    }
  +
  +
  +    /**
  +     * <p>Parse the XML document at the specified URL using the configured
  +     * <code>RuleSet</code>, registering catalogs with nested chains and
  +     * commands as they are encountered.  Use this method <strong>only</strong>
  +     * if you have included one or more <code>factory</code> elements in your
  +     * configuration resource.</p>
  +     *
  +     * @param url <code>URL</code> of the XML document to be parsed
  +     *
  +     * @exception Exception if a parsing error occurs
  +     */
  +    public void parse(URL url) throws Exception {
  +
  +        // Prepare our Digester instance
  +        Digester digester = getDigester();
  +        digester.clear();
   
           // Prepare our InputSource
           InputSource source = new InputSource(url.toExternalForm());
  
  
  
  1.8       +55 -1     jakarta-commons/chain/src/java/org/apache/commons/chain/config/ConfigRuleSet.java
  
  Index: ConfigRuleSet.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/chain/src/java/org/apache/commons/chain/config/ConfigRuleSet.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- ConfigRuleSet.java	16 Jul 2004 19:06:01 -0000	1.7
  +++ ConfigRuleSet.java	18 Oct 2004 01:07:41 -0000	1.8
  @@ -17,6 +17,7 @@
   
   
   import org.apache.commons.chain.Catalog;
  +import org.apache.commons.chain.CatalogFactory;
   import org.apache.commons.chain.Chain;
   import org.apache.commons.chain.Command;
   import org.apache.commons.digester.Digester;
  @@ -30,6 +31,16 @@
    * executing the <code>addRuleInstance()</code> method in order to influence
    * the rules that get added, with default values in square brackets:</p>
    * <ul>
  + * <li><strong>catalogClass</strong> -- Fully qualified name of the
  + *     implementation class used to create new {@link Catalog} instances.
  + *     If not specified, the default value is
  + *     <code>org.apache.commons.chain.impl.CatalogBsae</code>.</li>
  + * <li><strong>catalogElement</strong> -- Name of the XML element representing
  + *     the addition of a {@link Catalog}.  Any such catalog that is created
  + *     will be registered with the {@link CatalogFactory} instance for our
  + *     application, under the name specified by the <code>nameAttribute</code>
  + *     attribute (if present), or as the default {@link Catalog}.  If not
  + *     specified, the default value is <code>catalog</code>.</li>
    * <li><strong>chainClass</strong> -- Fully qualified name of the implementation
    *     class used to create new {@link Chain} instances.  If not specified, the
    *     default value is <code>org.apache.commons.chain.impl.ChainBase</code>.
  @@ -69,6 +80,8 @@
       // ----------------------------------------------------- Instance Variables
   
   
  +    private String catalogClass = "org.apache.commons.chain.impl.CatalogBase";
  +    private String catalogElement = "catalog";
       private String chainClass = "org.apache.commons.chain.impl.ChainBase";
       private String chainElement = "chain";
       private String classAttribute = "className";
  @@ -81,6 +94,42 @@
   
   
       /**
  +     * <p>Return the fully qualified {@link Catalog} implementation class.</p>
  +     */
  +    public String getCatalogClass() {
  +        return (this.catalogClass);
  +    }
  +
  +
  +    /**
  +     * <p>Set the fully qualified {@link Catalog} implementation class.</p>
  +     *
  +     * @param catalogClass The new {@link Catalog} implementation class
  +     */
  +    public void setCatalogClass(String catalogClass) {
  +        this.catalogClass = catalogClass;
  +    }
  +
  +
  +    /**
  +     * <p>Return the element name of a catalog element.</p>
  +     */
  +    public String getCatalogElement() {
  +        return (this.catalogElement);
  +    }
  +
  +
  +    /**
  +     * <p>Set the element name of a catalog element.</p>
  +     *
  +     * @param catalogElement The new element name
  +     */
  +    public void setCatalogElement(String catalogElement) {
  +        this.catalogElement = catalogElement;
  +    }
  +
  +
  +    /**
        * <p>Return the fully qualified {@link Chain} implementation class.</p>
        */
       public String getChainClass() {
  @@ -201,6 +250,11 @@
        *  should be added.
        */
       public void addRuleInstances(Digester digester) {
  +
  +        // Add rules for a catalog element
  +        digester.addRule("*/" + getCatalogElement(),
  +                         new ConfigCatalogRule(nameAttribute, catalogClass));
  +        digester.addSetProperties("*/" + getCatalogElement());
   
           // Add rules for a chain element
           digester.addObjectCreate("*/" + getChainElement(),
  
  
  
  1.3       +21 -120   jakarta-commons/chain/src/java/org/apache/commons/chain/impl/CatalogFactoryBase.java
  
  Index: CatalogFactoryBase.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/chain/src/java/org/apache/commons/chain/impl/CatalogFactoryBase.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- CatalogFactoryBase.java	17 Oct 2004 22:39:00 -0000	1.2
  +++ CatalogFactoryBase.java	18 Oct 2004 01:07:42 -0000	1.3
  @@ -30,66 +30,41 @@
    * @version $Revision$ $Date$
    */
   
  -public class CatalogFactoryBase implements CatalogFactory {
  -    
  -
  -    // ------------------------------------------------------- Static Variables
  -    
  -
  -    /**
  -     * <p>The singleton instance.</p>
  -     */
  -    private static CatalogFactoryBase instance = new CatalogFactoryBase();
  -
  -
  -    /**
  -     * <p>A default value to store an unamed {@link Catalog} in the local 
  -     * Map.</p>
  -     */
  -    private static String DEFAULT_CATALOG =
  -        "org.apache.commons.chain.DEFAULT_CATALOG";
  +public class CatalogFactoryBase extends CatalogFactory {
       
   
       // ----------------------------------------------------------- Constructors
       
       
       /**
  -     * <p>Constructs an instance of CatalogFactoryBase.  NOTE: This is private 
  -     * because it is not meant to be created directly outside of the class.  
  -     * Use the <code>getInstance()</code> method instead.</p>
  +     * <p>Construct an empty instance of {@link CatalogFactoryBase}.  This
  +     * constructor is intended solely for use by {@link CatalogFactory}.</p>
        */
  -    private CatalogFactoryBase() {}
  +    public CatalogFactoryBase() {}
       
       
       // ----------------------------------------------------- Instance Variables
       
       
       /**
  -     * <p>Map of Maps of {@link Catalog}s, keyed by the object's 
  -     * ClassLoader.</p>
  +     * <p>The default {@link Catalog} for this {@link CatalogFactory).</p>
        */
  -    protected Map loaderMap = new HashMap();
  -    
  -    
  -    // --------------------------------------------------------- Public Methods
  -    
  +    private Catalog catalog = null;
  +
   
       /**
  -     * <p>Gets the singleton instance of CatalogFactoryBase.</p>
  -     * 
  -     * @return the singleton instance of CatalogFactoryBase.
  +     * <p>Map of named {@link Catalog}s, keyed by catalog name.</p>
        */
  -    public static CatalogFactory getInstance() {
  -        
  -        return instance;    
  -        
  -    }
  +    private Map catalogs = new HashMap();
  +    
  +    
  +    // --------------------------------------------------------- Public Methods
       
   
       // Documented in CatalogFactory interface
       public Catalog getCatalog() {
           
  -        return getCatalog(DEFAULT_CATALOG);        
  +        return catalog;
   
       }
   
  @@ -97,7 +72,7 @@
       // Documented in CatalogFactory interface
       public void setCatalog(Catalog catalog) {
           
  -        addCatalog(DEFAULT_CATALOG, catalog);
  +        this.catalog = catalog;
           
       }
   
  @@ -105,20 +80,8 @@
       // Documented in CatalogFactory interface
       public Catalog getCatalog(String name) {
           
  -        /**
  -         * In the event that this class will be used by multiple applications 
  -         * with the same class loader (as with web applications), there will 
  -         * be a separate Map of Catalogs for each instance of 
  -         * ClassLoader.  That way each web application (which will always have 
  -         * its own) can operate without interfering with one another.
  -         */
  -        Map catalogMap = getCatalogMap();
  -        if (catalogMap != null) {
  -            synchronized (catalogMap) {
  -                return (Catalog) catalogMap.get(name);
  -            }
  -        } else {
  -            return null;
  +        synchronized (catalogs) {
  +            return (Catalog) catalogs.get(name);
           }
   
       }
  @@ -127,18 +90,8 @@
       // Documented in CatalogFactory interface
       public void addCatalog(String name, Catalog catalog) {
   
  -        // Retrieve or create the catalog map for the correct class loader
  -        Map catalogMap = getCatalogMap();
  -        if (catalogMap == null) {
  -            catalogMap = new HashMap();
  -            synchronized (loaderMap) {
  -                loaderMap.put(getLoaderMapKey(), catalogMap);
  -            }
  -        }
  -
  -        // Add or replace the specified Catalog
  -        synchronized (catalogMap) {
  -            catalogMap.put(name, catalog);
  +        synchronized (catalogs) {
  +            catalogs.put(name, catalog);
           }
   
       }
  @@ -147,61 +100,9 @@
       // Documented in CatalogFactory interface
       public Iterator getNames() {
   
  -        Map catalogMap = getCatalogMap();
  -        if (catalogMap != null) {
  -            synchronized (catalogMap) {
  -                return catalogMap.keySet().iterator();
  -            }
  -        } else {
  -            return Collections.EMPTY_LIST.iterator();
  -        }
  -
  -    }
  -
  -
  -    // Documented in CatalogFactory interface
  -    public void clear() {
  -
  -        Map catalogMap = getCatalogMap();
  -        if (catalogMap != null) {
  -            synchronized (catalogMap) {
  -                catalogMap.clear();
  -            }
  -        }
  -
  -    }
  -
  -
  -    // ------------------------------------------------------- Private Methods
  -
  -
  -    /**
  -     * <p>Return the <code>Map</code> containing the relevant
  -     * {@link Catalog}s for an application, keyed by cataog name.
  -     * If there is no such <code>Map</code>, return <code>null</code>.</p>
  -     */
  -    private Map getCatalogMap() {
  -
  -        ClassLoader cl = getLoaderMapKey();
  -        synchronized (loaderMap) {
  -            return (Map) loaderMap.get(cl);
  -        }
  -
  -    }
  -
  -
  -    /**
  -     * <p>Return the <code>ClassLoader</code> to serve as the key
  -     * for a <code>loaderMap</code> entry that consists of the
  -     * <code>Map</code> of {@link Catalog}s for that class laoder.</p>
  -     */
  -    private ClassLoader getLoaderMapKey() {
  -
  -        ClassLoader cl = Thread.currentThread().getContextClassLoader();
  -        if (cl == null) { // If context class loader is not defined ...
  -            cl = this.getClass().getClassLoader(); // Get CL that loaded us
  +        synchronized (catalogs) {
  +            return catalogs.keySet().iterator();
           }
  -        return cl;
   
       }
   
  
  
  
  1.6       +103 -0    jakarta-commons/chain/src/java/org/apache/commons/chain/web/ChainResources.java
  
  Index: ChainResources.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/chain/src/java/org/apache/commons/chain/web/ChainResources.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- ChainResources.java	25 Feb 2004 00:01:06 -0000	1.5
  +++ ChainResources.java	18 Oct 2004 01:07:42 -0000	1.6
  @@ -51,9 +51,62 @@
       /**
        * <p>Parse the specified class loader resources.</p>
        *
  +     * @param resources Comma-delimited list of resources (or <code>null</code>)
  +     * @param parser {@link ConfigParser} to use for parsing
  +     */
  +    static void parseClassResources(String resources,
  +                                    ConfigParser parser) {
  +
  +        if (resources == null) {
  +            return;
  +        }
  +        ClassLoader loader =
  +            Thread.currentThread().getContextClassLoader();
  +        if (loader == null) {
  +            loader = ChainResources.class.getClassLoader();
  +        }
  +        String path = null;
  +        try {
  +            while (true) {
  +                int comma = resources.indexOf(",");
  +                if (comma < 0) {
  +                    path = resources.trim();
  +                    resources = "";
  +                } else {
  +                    path = resources.substring(0, comma);
  +                    resources = resources.substring(comma + 1);
  +                }
  +                if (path.length() < 1) {
  +                    break;
  +                }
  +                URL url = loader.getResource(path);
  +                if (url == null) {
  +                    throw new IllegalStateException
  +                        ("Missing chain config resource '" + path + "'");
  +                }
  +                if (log.isDebugEnabled()) {
  +                    log.debug("Loading chain config resource '" + path + "'");
  +                }
  +                parser.parse(url);
  +            }
  +        } catch (Exception e) {
  +            throw new RuntimeException
  +                ("Exception parsing chain config resource '" + path + "': " +
  +                 e.getMessage());
  +        }
  +
  +    }
  +
  +
  +    /**
  +     * <p>Parse the specified class loader resources.</p>
  +     *
        * @param catalog {@link Catalog} we are populating
        * @param resources Comma-delimited list of resources (or <code>null</code>)
        * @param parser {@link ConfigParser} to use for parsing
  +     *
  +     * @deprecated Use the variant that does not take a catalog, on a
  +     *  configuration resource containing "catalog" element(s)
        */
       static void parseClassResources(Catalog catalog, String resources,
                                       ConfigParser parser) {
  @@ -102,10 +155,60 @@
       /**
        * <p>Parse the specified web application resources.</p>
        *
  +     * @param context <code>ServletContext</code> for this web application
  +     * @param resources Comma-delimited list of resources (or <code>null</code>)
  +     * @param parser {@link ConfigParser} to use for parsing
  +     */
  +    static void parseWebResources(ServletContext context,
  +                                  String resources,
  +                                  ConfigParser parser) {
  +
  +        if (resources == null) {
  +            return;
  +        }
  +        String path = null;
  +        try {
  +            while (true) {
  +                int comma = resources.indexOf(",");
  +                if (comma < 0) {
  +                    path = resources.trim();
  +                    resources = "";
  +                } else {
  +                    path = resources.substring(0, comma);
  +                    resources = resources.substring(comma + 1);
  +                }
  +                if (path.length() < 1) {
  +                    break;
  +                }
  +                URL url = context.getResource(path);
  +                if (url == null) {
  +                    throw new IllegalStateException
  +                        ("Missing chain config resource '" + path + "'");
  +                }
  +                if (log.isDebugEnabled()) {
  +                    log.debug("Loading chain config resource '" + path + "'");
  +                }
  +                parser.parse(url);
  +            }
  +        } catch (Exception e) {
  +            throw new RuntimeException
  +                ("Exception parsing chain config resource '" + path + "': " +
  +                 e.getMessage());
  +        }
  +
  +    }
  +
  +
  +    /**
  +     * <p>Parse the specified web application resources.</p>
  +     *
        * @param catalog {@link Catalog} we are populating
        * @param context <code>ServletContext</code> for this web application
        * @param resources Comma-delimited list of resources (or <code>null</code>)
        * @param parser {@link ConfigParser} to use for parsing
  +     *
  +     * @deprecated Use the variant that does not take a catalog, on a
  +     *  configuration resource containing "catalog" element(s)
        */
       static void parseWebResources(Catalog catalog, ServletContext context,
                                     String resources,
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Mime
View raw message