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