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 }