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.beanutils;
019
020 import java.lang.reflect.Array;
021 import java.util.Collection;
022 import java.util.Iterator;
023 import java.util.List;
024
025 import org.apache.commons.beanutils.DynaBean;
026 import org.apache.commons.beanutils.DynaClass;
027 import org.apache.commons.configuration.Configuration;
028 import org.apache.commons.configuration.ConfigurationMap;
029 import org.apache.commons.configuration.ConversionException;
030 import org.apache.commons.configuration.SubsetConfiguration;
031 import org.apache.commons.logging.Log;
032 import org.apache.commons.logging.LogFactory;
033
034 /**
035 * The <tt>ConfigurationDynaBean</tt> dynamically reads and writes
036 * configurations properties from a wrapped configuration-collection
037 * {@link org.apache.commons.configuration.Configuration} instance. It also
038 * implements a {@link java.util.Map} interface so that it can be used in
039 * JSP 2.0 Expression Language expressions.
040 *
041 * <p>The <code>ConfigurationDynaBean</code> maps nested and mapped properties
042 * to the appropriate <code>Configuration</code> subset using the
043 * {@link org.apache.commons.configuration.Configuration#subset}
044 * method. Similarly, indexed properties reference lists of configuration
045 * properties using the
046 * {@link org.apache.commons.configuration.Configuration#getList(String)}
047 * method. Setting an indexed property always throws an exception.</p>
048 *
049 * <p>Note: Some of the methods expect that a dot (".") is used as
050 * property delimitor for the wrapped configuration. This is true for most of
051 * the default configurations. Hierarchical configurations, for which a specific
052 * expression engine is set, may cause problems.</p>
053 *
054 * @author <a href="mailto:ricardo.gladwell@btinternet.com">Ricardo Gladwell</a>
055 * @version $Revision: 681804 $, $Date: 2008-08-01 21:58:59 +0200 (Fr, 01 Aug 2008) $
056 * @since 1.0-rc1
057 */
058 public class ConfigurationDynaBean extends ConfigurationMap implements DynaBean
059 {
060 /** Constant for the property delimiter.*/
061 private static final String PROPERTY_DELIMITER = ".";
062
063 /** The logger.*/
064 private static Log log = LogFactory.getLog(ConfigurationDynaBean.class);
065
066 /**
067 * Creates a new instance of <code>ConfigurationDynaBean</code> and sets
068 * the configuration this bean is associated with.
069 *
070 * @param configuration the configuration
071 */
072 public ConfigurationDynaBean(Configuration configuration)
073 {
074 super(configuration);
075 if (log.isTraceEnabled())
076 {
077 log.trace("ConfigurationDynaBean(" + configuration + ")");
078 }
079 }
080
081 public void set(String name, Object value)
082 {
083 if (log.isTraceEnabled())
084 {
085 log.trace("set(" + name + "," + value + ")");
086 }
087
088 if (value == null)
089 {
090 throw new NullPointerException("Error trying to set property to null.");
091 }
092
093 if (value instanceof Collection)
094 {
095 Collection collection = (Collection) value;
096 Iterator iterator = collection.iterator();
097 while (iterator.hasNext())
098 {
099 getConfiguration().addProperty(name, iterator.next());
100 }
101 }
102 else if (value.getClass().isArray())
103 {
104 int length = Array.getLength(value);
105 for (int i = 0; i < length; i++)
106 {
107 getConfiguration().addProperty(name, Array.get(value, i));
108 }
109 }
110 else
111 {
112 getConfiguration().setProperty(name, value);
113 }
114 }
115
116 public Object get(String name)
117 {
118 if (log.isTraceEnabled())
119 {
120 log.trace("get(" + name + ")");
121 }
122
123 // get configuration property
124 Object result = getConfiguration().getProperty(name);
125 if (result == null)
126 {
127 // otherwise attempt to create bean from configuration subset
128 Configuration subset = new SubsetConfiguration(getConfiguration(), name, PROPERTY_DELIMITER);
129 if (!subset.isEmpty())
130 {
131 result = new ConfigurationDynaBean(subset);
132 }
133 }
134
135 if (log.isDebugEnabled())
136 {
137 log.debug(name + "=[" + result + "]");
138 }
139
140 if (result == null)
141 {
142 throw new IllegalArgumentException("Property '" + name + "' does not exist.");
143 }
144 return result;
145 }
146
147 public boolean contains(String name, String key)
148 {
149 Configuration subset = getConfiguration().subset(name);
150 if (subset == null)
151 {
152 throw new IllegalArgumentException("Mapped property '" + name + "' does not exist.");
153 }
154
155 return subset.containsKey(key);
156 }
157
158 public Object get(String name, int index)
159 {
160 try
161 {
162 List list = getConfiguration().getList(name);
163 if (list.isEmpty())
164 {
165 throw new IllegalArgumentException("Indexed property '" + name + "' does not exist.");
166 }
167
168 return list.get(index);
169 }
170 catch (ConversionException e)
171 {
172 throw new IllegalArgumentException("Property '" + name + "' is not indexed.");
173 }
174 }
175
176 public Object get(String name, String key)
177 {
178 Configuration subset = getConfiguration().subset(name);
179 if (subset == null)
180 {
181 throw new IllegalArgumentException("Mapped property '" + name + "' does not exist.");
182 }
183
184 return subset.getProperty(key);
185 }
186
187 public DynaClass getDynaClass()
188 {
189 return new ConfigurationDynaClass(getConfiguration());
190 }
191
192 public void remove(String name, String key)
193 {
194 Configuration subset = new SubsetConfiguration(getConfiguration(), name, PROPERTY_DELIMITER);
195 subset.setProperty(key, null);
196 }
197
198 public void set(String name, int index, Object value)
199 {
200 try
201 {
202 Object property = getConfiguration().getProperty(name);
203
204 if (property == null)
205 {
206 throw new IllegalArgumentException("Property '" + name + "' does not exist.");
207 }
208 else if (property instanceof List)
209 {
210 List list = (List) property;
211 list.set(index, value);
212 getConfiguration().setProperty(name, list);
213 }
214 else if (property.getClass().isArray())
215 {
216 Array.set(property, index, value);
217 }
218 else if (index == 0)
219 {
220 getConfiguration().setProperty(name, value);
221 }
222 else
223 {
224 throw new IllegalArgumentException("Property '" + name + "' is not indexed.");
225 }
226 }
227 catch (ConversionException e)
228 {
229 throw new IllegalArgumentException("Property '" + name + "' is not indexed.");
230 }
231 }
232
233 public void set(String name, String key, Object value)
234 {
235 getConfiguration().setProperty(name + "." + key, value);
236 }
237 }