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 (&quot;.&quot;) 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    }