View Javadoc

1   /*
2    * Copyright 2001-2005 The Apache Software Foundation.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License")
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.apache.commons.configuration;
18  
19  import java.util.ArrayList;
20  import java.util.Iterator;
21  import java.util.LinkedList;
22  import java.util.List;
23  
24  /***
25   * This Configuration class allows you to add multiple different types of Configuration
26   * to this CompositeConfiguration.  If you add Configuration1, and then Configuration2,
27   * any properties shared will mean that Configuration1 will be returned.
28   * You can add multiple different types or the same type of properties file.
29   * If Configuration1 doesn't have the property, then Configuration2 will be checked.
30   *
31   * @author <a href="mailto:epugh@upstate.com">Eric Pugh</a>
32   * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
33   * @version $Id: CompositeConfiguration.java 332561 2005-11-11 14:17:23Z oheger $
34   */
35  public class CompositeConfiguration extends AbstractConfiguration
36  {
37      /*** List holding all the configuration */
38      private List configList = new LinkedList();
39  
40      /***
41       * Configuration that holds in memory stuff.  Inserted as first so any
42       * setProperty() override anything else added.
43       */
44      private Configuration inMemoryConfiguration;
45  
46      /***
47       * Creates an empty CompositeConfiguration object which can then
48       * be added some other Configuration files
49       */
50      public CompositeConfiguration()
51      {
52          clear();
53      }
54  
55      /***
56       * Creates an CompositeConfiguration object with a specified InMemory
57       * configuration. This configuration will store any changes made to
58       * the CompositeConfiguration.
59       *
60       * @param inMemoryConfiguration the in memory configuration to use
61       */
62      public CompositeConfiguration(Configuration inMemoryConfiguration)
63      {
64          configList.clear();
65          this.inMemoryConfiguration = inMemoryConfiguration;
66          configList.add(inMemoryConfiguration);
67      }
68  
69      /***
70       * Add a configuration.
71       *
72       * @param config the configuration to add
73       */
74      public void addConfiguration(Configuration config)
75      {
76          if (!configList.contains(config))
77          {
78              // As the inMemoryConfiguration contains all manually added keys,
79              // we must make sure that it is always last. "Normal", non composed
80              // configuration add their keys at the end of the configuration and
81              // we want to mimic this behaviour.
82              configList.add(configList.indexOf(inMemoryConfiguration), config);
83  
84              if (config instanceof AbstractConfiguration)
85              {
86                  ((AbstractConfiguration) config).setThrowExceptionOnMissing(isThrowExceptionOnMissing());
87              }
88          }
89      }
90  
91      /***
92       * Remove a configuration. The in memory configuration cannot be removed.
93       *
94       * @param config The configuration to remove
95       */
96      public void removeConfiguration(Configuration config)
97      {
98          // Make sure that you can't remove the inMemoryConfiguration from
99          // the CompositeConfiguration object
100         if (!config.equals(inMemoryConfiguration))
101         {
102             configList.remove(config);
103         }
104     }
105 
106     /***
107      * Return the number of configurations.
108      *
109      * @return the number of configuration
110      */
111     public int getNumberOfConfigurations()
112     {
113         return configList.size();
114     }
115 
116     /***
117      * Remove all configuration reinitialize the in memory configuration.
118      */
119     public void clear()
120     {
121         configList.clear();
122         // recreate the in memory configuration
123         inMemoryConfiguration = new BaseConfiguration();
124         ((BaseConfiguration) inMemoryConfiguration).setThrowExceptionOnMissing(isThrowExceptionOnMissing());
125         configList.add(inMemoryConfiguration);
126     }
127 
128     /***
129      * Add this property to the inmemory Configuration.
130      *
131      * @param key The Key to add the property to.
132      * @param token The Value to add.
133      */
134     protected void addPropertyDirect(String key, Object token)
135     {
136         inMemoryConfiguration.addProperty(key, token);
137     }
138 
139     /***
140      * Read property from underlying composite
141      *
142      * @param key key to use for mapping
143      *
144      * @return object associated with the given configuration key.
145      */
146     public Object getProperty(String key)
147     {
148         Configuration firstMatchingConfiguration = null;
149         for (Iterator i = configList.iterator(); i.hasNext();)
150         {
151             Configuration config = (Configuration) i.next();
152             if (config.containsKey(key))
153             {
154                 firstMatchingConfiguration = config;
155                 break;
156             }
157         }
158 
159         if (firstMatchingConfiguration != null)
160         {
161             return firstMatchingConfiguration.getProperty(key);
162         }
163         else
164         {
165             return null;
166         }
167     }
168 
169     /***
170      * {@inheritDoc}
171      */
172     public Iterator getKeys()
173     {
174         List keys = new ArrayList();
175         for (Iterator i = configList.iterator(); i.hasNext();)
176         {
177             Configuration config = (Configuration) i.next();
178 
179             Iterator j = config.getKeys();
180             while (j.hasNext())
181             {
182                 String key = (String) j.next();
183                 if (!keys.contains(key))
184                 {
185                     keys.add(key);
186                 }
187             }
188         }
189 
190         return keys.iterator();
191     }
192 
193     /***
194      * {@inheritDoc}
195      */
196     public Iterator getKeys(String key)
197     {
198         List keys = new ArrayList();
199         for (Iterator i = configList.iterator(); i.hasNext();)
200         {
201             Configuration config = (Configuration) i.next();
202 
203             Iterator j = config.getKeys(key);
204             while (j.hasNext())
205             {
206                 String newKey = (String) j.next();
207                 if (!keys.contains(newKey))
208                 {
209                     keys.add(newKey);
210                 }
211             }
212         }
213 
214         return keys.iterator();
215     }
216 
217     /***
218      * {@inheritDoc}
219      */
220     public boolean isEmpty()
221     {
222         boolean isEmpty = true;
223         for (Iterator i = configList.iterator(); i.hasNext();)
224         {
225             Configuration config = (Configuration) i.next();
226             if (!config.isEmpty())
227             {
228                 return false;
229             }
230         }
231 
232         return isEmpty;
233     }
234 
235     /***
236      * {@inheritDoc}
237      */
238     public void clearProperty(String key)
239     {
240         for (Iterator i = configList.iterator(); i.hasNext();)
241         {
242             Configuration config = (Configuration) i.next();
243             config.clearProperty(key);
244         }
245     }
246 
247     /***
248      * {@inheritDoc}
249      */
250     public boolean containsKey(String key)
251     {
252         for (Iterator i = configList.iterator(); i.hasNext();)
253         {
254             Configuration config = (Configuration) i.next();
255             if (config.containsKey(key))
256             {
257                 return true;
258             }
259         }
260         return false;
261     }
262 
263     /***
264      * {@inheritDoc}
265      */
266     public List getList(String key, List defaultValue)
267     {
268         List list = new ArrayList();
269 
270         // add all elements from the first configuration containing the requested key
271         Iterator it = configList.iterator();
272         while (it.hasNext() && list.isEmpty())
273         {
274             Configuration config = (Configuration) it.next();
275             if (config != inMemoryConfiguration && config.containsKey(key))
276             {
277                 list.addAll(config.getList(key));
278             }
279         }
280 
281         // add all elements from the in memory configuration
282         list.addAll(inMemoryConfiguration.getList(key));
283 
284         if (list.isEmpty())
285         {
286             return defaultValue;
287         }
288 
289         return list;
290     }
291 
292     /***
293      * {@inheritDoc}
294      */
295     public String[] getStringArray(String key)
296     {
297         List list = getList(key);
298 
299         // interpolate the strings
300         String[] tokens = new String[list.size()];
301 
302         for (int i = 0; i < tokens.length; i++)
303         {
304             tokens[i] = interpolate(String.valueOf(list.get(i)));
305         }
306 
307         return tokens;
308     }
309 
310     /***
311      * Return the configuration at the specified index.
312      *
313      * @param index The index of the configuration to retrieve
314      * @return the configuration at this index
315      */
316     public Configuration getConfiguration(int index)
317     {
318         return (Configuration) configList.get(index);
319     }
320 
321     /***
322      * Returns the &quot;in memory configuration&quot;. In this configuration
323      * changes are stored.
324      *
325      * @return the in memory configuration
326      */
327     public Configuration getInMemoryConfiguration()
328     {
329         return inMemoryConfiguration;
330     }
331 }