epugh       2004/04/01 10:43:04

  Modified:    configuration/src/test/org/apache/commons/configuration
                        TestCompositeConfiguration.java
               configuration/xdocs changes.xml
               configuration/src/java/org/apache/commons/configuration
                        SubsetConfiguration.java
                        PropertiesConfiguration.java
                        CompositeConfiguration.java
               configuration project.xml
  Added:       configuration/src/test/org/apache/commons/configuration
                        TestDOMConfiguration.java
                        TestHierarchicalDOMConfiguration.java
               configuration/src/java/org/apache/commons/configuration
                        DOMConfiguration.java
                        HierarchicalDOMConfiguration.java
  Log:
  Bugzilla Bug 27498   DOM based XMLConfiguration
  
  Revision  Changes    Path
  1.7       +16 -1     
jakarta-commons/configuration/src/test/org/apache/commons/configuration/TestCompositeConfiguration.java
  
  Index: TestCompositeConfiguration.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-commons/configuration/src/test/org/apache/commons/configuration/TestCompositeConfiguration.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- TestCompositeConfiguration.java   9 Mar 2004 10:31:31 -0000       1.6
  +++ TestCompositeConfiguration.java   1 Apr 2004 18:43:03 -0000       1.7
  @@ -229,6 +229,21 @@
       }
   
       /**
  +     * Tests subsets and still can resolve elements
  +     */
  +    public void testSubsetCanResolve() throws Exception
  +    {
  +        cc = new CompositeConfiguration();
  +        final BaseConfiguration config = new BaseConfiguration();
  +        config.addProperty("subset.tempfile", "${java.io.tmpdir}/file.tmp");
  +        cc.addConfiguration(config);
  +        
cc.addConfiguration(ConfigurationConverter.getConfiguration(System.getProperties()));
  +
  +        Configuration subset = cc.subset("subset");
  +        assertEquals(System.getProperty("java.io.tmpdir") + "/file.tmp", 
subset.getString("tempfile"));
  +    }
  +
  +    /**
         * Tests <code>List</code> parsing.
         */
       public void testList() throws Exception
  
  
  
  1.1                  
jakarta-commons/configuration/src/test/org/apache/commons/configuration/TestDOMConfiguration.java
  
  Index: TestDOMConfiguration.java
  ===================================================================
  package org.apache.commons.configuration;
  
  /*
   * Copyright 2001-2004 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.
   */
  
  import java.io.File;
  
  import junit.framework.TestCase;
  
  /**
   * test for loading and saving xml properties files
   *
   * @version $Id: TestDOMConfiguration.java,v 1.1 2004/04/01 18:43:03 epugh Exp $
   */
  public class TestDOMConfiguration extends TestCase
  {
      /** The File that we test with */
      private String testProperties = new File("conf/test.xml").getAbsolutePath();
      private String testBasePath = new File("conf").getAbsolutePath();
      private DOMConfiguration conf;
  
      protected void setUp() throws Exception
      {
          conf = new DOMConfiguration(new File(testProperties));
      }
  
      public void testGetProperty() throws Exception
      {
          assertEquals("value", conf.getProperty("element"));
      }
  
      public void testGetComplexProperty() throws Exception
      {
          assertEquals("I'm complex!", 
conf.getProperty("element2.subelement.subsubelement"));
      }
  
      public void testSettingFileNames() throws Exception
      {
          conf = new DOMConfiguration();
          conf.setFileName(testProperties);
          assertEquals(testProperties.toString(), conf.getFileName());
  
          conf.setBasePath(testBasePath);
          conf.setFileName("hello.xml");
          assertEquals("hello.xml", conf.getFileName());
          assertEquals(testBasePath.toString(), conf.getBasePath());
          assertEquals(new File(testBasePath, "hello.xml"), conf.getFile());
  
          conf.setBasePath(testBasePath);
          conf.setFileName("/subdir/hello.xml");
          assertEquals("/subdir/hello.xml", conf.getFileName());
          assertEquals(testBasePath.toString(), conf.getBasePath());
          assertEquals(new File(testBasePath, "/subdir/hello.xml"), conf.getFile());
      }
  
      public void testLoad() throws Exception
      {
          conf = new DOMConfiguration();
          conf.setFileName(testProperties);
          conf.load();
  
          assertEquals("I'm complex!", 
conf.getProperty("element2.subelement.subsubelement"));
      }
      
      public void testLoadWithBasePath() throws Exception
      {
          conf = new DOMConfiguration();
          
          conf.setFileName("test.xml");
          conf.setBasePath(testBasePath);
          conf.load();
  
          assertEquals("I'm complex!", 
conf.getProperty("element2.subelement.subsubelement"));
      }
  }
  
  
  
  1.1                  
