1
/* ========================================================================
2
* JCommon : a free general purpose class library for the Java(tm) platform
3
* ========================================================================
5
* (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
7
* Project Info: http://www.jfree.org/jcommon/index.html
9
* This library is free software; you can redistribute it and/or modify it
10
* under the terms of the GNU Lesser General Public License as published by
11
* the Free Software Foundation; either version 2.1 of the License, or
12
* (at your option) any later version.
14
* This library is distributed in the hope that it will be useful, but
15
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17
* License for more details.
19
* You should have received a copy of the GNU Lesser General Public
20
* License along with this library; if not, write to the Free Software
21
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
24
* [Java is a trademark or registered trademark of Sun Microsystems, Inc.
25
* in the United States and other countries.]
27
* ------------------------------
28
* HierarchicalConfiguration.java
29
* ------------------------------
30
* (C) Copyright 2004, by Object Refinery Limited.
32
* Original Author: Thomas Morgner;
33
* Contributor(s): David Gilbert (for Object Refinery Limited);
35
* $Id: HierarchicalConfiguration.java,v 1.6 2005/10/18 13:14:12 mungady Exp $
39
* 07-Jun-2004 : Added JCommon header (DG);
40
* 29-Jul-2004 : Replaced 'enum' variable name (reserved word in JDK 1.5) (DG);
44
package org.jfree.base.config;
46
import java.io.IOException;
47
import java.io.ObjectInputStream;
48
import java.io.ObjectOutputStream;
49
import java.util.Collections;
50
import java.util.Enumeration;
51
import java.util.Iterator;
52
import java.util.Properties;
53
import java.util.TreeSet;
55
import org.jfree.util.Configuration;
58
* A hierarchical configuration. Such a configuration can have one or more
59
* parent configurations providing usefull default values.
61
* @author Thomas Morgner
63
public class HierarchicalConfiguration
64
implements ModifiableConfiguration {
67
* The instance configuration properties.
69
private Properties configuration;
72
* The parent configuration (null if this is the root configuration).
74
private transient Configuration parentConfiguration;
77
* Creates a new configuration.
79
public HierarchicalConfiguration() {
80
this.configuration = new Properties();
84
* Creates a new configuration.
86
* @param parentConfiguration the parent configuration.
88
public HierarchicalConfiguration(final Configuration parentConfiguration) {
90
this.parentConfiguration = parentConfiguration;
94
* Returns the configuration property with the specified key.
96
* @param key the property key.
97
* @return the property value.
99
public String getConfigProperty(final String key) {
100
return getConfigProperty(key, null);
104
* Returns the configuration property with the specified key
105
* (or the specified default value if there is no such property).
107
* If the property is not defined in this configuration, the code
108
* will lookup the property in the parent configuration.
110
* @param key the property key.
111
* @param defaultValue the default value.
112
* @return the property value.
114
public String getConfigProperty(final String key, final String defaultValue) {
115
String value = this.configuration.getProperty(key);
117
if (isRootConfig()) {
118
value = defaultValue;
121
value = this.parentConfiguration.getConfigProperty(key, defaultValue);
128
* Sets a configuration property.
130
* @param key the property key.
131
* @param value the property value.
133
public void setConfigProperty(final String key, final String value) {
135
throw new NullPointerException();
139
this.configuration.remove(key);
142
this.configuration.setProperty(key, value);
147
* Returns true if this object has no parent.
149
* @return true, if this report is the root configuration, false otherwise.
151
private boolean isRootConfig() {
152
return this.parentConfiguration == null;
156
* Checks, whether the given key is localy defined in this instance or
157
* whether the key's value is inherited.
159
* @param key the key that should be checked.
160
* @return true, if the key is defined locally, false otherwise.
162
public boolean isLocallyDefined(final String key) {
163
return this.configuration.containsKey(key);
167
* Returns the collection of properties for the configuration.
169
* @return the properties.
171
protected Properties getConfiguration() {
172
return this.configuration;
176
* The new configuartion will be inserted into the list of report configuration,
177
* so that this configuration has the given report configuration instance as parent.
179
* @param config the new report configuration.
181
public void insertConfiguration(final HierarchicalConfiguration config) {
182
config.setParentConfig(getParentConfig());
183
setParentConfig(config);
187
* Set the parent configuration. The parent configuration is queried, if the
188
* requested configuration values was not found in this report configuration.
190
* @param config the parent configuration.
192
protected void setParentConfig(final Configuration config) {
193
if (this.parentConfiguration == this) {
194
throw new IllegalArgumentException("Cannot add myself as parent configuration.");
196
this.parentConfiguration = config;
200
* Returns the parent configuration. The parent configuration is queried, if the
201
* requested configuration values was not found in this report configuration.
203
* @return the parent configuration.
205
protected Configuration getParentConfig() {
206
return this.parentConfiguration;
210
* Returns all defined configuration properties for the report. The enumeration
211
* contains all keys of the changed properties, properties set from files or
212
* the system properties are not included.
214
* @return all defined configuration properties for the report.
216
public Enumeration getConfigProperties() {
217
return this.configuration.keys();
221
* Searches all property keys that start with a given prefix.
223
* @param prefix the prefix that all selected property keys should share
224
* @return the properties as iterator.
226
public Iterator findPropertyKeys(final String prefix) {
227
final TreeSet keys = new TreeSet();
228
collectPropertyKeys(prefix, this, keys);
229
return Collections.unmodifiableSet(keys).iterator();
233
* Collects property keys from this and all parent report configurations, which
234
* start with the given prefix.
236
* @param prefix the prefix, that selects the property keys.
237
* @param config the currently processed report configuration.
238
* @param collector the target list, that should receive all valid keys.
240
private void collectPropertyKeys(final String prefix, final Configuration config,
241
final TreeSet collector) {
242
final Enumeration enum1 = config.getConfigProperties();
243
while (enum1.hasMoreElements()) {
244
final String key = (String) enum1.nextElement();
245
if (key.startsWith(prefix)) {
246
if (collector.contains(key) == false) {
252
if (config instanceof HierarchicalConfiguration) {
253
final HierarchicalConfiguration hconfig = (HierarchicalConfiguration) config;
254
if (hconfig.parentConfiguration != null) {
255
collectPropertyKeys(prefix, hconfig.parentConfiguration, collector);
261
* Checks, whether the parent configuration can be serialized. Usually the
262
* global configuration is not serialized and should return false here.
264
* @return true, if the parent config can be serialized, false otherwise.
266
protected boolean isParentSaved() {
271
* A callback method to reconnect this configuration with the global configuration
272
* after deserialization.
274
protected void configurationLoaded() {
278
* Helper method for serialization.
280
* @param out the output stream where to write the object.
281
* @throws java.io.IOException if errors occur while writing the stream.
283
private void writeObject(final ObjectOutputStream out)
285
out.defaultWriteObject();
286
if (isParentSaved() == false) {
287
out.writeBoolean(false);
290
out.writeBoolean(true);
291
out.writeObject(parentConfiguration);
296
* Helper method for serialization.
298
* @param in the input stream from where to read the serialized object.
299
* @throws IOException when reading the stream fails.
300
* @throws ClassNotFoundException if a class definition for a serialized object
301
* could not be found.
303
private void readObject(final ObjectInputStream in)
304
throws IOException, ClassNotFoundException {
305
in.defaultReadObject();
306
final boolean readParent = in.readBoolean();
308
parentConfiguration = (ModifiableConfiguration) in.readObject();
311
parentConfiguration = null;
313
configurationLoaded();