Java tutorial
/* * Copyright 2004-2005 Germinus XXI * * Licensed under the Apache License, Version 2.0 (the "License") * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.germinus.easyconf; import java.math.BigDecimal; import java.math.BigInteger; import java.util.*; import org.apache.commons.beanutils.DynaBean; import org.apache.commons.configuration.beanutils.ConfigurationDynaBean; import org.apache.commons.configuration.CompositeConfiguration; import org.apache.commons.configuration.Configuration; import org.apache.commons.configuration.ConfigurationConverter; import org.apache.commons.configuration.DataConfiguration; import org.apache.commons.configuration.MapConfiguration; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * Part of a component configuration which contains its properties. * * The properties can be accessed by type and automatic conversion will be * performed. The supported types are: BigDecimal, BigInteger, Boolean, Byte, * Double, Float, Integer, List, Long, Short, String and StringArray * * It is based on the <code>Configuration</code> interface from Jakarta * Commons Configuration but it is given a different name which makes more sense * inside EasyConf. * * The boolean flag throwExceptionOnMissing controls the behaviour of this class * when a property that does not exist is queried. If set to true (the default) * a <tt>NoSuchElementException</tt> will be thrown if the given key does not * exist and no default was provided. If set to false, <tt>null</tt> will be * returned except for the method getList() which will return an empty * unmodifyiable list. * * @author Jorge Ferrer * @version $Revision: 1.23 $ * */ public class ComponentProperties { public static final String NULL_STRING = null; private static final List EMPTY_LIST = Collections.unmodifiableList(new ArrayList()); private static final Log log = LogFactory.getLog(ComponentProperties.class); AggregatedProperties properties; ComponentProperties(AggregatedProperties conf) { this.properties = conf; setThrowExceptionOnMissing(false); } // .................. Conversion methods ................... /** * Returns a decorator of the configuration that implements the Map * interface. Note that any changes made to this decorator will be made to * the original configuration and viceversa. * * @return a <code>java.util.Map</code> instance */ public Map toMap() { return ConfigurationConverter.getMap(properties); } /** * Returns a decorator of the configuration that can be used as a DynaBean. * Note that any changes made to this decorator will be made to the original * configuration and viceversa. * * @return a <code>DynaBean</code> instance */ public DynaBean toDynaBean() { return new ConfigurationDynaBean(properties); } /** * Returns a decorator of the configuration of type * <tt>org.apache.commons.configuration.Configuration</tt> Note that any * changes made to this decorator will be made to the original configuration * and viceversa. * * @return a <code>Configuration</code> instance */ public Configuration toConfiguration() { return properties; } /** * Returns a decorator of the configuration of type * <tt>org.apache.commons.configuration.DataConfiguration</tt>. This * decorator has many extra methods for retrieving typed properties such as * color, URL, locale, Calendar and lists and array of any of these types. * * Note that any changes made to this decorator will be made to the original * configuration and viceversa. * * @return a <code>DataConfiguration</code> instance */ public DataConfiguration toDataConfiguration() { return new DataConfiguration(properties); } /** * Returns a <b>copy </b> of the configuration into a * <tt>java.util.Properties</tt> class. Multivalued properties will be * converted to comma-separated strings. Any changes made to the * configuration will <b>not </b>be available to the Properties and * viceversa. * * @return a <code>Properties</code> instance */ public java.util.Properties getProperties() { return ConfigurationConverter.getProperties(properties); } public Object getProperty(String key) { return properties.getProperty(key); } // ..................... Delegated methods ............... public boolean containsKey(String key) { return properties.containsKey(key); } public boolean equals(Object obj) { return properties.equals(obj); } public Iterator getKeys() { return properties.getKeys(); } public Iterator getKeys(String prefix) { return properties.getKeys(prefix); } public int hashCode() { return properties.hashCode(); } public boolean isEmpty() { return properties.isEmpty(); } public void setProperty(String key, Object value) { properties.setProperty(key, value); } public Configuration subset(String prefix) { return properties.subset(prefix); } public String toString() { return properties.toString(); } // ..................... BigDecimal ...................... public BigDecimal getBigDecimal(String key) { return properties.getBigDecimal(key); } public BigDecimal getBigDecimal(String key, BigDecimal defaultValue) { return properties.getBigDecimal(key, defaultValue); } public BigDecimal getBigDecimal(String key, Filter filter) { BigDecimal value = getBigDecimal(key, filter, null); validateValue(key, value); return value; } public BigDecimal getBigDecimal(String key, Filter filter, BigDecimal defaultValue) { return (BigDecimal) getPropertyWithFilter(key, filter, BigDecimal.class, defaultValue); } // ..................... BigInteger ...................... public BigInteger getBigInteger(String key) { return properties.getBigInteger(key); } public BigInteger getBigInteger(String key, BigInteger defaultValue) { return properties.getBigInteger(key, defaultValue); } public BigInteger getBigInteger(String key, Filter filter) { BigInteger value = getBigInteger(key, filter, null); validateValue(key, value); return value; } public BigInteger getBigInteger(String key, Filter filter, BigInteger defaultValue) { return (BigInteger) getPropertyWithFilter(key, filter, BigInteger.class, defaultValue); } // ..................... Boolean ...................... public boolean getBoolean(String key) { return properties.getBoolean(key); } public boolean getBoolean(String key, boolean defaultValue) { return properties.getBoolean(key, defaultValue); } public Boolean getBoolean(String key, Boolean defaultValue) throws NoClassDefFoundError { return properties.getBoolean(key, defaultValue); } public boolean getBoolean(String key, Filter filter) { Boolean value = getBoolean(key, filter, null); validateValue(key, value); return value.booleanValue(); } public Boolean getBoolean(String key, Filter filter, Boolean defaultValue) throws NoClassDefFoundError { return (Boolean) getPropertyWithFilter(key, filter, Boolean.class, defaultValue); } public boolean getBoolean(String key, Filter filter, boolean defaultValue) { return getBoolean(key, filter, new Boolean(defaultValue)).booleanValue(); } // ..................... Byte ...................... public byte getByte(String key) { return properties.getByte(key); } public byte getByte(String key, byte defaultValue) { return properties.getByte(key, defaultValue); } public Byte getByte(String key, Byte defaultValue) { return properties.getByte(key, defaultValue); } public byte getByte(String key, Filter filter) { Byte value = getByte(key, filter, null); validateValue(key, value); return value.byteValue(); } public Byte getByte(String key, Filter filter, Byte defaultValue) { return (Byte) getPropertyWithFilter(key, filter, Byte.class, defaultValue); } public byte getByte(String key, Filter filter, byte defaultValue) { return getByte(key, filter, new Byte(defaultValue)).byteValue(); } // ..................... Double ...................... public double getDouble(String key) { return properties.getDouble(key); } public double getDouble(String key, double defaultValue) { return properties.getDouble(key, defaultValue); } public Double getDouble(String key, Double defaultValue) { return properties.getDouble(key, defaultValue); } public double getDouble(String key, Filter filter) { Double value = getDouble(key, filter, null); validateValue(key, value); return value.doubleValue(); } public Double getDouble(String key, Filter filter, Double defaultValue) { return (Double) getPropertyWithFilter(key, filter, Double.class, defaultValue); } public double getDouble(String key, Filter filter, double defaultValue) { return getDouble(key, filter, new Double(defaultValue)).doubleValue(); } // ..................... Class ...................... /** * Get the <code>Class</code> representation of the class name specified * in the given property * * @throws ClassNotFoundException * if the specified class is not found */ public Class getClass(String key) throws ClassNotFoundException { String className = getString(key); return ClasspathUtil.locateClass(className); } /** * Get the <code>Class</code> representation of the class name specified * in the given property. Or the <code>defaultValue</code> if no value has * been given to the property. * * @throws ClassNotFoundException * if a class has been configured but it is not found */ public Class getClass(String key, Class defaultValue) throws ClassNotFoundException { String defaultStringValue = null; String className = getString(key, defaultStringValue); if (className == defaultStringValue) { return defaultValue; } return ClasspathUtil.locateClass(className); } /** * Similar to the previous methods but complementing the property key with * the given filter */ public Class getClass(String key, Filter filter) throws ClassNotFoundException { String className = getString(key, filter); return ClasspathUtil.locateClass(className); } /** * Equivalent to the previous method but giving a default value which will * be used if no value has been specified in the configurations file */ public Class getClass(String key, Filter filter, Class defaultValue) throws ClassNotFoundException { String defaultStringValue = null; String className = getString(key, filter, null); if (className == defaultStringValue) { return defaultValue; } return ClasspathUtil.locateClass(className); } // ..................... Class ...................... /** * Get an array of <code>Class</code> objects for the class names * specified in the given property * * @throws ClassNotFoundException * if the any of the configured classes is not found */ public Class[] getClassArray(String key) throws ClassNotFoundException { String[] classNames = getStringArray(key); return ClasspathUtil.locateClasses(classNames); } /** * Get an array of <code>Class</code> objects for the class names * specified in the given property. Or the <code>defaultValue</code> if no * value has been given to the property. * * @throws ClassNotFoundException * if the any of the configured classes is not found */ public Class[] getClassArray(String key, Class[] defaultValue) throws ClassNotFoundException { String[] defaultStringArrayValue = null; String[] classNames = getStringArray(key, defaultStringArrayValue); if (classNames == defaultStringArrayValue) { return defaultValue; } return ClasspathUtil.locateClasses(classNames); } /** * Similar to the previous methods but complementing the property key with * the given filter */ public Class[] getClassArray(String key, Filter filter) throws ClassNotFoundException { String[] classNames = getStringArray(key, filter); return ClasspathUtil.locateClasses(classNames); } /** * Equivalent to the previous method but giving a default value which will * be used if no value has been specified in the configurations file */ public Class[] getClassArray(String key, Filter filter, Class[] defaultValue) throws ClassNotFoundException { String[] defaultStringArrayValue = null; String[] classNames = getStringArray(key, filter, defaultStringArrayValue); if (classNames == defaultStringArrayValue) { return defaultValue; } return ClasspathUtil.locateClasses(classNames); } // ..................... Float ...................... public float getFloat(String key) { return properties.getFloat(key); } public float getFloat(String key, float defaultValue) { return properties.getFloat(key, defaultValue); } public Float getFloat(String key, Float defaultValue) { return properties.getFloat(key, defaultValue); } public float getFloat(String key, Filter filter) { Float value = getFloat(key, filter, null); validateValue(key, value); return value.floatValue(); } public Float getFloat(String key, Filter filter, Float defaultValue) { return (Float) getPropertyWithFilter(key, filter, Float.class, defaultValue); } public float getFloat(String key, Filter filter, float defaultValue) { return getFloat(key, filter, new Float(defaultValue)).floatValue(); } // ..................... Integer ...................... public int getInt(String key) { return properties.getInt(key); } public int getInt(String key, int defaultValue) { return properties.getInt(key, defaultValue); } public Integer getInteger(String key, Integer defaultValue) { return properties.getInteger(key, defaultValue); } public int getInt(String key, Filter filter) { Integer value = getInteger(key, filter, null); validateValue(key, value); return value.intValue(); } public Integer getInteger(String key, Filter filter, Integer defaultValue) { return (Integer) getPropertyWithFilter(key, filter, Integer.class, defaultValue); } public int getInt(String key, Filter filter, int defaultValue) { return getInteger(key, filter, new Integer(defaultValue)).intValue(); } // ..................... List ...................... public List getList(String key) { return properties.getList(key); } public List getList(String key, List defaultValue) { return properties.getList(key, defaultValue); } public List getList(String key, Filter filter) { List value = (List) getPropertyWithFilter(key, filter, List.class, null); validateValue(key, value); if (value == null) { value = EMPTY_LIST; } return value; } public List getList(String key, Filter filter, List defaultValue) { return (List) getPropertyWithFilter(key, filter, List.class, defaultValue); } // ..................... Long ...................... public long getLong(String key) { return properties.getLong(key); } public Long getLong(String key, Long defaultValue) { return properties.getLong(key, defaultValue); } public long getLong(String key, long defaultValue) { return properties.getLong(key, defaultValue); } public long getLong(String key, Filter filter) { Long value = getLong(key, filter, null); validateValue(key, value); return value.longValue(); } public Long getLong(String key, Filter filter, Long defaultValue) { return (Long) getPropertyWithFilter(key, filter, Long.class, defaultValue); } public long getLong(String key, Filter filter, long defaultValue) { return getLong(key, filter, new Long(defaultValue)).longValue(); } // ..................... Short ...................... public short getShort(String key) { return properties.getShort(key); } public Short getShort(String key, Short defaultValue) { return properties.getShort(key, defaultValue); } public short getShort(String key, short defaultValue) { return properties.getShort(key, defaultValue); } public short getShort(String key, Filter filter) { Short value = getShort(key, filter, null); validateValue(key, value); return value.shortValue(); } public Short getShort(String key, Filter filter, Short defaultValue) { return (Short) getPropertyWithFilter(key, filter, Short.class, defaultValue); } public short getShort(String key, Filter filter, short defaultValue) { return getShort(key, filter, new Short(defaultValue)).shortValue(); } // ..................... String ...................... /** * Get the String value of the given key. If it contains a list of values, * they will be serialized to a comma-separated format (use getList or * getStringArray if you want separated list items) */ public String getString(String key) { Object value = properties.getProperty(key); String result; if (value instanceof List) { result = listToString((List) value); } else { result = properties.getString(key); } return result; // return properties.getString(key); } public String getString(String key, String defaultValue) { return properties.getString(key, defaultValue); } public String getString(String key, Filter filter) { String value = getString(key, filter, null); validateValue(key, value); return value; } public String getString(String key, Filter filter, String defaultValue) { return (String) getPropertyWithFilter(key, filter, String.class, defaultValue); } // ..................... StringArray ...................... public String[] getStringArray(String key) { return properties.getStringArray(key); } public String[] getStringArray(String key, Filter filter) { List value = getList(key, filter); return (String[]) value.toArray(new String[0]); } public String[] getStringArray(String key, Filter filter, String[] defaultValue) { List defaultList = null; if (defaultValue != null) { defaultList = Arrays.asList(defaultValue); } List value = getList(key, filter, defaultList); if (value == null) { //This should never happen return null; } else { return (String[]) value.toArray(new String[0]); } } public String[] getStringArray(String key, String[] defaultValue) { List defaultList = null; if (defaultValue != null) { defaultList = Arrays.asList(defaultValue); } List value = getList(key, defaultList); if (value == null) { return null; } else { return (String[]) value.toArray(new String[0]); } } // ................. Control methods ..................... public boolean hasBaseConfiguration() { return properties.hasBaseConfiguration(); } /** * Get a list of the sources which have been loaded for this component */ public List getLoadedSources() { return properties.loadedSources(); } /** * Set the flag throwExceptionOnMissing. See the class documentation for * more details. */ public void setThrowExceptionOnMissing(boolean throwExceptionOnMissing) { properties.setThrowExceptionOnMissing(throwExceptionOnMissing); } public boolean isThrowExceptionOnMissing() { return properties.isThrowExceptionOnMissing(); } /** * Returned the configured delay period for this component or null if * reloading is not being performed */ public Long getDelayPeriod() { Long nullLong = null; return getLong(Conventions.RELOAD_DELAY_PROPERTY, nullLong); } public String getComponentName() { return properties.getComponentName(); } // ............. Helper methods ...................... protected Object getPropertyWithFilter(String key, Filter filter, Class theClass, Object defaultValue) { CompositeConfiguration filteredConf = properties; Object value = null; for (int i = filter.numOfSelectors(); (i >= 0) && (value == null); i--) { MapConfiguration varsConf = null; if (filter.hasVariables()) { varsConf = new MapConfiguration(filter.getVariables()); filteredConf = new CompositeConfiguration(); filteredConf.addConfiguration(varsConf); filteredConf.addConfiguration(properties); } value = getTypedPropertyWithDefault(key + filter.getFilterSuffix(i), theClass, filteredConf, null); if (varsConf != null) { properties.removeConfiguration(varsConf); } log.debug("Value for " + key + filter.getFilterSuffix(i) + "=" + value); } if (value == null) { value = defaultValue; } return value; } protected static Object getTypedPropertyWithDefault(String key, Class theClass, Configuration properties, Object defaultValue) { if (theClass.equals(Float.class)) { return properties.getFloat(key, (Float) defaultValue); } else if (theClass.equals(Integer.class)) { return properties.getInteger(key, (Integer) defaultValue); } else if (theClass.equals(String.class)) { return properties.getString(key, (String) defaultValue); } else if (theClass.equals(Double.class)) { return properties.getDouble(key, (Double) defaultValue); } else if (theClass.equals(Long.class)) { return properties.getLong(key, (Long) defaultValue); } else if (theClass.equals(Boolean.class)) { return properties.getBoolean(key, (Boolean) defaultValue); } else if (theClass.equals(List.class)) { return properties.getList(key, (List) defaultValue); } else if (theClass.equals(BigInteger.class)) { return properties.getBigInteger(key, (BigInteger) defaultValue); } else if (theClass.equals(BigDecimal.class)) { return properties.getBigDecimal(key, (BigDecimal) defaultValue); } else if (theClass.equals(Byte.class)) { return properties.getByte(key, (Byte) defaultValue); } else if (theClass.equals(Short.class)) { return properties.getShort(key, (Short) defaultValue); } throw new IllegalArgumentException("Class " + theClass + " is not" + "supported for properties"); } protected void validateValue(String key, Object value) { if ((value == null) && isThrowExceptionOnMissing()) { throw new NoSuchElementException("Property with key=" + key + " was not found"); } } protected String listToString(List list) { StringBuffer property = new StringBuffer(); Iterator it = list.iterator(); while (it.hasNext()) { property.append(String.valueOf(it.next())); if (it.hasNext()) { property.append(","); } } return property.toString(); } }