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  package org.apache.commons.configuration;
    18
    19  import java.io.Reader;
    20  import java.io.Writer;
    21  import java.math.BigDecimal;
    22  import java.math.BigInteger;
    23  import java.util.Collection;
    24  import java.util.Iterator;
    25  import java.util.List;
    26  import java.util.Properties;
    27
    28  import org.apache.commons.configuration.event.ConfigurationErrorListener;
    29  import org.apache.commons.configuration.event.ConfigurationListener;
    30  import org.apache.commons.configuration.tree.ConfigurationNode;
    31  import org.apache.commons.configuration.tree.ExpressionEngine;
    32
    33  /***
    34   * Wraps a HierarchicalConfiguration and allows subtrees to be access via a configured path with
    35   * replaceable tokens derived from the ConfigurationInterpolator. When used with injection frameworks
    36   * such as Spring it allows components to be injected with subtrees of the configuration.
    37   * @since 1.6
    38   * @author <a
    39   * href="http://commons.apache.org/configuration/team-list.html">Commons
    40   * Configuration team</a>
    41   * @version $Id: PatternSubtreeConfigurationWrapper.java 727958 2008-12-19 07:19:24Z oheger $
    42   */
    43  public class PatternSubtreeConfigurationWrapper extends AbstractHierarchicalFileConfiguration
    44  {
    45      /***
    46       * Prevent recursion while resolving unprefixed properties.
    47       */
    48      private static ThreadLocal recursive = new ThreadLocal()
    49      {
    50          protected synchronized Object initialValue()
    51          {
    52              return Boolean.FALSE;
    53          }
    54      };
    55
    56      /*** The wrapped configuration */
    57      private final AbstractHierarchicalFileConfiguration config;
    58
    59      /*** The path to the subtree */
    60      private final String path;
    61
    62      /*** True if the path ends with '/', false otherwise */
    63      private final boolean trailing;
    64
    65      /*** True if the constructor has finished */
    66      private boolean init;
    67
    68      /***
    69       * Constructor
    70       * @param config The Configuration to be wrapped.
    71       * @param path The base path pattern.
    72       */
    73      public PatternSubtreeConfigurationWrapper(AbstractHierarchicalFileConfiguration config, String path)
    74      {
    75          this.config = config;
    76          this.path = path;
    77          this.trailing = path.endsWith("/");
    78          this.init = true;
    79      }
    80
    81      public void addProperty(String key, Object value)
    82      {
    83          config.addProperty(makePath(key), value);
    84      }
    85
    86      public void clear()
    87      {
    88          getConfig().clear();
    89      }
    90
    91      public void clearProperty(String key)
    92      {
    93          config.clearProperty(makePath(key));
    94      }
    95
    96      public boolean containsKey(String key)
    97      {
    98          return config.containsKey(makePath(key));
    99      }
    100
    101     public BigDecimal getBigDecimal(String key, BigDecimal defaultValue)
    102     {
    103         return config.getBigDecimal(makePath(key), defaultValue);
    104     }
    105
    106     public BigDecimal getBigDecimal(String key)
    107     {
    108         return config.getBigDecimal(makePath(key));
    109     }
    110
    111     public BigInteger getBigInteger(String key, BigInteger defaultValue)
    112     {
    113         return config.getBigInteger(makePath(key), defaultValue);
    114     }
    115
    116     public BigInteger getBigInteger(String key)
    117     {
    118         return config.getBigInteger(makePath(key));
    119     }
    120
    121     public boolean getBoolean(String key, boolean defaultValue)
    122     {
    123         return config.getBoolean(makePath(key), defaultValue);
    124     }
    125
    126     public Boolean getBoolean(String key, Boolean defaultValue)
    127     {
    128         return config.getBoolean(makePath(key), defaultValue);
    129     }
    130
    131     public boolean getBoolean(String key)
    132     {
    133         return config.getBoolean(makePath(key));
    134     }
    135
    136     public byte getByte(String key, byte defaultValue)
    137     {
    138         return config.getByte(makePath(key), defaultValue);
    139     }
    140
    141     public Byte getByte(String key, Byte defaultValue)
    142     {
    143         return config.getByte(makePath(key), defaultValue);
    144     }
    145
    146     public byte getByte(String key)
    147     {
    148         return config.getByte(makePath(key));
    149     }
    150
    151     public double getDouble(String key, double defaultValue)
    152     {
    153         return config.getDouble(makePath(key), defaultValue);
    154     }
    155
    156     public Double getDouble(String key, Double defaultValue)
    157     {
    158         return config.getDouble(makePath(key), defaultValue);
    159     }
    160
    161     public double getDouble(String key)
    162     {
    163         return config.getDouble(makePath(key));
    164     }
    165
    166     public float getFloat(String key, float defaultValue)
    167     {
    168         return config.getFloat(makePath(key), defaultValue);
    169     }
    170
    171     public Float getFloat(String key, Float defaultValue)
    172     {
    173         return config.getFloat(makePath(key), defaultValue);
    174     }
    175
    176     public float getFloat(String key)
    177     {
    178         return config.getFloat(makePath(key));
    179     }
    180
    181     public int getInt(String key, int defaultValue)
    182     {
    183         return config.getInt(makePath(key), defaultValue);
    184     }
    185
    186     public int getInt(String key)
    187     {
    188         return config.getInt(makePath(key));
    189     }
    190
    191     public Integer getInteger(String key, Integer defaultValue)
    192     {
    193         return config.getInteger(makePath(key), defaultValue);
    194     }
    195
    196     public Iterator getKeys()
    197     {
    198         return config.getKeys(makePath());
    199     }
    200
    201     public Iterator getKeys(String prefix)
    202     {
    203         return config.getKeys(makePath(prefix));
    204     }
    205
    206     public List getList(String key, List defaultValue)
    207     {
    208         return config.getList(makePath(key), defaultValue);
    209     }
    210
    211     public List getList(String key)
    212     {
    213         return config.getList(makePath(key));
    214     }
    215
    216     public long getLong(String key, long defaultValue)
    217     {
    218         return config.getLong(makePath(key), defaultValue);
    219     }
    220
    221     public Long getLong(String key, Long defaultValue)
    222     {
    223         return config.getLong(makePath(key), defaultValue);
    224     }
    225
    226     public long getLong(String key)
    227     {
    228         return config.getLong(makePath(key));
    229     }
    230
    231     public Properties getProperties(String key)
    232     {
    233         return config.getProperties(makePath(key));
    234     }
    235
    236     public Object getProperty(String key)
    237     {
    238         return config.getProperty(makePath(key));
    239     }
    240
    241     public short getShort(String key, short defaultValue)
    242     {
    243         return config.getShort(makePath(key), defaultValue);
    244     }
    245
    246     public Short getShort(String key, Short defaultValue)
    247     {
    248         return config.getShort(makePath(key), defaultValue);
    249     }
    250
    251     public short getShort(String key)
    252     {
    253         return config.getShort(makePath(key));
    254     }
    255
    256     public String getString(String key, String defaultValue)
    257     {
    258         return config.getString(makePath(key), defaultValue);
    259     }
    260
    261     public String getString(String key)
    262     {
    263         return config.getString(makePath(key));
    264     }
    265
    266     public String[] getStringArray(String key)
    267     {
    268         return config.getStringArray(makePath(key));
    269     }
    270
    271     public boolean isEmpty()
    272     {
    273         return getConfig().isEmpty();
    274     }
    275
    276     public void setProperty(String key, Object value)
    277     {
    278         getConfig().setProperty(key, value);
    279     }
    280
    281     public Configuration subset(String prefix)
    282     {
    283         return getConfig().subset(prefix);
    284     }
    285
    286     public Node getRoot()
    287     {
    288         return getConfig().getRoot();
    289     }
    290
    291     public void setRoot(Node node)
    292     {
    293         if (init)
    294         {
    295             getConfig().setRoot(node);
    296         }
    297         else
    298         {
    299             super.setRoot(node);
    300         }
    301     }
    302
    303     public ConfigurationNode getRootNode()
    304     {
    305         return getConfig().getRootNode();
    306     }
    307
    308     public void setRootNode(ConfigurationNode rootNode)
    309     {
    310         if (init)
    311         {
    312             getConfig().setRootNode(rootNode);
    313         }
    314         else
    315         {
    316             super.setRootNode(rootNode);
    317         }
    318     }
    319
    320     public ExpressionEngine getExpressionEngine()
    321     {
    322         return config.getExpressionEngine();
    323     }
    324
    325     public void setExpressionEngine(ExpressionEngine expressionEngine)
    326     {
    327         if (init)
    328         {
    329             config.setExpressionEngine(expressionEngine);
    330         }
    331         else
    332         {
    333             super.setExpressionEngine(expressionEngine);
    334         }
    335     }
    336
    337     public void addNodes(String key, Collection nodes)
    338     {
    339         getConfig().addNodes(key, nodes);
    340     }
    341
    342     public SubnodeConfiguration configurationAt(String key, boolean supportUpdates)
    343     {
    344         return config.configurationAt(makePath(key), supportUpdates);
    345     }
    346
    347     public SubnodeConfiguration configurationAt(String key)
    348     {
    349         return config.configurationAt(makePath(key));
    350     }
    351
    352     public List configurationsAt(String key)
    353     {
    354         return config.configurationsAt(makePath(key));
    355     }
    356
    357     public void clearTree(String key)
    358     {
    359         config.clearTree(makePath(key));
    360     }
    361
    362     public int getMaxIndex(String key)
    363     {
    364         return config.getMaxIndex(makePath(key));
    365     }
    366
    367     public Configuration interpolatedConfiguration()
    368     {
    369         return getConfig().interpolatedConfiguration();
    370     }
    371
    372     public void addConfigurationListener(ConfigurationListener l)
    373     {
    374         getConfig().addConfigurationListener(l);
    375     }
    376
    377     public boolean removeConfigurationListener(ConfigurationListener l)
    378     {
    379         return getConfig().removeConfigurationListener(l);
    380     }
    381
    382     public Collection getConfigurationListeners()
    383     {
    384         return getConfig().getConfigurationListeners();
    385     }
    386
    387     public void clearConfigurationListeners()
    388     {
    389         getConfig().clearConfigurationListeners();
    390     }
    391
    392     public void addErrorListener(ConfigurationErrorListener l)
    393     {
    394         getConfig().addErrorListener(l);
    395     }
    396
    397     public boolean removeErrorListener(ConfigurationErrorListener l)
    398     {
    399         return getConfig().removeErrorListener(l);
    400     }
    401
    402     public void clearErrorListeners()
    403     {
    404         getConfig().clearErrorListeners();
    405     }
    406
    407     public void save(Writer writer) throws ConfigurationException
    408     {
    409         config.save(writer);
    410     }
    411
    412     public void load(Reader reader) throws ConfigurationException
    413     {
    414         config.load(reader);
    415     }
    416
    417     public Collection getErrorListeners()
    418     {
    419         return getConfig().getErrorListeners();
    420     }
    421
    422     protected Object resolveContainerStore(String key)
    423     {
    424         if (((Boolean) recursive.get()).booleanValue())
    425         {
    426             return null;
    427         }
    428         recursive.set(Boolean.TRUE);
    429         try
    430         {
    431             return super.resolveContainerStore(key);
    432         }
    433         finally
    434         {
    435             recursive.set(Boolean.FALSE);
    436         }
    437     }
    438
    439     private HierarchicalConfiguration getConfig()
    440     {
    441         return config.configurationAt(makePath());
    442     }
    443
    444     private String makePath()
    445     {
    446         String pathPattern = trailing ? path.substring(0, path.length() - 1) : path;
    447         return getSubstitutor().replace(pathPattern);
    448     }
    449
    450     /*
    451      * Resolve the root expression and then add the item being retrieved. Insert a
    452      * separator character as required.
    453      */
    454     private String makePath(String item)
    455     {
    456         String pathPattern;
    457         if ((item.length() == 0 || item.startsWith("/")) && trailing)
    458         {
    459             pathPattern = path.substring(0, path.length() - 1);
    460         }
    461         else  if (!item.startsWith("/") || !trailing)
    462         {
    463             pathPattern = path + "/";
    464         }
    465         else
    466         {
    467             pathPattern = path;
    468         }
    469         return getSubstitutor().replace(pathPattern) + item;
    470     }
    471 }