/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.commons.configuration;

import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.net.URL;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.configuration.event.ConfigurationErrorEvent;
import org.apache.commons.configuration.event.ConfigurationErrorListener;
import org.apache.commons.configuration.event.ConfigurationEvent;
import org.apache.commons.configuration.event.ConfigurationListener;
import org.apache.commons.configuration.reloading.Reloadable;
import org.apache.commons.configuration.reloading.ReloadingStrategy;
import org.apache.commons.configuration.tree.ConfigurationNode;

Base class for implementing file based hierarchical configurations.

This class serves an analogous purpose as the AbstractFileConfiguration class for non hierarchical configurations. It behaves in exactly the same way, so please refer to the documentation of AbstractFileConfiguration for further details.

Author:Emmanuel Bourg
Since:1.2
Version:$Id: AbstractHierarchicalFileConfiguration.java 1206575 2011-11-26 20:07:52Z oheger $
/** * <p>Base class for implementing file based hierarchical configurations.</p> * <p>This class serves an analogous purpose as the * {@link AbstractFileConfiguration} class for non hierarchical * configurations. It behaves in exactly the same way, so please refer to the * documentation of {@code AbstractFileConfiguration} for further details.</p> * * @since 1.2 * * @author Emmanuel Bourg * @version $Id: AbstractHierarchicalFileConfiguration.java 1206575 2011-11-26 20:07:52Z oheger $ */
public abstract class AbstractHierarchicalFileConfiguration extends HierarchicalConfiguration implements FileConfiguration, ConfigurationListener, ConfigurationErrorListener, FileSystemBased, Reloadable {
Stores the delegate used for implementing functionality related to the FileConfiguration interface.
/** Stores the delegate used for implementing functionality related to the * {@code FileConfiguration} interface. */
private FileConfigurationDelegate delegate;
Creates a new instance of AbstractHierarchicalFileConfiguration.
/** * Creates a new instance of {@code AbstractHierarchicalFileConfiguration}. */
protected AbstractHierarchicalFileConfiguration() { initialize(); }
Creates a new instance of AbstractHierarchicalFileConfiguration and copies the content of the specified configuration into this object.
Params:
  • c – the configuration to copy
Since:1.4
/** * Creates a new instance of * {@code AbstractHierarchicalFileConfiguration} and copies the * content of the specified configuration into this object. * * @param c the configuration to copy * @since 1.4 */
protected AbstractHierarchicalFileConfiguration(HierarchicalConfiguration c) { super(c); initialize(); }
Creates and loads the configuration from the specified file.
Params:
  • fileName – The name of the plist file to load.
Throws:
/** * Creates and loads the configuration from the specified file. * * @param fileName The name of the plist file to load. * @throws ConfigurationException Error while loading the file */
public AbstractHierarchicalFileConfiguration(String fileName) throws ConfigurationException { this(); // store the file name delegate.setFileName(fileName); // load the file load(); }
Creates and loads the configuration from the specified file.
Params:
  • file – The configuration file to load.
Throws:
/** * Creates and loads the configuration from the specified file. * * @param file The configuration file to load. * @throws ConfigurationException Error while loading the file */
public AbstractHierarchicalFileConfiguration(File file) throws ConfigurationException { this(); // set the file and update the url, the base path and the file name setFile(file); // load the file if (file.exists()) { load(); } }
Creates and loads the configuration from the specified URL.
Params:
  • url – The location of the configuration file to load.
Throws:
/** * Creates and loads the configuration from the specified URL. * * @param url The location of the configuration file to load. * @throws ConfigurationException Error while loading the file */
public AbstractHierarchicalFileConfiguration(URL url) throws ConfigurationException { this(); // set the URL and update the base path and the file name setURL(url); // load the file load(); }
Initializes this instance, mainly the internally used delegate object.
/** * Initializes this instance, mainly the internally used delegate object. */
private void initialize() { delegate = createDelegate(); initDelegate(delegate); } @Override protected void addPropertyDirect(String key, Object obj) { synchronized (delegate.getReloadLock()) { super.addPropertyDirect(key, obj); delegate.possiblySave(); } } @Override public void clearProperty(String key) { synchronized (delegate.getReloadLock()) { super.clearProperty(key); delegate.possiblySave(); } } @Override public void clearTree(String key) { synchronized (delegate.getReloadLock()) { super.clearTree(key); delegate.possiblySave(); } } @Override public void setProperty(String key, Object value) { synchronized (delegate.getReloadLock()) { super.setProperty(key, value); delegate.possiblySave(); } } public void load() throws ConfigurationException { delegate.load(); } public void load(String fileName) throws ConfigurationException { delegate.load(fileName); } public void load(File file) throws ConfigurationException { delegate.load(file); } public void load(URL url) throws ConfigurationException { delegate.load(url); } public void load(InputStream in) throws ConfigurationException { delegate.load(in); } public void load(InputStream in, String encoding) throws ConfigurationException { delegate.load(in, encoding); } public void save() throws ConfigurationException { delegate.save(); } public void save(String fileName) throws ConfigurationException { delegate.save(fileName); } public void save(File file) throws ConfigurationException { delegate.save(file); } public void save(URL url) throws ConfigurationException { delegate.save(url); } public void save(OutputStream out) throws ConfigurationException { delegate.save(out); } public void save(OutputStream out, String encoding) throws ConfigurationException { delegate.save(out, encoding); } public String getFileName() { return delegate.getFileName(); } public void setFileName(String fileName) { delegate.setFileName(fileName); } public String getBasePath() { return delegate.getBasePath(); } public void setBasePath(String basePath) { delegate.setBasePath(basePath); } public File getFile() { return delegate.getFile(); } public void setFile(File file) { delegate.setFile(file); } public URL getURL() { return delegate.getURL(); } public void setURL(URL url) { delegate.setURL(url); } public void setAutoSave(boolean autoSave) { delegate.setAutoSave(autoSave); } public boolean isAutoSave() { return delegate.isAutoSave(); } public ReloadingStrategy getReloadingStrategy() { return delegate.getReloadingStrategy(); } public void setReloadingStrategy(ReloadingStrategy strategy) { delegate.setReloadingStrategy(strategy); } public void reload() { reload(false); } private boolean reload(boolean checkReload) { synchronized (delegate.getReloadLock()) { setDetailEvents(false); try { return delegate.reload(checkReload); } finally { setDetailEvents(true); } } }
Reloads the associated configuration file. This method first clears the content of this configuration, then the associated configuration file is loaded again. Updates on this configuration which have not yet been saved are lost. Calling this method is like invoking reload() without checking the reloading strategy.
Throws:
Since:1.7
/** * Reloads the associated configuration file. This method first clears the * content of this configuration, then the associated configuration file is * loaded again. Updates on this configuration which have not yet been saved * are lost. Calling this method is like invoking {@code reload()} * without checking the reloading strategy. * * @throws ConfigurationException if an error occurs * @since 1.7 */
public void refresh() throws ConfigurationException { delegate.refresh(); } public String getEncoding() { return delegate.getEncoding(); } public void setEncoding(String encoding) { delegate.setEncoding(encoding); } @Override public Object getReloadLock() { return delegate.getReloadLock(); } @Override public boolean containsKey(String key) { reload(); synchronized (delegate.getReloadLock()) { return super.containsKey(key); } } @Override public Iterator<String> getKeys() { reload(); synchronized (delegate.getReloadLock()) { return super.getKeys(); } } @Override public Iterator<String> getKeys(String prefix) { reload(); synchronized (delegate.getReloadLock()) { return super.getKeys(prefix); } } @Override public Object getProperty(String key) { if (reload(true)) { // Avoid reloading again and getting the same error. synchronized (delegate.getReloadLock()) { return super.getProperty(key); } } return null; } @Override public boolean isEmpty() { reload(); synchronized (delegate.getReloadLock()) { return super.isEmpty(); } }
Directly adds sub nodes to this configuration. This implementation checks whether auto save is necessary after executing the operation.
Params:
  • key – the key where the nodes are to be added
  • nodes – a collection with the nodes to be added
Since:1.5
/** * Directly adds sub nodes to this configuration. This implementation checks * whether auto save is necessary after executing the operation. * * @param key the key where the nodes are to be added * @param nodes a collection with the nodes to be added * @since 1.5 */
@Override public void addNodes(String key, Collection<? extends ConfigurationNode> nodes) { synchronized (delegate.getReloadLock()) { super.addNodes(key, nodes); delegate.possiblySave(); } }
Fetches a list of nodes, which are selected by the specified key. This implementation will perform a reload if necessary.
Params:
  • key – the key
Returns:a list with the selected nodes
/** * Fetches a list of nodes, which are selected by the specified key. This * implementation will perform a reload if necessary. * * @param key the key * @return a list with the selected nodes */
@Override protected List<ConfigurationNode> fetchNodeList(String key) { reload(); synchronized (delegate.getReloadLock()) { return super.fetchNodeList(key); } }
Reacts on changes of an associated subnode configuration. If the auto save mechanism is active, the configuration must be saved.
Params:
  • event – the event describing the change
Since:1.5
/** * Reacts on changes of an associated subnode configuration. If the auto * save mechanism is active, the configuration must be saved. * * @param event the event describing the change * @since 1.5 */
@Override protected void subnodeConfigurationChanged(ConfigurationEvent event) { delegate.possiblySave(); super.subnodeConfigurationChanged(event); }
Creates the file configuration delegate, i.e. the object that implements functionality required by the FileConfiguration interface. This base implementation will return an instance of the FileConfigurationDelegate class. Derived classes may override it to create a different delegate object.
Returns:the file configuration delegate
/** * Creates the file configuration delegate, i.e. the object that implements * functionality required by the {@code FileConfiguration} interface. * This base implementation will return an instance of the * {@code FileConfigurationDelegate} class. Derived classes may * override it to create a different delegate object. * * @return the file configuration delegate */
protected FileConfigurationDelegate createDelegate() { return new FileConfigurationDelegate(); }
Helper method for initializing the file configuration delegate.
Params:
  • del – the delegate
/** * Helper method for initializing the file configuration delegate. * * @param del the delegate */
private void initDelegate(FileConfigurationDelegate del) { del.addConfigurationListener(this); del.addErrorListener(this); del.setLogger(getLogger()); }
Reacts on configuration change events triggered by the delegate. These events are passed to the registered configuration listeners.
Params:
  • event – the triggered event
Since:1.3
/** * Reacts on configuration change events triggered by the delegate. These * events are passed to the registered configuration listeners. * * @param event the triggered event * @since 1.3 */
public void configurationChanged(ConfigurationEvent event) { // deliver reload events to registered listeners setDetailEvents(true); try { fireEvent(event.getType(), event.getPropertyName(), event .getPropertyValue(), event.isBeforeUpdate()); } finally { setDetailEvents(false); } } public void configurationError(ConfigurationErrorEvent event) { fireError(event.getType(), event.getPropertyName(), event.getPropertyValue(), event.getCause()); }
Returns the file configuration delegate.
Returns:the delegate
/** * Returns the file configuration delegate. * * @return the delegate */
protected FileConfigurationDelegate getDelegate() { return delegate; }
Allows to set the file configuration delegate.
Params:
  • delegate – the new delegate
/** * Allows to set the file configuration delegate. * @param delegate the new delegate */
protected void setDelegate(FileConfigurationDelegate delegate) { this.delegate = delegate; }
Set the FileSystem to be used for this Configuration.
Params:
  • fileSystem – The FileSystem to use.
/** * Set the FileSystem to be used for this Configuration. * @param fileSystem The FileSystem to use. */
public void setFileSystem(FileSystem fileSystem) { delegate.setFileSystem(fileSystem); }
Reset the FileSystem to the default;
/** * Reset the FileSystem to the default; */
public void resetFileSystem() { delegate.resetFileSystem(); }
Retrieve the FileSystem being used.
Returns:The FileSystem.
/** * Retrieve the FileSystem being used. * @return The FileSystem. */
public FileSystem getFileSystem() { return delegate.getFileSystem(); }
A special implementation of the FileConfiguration interface that is used internally to implement the FileConfiguration methods for hierarchical configurations.
/** * A special implementation of the {@code FileConfiguration} interface that is * used internally to implement the {@code FileConfiguration} methods * for hierarchical configurations. */
protected class FileConfigurationDelegate extends AbstractFileConfiguration { public void load(Reader in) throws ConfigurationException { AbstractHierarchicalFileConfiguration.this.load(in); } public void save(Writer out) throws ConfigurationException { AbstractHierarchicalFileConfiguration.this.save(out); } @Override public void clear() { AbstractHierarchicalFileConfiguration.this.clear(); } } }