Coverage report

  %line %branch
org.apache.jcs.config.PropertySetter
83% 
84% 

 1  
 package org.apache.jcs.config;
 2  
 
 3  
 /*
 4  
  * Licensed to the Apache Software Foundation (ASF) under one
 5  
  * or more contributor license agreements.  See the NOTICE file
 6  
  * distributed with this work for additional information
 7  
  * regarding copyright ownership.  The ASF licenses this file
 8  
  * to you under the Apache License, Version 2.0 (the
 9  
  * "License"); you may not use this file except in compliance
 10  
  * with the License.  You may obtain a copy of the License at
 11  
  *
 12  
  *   http://www.apache.org/licenses/LICENSE-2.0
 13  
  *
 14  
  * Unless required by applicable law or agreed to in writing,
 15  
  * software distributed under the License is distributed on an
 16  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 17  
  * KIND, either express or implied.  See the License for the
 18  
  * specific language governing permissions and limitations
 19  
  * under the License.
 20  
  */
 21  
 
 22  
 import java.beans.BeanInfo;
 23  
 import java.beans.IntrospectionException;
 24  
 import java.beans.Introspector;
 25  
 import java.beans.PropertyDescriptor;
 26  
 
 27  
 import java.lang.reflect.Method;
 28  
 
 29  
 import java.util.Enumeration;
 30  
 import java.util.Properties;
 31  
 
 32  
 import org.apache.jcs.config.OptionConverter;
 33  
 import org.apache.jcs.config.PropertySetterException;
 34  
 
 35  
 import org.apache.commons.logging.Log;
 36  
 import org.apache.commons.logging.LogFactory;
 37  
 
 38  
 /**
 39  
  * This class is based on the log4j class org.apache.log4j.config.PropertySetter
 40  
  * that was made by Anders Kristensen
 41  
  *
 42  
  */
 43  
 
 44  
 /**
 45  
  * General purpose Object property setter. Clients repeatedly invokes {@link
 46  
  * #setProperty setProperty(name,value)} in order to invoke setters on the
 47  
  * Object specified in the constructor. This class relies on the JavaBeans
 48  
  * {@link Introspector}to analyze the given Object Class using reflection.
 49  
  * <p>
 50  
  *
 51  
  * Usage:
 52  
  *
 53  
  * <pre>
 54  
  * PropertySetter ps = new PropertySetter( anObject );
 55  
  * ps.set( &quot;name&quot;, &quot;Joe&quot; );
 56  
  * ps.set( &quot;age&quot;, &quot;32&quot; );
 57  
  * ps.set( &quot;isMale&quot;, &quot;true&quot; );
 58  
  * </pre>
 59  
  *
 60  
  * will cause the invocations anObject.setName("Joe"), anObject.setAge(32), and
 61  
  * setMale(true) if such methods exist with those signatures. Otherwise an
 62  
  * {@link IntrospectionException}are thrown.
 63  
  *
 64  
  * @since 1.1
 65  
  */
 66  6
 public class PropertySetter
 67  
 {
 68  591
     private final static Log log = LogFactory.getLog( OptionConverter.class );
 69  
 
 70  
     /** Description of the Field */
 71  
     protected Object obj;
 72  
 
 73  
     /** Description of the Field */
 74  
     protected PropertyDescriptor[] props;
 75  
 
 76  
     /**
 77  
      * Create a new PropertySetter for the specified Object. This is done in
 78  
      * prepartion for invoking {@link #setProperty}one or more times.
 79  
      *
 80  
      * @param obj
 81  
      *            the object for which to set properties
 82  
      */
 83  37
     public PropertySetter( Object obj )
 84  1878
     {
 85  1915
         this.obj = obj;
 86  1915
     }
 87  
 
 88  
     /**
 89  
      * Uses JavaBeans {@link Introspector}to computer setters of object to be
 90  
      * configured.
 91  
      */
 92  
     protected void introspect()
 93  
     {
 94  
         try
 95  
         {
 96  1137
             BeanInfo bi = Introspector.getBeanInfo( obj.getClass() );
 97  1137
             props = bi.getPropertyDescriptors();
 98  
         }
 99  0
         catch ( IntrospectionException ex )
 100  
         {
 101  0
             log.error( "Failed to introspect " + obj + ": " + ex.getMessage() );
 102  0
             props = new PropertyDescriptor[0];
 103  1119
         }
 104  1137
     }
 105  
 
 106  
     /**
 107  
      * Set the properties of an object passed as a parameter in one go. The
 108  
      * <code>properties</code> are parsed relative to a <code>prefix</code>.
 109  
      *
 110  
      * @param obj
 111  
      *            The object to configure.
 112  
      * @param properties
 113  
      *            A java.util.Properties containing keys and values.
 114  
      * @param prefix
 115  
      *            Only keys having the specified prefix will be set.
 116  
      */
 117  
     public static void setProperties( Object obj, Properties properties, String prefix )
 118  
     {
 119  1915
         new PropertySetter( obj ).setProperties( properties, prefix );
 120  1915
     }
 121  
 
 122  
     /**
 123  
      * Set the properites for the object that match the <code>prefix</code>
 124  
      * passed as parameter.
 125  
      *
 126  
      * @param properties
 127  
      *            The new properties value
 128  
      * @param prefix
 129  
      *            The new properties value
 130  
      */
 131  
     public void setProperties( Properties properties, String prefix )
 132  
     {
 133  1915
         int len = prefix.length();
 134  
 
 135  2614
         for ( Enumeration e = properties.keys(); e.hasMoreElements(); )
 136  
         {
 137  64759
             String key = (String) e.nextElement();
 138  
 
 139  
             // handle only properties that start with the desired frefix.
 140  64759
             if ( key.startsWith( prefix ) )
 141  
             {
 142  
 
 143  
                 // ignore key if it contains dots after the prefix
 144  3433
                 if ( key.indexOf( '.', len + 1 ) > 0 )
 145  
                 {
 146  
                     //System.err.println("----------Ignoring---["+key
 147  
                     //	     +"], prefix=["+prefix+"].");
 148  0
                     continue;
 149  
                 }
 150  
 
 151  3433
                 String value = OptionConverter.findAndSubst( key, properties );
 152  3433
                 key = key.substring( len );
 153  
 
 154  3433
                 setProperty( key, value );
 155  
             }
 156  64097
         }
 157  
 
 158  1915
     }
 159  
 
 160  
     /**
 161  
      * Set a property on this PropertySetter's Object. If successful, this
 162  
      * method will invoke a setter method on the underlying Object. The setter
 163  
      * is the one for the specified property name and the value is determined
 164  
      * partly from the setter argument type and partly from the value specified
 165  
      * in the call to this method.
 166  
      * <p>
 167  
      *
 168  
      * If the setter expects a String no conversion is necessary. If it expects
 169  
      * an int, then an attempt is made to convert 'value' to an int using new
 170  
      * Integer(value). If the setter expects a boolean, the conversion is by new
 171  
      * Boolean(value).
 172  
      *
 173  
      * @param name
 174  
      *            name of the property
 175  
      * @param value
 176  
      *            String value of the property
 177  
      */
 178  
 
 179  
     public void setProperty( String name, String value )
 180  
     {
 181  3433
         if ( value == null )
 182  
         {
 183  0
             return;
 184  
         }
 185  
 
 186  3433
         name = Introspector.decapitalize( name );
 187  3433
         PropertyDescriptor prop = getPropertyDescriptor( name );
 188  
 
 189  
         //log.debug("---------Key: "+name+", type="+prop.getPropertyType());
 190  
 
 191  3433
         if ( prop == null )
 192  
         {
 193  0
             log.warn( "No such property [" + name + "] in " + obj.getClass().getName() + "." );
 194  0
         }
 195  
         else
 196  
         {
 197  
             try
 198  
             {
 199  3433
                 setProperty( prop, name, value );
 200  
             }
 201  16
             catch ( PropertySetterException ex )
 202  
             {
 203  16
                 log.warn( "Failed to set property " + name + " to value \"" + value + "\". " + ex.getMessage() );
 204  3360
             }
 205  
         }
 206  3433
     }
 207  
 
 208  
     /**
 209  
      * Set the named property given a {@link PropertyDescriptor}.
 210  
      *
 211  
      * @param prop
 212  
      *            A PropertyDescriptor describing the characteristics of the
 213  
      *            property to set.
 214  
      * @param name
 215  
      *            The named of the property to set.
 216  
      * @param value
 217  
      *            The value of the property.
 218  
      * @throws PropertySetterException
 219  
      */
 220  
 
 221  
     public void setProperty( PropertyDescriptor prop, String name, String value )
 222  
         throws PropertySetterException
 223  
     {
 224  3433
         Method setter = prop.getWriteMethod();
 225  3433
         if ( setter == null )
 226  
         {
 227  0
             throw new PropertySetterException( "No setter for property" );
 228  
         }
 229  3433
         Class[] paramTypes = setter.getParameterTypes();
 230  3433
         if ( paramTypes.length != 1 )
 231  
         {
 232  0
             throw new PropertySetterException( "#params for setter != 1" );
 233  
         }
 234  
 
 235  
         Object arg;
 236  
         try
 237  
         {
 238  3433
             arg = convertArg( value, paramTypes[0] );
 239  
         }
 240  16
         catch ( Throwable t )
 241  
         {
 242  16
             throw new PropertySetterException( "Conversion to type [" + paramTypes[0] + "] failed. Reason: " + t );
 243  3360
         }
 244  3417
         if ( arg == null )
 245  
         {
 246  0
             throw new PropertySetterException( "Conversion to type [" + paramTypes[0] + "] failed." );
 247  
         }
 248  3417
         log.debug( "Setting property [" + name + "] to [" + arg + "]." );
 249  
         try
 250  
         {
 251  3417
             setter.invoke( obj, new Object[] { arg } );
 252  
         }
 253  0
         catch ( Exception ex )
 254  
         {
 255  0
             throw new PropertySetterException( ex );
 256  3360
         }
 257  3417
     }
 258  
 
 259  
     /**
 260  
      * Convert <code>val</code> a String parameter to an object of a given
 261  
      * type.
 262  
      * @param val
 263  
      * @param type
 264  
      * @return Object
 265  
      */
 266  
     protected Object convertArg( String val, Class type )
 267  
     {
 268  3433
         if ( val == null )
 269  
         {
 270  0
             return null;
 271  
         }
 272  
 
 273  3433
         String v = val.trim();
 274  3433
         if ( String.class.isAssignableFrom( type ) )
 275  
         {
 276  1544
             return val;
 277  
         }
 278  1889
         else if ( Integer.TYPE.isAssignableFrom( type ) )
 279  
         {
 280  1193
             return new Integer( v );
 281  
         }
 282  696
         else if ( Long.TYPE.isAssignableFrom( type ) )
 283  
         {
 284  229
             return new Long( v );
 285  
         }
 286  467
         else if ( Boolean.TYPE.isAssignableFrom( type ) )
 287  
         {
 288  467
             if ( "true".equalsIgnoreCase( v ) )
 289  
             {
 290  311
                 return Boolean.TRUE;
 291  
             }
 292  156
             else if ( "false".equalsIgnoreCase( v ) )
 293  
             {
 294  156
                 return Boolean.FALSE;
 295  
             }
 296  
         }
 297  0
         return null;
 298  
     }
 299  
 
 300  
     /**
 301  
      * Gets the propertyDescriptor attribute of the PropertySetter object
 302  
      * @param name
 303  
      *
 304  
      * @return The propertyDescriptor value
 305  
      */
 306  
     protected PropertyDescriptor getPropertyDescriptor( String name )
 307  
     {
 308  3433
         if ( props == null )
 309  
         {
 310  1137
             introspect();
 311  
         }
 312  
 
 313  27509
         for ( int i = 0; i < props.length; i++ )
 314  
         {
 315  27509
             if ( name.equals( props[i].getName() ) )
 316  
             {
 317  3433
                 return props[i];
 318  
             }
 319  
         }
 320  0
         return null;
 321  
     }
 322  
 
 323  
 }

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.