You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by he...@apache.org on 2003/06/07 19:57:29 UTC

cvs commit: jakarta-commons-sandbox/configuration/src/test/org/apache/commons/configuration TestConfigurationFactory.java

henning     2003/06/07 10:57:29

  Modified:    configuration project.xml
               configuration/src/java/org/apache/commons/configuration
                        ConfigurationFactory.java
                        CompositeConfiguration.java
               configuration/src/test/org/apache/commons/configuration
                        TestConfigurationFactory.java
  Log:
  While hunting for some obscure Turbine configuration load bug, I
  stumbled across the ConfigurationFactory... poor thingie.
  
  - added lots of javadocs
  - cleaned up the init logics (Eric you can trust void xxx(Foo foo) to
    really keep the same object in foo. ;-) )
  - clean up the digester setup, replaced the non-working setBasePath
    with a factory creation which sets the BasePath right even before
    the configuration file itself is loaded
  - add two tiny inner classes to allow setting of the base path from
    the factory itself
  - make sure that getBasePath never returns null
  - replaced class names in strings by class.getName() so that typos
    are caught at compile time.
  
  I'm 99% sure that setting the RuleNamespace will blow this bugger
  apart.  You do need a factory from an inner class of the Configuration
  factory to get the base Path right; even if the test with the rule
  configuration file works, I'm pretty sure that the resulting rule set
  will not read configuration files if you're not running from the
  current (".") directory as base path.
  
  I'm also 99% sure that the RuleNamespace and Namespace awareness in the
  configuration file can't be used together. As far as I can see, the
  namespace awareness must be set/reset before the rules are added. In
  the case of the DigestLoader (using a DigesterRules() URI), the rules
  are already added when configureNamespace() is called on the digester.
  
  I added the last two point to the tasks list in the docs.
  
  Revision  Changes    Path
  1.26      +2 -2      jakarta-commons-sandbox/configuration/project.xml
  
  Index: project.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-commons-sandbox/configuration/project.xml,v
  retrieving revision 1.25
  retrieving revision 1.26
  diff -u -r1.25 -r1.26
  --- project.xml	3 Jun 2003 14:15:23 -0000	1.25
  +++ project.xml	7 Jun 2003 17:57:28 -0000	1.26
  @@ -10,7 +10,7 @@
     <pomVersion>3</pomVersion>
     <name>commons-configuration</name>
     <id>commons-configuration</id>
  -  <currentVersion>1.0-dev-3.20030603.101200</currentVersion>
  +  <currentVersion>1.0-dev-3.20030607.194155</currentVersion>
     <organization>
       <name>Apache Software Foundation</name>
       <url>http://jakarta.apache.org/</url>
  
  
  
  1.4       +175 -47   jakarta-commons-sandbox/configuration/src/java/org/apache/commons/configuration/ConfigurationFactory.java
  
  Index: ConfigurationFactory.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons-sandbox/configuration/src/java/org/apache/commons/configuration/ConfigurationFactory.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- ConfigurationFactory.java	24 Mar 2003 07:23:47 -0000	1.3
  +++ ConfigurationFactory.java	7 Jun 2003 17:57:29 -0000	1.4
  @@ -59,11 +59,18 @@
   import java.io.InputStream;
   import java.net.URL;
   
  +import org.apache.commons.digester.AbstractObjectCreationFactory;
  +import org.apache.commons.digester.ObjectCreationFactory;
   import org.apache.commons.digester.Digester;
   import org.apache.commons.digester.ObjectParamRule;
   import org.apache.commons.digester.xmlrules.DigesterLoader;
  +
  +import org.apache.commons.lang.StringUtils;
  +
   import org.apache.commons.logging.Log;
   import org.apache.commons.logging.LogFactory;
  +
  +import org.xml.sax.Attributes;
   import org.xml.sax.SAXException;
   
   /**
  @@ -73,8 +80,8 @@
    * digester rules to use.  It is also namespace aware, by providing a
    * digesterRuleNamespaceURI.
    *
  - 
    * @author <a href="mailto:epugh@upstate.com">Eric Pugh</a>
  + * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
    * @version $Id$
    */
   public class ConfigurationFactory
  @@ -94,30 +101,57 @@
       /** The digester namespace to parse */
       private String digesterRuleNamespaceURI;
   
  +    /**
  +     * C'tor
  +     */
       public ConfigurationFactory()
  -    {}
  +    {
  +    }
  +
  +    /**
  +     * C'tor with ConfigurationFile Name passed
  +     *
  +     * @param configurationFileName The path to the configuration file
  +     */
  +    public ConfigurationFactory(String configurationFileName)
  +    {
  +        this.configurationFileName = configurationFileName;
  +    }
   
  +    /**
  +     * Return the configuration provided by this factory. It
  +     * loads the configuration file which is a XML description of
  +     * the actual configurations to load. It can contain various
  +     * different types of configuration, currently Properties, XML and JNDI.
  +     *
  +     * @return A Configuration object
  +     * @throws Exception A generic exception that we had trouble during the
  +     * loading of the configuration data.
  +     */
       public Configuration getConfiguration() throws Exception
       {
  +        Digester digester;
  +        CompositeConfiguration configuration = new CompositeConfiguration();
           InputStream input = new FileInputStream(new File(getConfigurationFileName()));
  -        CompositeConfiguration compositeConfiguration = new CompositeConfiguration();
  -
  -        Digester digester = null;
   
           if (getDigesterRules() == null)
           {
               digester = new Digester();
  -            digester = configureDigester(compositeConfiguration, digester);
  -            digester = initDefaultDigester(digester);
  +            configureNamespace(digester);
  +            initDefaultDigesterRules(digester);
           }
           else
           {
               digester = DigesterLoader.createDigester(getDigesterRules());
  -            digester = configureDigester(compositeConfiguration, digester);
   
  -            digester.push(compositeConfiguration);
  +            // This might already be too late. As far as I can see, the namespace
  +            // awareness must be configured before the digester rules are loaded.
  +            configureNamespace(digester);
           }
   
  +        // Put the composite object below all of the other objects.
  +        digester.push(configuration);
  +
           // Parse the input stream to configure our mappings
           try
           {
  @@ -126,14 +160,15 @@
           }
           catch (SAXException e)
           {
  -            log.error("::initXMLConfig - SaxException", e);
  -            throw new Exception(e.toString());
  +            log.error("SAX Exception caught", e);
  +            throw e;
           }
  -        return compositeConfiguration;
  +        return configuration;
       }
       /**
        * Returns the configurationFile.
  -     * @return String
  +     *
  +     * @return The name of the configuration file. Can be null.
        */
       public String getConfigurationFileName()
       {
  @@ -142,7 +177,7 @@
   
       /**
        * Sets the configurationFile.
  -     * @param configurationFile The configurationFile to set
  +     * @param configurationFileName  The name of the configurationFile to use.
        */
       public void setConfigurationFileName(String configurationFileName)
       {
  @@ -167,36 +202,59 @@
           this.digesterRules = digesterRules;
       }
   
  -    protected Digester initDefaultDigester(Digester digester)
  +    /**
  +     * Initializes the parsing rules for the default digester
  +     *
  +     * This allows the Configuration Factory to understand the 
  +     * default types: Properties, XML and JNDI.
  +     *
  +     * @param digester The digester to configure
  +     */
  +    protected void initDefaultDigesterRules(Digester digester)
       {
  -        // Initialize a new Digester instance
  +        // Properties and DOM4J need a base path. Supply it with inner classes
  +        setupDigesterInstance(digester, "configuration/properties", new PropertiesConfigurationFactory());
  +        setupDigesterInstance(digester, "configuration/dom4j", new DOM4JConfigurationFactory());
  +        
  +        // JNDI can be instantiated directly.
  +        setupDigesterInstance(digester, "configuration/jndi", JNDIConfiguration.class);
  +    }
   
  -        digester.addObjectCreate("configuration/properties", "org.apache.commons.configuration.PropertiesConfiguration");
  -        digester.addSetProperties("configuration/properties");
  -        digester.addCallMethod("configuration/properties", "load");
  -        digester.addCallMethod("configuration/properties", "setBasePath", 1, new String[] { "java.lang.String" });
  -        ObjectParamRule opr = new ObjectParamRule(0, getBasePath());
  -        digester.addRule("configuration/properties", opr);
  -        digester.addSetNext("configuration/properties", "addConfiguration", "org.apache.commons.configuration.Configuration");
  -
  -        digester.addObjectCreate("configuration/dom4j", "org.apache.commons.configuration.DOM4JConfiguration");
  -        digester.addSetProperties("configuration/dom4j");
  -        digester.addCallMethod("configuration/dom4j", "load");
  -        digester.addCallMethod("configuration/dom4j", "setBasePath", 1, new String[] { "java.lang.String" });
  -        ObjectParamRule opr2 = new ObjectParamRule(0, getBasePath());
  -        digester.addRule("configuration/dom4j", opr2);
  -        digester.addSetNext("configuration/dom4j", "addConfiguration", "org.apache.commons.configuration.Configuration");
  -
  -        digester.addObjectCreate("configuration/jndi", "org.apache.commons.configuration.JNDIConfiguration");
  -        digester.addSetProperties("configuration/jndi");
  -        digester.addSetNext("configuration/jndi", "addConfiguration", "org.apache.commons.configuration.Configuration");
  +    /**
  +     * Sets up a configuration instance that needs an ObjectCreation Factory to
  +     * generate new Objects.
  +     *
  +     * @param digester The current digester
  +     * @param matchString The pattern to match with this Rule
  +     * @param factory An ObjectCreationFactory Instance to use for creating new
  +     *                objects
  +     */
  +    protected void setupDigesterInstance(Digester digester, String matchString, ObjectCreationFactory factory)
  +    {
  +        digester.addFactoryCreate(matchString, factory);
  +        digester.addSetProperties(matchString);
  +        digester.addCallMethod(matchString, "load");
  +        digester.addSetNext(matchString, "addConfiguration", Configuration.class.getName());
  +    }
   
  -        return digester;
  +    /**
  +     * Sets up a configuration instance that can directly construct a new object.
  +     *
  +     * @param digester The current digester
  +     * @param matchString The pattern to match with this Rule
  +     * @param factory A Class object that describes the wanted class.
  +     */
  +    protected void setupDigesterInstance(Digester digester, String matchString, Class clazz)
  +    {
  +        digester.addFactoryCreate(matchString, clazz);
  +        digester.addSetProperties(matchString);
  +        digester.addSetNext(matchString, "addConfiguration", Configuration.class.getName());
       }
   
       /**
        * Returns the digesterRuleNamespaceURI.
  -     * @return String
  +     *
  +     * @return A String with the digesterRuleNamespaceURI.
        */
       public String getDigesterRuleNamespaceURI()
       {
  @@ -205,21 +263,28 @@
   
       /**
        * Sets the digesterRuleNamespaceURI.
  -     * @param digesterRuleNamespaceURI The digesterRuleNamespaceURI to set
  +     *
  +     * @param digesterRuleNamespaceURI The new digesterRuleNamespaceURI to use
        */
       public void setDigesterRuleNamespaceURI(String digesterRuleNamespaceURI)
       {
           this.digesterRuleNamespaceURI = digesterRuleNamespaceURI;
       }
   
  -    private Digester configureDigester(CompositeConfiguration compositeConfiguration, Digester digester)
  +    /**
  +     * Configure the current digester to be namespace aware and to have
  +     * a Configuration object to which all of the other configurations 
  +     * should be added
  +     *
  +     * @param digester The Digester to configure
  +     * @param configuration The CompositeConfiguration Object to use.
  +     */
  +    private void configureNamespace(Digester digester)
       {
  -        digester.push(compositeConfiguration);
           if (getDigesterRuleNamespaceURI() != null)
           {
               digester.setNamespaceAware(true);
               digester.setRuleNamespaceURI(getDigesterRuleNamespaceURI());
  -
           }
           else
           {
  @@ -227,24 +292,87 @@
           }
   
           digester.setValidating(false);
  -        return digester;
       }
   
       /**
  -     * @return String
  +     * Returns the Base path from which this Configuration Factory operates.
  +     * This is never null. If you set the BasePath to null, then "." is returned.
  +     *
  +     * @return The base Path of this configuration factory.
        */
       public String getBasePath()
       {
  -        return basePath;
  +        return StringUtils.isEmpty(basePath) ? "." : basePath;
       }
   
       /**
  -     * Sets the basePath.
  -     * @param basePath The basePath to set
  +     * Sets the basePath for all file references from this Configuration Factory.
  +     * If you pass null in, this is interpreted as "current directory".
  +     *
  +     * @param basePath The new basePath to set.
        */
       public void setBasePath(String basePath)
       {
           this.basePath = basePath;
       }
   
  +    /**
  +     * A tiny inner class that allows the Configuration Factory to
  +     * let the digester construct PropertiesConfiguration objects
  +     * that already have the correct base Path set.
  +     *
  +     */
  +    public class PropertiesConfigurationFactory
  +            extends AbstractObjectCreationFactory
  +            implements ObjectCreationFactory
  +    {
  +        /**
  +         * C'tor
  +         */
  +        public PropertiesConfigurationFactory()
  +        {
  +        }
  +        
  +        /**
  +         * Gets called by the digester. We ignore the attributes
  +         *
  +         * @param attributes ignored
  +         */
  +        public Object createObject(Attributes attributes)
  +        {
  +            PropertiesConfiguration pc = new PropertiesConfiguration();
  +            pc.setBasePath(getBasePath());
  +            return pc;
  +        }
  +    }
  +    
  +    /**
  +     * A tiny inner class that allows the Configuration Factory to
  +     * let the digester construct DOM4JConfiguration objects
  +     * that already have the correct base Path set.
  +     *
  +     */
  +    public class DOM4JConfigurationFactory
  +            extends AbstractObjectCreationFactory
  +            implements ObjectCreationFactory
  +    {
  +        /**
  +         * C'tor
  +         */
  +        public DOM4JConfigurationFactory()
  +        {
  +        }
  +        
  +        /**
  +         * Gets called by the digester. We ignore the attributes
  +         *
  +         * @param attributes ignored
  +         */
  +        public Object createObject(Attributes attributes)
  +        {
  +            DOM4JConfiguration dc = new DOM4JConfiguration();
  +            dc.setBasePath(getBasePath());
  +            return dc;
  +        }
  +    }
   }
  
  
  
  1.9       +2 -2      jakarta-commons-sandbox/configuration/src/java/org/apache/commons/configuration/CompositeConfiguration.java
  
  Index: CompositeConfiguration.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons-sandbox/configuration/src/java/org/apache/commons/configuration/CompositeConfiguration.java,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- CompositeConfiguration.java	22 Mar 2003 05:19:50 -0000	1.8
  +++ CompositeConfiguration.java	7 Jun 2003 17:57:29 -0000	1.9
  @@ -113,7 +113,7 @@
       public void clear()
       {
           configList.clear();
  -        // recreate the inmemory configuration
  +        // recreate the in memory configuration
           inMemoryConfiguration = new BaseConfiguration();
           addConfiguration(inMemoryConfiguration);
   
  
  
  
  1.5       +1 -2      jakarta-commons-sandbox/configuration/src/test/org/apache/commons/configuration/TestConfigurationFactory.java
  
  Index: TestConfigurationFactory.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons-sandbox/configuration/src/test/org/apache/commons/configuration/TestConfigurationFactory.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- TestConfigurationFactory.java	24 Mar 2003 07:23:47 -0000	1.4
  +++ TestConfigurationFactory.java	7 Jun 2003 17:57:29 -0000	1.5
  @@ -160,7 +160,6 @@
   
       public void testLoadingConfigurationNamespaceAware() throws Exception
       {
  -
           configurationFactory.setConfigurationFileName(testDigesterFileNamespaceAware.toString());
           //configurationFactory.setDigesterRules(digesterRules.toURL());
           configurationFactory.setDigesterRuleNamespaceURI("namespace-one");
  
  
  

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