jakarta-commons/configuration/src/test/org/apache/commons/configuration/TestHierarchicalDOMConfiguration.java
  
  Index: TestHierarchicalDOMConfiguration.java
  ===================================================================
  package org.apache.commons.configuration;
  
  /*
   * Copyright 2001-2004 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.
   */
   
  import java.io.File;
  import java.util.Collection;
  
  import junit.framework.TestCase;
  
  /**
   * Test class for HierarchicalDOM4JConfiguration,
   *
   * @version $Id: TestHierarchicalDOMConfiguration.java,v 1.1 2004/04/01 18:43:03 
epugh Exp $
   */
  public class TestHierarchicalDOMConfiguration extends TestCase
  {
      private static final String TEST_DIR = "conf";
      
      private static final String TEST_FILENAME = 
"testHierarchicalDOM4JConfiguration.xml";
      
      private static final String TEST_FILE = TEST_DIR + File.separator + 
TEST_FILENAME;
      
      private HierarchicalDOMConfiguration config;
      
      protected void setUp() throws Exception
      {
          config = new HierarchicalDOMConfiguration();
      }
  
      private void configTest(HierarchicalDOMConfiguration config)
      {
          assertEquals(1, config.getMaxIndex("tables.table"));
          assertEquals("system", config.getProperty("tables.table(0)[EMAIL 
PROTECTED]"));
          assertEquals("application", config.getProperty("tables.table(1)[EMAIL 
PROTECTED]"));
          
          assertEquals("users", config.getProperty("tables.table(0).name"));
          assertEquals("documents", config.getProperty("tables.table(1).name"));
          
          Object prop = config.getProperty("tables.table.fields.field.name");
          assertTrue(prop instanceof Collection);
          assertEquals(10, ((Collection) prop).size());
          
          prop = config.getProperty("tables.table(0).fields.field.type");
          assertTrue(prop instanceof Collection);
          assertEquals(5, ((Collection) prop).size());
          
          prop = config.getProperty("tables.table(1).fields.field.type");
          assertTrue(prop instanceof Collection);
          assertEquals(5, ((Collection) prop).size());
      }
      
      public void testGetProperty() throws Exception
      {
          config.setFileName(TEST_FILE);
          config.load();
  
          configTest(config);
      }
      
      public void testLoadURL() throws Exception
      {
          config.load(new File(TEST_FILE).getAbsoluteFile().toURL());
          configTest(config);
      }
      
      public void testLoadBasePath1() throws Exception
      {
          config.setBasePath(TEST_DIR);
          config.setFileName(TEST_FILENAME);
          config.load();
          configTest(config);
      }
      
      public void testLoadBasePath2() throws Exception
      {
          config.setBasePath(new File(TEST_FILE).getAbsoluteFile().toURL().toString());
          config.setFileName(TEST_FILENAME);
          config.load();
          configTest(config);
      }
  }
  
  
  
  1.18      +3 -0      jakarta-commons/configuration/xdocs/changes.xml
  
  Index: changes.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/configuration/xdocs/changes.xml,v
  retrieving revision 1.17
  retrieving revision 1.18
  diff -u -r1.17 -r1.18
  --- changes.xml       1 Apr 2004 18:21:46 -0000       1.17
  +++ changes.xml       1 Apr 2004 18:43:04 -0000       1.18
  @@ -7,6 +7,9 @@
   
     <body>
       <release version="1.0-dev-4" date="">  
  +     <action dev="jschaible" type="add">
  +        Direct support of XML via DOM. New classes DOMConfiguration and 
HierarchicalDOMConfiguration.
  +     </action>     
         <action dev="jschaible" type="update">
           Update build to not include test configuration files in resulting jar.
        </action>       
  
  
  
  1.2       +12 -133   
jakarta-commons/configuration/src/java/org/apache/commons/configuration/SubsetConfiguration.java
  
  Index: SubsetConfiguration.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-commons/configuration/src/java/org/apache/commons/configuration/SubsetConfiguration.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- SubsetConfiguration.java  9 Mar 2004 10:31:31 -0000       1.1
  +++ SubsetConfiguration.java  1 Apr 2004 18:43:04 -0000       1.2
  @@ -16,11 +16,7 @@
   
   package org.apache.commons.configuration;
   
  -import java.math.BigDecimal;
  -import java.math.BigInteger;
   import java.util.Iterator;
  -import java.util.List;
  -import java.util.Properties;
   
   import org.apache.commons.collections.Transformer;
   import org.apache.commons.collections.iterators.TransformIterator;
  @@ -33,7 +29,7 @@
    * @author Emmanuel Bourg
    * @version $Revision$, $Date$
    */
  -public class SubsetConfiguration implements Configuration {
  +public class SubsetConfiguration extends AbstractConfiguration {
   
       protected Configuration parent;
       protected String prefix;
  @@ -132,7 +128,7 @@
           return parent.containsKey(getParentKey(key));
       }
   
  -    public void addProperty(String key, Object value) {
  +    public void addPropertyDirect(String key, Object value) {
           parent.addProperty(getParentKey(key), value);
       }
   
  @@ -144,7 +140,7 @@
           parent.clearProperty(getParentKey(key));
       }
   
  -    public Object getProperty(String key) {
  +    public Object getPropertyDirect(String key) {
           return parent.getProperty(getParentKey(key));
       }
   
  @@ -164,130 +160,13 @@
           });
       }
   
  -    public Properties getProperties(String key) {
  -        return parent.getProperties(getParentKey(key));
  -    }
  -
  -    public boolean getBoolean(String key) {
  -        return parent.getBoolean(getParentKey(key));
  -    }
  -
  -    public boolean getBoolean(String key, boolean defaultValue) {
  -        return parent.getBoolean(getParentKey(key), defaultValue);
  -    }
  -
  -    public Boolean getBoolean(String key, Boolean defaultValue) {
  -        return parent.getBoolean(getParentKey(key), defaultValue);
  -    }
  -
  -    public byte getByte(String key) {
  -        return parent.getByte(getParentKey(key));
  -    }
  -
  -    public byte getByte(String key, byte defaultValue) {
  -        return parent.getByte(getParentKey(key), defaultValue);
  -    }
  -
  -    public Byte getByte(String key, Byte defaultValue) {
  -        return parent.getByte(getParentKey(key), defaultValue);
  -    }
  -
  -    public double getDouble(String key) {
  -        return parent.getDouble(getParentKey(key));
  -    }
  -
  -    public double getDouble(String key, double defaultValue) {
  -        return parent.getDouble(getParentKey(key), defaultValue);
  -    }
  -
  -    public Double getDouble(String key, Double defaultValue) {
  -        return parent.getDouble(getParentKey(key), defaultValue);
  -    }
  -
  -    public float getFloat(String key) {
  -        return parent.getFloat(getParentKey(key));
  -    }
  -
  -    public float getFloat(String key, float defaultValue) {
  -        return parent.getFloat(getParentKey(key), defaultValue);
  -    }
  -
  -    public Float getFloat(String key, Float defaultValue) {
  -        return parent.getFloat(getParentKey(key), defaultValue);
  -    }
  -
  -    public int getInt(String key) {
  -        return parent.getInt(getParentKey(key));
  -    }
  -
  -    public int getInt(String key, int defaultValue) {
  -        return parent.getInt(getParentKey(key), defaultValue);
  -    }
  -
  -    public Integer getInteger(String key, Integer defaultValue) {
  -        return parent.getInteger(getParentKey(key), defaultValue);
  -    }
  -
  -    public long getLong(String key) {
  -        return parent.getLong(getParentKey(key));
  -    }
  -
  -    public long getLong(String key, long defaultValue) {
  -        return parent.getLong(getParentKey(key), defaultValue);
  -    }
  -
  -    public Long getLong(String key, Long defaultValue) {
  -        return parent.getLong(getParentKey(key), defaultValue);
  -    }
  -
  -    public short getShort(String key) {
  -        return parent.getShort(getParentKey(key));
  -    }
  -
  -    public short getShort(String key, short defaultValue) {
  -        return parent.getShort(getParentKey(key), defaultValue);
  -    }
  -
  -    public Short getShort(String key, Short defaultValue) {
  -        return parent.getShort(getParentKey(key), defaultValue);
  -    }
  -
  -    public BigDecimal getBigDecimal(String key) {
  -        return parent.getBigDecimal(getParentKey(key));
  -    }
  -
  -    public BigDecimal getBigDecimal(String key, BigDecimal defaultValue) {
  -        return parent.getBigDecimal(getParentKey(key), defaultValue);
  -    }
  -
  -    public BigInteger getBigInteger(String key) {
  -        return parent.getBigInteger(getParentKey(key));
  -    }
  -
  -    public BigInteger getBigInteger(String key, BigInteger defaultValue) {
  -        return parent.getBigInteger(getParentKey(key), defaultValue);
  -    }
  -
  -    public String getString(String key) {
  -        return parent.getString(getParentKey(key));
  -    }
  -
  -    public String getString(String key, String defaultValue) {
  -        return parent.getString(getParentKey(key), defaultValue);
  -    }
  -
  -    public String[] getStringArray(String key) {
  -        return parent.getStringArray(getParentKey(key));
  -    }
  -
  -    public List getList(String key) {
  -        return parent.getList(getParentKey(key));
  -    }
  -
  -    public List getList(String key, List defaultValue) {
  -        return parent.getList(getParentKey(key), defaultValue);
  +    protected String interpolate(String base)
  +    {
  +        if (delimiter == null && "".equals(prefix)) {
  +            return super.interpolate(base);
  +        } else {
  +            SubsetConfiguration config = new SubsetConfiguration(parent, "");
  +            return config.interpolate(base);
  +        }
       }
  -
  -
  -
   }
  
  
  
  1.7       +14 -4     
jakarta-commons/configuration/src/java/org/apache/commons/configuration/PropertiesConfiguration.java
  
  Index: PropertiesConfiguration.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-commons/configuration/src/java/org/apache/commons/configuration/PropertiesConfiguration.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- PropertiesConfiguration.java      28 Mar 2004 15:34:23 -0000      1.6
  +++ PropertiesConfiguration.java      1 Apr 2004 18:43:04 -0000       1.7
  @@ -98,13 +98,23 @@
        */
       public void load(String fileName) throws ConfigurationException
       {
  +             InputStream is=null;
        try {
  -         InputStream is = getPropertyStream(fileName);
  -             load(is);
  -             is.close();
  +         is = getPropertyStream(fileName);
  +             load(is);               
        }
        catch (IOException ioe){
                throw new ConfigurationException("Could not load from file " + 
fileName,ioe);
  +     }
  +     finally{
  +         if(is !=null){
  +             try{                
  +                 is.close();
  +             }
  +             catch (IOException ioe2){
  +                 ioe2.printStackTrace();
  +             }
  +         }
        }
       }
   
  
  
  
  1.11      +1 -27     
jakarta-commons/configuration/src/java/org/apache/commons/configuration/CompositeConfiguration.java
  
  Index: CompositeConfiguration.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-commons/configuration/src/java/org/apache/commons/configuration/CompositeConfiguration.java,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- CompositeConfiguration.java       13 Mar 2004 17:04:04 -0000      1.10
  +++ CompositeConfiguration.java       1 Apr 2004 18:43:04 -0000       1.11
  @@ -249,32 +249,6 @@
       }
    
       /**
  -     * Create a CompositeConfiguration object that is a subset
  -     * of this one. Cycles over all the config objects, and calls
  -     * their subset method and then just adds that.
  -     *
  -     * @param prefix
  -     */
  -    public Configuration subset(String prefix)
  -    {
  -        CompositeConfiguration subsetCompositeConfiguration =
  -            new CompositeConfiguration();
  -        Configuration subConf = null;
  -        int count = 0;
  -        for (ListIterator i = configList.listIterator(); i.hasNext();)
  -        {
  -            Configuration config = (Configuration) i.next();
  -            Configuration subset = config.subset(prefix);
  -            if (subset != null && !subset.isEmpty())
  -            {
  -                subsetCompositeConfiguration.addConfiguration(subset);
  -                subConf = subset;
  -                count++;
  -            }
  -        }
  -        return (count == 1) ? subConf : subsetCompositeConfiguration;
  -    }
  -    /**
        * Get a List of strings associated with the given configuration key.
        *
        * @param key The configuration key.
  
  
  
  1.1                  
jakarta-commons/configuration/src/java/org/apache/commons/configuration/DOMConfiguration.java
  
  Index: DOMConfiguration.java
  ===================================================================
  package org.apache.commons.configuration;
  
  /*
   * Copyright 2004 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.
   */
  
  import java.io.File;
  import java.io.FileWriter;
  import java.io.IOException;
  import java.net.URL;
  
  import javax.xml.parsers.DocumentBuilder;
  import javax.xml.parsers.DocumentBuilderFactory;
  import javax.xml.parsers.FactoryConfigurationError;
  import javax.xml.parsers.ParserConfigurationException;
  
  import org.apache.commons.lang.StringUtils;
  import org.apache.commons.lang.exception.NestableRuntimeException;
  
  import org.w3c.dom.Attr;
  import org.w3c.dom.CharacterData;
  import org.w3c.dom.Document;
  import org.w3c.dom.Element;
  import org.w3c.dom.NamedNodeMap;
  import org.w3c.dom.NodeList;
  
  import org.xml.sax.SAXException;
  
  /**
   * Reads a XML configuration file.
   *
   * To retrieve the value of an attribute of an element, use
   * <code>[EMAIL PROTECTED]</code>.  The '@' symbol was chosen for
   * consistency with XPath.
   *
   * Setting property values will <b>NOT</b> automatically persist
   * changes to disk, unless <code>autoSave=true</code>.
   *
   * @since commons-configuragtion 1.0
   */
  public class DOMConfiguration extends XMLConfiguration
  {
      // For conformance with xpath
      private static final char ATTRIB_MARKER = '@';
      private static final String ATTRIB_START_MARKER = "[" + ATTRIB_MARKER;
  
      /**
       * For consistency with properties files.  Access nodes via an
       * "A.B.C" notation.
       */
      private static final String NODE_DELIMITER = ".";
  
      /**
       * A handle to our data source.
       */
      private String fileName;
  
      /**
       * The XML document from our data source.
       */
      private Document document;
  
      /**
       * If true, modifications are immediately persisted.
       */
      private boolean autoSave = false;
  
      /**
       * Empty construtor.  You must provide a file/fileName
       * and call the load method
       *
       */
      public DOMConfiguration()
      {
      }
  
      /**
       * Attempts to load the XML file as a resource from the
       * classpath. The XML file must be located somewhere in the
       * classpath.
       *
       * @param resource Name of the resource
       * @exception ConfigurationException If error reading data source.
       * @see DOMConfiguration(String)
       */
      public DOMConfiguration(String resource) throws ConfigurationException
      {
          setFile(resourceURLToFile(resource));
          load();
      }
  
      /**
       * Attempts to load the XML file.
       *
       * @param file File object representing the XML file.
       * @exception ConfigurationException If error reading data source.
       */
      public DOMConfiguration(File file) throws ConfigurationException
      {
          setFile(file);
          load();
      }
  
      public void load() throws ConfigurationException
      {
          File file = null;
          try
              {
              file = new File(getBasePath(), getFileName());
              DocumentBuilder builder =
                  DocumentBuilderFactory.newInstance().newDocumentBuilder();
              document = builder.parse(file);
          }
          catch (IOException de)
          {
              throw new ConfigurationException("Could not load from " + 
file.getAbsolutePath());
          }
          catch (ParserConfigurationException ex)
          {
              throw new ConfigurationException("Could not configure parser");
                }
          catch (FactoryConfigurationError ex)
          {
              throw new ConfigurationException("Could not create parser");
          }
          catch (SAXException ex)
          {
              throw new ConfigurationException("Error parsing file " + 
file.getAbsolutePath());
                }
          initProperties(document.getDocumentElement(), new StringBuffer());
  
      }
  
      private static File resourceURLToFile(String resource)
      {
          URL confURL = DOMConfiguration.class.getClassLoader().getResource(resource);
          if (confURL == null)
          {
              confURL = ClassLoader.getSystemResource(resource);
          }
          return new File(confURL.getFile());
      }
  
      /**
       * Loads and initializes from the XML file.
       *
       * @param element The element to start processing from.  Callers
       * should supply the root element of the document.
       * @param hierarchy
       */
      private void initProperties(final Element element, final StringBuffer hierarchy)
      {
          final StringBuffer buffer = new StringBuffer();
          final NodeList list = element.getChildNodes();
          for (int i = 0; i < list.getLength(); i++)
          {
              final org.w3c.dom.Node w3cNode = list.item(i);
              if(w3cNode instanceof Element)
              {
                  final StringBuffer subhierarchy = 
                      new StringBuffer(hierarchy.toString());
                  final Element child = (Element)w3cNode;
                  subhierarchy.append(child.getTagName());
                  processAttributes(subhierarchy.toString(), child);
                  initProperties(child, 
                          new StringBuffer(subhierarchy.toString()).append('.'));
              } 
              else if(w3cNode instanceof CharacterData)
              {
                  final CharacterData data = (CharacterData)w3cNode;
                  buffer.append(data.getData());
              }
          }
          final String text = buffer.toString().trim();
          if (text.length() > 0 && hierarchy.length() > 0)
          {
              super.addProperty(
                      hierarchy.substring(0, hierarchy.length()-1), text);
          }
      }
  
      /**
       * Helper method for constructing properties for the attributes of the
       * given XML element.
       * @param hierarchy the actual hierarchy
       * @param element the actual XML element
       */
      private void processAttributes(String hierarchy, Element element)
      {
          // Add attributes as x.y{ATTRIB_START_MARKER}att{ATTRIB_END_MARKER}
          final NamedNodeMap attributes = element.getAttributes();
          for (int i = 0; i < attributes.getLength(); ++i)
          {
              final org.w3c.dom.Node w3cNode = attributes.item(i);
              if (w3cNode instanceof Attr)
              {
                  Attr attr = (Attr) w3cNode;
                  String attrName = 
                      hierarchy + '[' + ATTRIB_MARKER + attr.getName() + ']';
                  super.addProperty(attrName, attr.getValue());
              }
          }
      }
  
      /**
       * Calls super method, and also ensures the underlying [EMAIL PROTECTED]
       * Document} is modified so changes are persisted when saved.
       *
       * @param name
       * @param value
       */
      public void addProperty(String name, Object value)
      {
          super.addProperty(name, value);
          setXmlProperty(name, value);
          possiblySave();
      }
  
      /**
       * Calls super method, and also ensures the underlying [EMAIL PROTECTED]
       * Document} is modified so changes are persisted when saved.
       *
       * @param name
       * @param value
       */
      public void setProperty(String name, Object value)
      {
          super.setProperty(name, value);
          setXmlProperty(name, value);
          possiblySave();
      }
  
      /**
       * Sets the property value in our document tree, auto-saving if
       * appropriate.
       *
       * @param name The name of the element to set a value for.
       * @param value The value to set.
       */
      private void setXmlProperty(String name, Object value)
      {
          String[] nodes = StringUtils.split(name, NODE_DELIMITER);
          String attName = null;
          Element element = document.getDocumentElement();
          for (int i = 0; i < nodes.length; i++)
          {
              String eName = nodes[i];
              int index = eName.indexOf(ATTRIB_START_MARKER);
              if (index > -1)
              {
                  attName = eName.substring(index + ATTRIB_START_MARKER.length(), 
eName.length() - 1);
                  eName = eName.substring(0, index);
              }
              
              Element child = null;
              final NodeList list = element.getChildNodes();
              for (int j = 0; j < list.getLength(); j++)
              {
                  final org.w3c.dom.Node w3cNode = list.item(j);
                  if (w3cNode instanceof Element)
                  {
                      child = (Element) w3cNode;
                      if (eName.equals(child.getTagName()))
                      {
                          break;
                      }
                      child = null;
                  }
              }
              // If we don't find this part of the property in the XML hierarchy
              // we add it as a new node
              if (child == null && attName == null)
              {
                  child = document.createElement(eName);
                  element.appendChild(child);
              }
              element = child;
          }
  
          if (attName == null)
          {
              final CharacterData data = document.createTextNode((String) value);
              element.appendChild(data);
          }
          else
          {
              element.setAttribute(attName, (String) value);
          }
      }
  
      /**
       * Calls super method, and also ensures the underlying [EMAIL PROTECTED]
       * Document} is modified so changes are persisted when saved.
       *
       * @param name The name of the property to clear.
       */
      public void clearProperty(String name)
      {
          super.clearProperty(name);
          clearXmlProperty(name);
          possiblySave();
      }
  
      private void clearXmlProperty(String name)
      {
          String[] nodes = StringUtils.split(name, NODE_DELIMITER);
          String attName = null;
          Element element = null;
          Element child = document.getDocumentElement();
          for (int i = 0; i < nodes.length; i++)
          {
              element = child;
              String eName = nodes[i];
              int index = eName.indexOf(ATTRIB_START_MARKER);
              if (index > -1)
              {
                  attName = eName.substring(index + ATTRIB_START_MARKER.length(), 
eName.length() - 1);
                  eName = eName.substring(0, index);
              }
              
              final NodeList list = element.getChildNodes();
              for (int j = 0; j < list.getLength(); j++) {
                  final org.w3c.dom.Node w3cNode = list.item(j);
                  if (w3cNode instanceof Element)
                  {
                      child = (Element) w3cNode;
                      if (eName.equals(child.getTagName()))
                      {
                          break;
                      }
                      child = null;
                  }
              }
              if (child == null)
              {
                  return;
              }
          }
  
          if (attName == null)
          {
              element.removeChild(child);
          }
          else
          {
              child.removeAttribute(attName);
          }
      }
  
      private void possiblySave()
      {
          if (autoSave)
          {
              try
              {
                  save();
              }
              catch (ConfigurationException ce)
              {
                  throw new NestableRuntimeException("Failed to auto-save", ce);
              }
          }
      }
  
      /**
       * If true, changes are automatically persisted.
       * @param autoSave
       */
      public void setAutoSave(boolean autoSave)
      {
          this.autoSave = autoSave;
      }
  
      public synchronized void save() throws ConfigurationException
      {
          FileWriter writer = null;
          try
          {
              writer = new FileWriter(getFile());
              writer.write(toString());
          }
          catch (IOException ioe){
                throw new ConfigurationException("Could not save to " + getFile());
          }
          finally
          {
                try
              {
                  if (writer != null)
                  {
                      writer.close();
                  }
                }
                catch (IOException ioe)
              {
                        throw new ConfigurationException(ioe);
                }
          }
      }
      /**
       * Returns the file.
       * @return File
       */
      public File getFile()
      {
          return ConfigurationUtils.constructFile(getBasePath(), getFileName());
      }
  
      /**
       * Sets the file.
       * @param file The file to set
       */
      public void setFile(File file)
      {
          this.fileName = file.getAbsolutePath();
      }
  
      public void setFileName(String fileName)
      {
  
          this.fileName = fileName;
          
      }
  
      /**
       * Returns the fileName.
       * @return String
       */
      public String getFileName()
      {
          return fileName;
      }
      
      public String toString() {
          StringBuffer buffer = new StringBuffer();
          toXML(document, buffer);
        return buffer.toString();
      }
      
      private void toXML(final org.w3c.dom.Node element, final StringBuffer buffer)
        {
        final NodeList nodeList = element.getChildNodes();
        for (int i=0; i<nodeList.getLength(); i++) {
                final org.w3c.dom.Node node = nodeList.item(i);
                if (node instanceof Element)
              {
                        buffer.append("<" + node.getNodeName());
                  if (node.hasAttributes())
                  {
                        final NamedNodeMap map = node.getAttributes();
                      for (int j = 0; j < map.getLength(); j++)
                      {
                        final Attr attr = (Attr) map.item(j);
                          buffer.append(" " + attr.getName());
                          buffer.append("=\"" + attr.getValue() + "\"");
                      }
                  }
                  buffer.append(">");
                        toXML(node, buffer);
                        buffer.append("</" + node.getNodeName() + ">");
                } 
                else if(node instanceof CharacterData)
                {
                        final CharacterData data = (CharacterData)node;
                        buffer.append(data.getData());
                }
        }
      }
  }
  
  
  
  1.1                  
