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.util.ArrayList; 021 import java.util.Collection; 022 import java.util.Iterator; 023 import java.util.List; 024 import java.util.Map; 025 026 import org.apache.commons.collections.map.LinkedMap; 027 028 /** 029 * Basic configuration class. Stores the configuration data but does not 030 * provide any load or save functions. If you want to load your Configuration 031 * from a file use PropertiesConfiguration or XmlConfiguration. 032 * 033 * This class extends normal Java properties by adding the possibility 034 * to use the same key many times concatenating the value strings 035 * instead of overwriting them. 036 * 037 * @author <a href="mailto:stefano@apache.org">Stefano Mazzocchi</a> 038 * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a> 039 * @author <a href="mailto:daveb@miceda-data">Dave Bryson</a> 040 * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a> 041 * @author <a href="mailto:leon@opticode.co.za">Leon Messerschmidt</a> 042 * @author <a href="mailto:kjohnson@transparent.com">Kent Johnson</a> 043 * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a> 044 * @author <a href="mailto:ipriha@surfeu.fi">Ilkka Priha</a> 045 * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a> 046 * @author <a href="mailto:mpoeschl@marmot.at">Martin Poeschl</a> 047 * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a> 048 * @author <a href="mailto:ksh@scand.com">Konstantin Shaposhnikov</a> 049 * @author Oliver Heger 050 * @version $Id: BaseConfiguration.java 806862 2009-08-22 15:13:31Z oheger $ 051 */ 052 public class BaseConfiguration extends AbstractConfiguration implements Cloneable 053 { 054 /** stores the configuration key-value pairs */ 055 private Map store = new LinkedMap(); 056 057 /** 058 * Adds a key/value pair to the map. This routine does no magic morphing. 059 * It ensures the keylist is maintained 060 * 061 * @param key key to use for mapping 062 * @param value object to store 063 */ 064 protected void addPropertyDirect(String key, Object value) 065 { 066 Object previousValue = getProperty(key); 067 068 if (previousValue == null) 069 { 070 store.put(key, value); 071 } 072 else if (previousValue instanceof List) 073 { 074 // the value is added to the existing list 075 ((List) previousValue).add(value); 076 } 077 else 078 { 079 // the previous value is replaced by a list containing the previous value and the new value 080 List list = new ArrayList(); 081 list.add(previousValue); 082 list.add(value); 083 084 store.put(key, list); 085 } 086 } 087 088 /** 089 * Read property from underlying map. 090 * 091 * @param key key to use for mapping 092 * 093 * @return object associated with the given configuration key. 094 */ 095 public Object getProperty(String key) 096 { 097 return store.get(key); 098 } 099 100 /** 101 * Check if the configuration is empty 102 * 103 * @return <code>true</code> if Configuration is empty, 104 * <code>false</code> otherwise. 105 */ 106 public boolean isEmpty() 107 { 108 return store.isEmpty(); 109 } 110 111 /** 112 * check if the configuration contains the key 113 * 114 * @param key the configuration key 115 * 116 * @return <code>true</code> if Configuration contain given key, 117 * <code>false</code> otherwise. 118 */ 119 public boolean containsKey(String key) 120 { 121 return store.containsKey(key); 122 } 123 124 /** 125 * Clear a property in the configuration. 126 * 127 * @param key the key to remove along with corresponding value. 128 */ 129 protected void clearPropertyDirect(String key) 130 { 131 if (containsKey(key)) 132 { 133 store.remove(key); 134 } 135 } 136 137 public void clear() 138 { 139 fireEvent(EVENT_CLEAR, null, null, true); 140 store.clear(); 141 fireEvent(EVENT_CLEAR, null, null, false); 142 } 143 144 /** 145 * Get the list of the keys contained in the configuration 146 * repository. 147 * 148 * @return An Iterator. 149 */ 150 public Iterator getKeys() 151 { 152 return store.keySet().iterator(); 153 } 154 155 /** 156 * Creates a copy of this object. This implementation will create a deep 157 * clone, i.e. the map that stores the properties is cloned, too. So changes 158 * performed at the copy won't affect the original and vice versa. 159 * 160 * @return the copy 161 * @since 1.3 162 */ 163 public Object clone() 164 { 165 try 166 { 167 BaseConfiguration copy = (BaseConfiguration) super.clone(); 168 copy.store = (Map) ConfigurationUtils.clone(store); 169 170 // Handle collections in the map; they have to be cloned, too 171 for (Iterator it = store.entrySet().iterator(); it.hasNext();) 172 { 173 Map.Entry e = (Map.Entry) it.next(); 174 if (e.getValue() instanceof Collection) 175 { 176 copy.store.put(e.getKey(), new ArrayList((Collection) e 177 .getValue())); 178 } 179 } 180 181 return copy; 182 } 183 catch (CloneNotSupportedException cex) 184 { 185 // should not happen 186 throw new ConfigurationRuntimeException(cex); 187 } 188 } 189 }