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
9
* http://www.apache.org/licenses/LICENSE-2.0
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.
18
package org.apache.commons.configuration;
21
import java.io.InputStream;
22
import java.io.OutputStream;
23
import java.io.Reader;
24
import java.io.Writer;
26
import java.util.Collection;
27
import java.util.Iterator;
28
import java.util.List;
30
import org.apache.commons.configuration.event.ConfigurationErrorEvent;
31
import org.apache.commons.configuration.event.ConfigurationErrorListener;
32
import org.apache.commons.configuration.event.ConfigurationEvent;
33
import org.apache.commons.configuration.event.ConfigurationListener;
34
import org.apache.commons.configuration.reloading.Reloadable;
35
import org.apache.commons.configuration.reloading.ReloadingStrategy;
36
import org.apache.commons.configuration.tree.ConfigurationNode;
39
* <p>Base class for implementing file based hierarchical configurations.</p>
40
* <p>This class serves an analogous purpose as the
41
* {@link AbstractFileConfiguration} class for non hierarchical
42
* configurations. It behaves in exactly the same way, so please refer to the
43
* documentation of {@code AbstractFileConfiguration} for further details.</p>
47
* @author Emmanuel Bourg
48
* @version $Id: AbstractHierarchicalFileConfiguration.java 1206575 2011-11-26 20:07:52Z oheger $
50
public abstract class AbstractHierarchicalFileConfiguration
51
extends HierarchicalConfiguration
52
implements FileConfiguration, ConfigurationListener, ConfigurationErrorListener, FileSystemBased,
55
/** Stores the delegate used for implementing functionality related to the
56
* {@code FileConfiguration} interface.
58
private FileConfigurationDelegate delegate;
61
* Creates a new instance of {@code AbstractHierarchicalFileConfiguration}.
63
protected AbstractHierarchicalFileConfiguration()
69
* Creates a new instance of
70
* {@code AbstractHierarchicalFileConfiguration} and copies the
71
* content of the specified configuration into this object.
73
* @param c the configuration to copy
76
protected AbstractHierarchicalFileConfiguration(HierarchicalConfiguration c)
83
* Creates and loads the configuration from the specified file.
85
* @param fileName The name of the plist file to load.
86
* @throws ConfigurationException Error while loading the file
88
public AbstractHierarchicalFileConfiguration(String fileName) throws ConfigurationException
91
// store the file name
92
delegate.setFileName(fileName);
99
* Creates and loads the configuration from the specified file.
101
* @param file The configuration file to load.
102
* @throws ConfigurationException Error while loading the file
104
public AbstractHierarchicalFileConfiguration(File file) throws ConfigurationException
107
// set the file and update the url, the base path and the file name
118
* Creates and loads the configuration from the specified URL.
120
* @param url The location of the configuration file to load.
121
* @throws ConfigurationException Error while loading the file
123
public AbstractHierarchicalFileConfiguration(URL url) throws ConfigurationException
126
// set the URL and update the base path and the file name
134
* Initializes this instance, mainly the internally used delegate object.
136
private void initialize()
138
delegate = createDelegate();
139
initDelegate(delegate);
143
protected void addPropertyDirect(String key, Object obj)
145
synchronized (delegate.getReloadLock())
147
super.addPropertyDirect(key, obj);
148
delegate.possiblySave();
153
public void clearProperty(String key)
155
synchronized (delegate.getReloadLock())
157
super.clearProperty(key);
158
delegate.possiblySave();
163
public void clearTree(String key)
165
synchronized (delegate.getReloadLock())
167
super.clearTree(key);
168
delegate.possiblySave();
173
public void setProperty(String key, Object value)
175
synchronized (delegate.getReloadLock())
177
super.setProperty(key, value);
178
delegate.possiblySave();
182
public void load() throws ConfigurationException
187
public void load(String fileName) throws ConfigurationException
189
delegate.load(fileName);
192
public void load(File file) throws ConfigurationException
197
public void load(URL url) throws ConfigurationException
202
public void load(InputStream in) throws ConfigurationException
207
public void load(InputStream in, String encoding) throws ConfigurationException
209
delegate.load(in, encoding);
212
public void save() throws ConfigurationException
217
public void save(String fileName) throws ConfigurationException
219
delegate.save(fileName);
222
public void save(File file) throws ConfigurationException
227
public void save(URL url) throws ConfigurationException
232
public void save(OutputStream out) throws ConfigurationException
237
public void save(OutputStream out, String encoding) throws ConfigurationException
239
delegate.save(out, encoding);
242
public String getFileName()
244
return delegate.getFileName();
247
public void setFileName(String fileName)
249
delegate.setFileName(fileName);
252
public String getBasePath()
254
return delegate.getBasePath();
257
public void setBasePath(String basePath)
259
delegate.setBasePath(basePath);
262
public File getFile()
264
return delegate.getFile();
267
public void setFile(File file)
269
delegate.setFile(file);
274
return delegate.getURL();
277
public void setURL(URL url)
279
delegate.setURL(url);
282
public void setAutoSave(boolean autoSave)
284
delegate.setAutoSave(autoSave);
287
public boolean isAutoSave()
289
return delegate.isAutoSave();
292
public ReloadingStrategy getReloadingStrategy()
294
return delegate.getReloadingStrategy();
297
public void setReloadingStrategy(ReloadingStrategy strategy)
299
delegate.setReloadingStrategy(strategy);
307
private boolean reload(boolean checkReload)
309
synchronized (delegate.getReloadLock())
311
setDetailEvents(false);
314
return delegate.reload(checkReload);
318
setDetailEvents(true);
324
* Reloads the associated configuration file. This method first clears the
325
* content of this configuration, then the associated configuration file is
326
* loaded again. Updates on this configuration which have not yet been saved
327
* are lost. Calling this method is like invoking {@code reload()}
328
* without checking the reloading strategy.
330
* @throws ConfigurationException if an error occurs
333
public void refresh() throws ConfigurationException
338
public String getEncoding()
340
return delegate.getEncoding();
343
public void setEncoding(String encoding)
345
delegate.setEncoding(encoding);
349
public Object getReloadLock()
351
return delegate.getReloadLock();
355
public boolean containsKey(String key)
358
synchronized (delegate.getReloadLock())
360
return super.containsKey(key);
365
public Iterator<String> getKeys()
368
synchronized (delegate.getReloadLock())
370
return super.getKeys();
375
public Iterator<String> getKeys(String prefix)
378
synchronized (delegate.getReloadLock())
380
return super.getKeys(prefix);
385
public Object getProperty(String key)
389
// Avoid reloading again and getting the same error.
390
synchronized (delegate.getReloadLock())
392
return super.getProperty(key);
399
public boolean isEmpty()
402
synchronized (delegate.getReloadLock())
404
return super.isEmpty();
409
* Directly adds sub nodes to this configuration. This implementation checks
410
* whether auto save is necessary after executing the operation.
412
* @param key the key where the nodes are to be added
413
* @param nodes a collection with the nodes to be added
417
public void addNodes(String key, Collection<? extends ConfigurationNode> nodes)
419
synchronized (delegate.getReloadLock())
421
super.addNodes(key, nodes);
422
delegate.possiblySave();
427
* Fetches a list of nodes, which are selected by the specified key. This
428
* implementation will perform a reload if necessary.
431
* @return a list with the selected nodes
434
protected List<ConfigurationNode> fetchNodeList(String key)
437
synchronized (delegate.getReloadLock())
439
return super.fetchNodeList(key);
444
* Reacts on changes of an associated subnode configuration. If the auto
445
* save mechanism is active, the configuration must be saved.
447
* @param event the event describing the change
451
protected void subnodeConfigurationChanged(ConfigurationEvent event)
453
delegate.possiblySave();
454
super.subnodeConfigurationChanged(event);
458
* Creates the file configuration delegate, i.e. the object that implements
459
* functionality required by the {@code FileConfiguration} interface.
460
* This base implementation will return an instance of the
461
* {@code FileConfigurationDelegate} class. Derived classes may
462
* override it to create a different delegate object.
464
* @return the file configuration delegate
466
protected FileConfigurationDelegate createDelegate()
468
return new FileConfigurationDelegate();
472
* Helper method for initializing the file configuration delegate.
474
* @param del the delegate
476
private void initDelegate(FileConfigurationDelegate del)
478
del.addConfigurationListener(this);
479
del.addErrorListener(this);
480
del.setLogger(getLogger());
484
* Reacts on configuration change events triggered by the delegate. These
485
* events are passed to the registered configuration listeners.
487
* @param event the triggered event
490
public void configurationChanged(ConfigurationEvent event)
492
// deliver reload events to registered listeners
493
setDetailEvents(true);
496
fireEvent(event.getType(), event.getPropertyName(), event
497
.getPropertyValue(), event.isBeforeUpdate());
501
setDetailEvents(false);
505
public void configurationError(ConfigurationErrorEvent event)
507
fireError(event.getType(), event.getPropertyName(), event.getPropertyValue(),
512
* Returns the file configuration delegate.
514
* @return the delegate
516
protected FileConfigurationDelegate getDelegate()
522
* Allows to set the file configuration delegate.
523
* @param delegate the new delegate
525
protected void setDelegate(FileConfigurationDelegate delegate)
527
this.delegate = delegate;
531
* Set the FileSystem to be used for this Configuration.
532
* @param fileSystem The FileSystem to use.
534
public void setFileSystem(FileSystem fileSystem)
536
delegate.setFileSystem(fileSystem);
540
* Reset the FileSystem to the default;
542
public void resetFileSystem()
544
delegate.resetFileSystem();
548
* Retrieve the FileSystem being used.
549
* @return The FileSystem.
551
public FileSystem getFileSystem()
553
return delegate.getFileSystem();
557
* A special implementation of the {@code FileConfiguration} interface that is
558
* used internally to implement the {@code FileConfiguration} methods
559
* for hierarchical configurations.
561
protected class FileConfigurationDelegate extends AbstractFileConfiguration
563
public void load(Reader in) throws ConfigurationException
565
AbstractHierarchicalFileConfiguration.this.load(in);
568
public void save(Writer out) throws ConfigurationException
570
AbstractHierarchicalFileConfiguration.this.save(out);
576
AbstractHierarchicalFileConfiguration.this.clear();