View Javadoc

    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    *
    9    *     http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17
    18  package org.apache.commons.configuration;
    19
    20  import java.io.Reader;
    21  import java.io.Writer;
    22  import java.io.File;
    23  import java.io.InputStream;
    24  import java.io.OutputStream;
    25  import java.net.URL;
    26  import java.util.Collection;
    27  import java.util.Iterator;
    28  import java.util.List;
    29
    30  import org.apache.commons.configuration.event.ConfigurationEvent;
    31  import org.apache.commons.configuration.event.ConfigurationListener;
    32  import org.apache.commons.configuration.reloading.ReloadingStrategy;
    33
    34  /***
    35   * <p>Base class for implementing file based hierarchical configurations.</p>
    36   * <p>This class serves an analogous purpose as the
    37   * <code>{@link AbstractFileConfiguration}</code> class for non hierarchical
    38   * configurations. It behaves in exactly the same way, so please refer to the
    39   * documentation of <code>AbstractFileConfiguration</code> for further details.</p>
    40   *
    41   * @since 1.2
    42   *
    43   * @author Emmanuel Bourg
    44   * @version $Revision: 589380 $, $Date: 2007-10-28 17:37:35 +0100 (So, 28 Okt 2007) $
    45   */
    46  public abstract class AbstractHierarchicalFileConfiguration
    47  extends HierarchicalConfiguration
    48  implements FileConfiguration, ConfigurationListener
    49  {
    50      /*** Stores the delegate used for implementing functionality related to the
    51       * <code>FileConfiguration</code> interface.
    52       */
    53      private FileConfigurationDelegate delegate;
    54
    55      /***
    56       * Creates a new instance of
    57       * <code>AbstractHierarchicalFileConfiguration</code>.
    58       */
    59      protected AbstractHierarchicalFileConfiguration()
    60      {
    61          initialize();
    62      }
    63
    64      /***
    65       * Creates a new instance of
    66       * <code>AbstractHierarchicalFileConfiguration</code> and copies the
    67       * content of the specified configuration into this object.
    68       *
    69       * @param c the configuration to copy
    70       * @since 1.4
    71       */
    72      protected AbstractHierarchicalFileConfiguration(HierarchicalConfiguration c)
    73      {
    74          super(c);
    75          initialize();
    76      }
    77
    78      /***
    79       * Creates and loads the configuration from the specified file.
    80       *
    81       * @param fileName The name of the plist file to load.
    82       * @throws ConfigurationException Error while loading the file
    83       */
    84      public AbstractHierarchicalFileConfiguration(String fileName) throws ConfigurationException
    85      {
    86          this();
    87          // store the file name
    88          delegate.setFileName(fileName);
    89
    90          // load the file
    91          load();
    92      }
    93
    94      /***
    95       * Creates and loads the configuration from the specified file.
    96       *
    97       * @param file The configuration file to load.
    98       * @throws ConfigurationException Error while loading the file
    99       */
    100     public AbstractHierarchicalFileConfiguration(File file) throws ConfigurationException
    101     {
    102         this();
    103         // set the file and update the url, the base path and the file name
    104         setFile(file);
    105
    106         // load the file
    107         if (file.exists())
    108         {
    109             load();
    110         }
    111     }
    112
    113     /***
    114      * Creates and loads the configuration from the specified URL.
    115      *
    116      * @param url The location of the configuration file to load.
    117      * @throws ConfigurationException Error while loading the file
    118      */
    119     public AbstractHierarchicalFileConfiguration(URL url) throws ConfigurationException
    120     {
    121         this();
    122         // set the URL and update the base path and the file name
    123         setURL(url);
    124
    125         // load the file
    126         load();
    127     }
    128
    129     /***
    130      * Initializes this instance, mainly the internally used delegate object.
    131      */
    132     private void initialize()
    133     {
    134         delegate = createDelegate();
    135         initDelegate(delegate);
    136     }
    137
    138     protected void addPropertyDirect(String key, Object obj)
    139     {
    140         super.addPropertyDirect(key, obj);
    141         delegate.possiblySave();
    142     }
    143
    144     public void clearProperty(String key)
    145     {
    146         super.clearProperty(key);
    147         delegate.possiblySave();
    148     }
    149
    150     public void clearTree(String key)
    151     {
    152         super.clearTree(key);
    153         delegate.possiblySave();
    154     }
    155
    156     public void setProperty(String key, Object value)
    157     {
    158         super.setProperty(key, value);
    159         delegate.possiblySave();
    160     }
    161
    162     public void load() throws ConfigurationException
    163     {
    164         delegate.load();
    165     }
    166
    167     public void load(String fileName) throws ConfigurationException
    168     {
    169         delegate.load(fileName);
    170     }
    171
    172     public void load(File file) throws ConfigurationException
    173     {
    174         delegate.load(file);
    175     }
    176
    177     public void load(URL url) throws ConfigurationException
    178     {
    179         delegate.load(url);
    180     }
    181
    182     public void load(InputStream in) throws ConfigurationException
    183     {
    184         delegate.load(in);
    185     }
    186
    187     public void load(InputStream in, String encoding) throws ConfigurationException
    188     {
    189         delegate.load(in, encoding);
    190     }
    191
    192     public void save() throws ConfigurationException
    193     {
    194         delegate.save();
    195     }
    196
    197     public void save(String fileName) throws ConfigurationException
    198     {
    199         delegate.save(fileName);
    200     }
    201
    202     public void save(File file) throws ConfigurationException
    203     {
    204         delegate.save(file);
    205     }
    206
    207     public void save(URL url) throws ConfigurationException
    208     {
    209         delegate.save(url);
    210     }
    211
    212     public void save(OutputStream out) throws ConfigurationException
    213     {
    214         delegate.save(out);
    215     }
    216
    217     public void save(OutputStream out, String encoding) throws ConfigurationException
    218     {
    219         delegate.save(out, encoding);
    220     }
    221
    222     public String getFileName()
    223     {
    224         return delegate.getFileName();
    225     }
    226
    227     public void setFileName(String fileName)
    228     {
    229         delegate.setFileName(fileName);
    230     }
    231
    232     public String getBasePath()
    233     {
    234         return delegate.getBasePath();
    235     }
    236
    237     public void setBasePath(String basePath)
    238     {
    239         delegate.setBasePath(basePath);
    240     }
    241
    242     public File getFile()
    243     {
    244         return delegate.getFile();
    245     }
    246
    247     public void setFile(File file)
    248     {
    249         delegate.setFile(file);
    250     }
    251
    252     public URL getURL()
    253     {
    254         return delegate.getURL();
    255     }
    256
    257     public void setURL(URL url)
    258     {
    259         delegate.setURL(url);
    260     }
    261
    262     public void setAutoSave(boolean autoSave)
    263     {
    264         delegate.setAutoSave(autoSave);
    265     }
    266
    267     public boolean isAutoSave()
    268     {
    269         return delegate.isAutoSave();
    270     }
    271
    272     public ReloadingStrategy getReloadingStrategy()
    273     {
    274         return delegate.getReloadingStrategy();
    275     }
    276
    277     public void setReloadingStrategy(ReloadingStrategy strategy)
    278     {
    279         delegate.setReloadingStrategy(strategy);
    280     }
    281
    282     public void reload()
    283     {
    284         setDetailEvents(false);
    285         try
    286         {
    287             delegate.reload();
    288         }
    289         finally
    290         {
    291             setDetailEvents(true);
    292         }
    293     }
    294
    295     public String getEncoding()
    296     {
    297         return delegate.getEncoding();
    298     }
    299
    300     public void setEncoding(String encoding)
    301     {
    302         delegate.setEncoding(encoding);
    303     }
    304
    305     public boolean containsKey(String key)
    306     {
    307         reload();
    308         return super.containsKey(key);
    309     }
    310
    311     public Iterator getKeys(String prefix)
    312     {
    313         reload();
    314         return super.getKeys(prefix);
    315     }
    316
    317     public Object getProperty(String key)
    318     {
    319         reload();
    320         return super.getProperty(key);
    321     }
    322
    323     public boolean isEmpty()
    324     {
    325         reload();
    326         return super.isEmpty();
    327     }
    328
    329     /***
    330      * Directly adds sub nodes to this configuration. This implementation checks
    331      * whether auto save is necessary after executing the operation.
    332      *
    333      * @param key the key where the nodes are to be added
    334      * @param nodes a collection with the nodes to be added
    335      * @since 1.5
    336      */
    337     public void addNodes(String key, Collection nodes)
    338     {
    339         super.addNodes(key, nodes);
    340         delegate.possiblySave();
    341     }
    342
    343     /***
    344      * Fetches a list of nodes, which are selected by the specified key. This
    345      * implementation will perform a reload if necessary.
    346      *
    347      * @param key the key
    348      * @return a list with the selected nodes
    349      */
    350     protected List fetchNodeList(String key)
    351     {
    352         reload();
    353         return super.fetchNodeList(key);
    354     }
    355
    356     /***
    357      * Reacts on changes of an associated subnode configuration. If the auto
    358      * save mechanism is active, the configuration must be saved.
    359      *
    360      * @param event the event describing the change
    361      * @since 1.5
    362      */
    363     protected void subnodeConfigurationChanged(ConfigurationEvent event)
    364     {
    365         delegate.possiblySave();
    366         super.subnodeConfigurationChanged(event);
    367     }
    368
    369     /***
    370      * Creates the file configuration delegate, i.e. the object that implements
    371      * functionality required by the <code>FileConfiguration</code> interface.
    372      * This base implementation will return an instance of the
    373      * <code>FileConfigurationDelegate</code> class. Derived classes may
    374      * override it to create a different delegate object.
    375      *
    376      * @return the file configuration delegate
    377      */
    378     protected FileConfigurationDelegate createDelegate()
    379     {
    380         return new FileConfigurationDelegate();
    381     }
    382
    383     /***
    384      * Helper method for initializing the file configuration delegate.
    385      *
    386      * @param del the delegate
    387      */
    388     private void initDelegate(FileConfigurationDelegate del)
    389     {
    390         del.addConfigurationListener(this);
    391     }
    392
    393     /***
    394      * Reacts on configuration change events triggered by the delegate. These
    395      * events are passed to the registered configuration listeners.
    396      *
    397      * @param event the triggered event
    398      * @since 1.3
    399      */
    400     public void configurationChanged(ConfigurationEvent event)
    401     {
    402         // deliver reload events to registered listeners
    403         setDetailEvents(true);
    404         try
    405         {
    406             fireEvent(event.getType(), event.getPropertyName(), event
    407                     .getPropertyValue(), event.isBeforeUpdate());
    408         }
    409         finally
    410         {
    411             setDetailEvents(false);
    412         }
    413     }
    414
    415     /***
    416      * Returns the file configuration delegate.
    417      *
    418      * @return the delegate
    419      */
    420     protected FileConfigurationDelegate getDelegate()
    421     {
    422         return delegate;
    423     }
    424
    425     /***
    426      * Allows to set the file configuration delegate.
    427      * @param delegate the new delegate
    428      */
    429     protected void setDelegate(FileConfigurationDelegate delegate)
    430     {
    431         this.delegate = delegate;
    432     }
    433
    434     /***
    435      * A special implementation of the <code>FileConfiguration</code> interface that is
    436      * used internally to implement the <code>FileConfiguration</code> methods
    437      * for hierarchical configurations.
    438      */
    439     protected class FileConfigurationDelegate extends AbstractFileConfiguration
    440     {
    441         public void load(Reader in) throws ConfigurationException
    442         {
    443             AbstractHierarchicalFileConfiguration.this.load(in);
    444         }
    445
    446         public void save(Writer out) throws ConfigurationException
    447         {
    448             AbstractHierarchicalFileConfiguration.this.save(out);
    449         }
    450
    451         public void clear()
    452         {
    453             AbstractHierarchicalFileConfiguration.this.clear();
    454         }
    455     }
    456 }