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