001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.commons.configuration;
019:
020: import java.io.Reader;
021: import java.io.Writer;
022: import java.io.File;
023: import java.io.InputStream;
024: import java.io.OutputStream;
025: import java.net.URL;
026: import java.util.Iterator;
027: import java.util.List;
028:
029: import org.apache.commons.configuration.event.ConfigurationEvent;
030: import org.apache.commons.configuration.event.ConfigurationListener;
031: import org.apache.commons.configuration.reloading.ReloadingStrategy;
032:
033: /**
034: * <p>Base class for implementing file based hierarchical configurations.</p>
035: * <p>This class serves an analogous purpose as the
036: * <code>{@link AbstractFileConfiguration}</code> class for non hierarchical
037: * configurations. It behaves in exactly the same way, so please refer to the
038: * documentation of <code>AbstractFileConfiguration</code> for further details.</p>
039: *
040: * @since 1.2
041: *
042: * @author Emmanuel Bourg
043: * @version $Revision: 492216 $, $Date: 2007-01-03 17:51:24 +0100 (Mi, 03 Jan 2007) $
044: */
045: public abstract class AbstractHierarchicalFileConfiguration extends
046: HierarchicalConfiguration implements FileConfiguration,
047: ConfigurationListener {
048: /** Stores the delegate used for implementing functionality related to the
049: * <code>FileConfiguration</code> interface.
050: */
051: private FileConfigurationDelegate delegate;
052:
053: /**
054: * Creates a new instance of
055: * <code>AbstractHierarchicalFileConfiguration</code>.
056: */
057: protected AbstractHierarchicalFileConfiguration() {
058: initialize();
059: }
060:
061: /**
062: * Creates a new instance of
063: * <code>AbstractHierarchicalFileConfiguration</code> and copies the
064: * content of the specified configuration into this object.
065: *
066: * @param c the configuration to copy
067: * @since 1.4
068: */
069: protected AbstractHierarchicalFileConfiguration(
070: HierarchicalConfiguration c) {
071: super (c);
072: initialize();
073: }
074:
075: /**
076: * Creates and loads the configuration from the specified file.
077: *
078: * @param fileName The name of the plist file to load.
079: * @throws ConfigurationException Error while loading the file
080: */
081: public AbstractHierarchicalFileConfiguration(String fileName)
082: throws ConfigurationException {
083: this ();
084: // store the file name
085: delegate.setFileName(fileName);
086:
087: // load the file
088: load();
089: }
090:
091: /**
092: * Creates and loads the configuration from the specified file.
093: *
094: * @param file The configuration file to load.
095: * @throws ConfigurationException Error while loading the file
096: */
097: public AbstractHierarchicalFileConfiguration(File file)
098: throws ConfigurationException {
099: this ();
100: // set the file and update the url, the base path and the file name
101: setFile(file);
102:
103: // load the file
104: if (file.exists()) {
105: load();
106: }
107: }
108:
109: /**
110: * Creates and loads the configuration from the specified URL.
111: *
112: * @param url The location of the configuration file to load.
113: * @throws ConfigurationException Error while loading the file
114: */
115: public AbstractHierarchicalFileConfiguration(URL url)
116: throws ConfigurationException {
117: this ();
118: // set the URL and update the base path and the file name
119: setURL(url);
120:
121: // load the file
122: load();
123: }
124:
125: /**
126: * Initializes this instance, mainly the internally used delegate object.
127: */
128: private void initialize() {
129: delegate = createDelegate();
130: initDelegate(delegate);
131: }
132:
133: protected void addPropertyDirect(String key, Object obj) {
134: super .addPropertyDirect(key, obj);
135: delegate.possiblySave();
136: }
137:
138: public void clearProperty(String key) {
139: super .clearProperty(key);
140: delegate.possiblySave();
141: }
142:
143: public void clearTree(String key) {
144: super .clearTree(key);
145: delegate.possiblySave();
146: }
147:
148: public void setProperty(String key, Object value) {
149: super .setProperty(key, value);
150: delegate.possiblySave();
151: }
152:
153: public void load() throws ConfigurationException {
154: delegate.load();
155: }
156:
157: public void load(String fileName) throws ConfigurationException {
158: delegate.load(fileName);
159: }
160:
161: public void load(File file) throws ConfigurationException {
162: delegate.load(file);
163: }
164:
165: public void load(URL url) throws ConfigurationException {
166: delegate.load(url);
167: }
168:
169: public void load(InputStream in) throws ConfigurationException {
170: delegate.load(in);
171: }
172:
173: public void load(InputStream in, String encoding)
174: throws ConfigurationException {
175: delegate.load(in, encoding);
176: }
177:
178: public void save() throws ConfigurationException {
179: delegate.save();
180: }
181:
182: public void save(String fileName) throws ConfigurationException {
183: delegate.save(fileName);
184: }
185:
186: public void save(File file) throws ConfigurationException {
187: delegate.save(file);
188: }
189:
190: public void save(URL url) throws ConfigurationException {
191: delegate.save(url);
192: }
193:
194: public void save(OutputStream out) throws ConfigurationException {
195: delegate.save(out);
196: }
197:
198: public void save(OutputStream out, String encoding)
199: throws ConfigurationException {
200: delegate.save(out, encoding);
201: }
202:
203: public String getFileName() {
204: return delegate.getFileName();
205: }
206:
207: public void setFileName(String fileName) {
208: delegate.setFileName(fileName);
209: }
210:
211: public String getBasePath() {
212: return delegate.getBasePath();
213: }
214:
215: public void setBasePath(String basePath) {
216: delegate.setBasePath(basePath);
217: }
218:
219: public File getFile() {
220: return delegate.getFile();
221: }
222:
223: public void setFile(File file) {
224: delegate.setFile(file);
225: }
226:
227: public URL getURL() {
228: return delegate.getURL();
229: }
230:
231: public void setURL(URL url) {
232: delegate.setURL(url);
233: }
234:
235: public void setAutoSave(boolean autoSave) {
236: delegate.setAutoSave(autoSave);
237: }
238:
239: public boolean isAutoSave() {
240: return delegate.isAutoSave();
241: }
242:
243: public ReloadingStrategy getReloadingStrategy() {
244: return delegate.getReloadingStrategy();
245: }
246:
247: public void setReloadingStrategy(ReloadingStrategy strategy) {
248: delegate.setReloadingStrategy(strategy);
249: }
250:
251: public void reload() {
252: setDetailEvents(false);
253: try {
254: delegate.reload();
255: } finally {
256: setDetailEvents(true);
257: }
258: }
259:
260: public String getEncoding() {
261: return delegate.getEncoding();
262: }
263:
264: public void setEncoding(String encoding) {
265: delegate.setEncoding(encoding);
266: }
267:
268: public boolean containsKey(String key) {
269: reload();
270: return super .containsKey(key);
271: }
272:
273: public Iterator getKeys(String prefix) {
274: reload();
275: return super .getKeys(prefix);
276: }
277:
278: public Object getProperty(String key) {
279: reload();
280: return super .getProperty(key);
281: }
282:
283: public boolean isEmpty() {
284: reload();
285: return super .isEmpty();
286: }
287:
288: /**
289: * Fetches a list of nodes, which are selected by the specified key. This
290: * implementation will perform a reload if necessary.
291: *
292: * @param key the key
293: * @return a list with the selected nodes
294: */
295: protected List fetchNodeList(String key) {
296: reload();
297: return super .fetchNodeList(key);
298: }
299:
300: /**
301: * Creates the file configuration delegate, i.e. the object that implements
302: * functionality required by the <code>FileConfiguration</code> interface.
303: * This base implementation will return an instance of the
304: * <code>FileConfigurationDelegate</code> class. Derived classes may
305: * override it to create a different delegate object.
306: *
307: * @return the file configuration delegate
308: */
309: protected FileConfigurationDelegate createDelegate() {
310: return new FileConfigurationDelegate();
311: }
312:
313: /**
314: * Helper method for initializing the file configuration delegate.
315: *
316: * @param del the delegate
317: */
318: private void initDelegate(FileConfigurationDelegate del) {
319: del.addConfigurationListener(this );
320: }
321:
322: /**
323: * Reacts on configuration change events triggered by the delegate. These
324: * events are passed to the registered configuration listeners.
325: *
326: * @param event the triggered event
327: * @since 1.3
328: */
329: public void configurationChanged(ConfigurationEvent event) {
330: // deliver reload events to registered listeners
331: setDetailEvents(true);
332: try {
333: fireEvent(event.getType(), event.getPropertyName(), event
334: .getPropertyValue(), event.isBeforeUpdate());
335: } finally {
336: setDetailEvents(false);
337: }
338: }
339:
340: /**
341: * Returns the file configuration delegate.
342: *
343: * @return the delegate
344: */
345: protected FileConfigurationDelegate getDelegate() {
346: return delegate;
347: }
348:
349: /**
350: * Allows to set the file configuration delegate.
351: * @param delegate the new delegate
352: */
353: protected void setDelegate(FileConfigurationDelegate delegate) {
354: this .delegate = delegate;
355: }
356:
357: /**
358: * A special implementation of the <code>FileConfiguration</code> interface that is
359: * used internally to implement the <code>FileConfiguration</code> methods
360: * for hierarchical configurations.
361: */
362: protected class FileConfigurationDelegate extends
363: AbstractFileConfiguration {
364: public void load(Reader in) throws ConfigurationException {
365: AbstractHierarchicalFileConfiguration.this .load(in);
366: }
367:
368: public void save(Writer out) throws ConfigurationException {
369: AbstractHierarchicalFileConfiguration.this .save(out);
370: }
371:
372: public void clear() {
373: AbstractHierarchicalFileConfiguration.this.clear();
374: }
375: }
376: }
|