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