jakarta-commons/configuration/src/java/org/apache/commons/configuration/HierarchicalDOMConfiguration.java
  
  Index: HierarchicalDOMConfiguration.java
  ===================================================================
  package org.apache.commons.configuration;
  
  /*
   * Copyright 2004 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.
   */
  
  import java.net.MalformedURLException;
  import java.net.URL;
  
  import javax.naming.ConfigurationException;
  import javax.xml.parsers.DocumentBuilder;
  import javax.xml.parsers.DocumentBuilderFactory;
  
  import org.w3c.dom.Attr;
  import org.w3c.dom.CharacterData;
  import org.w3c.dom.Document;
  import org.w3c.dom.Element;
  import org.w3c.dom.NamedNodeMap;
  import org.w3c.dom.NodeList;
  
  /**
   * <p>A specialized hierarchical configuration class that is able to parse
   * XML documents using DOM.</p>
   * <p>The parsed document will be stored keeping its structure. The
   * contained properties can be accessed using all methods supported by
   * the base class <code>HierarchicalConfiguration</code>.
   * This class is a direct adaption of the
   * <code>HierarchicalDOM4JConfiguration</code>. 
   * @author J&ouml;rg Schaible
   * @since commons-configuragtion 1.0
   */
  public class HierarchicalDOMConfiguration
          extends HierarchicalConfiguration
          implements BasePathLoader 
  {
  
      /** Stores the file name of the document to be parsed.*/
      private String file;
  
      /** Stores the base path of this configuration.*/
      private String basePath;
  
  
      /**
       * Constructs a HierarchicalDOMConfiguration.
       */
      public HierarchicalDOMConfiguration() 
      {
          super();
      }
  
      /**
       * Returns the name of the file to be parsed by this object.
       * @return the file to be parsed
       */
      public String getFileName() 
      {
          return file;
      }
  
      /**
       * Sets the name of the file to be parsed by this object.
       * @param file the file to be parsed
       */
      public void setFileName(final String file)
      {
          this.file = file;
      }
  
      /**
       * Returns the base path.
       * @return the base path
       */
      public String getBasePath()
      {
          return basePath;
      }
  
      /**
       * Allows to set a base path. Relative file names are resolved based on
       * this path.
       * @param path the base path; this can be a URL or a file path
       */
      public void setBasePath(final String path)
      {
          basePath = path;
      }
  
      /**
       * Loads and parses an XML document. The file to be loaded must have
       * been specified before.
       * @throws ConfigurationException Thrown if an error occurs
       */
      public void load() throws ConfigurationException
      {
          try
          {
              load(ConfigurationUtils.getURL(getBasePath(), getFileName()));
          }
          catch (MalformedURLException mue) {
              throw new ConfigurationException(
                      "Could not load from " + getBasePath() + 
                      ", " + getFileName());
          }
      }
  
      /**
       * Loads and parses the specified XML document.
       * @param url the URL to the XML document
       * @throws ConfigurationException Thrown if an error occurs
       */
      public void load(URL url) throws ConfigurationException
      {
          try
          {
              DocumentBuilder builder =
                  DocumentBuilderFactory.newInstance().newDocumentBuilder();
              initProperties(builder.parse(url.toExternalForm()));
          }
          catch (Exception de)
          {
              throw new ConfigurationException("Could not load from " + url);
          }
      }
  
      /**
       * Initializes this configuration from an XML document.
       * @param document the document to be parsed
       */
      public void initProperties(final Document document)
      {
          constructHierarchy(getRoot(), document.getDocumentElement());
      }
  
      /**
       * Helper method for building the internal storage hierarchy. The XML
       * elements are transformed into node objects.
       * @param node the actual node
       * @param element the actual XML element
       */
      private void constructHierarchy(final Node node, final Element element)
      {
          final StringBuffer buffer = new StringBuffer();
          final NodeList list = element.getChildNodes();
          for (int i = 0; i < list.getLength(); i++) {
              final org.w3c.dom.Node w3cNode = list.item(i);
              if (w3cNode instanceof Element)
              {
                  final Element child = (Element) w3cNode;
                  final Node childNode = new Node(child.getTagName());
                  constructHierarchy(childNode, child);
                  node.addChild(childNode);
                  processAttributes(childNode, child);
              } 
              else if (w3cNode instanceof CharacterData)
              {
                  final CharacterData data = (CharacterData) w3cNode;
                  buffer.append(data.getData());
              }
          }
          final String text = buffer.toString().trim();
          if (text.length() > 0)
          {
              node.setValue(text);
          }
      }
  
      /**
       * Helper method for constructing node objects for the attributes of the
       * given XML element.
       * @param node the actual node
       * @param element the actual XML element
       */
      private void processAttributes(final Node node, final Element element) 
      {
          final NamedNodeMap attributes = element.getAttributes();
          for (int i = 0; i < attributes.getLength(); ++i) 
          {
              final org.w3c.dom.Node w3cNode = attributes.item(i);
              if (w3cNode instanceof Attr) 
              {
                  final Attr attr = (Attr) w3cNode;
                  final Node child =
                      new Node(
                          ConfigurationKey.constructAttributeKey(attr.getName()));
                  child.setValue(attr.getValue());
                  node.addChild(child);
              }
          }
      }
  }
  
  
  
  1.16      +8 -3      jakarta-commons/configuration/project.xml
  
  Index: project.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/configuration/project.xml,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- project.xml       1 Apr 2004 18:26:15 -0000       1.15
  +++ project.xml       1 Apr 2004 18:43:04 -0000       1.16
  @@ -1,11 +1,14 @@
   <?xml version="1.0"?>
  -
  +<!DOCTYPE project [
  +    <!ENTITY ouml "&#246;">
  +]>
   <!-- ===================================================================== -->
   <!--                                                                       -->
   <!-- $Id$ -->
   <!--                                                                       -->
   <!-- ===================================================================== -->
   
  +
   <project>
     <pomVersion>3</pomVersion>
     <name>commons-configuration</name>
  @@ -119,9 +122,11 @@
         <email>[EMAIL PROTECTED]</email>
       </contributor> 
       <contributor>
  -      <name>Jorg Schaible</name>
  +      <name>J&ouml;rg Schaible</name>
         <id>jschaible</id>
         <email>[EMAIL PROTECTED]</email>
  +      <organization>Elsag-Solutions AG</organization>
  +      <timezone>+1</timezone>
       </contributor>            
       <contributor>
         <name>Konstantin Shaposhnikov</name>
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to