| package org.apache.jcs.config; |
| |
| |
| /* |
| * Copyright 2001-2004 The Apache Software Foundation. |
| * |
| * 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. |
| */ |
| |
| |
| import java.beans.BeanInfo; |
| import java.beans.IntrospectionException; |
| import java.beans.Introspector; |
| import java.beans.PropertyDescriptor; |
| |
| import java.lang.reflect.Method; |
| |
| import java.util.Enumeration; |
| import java.util.Properties; |
| |
| import org.apache.jcs.config.OptionConverter; |
| import org.apache.jcs.config.PropertySetterException; |
| |
| import org.apache.commons.logging.Log; |
| import org.apache.commons.logging.LogFactory; |
| |
| /** |
| * This class is based on the log4j class org.apache.log4j.config.PropertySetter |
| * that was made by Anders Kristensen |
| * |
| */ |
| |
| /** |
| * General purpose Object property setter. Clients repeatedly invokes {@link |
| * #setProperty setProperty(name,value)} in order to invoke setters on the |
| * Object specified in the constructor. This class relies on the JavaBeans |
| * {@link Introspector} to analyze the given Object Class using reflection. <p> |
| * |
| * Usage: <pre> |
| *PropertySetter ps = new PropertySetter(anObject); |
| *ps.set("name", "Joe"); |
| *ps.set("age", "32"); |
| *ps.set("isMale", "true"); |
| *</pre> will cause the invocations anObject.setName("Joe"), |
| * anObject.setAge(32), and setMale(true) if such methods exist with those |
| * signatures. Otherwise an {@link IntrospectionException} are thrown. |
| * |
| * @since 1.1 |
| */ |
| public class PropertySetter |
| { |
| private final static Log log = |
| LogFactory.getLog( OptionConverter.class ); |
| |
| /** Description of the Field */ |
| protected Object obj; |
| /** Description of the Field */ |
| protected PropertyDescriptor[] props; |
| |
| /** |
| * Create a new PropertySetter for the specified Object. This is done in |
| * prepartion for invoking {@link #setProperty} one or more times. |
| * |
| * @param obj the object for which to set properties |
| */ |
| public PropertySetter( Object obj ) |
| { |
| this.obj = obj; |
| } |
| |
| |
| /** |
| * Uses JavaBeans {@link Introspector} to computer setters of object to be |
| * configured. |
| */ |
| protected void introspect() |
| { |
| try |
| { |
| BeanInfo bi = Introspector.getBeanInfo( obj.getClass() ); |
| props = bi.getPropertyDescriptors(); |
| } |
| catch ( IntrospectionException ex ) |
| { |
| log.error( "Failed to introspect " + obj + ": " + ex.getMessage() ); |
| props = new PropertyDescriptor[0]; |
| } |
| } |
| |
| |
| /** |
| * Set the properties of an object passed as a parameter in one go. The |
| * <code>properties</code> are parsed relative to a <code>prefix</code>. |
| * |
| * @param obj The object to configure. |
| * @param properties A java.util.Properties containing keys and values. |
| * @param prefix Only keys having the specified prefix will be set. |
| */ |
| public static void setProperties( Object obj, Properties properties, String prefix ) |
| { |
| new PropertySetter( obj ).setProperties( properties, prefix ); |
| } |
| |
| |
| /** |
| * Set the properites for the object that match the <code>prefix</code> |
| * passed as parameter. |
| * |
| * @param properties The new properties value |
| * @param prefix The new properties value |
| */ |
| public void setProperties( Properties properties, String prefix ) |
| { |
| int len = prefix.length(); |
| |
| for ( Enumeration e = properties.keys(); e.hasMoreElements(); ) |
| { |
| String key = ( String ) e.nextElement(); |
| |
| // handle only properties that start with the desired frefix. |
| if ( key.startsWith( prefix ) ) |
| { |
| |
| // ignore key if it contains dots after the prefix |
| if ( key.indexOf( '.', len + 1 ) > 0 ) |
| { |
| //System.err.println("----------Ignoring---["+key |
| // +"], prefix=["+prefix+"]."); |
| continue; |
| } |
| |
| String value = OptionConverter.findAndSubst( key, properties ); |
| key = key.substring( len ); |
| |
| setProperty( key, value ); |
| } |
| } |
| |
| } |
| |
| |
| /** |
| * Set a property on this PropertySetter's Object. If successful, this |
| * method will invoke a setter method on the underlying Object. The setter |
| * is the one for the specified property name and the value is determined |
| * partly from the setter argument type and partly from the value specified |
| * in the call to this method. <p> |
| * |
| * If the setter expects a String no conversion is necessary. If it expects |
| * an int, then an attempt is made to convert 'value' to an int using new |
| * Integer(value). If the setter expects a boolean, the conversion is by new |
| * Boolean(value). |
| * |
| * @param name name of the property |
| * @param value String value of the property |
| */ |
| |
| public void setProperty( String name, String value ) |
| { |
| if ( value == null ) |
| { |
| return; |
| } |
| |
| name = Introspector.decapitalize( name ); |
| PropertyDescriptor prop = getPropertyDescriptor( name ); |
| |
| //log.debug("---------Key: "+name+", type="+prop.getPropertyType()); |
| |
| if ( prop == null ) |
| { |
| log.warn( "No such property [" + name + "] in " + |
| obj.getClass().getName() + "." ); |
| } |
| else |
| { |
| try |
| { |
| setProperty( prop, name, value ); |
| } |
| catch ( PropertySetterException ex ) |
| { |
| log.warn( "Failed to set property " + name + |
| " to value \"" + value + "\". " + ex.getMessage() ); |
| } |
| } |
| } |
| |
| |
| /** |
| * Set the named property given a {@link PropertyDescriptor}. |
| * |
| * @param prop A PropertyDescriptor describing the characteristics of the |
| * property to set. |
| * @param name The named of the property to set. |
| * @param value The value of the property. |
| */ |
| |
| public void setProperty( PropertyDescriptor prop, String name, String value ) |
| throws PropertySetterException |
| { |
| Method setter = prop.getWriteMethod(); |
| if ( setter == null ) |
| { |
| throw new PropertySetterException( "No setter for property" ); |
| } |
| Class[] paramTypes = setter.getParameterTypes(); |
| if ( paramTypes.length != 1 ) |
| { |
| throw new PropertySetterException( "#params for setter != 1" ); |
| } |
| |
| Object arg; |
| try |
| { |
| arg = convertArg( value, paramTypes[0] ); |
| } |
| catch ( Throwable t ) |
| { |
| throw new PropertySetterException( "Conversion to type [" + paramTypes[0] + |
| "] failed. Reason: " + t ); |
| } |
| if ( arg == null ) |
| { |
| throw new PropertySetterException( |
| "Conversion to type [" + paramTypes[0] + "] failed." ); |
| } |
| log.debug( "Setting property [" + name + "] to [" + arg + "]." ); |
| try |
| { |
| setter.invoke( obj, new Object[]{arg} ); |
| } |
| catch ( Exception ex ) |
| { |
| throw new PropertySetterException( ex ); |
| } |
| } |
| |
| |
| /** |
| * Convert <code>val</code> a String parameter to an object of a given type. |
| */ |
| protected Object convertArg( String val, Class type ) |
| { |
| if ( val == null ) |
| { |
| return null; |
| } |
| |
| String v = val.trim(); |
| if ( String.class.isAssignableFrom( type ) ) |
| { |
| return val; |
| } |
| else if ( Integer.TYPE.isAssignableFrom( type ) ) |
| { |
| return new Integer( v ); |
| } |
| else if ( Long.TYPE.isAssignableFrom( type ) ) |
| { |
| return new Long( v ); |
| } |
| else if ( Boolean.TYPE.isAssignableFrom( type ) ) |
| { |
| if ( "true".equalsIgnoreCase( v ) ) |
| { |
| return Boolean.TRUE; |
| } |
| else if ( "false".equalsIgnoreCase( v ) ) |
| { |
| return Boolean.FALSE; |
| } |
| } |
| return null; |
| } |
| |
| |
| /** |
| * Gets the propertyDescriptor attribute of the PropertySetter object |
| * |
| * @return The propertyDescriptor value |
| */ |
| protected PropertyDescriptor getPropertyDescriptor( String name ) |
| { |
| if ( props == null ) |
| { |
| introspect(); |
| } |
| |
| for ( int i = 0; i < props.length; i++ ) |
| { |
| if ( name.equals( props[i].getName() ) ) |
| { |
| return props[i]; |
| } |
| } |
| return null; |
| } |
| |
| } |