Coverage Report - org.codehaus.plexus.component.configurator.converters.ComponentValueSetter
 
Classes in this File Line Coverage Branch Coverage Complexity
ComponentValueSetter
64 %
53/82
54 %
24/44
7,571
 
 1  
 package org.codehaus.plexus.component.configurator.converters;
 2  
 
 3  
 /*
 4  
  * Copyright 2005-2007 Codehaus Foundation.
 5  
  *
 6  
  * Licensed under the Apache License, Version 2.0 (the "License");
 7  
  * you may not use this file except in compliance with the License.
 8  
  * You may obtain a copy of the License at
 9  
  *
 10  
  *      http://www.apache.org/licenses/LICENSE-2.0
 11  
  *
 12  
  * Unless required by applicable law or agreed to in writing, software
 13  
  * distributed under the License is distributed on an "AS IS" BASIS,
 14  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 15  
  * See the License for the specific language governing permissions and
 16  
  * limitations under the License.
 17  
  */
 18  
 
 19  
 import org.codehaus.plexus.component.configurator.ComponentConfigurationException;
 20  
 import org.codehaus.plexus.component.configurator.ConfigurationListener;
 21  
 import org.codehaus.plexus.component.configurator.converters.lookup.ConverterLookup;
 22  
 import org.codehaus.plexus.component.configurator.converters.lookup.DefaultConverterLookup;
 23  
 import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
 24  
 import org.codehaus.plexus.configuration.PlexusConfiguration;
 25  
 import org.codehaus.plexus.util.ReflectionUtils;
 26  
 
 27  
 import java.lang.reflect.Field;
 28  
 import java.lang.reflect.InvocationTargetException;
 29  
 import java.lang.reflect.Method;
 30  
 
 31  
 
 32  
 /** @author <a href="mailto:kenney@codehaus.org">Kenney Westerhof</a> */
 33  
 public class ComponentValueSetter
 34  
 {
 35  
     private Object object;
 36  
 
 37  
     private String fieldName;
 38  
 
 39  
     private ConverterLookup lookup;
 40  
 
 41  
     private Method setter;
 42  
 
 43  
     private Class setterParamType;
 44  
 
 45  
     private ConfigurationConverter setterTypeConverter;
 46  
 
 47  
     private Field field;
 48  
 
 49  
     private Class fieldType;
 50  
 
 51  
     private ConfigurationConverter fieldTypeConverter;
 52  
 
 53  
     private ConfigurationListener listener;
 54  
 
 55  
     public ComponentValueSetter( String fieldName,
 56  
                                  Object object,
 57  
                                  ConverterLookup lookup )
 58  
         throws ComponentConfigurationException
 59  
     {
 60  0
         this( fieldName, object, lookup, null );
 61  0
     }
 62  
 
 63  
     public ComponentValueSetter( String fieldName,
 64  
                                  Object object,
 65  
                                  ConverterLookup lookup,
 66  
                                  ConfigurationListener listener )
 67  
         throws ComponentConfigurationException
 68  71
     {
 69  71
         this.fieldName = fieldName;
 70  71
         this.object = object;
 71  71
         this.lookup = lookup;
 72  71
         this.listener = listener;
 73  
 
 74  71
         if ( object == null )
 75  
         {
 76  0
             throw new ComponentConfigurationException( "Component is null" );
 77  
         }
 78  
 
 79  71
         initSetter();
 80  
 
 81  71
         initField();
 82  
 
 83  71
         if ( setter == null && field == null )
 84  
         {
 85  0
             throw new ComponentConfigurationException(
 86  
                 "Cannot find setter nor field in " + object.getClass().getName() + " for '" + fieldName + "'" );
 87  
         }
 88  
 
 89  71
         if ( setterTypeConverter == null && fieldTypeConverter == null )
 90  
         {
 91  0
             throw new ComponentConfigurationException(
 92  
                 "Cannot find converter for " + setterParamType.getName() + ( fieldType != null && !fieldType.equals(
 93  
                     setterParamType ) ? " or " + fieldType.getName() : "" ) );
 94  
         }
 95  71
     }
 96  
 
 97  
     private void initSetter()
 98  
     {
 99  71
         setter = ReflectionUtils.getSetter( fieldName, object.getClass() );
 100  
 
 101  71
         if ( setter == null )
 102  
         {
 103  64
             return;
 104  
         }
 105  
 
 106  7
         setterParamType = setter.getParameterTypes()[0];
 107  
 
 108  
         try
 109  
         {
 110  7
             setterTypeConverter = lookup.lookupConverterForType( setterParamType );
 111  
         }
 112  0
         catch ( ComponentConfigurationException e )
 113  
         {
 114  
             // ignore, handle later
 115  7
         }
 116  7
     }
 117  
 
 118  
     private void initField()
 119  
     {
 120  71
         field = ReflectionUtils.getFieldByNameIncludingSuperclasses( fieldName, object.getClass() );
 121  
 
 122  71
         if ( field == null )
 123  
         {
 124  7
             return;
 125  
         }
 126  
 
 127  64
         fieldType = field.getType();
 128  
 
 129  
         try
 130  
         {
 131  64
             fieldTypeConverter = lookup.lookupConverterForType( fieldType );
 132  
         }
 133  0
         catch ( ComponentConfigurationException e )
 134  
         {
 135  
             // ignore, handle later
 136  64
         }
 137  64
     }
 138  
 
 139  
     private void setValueUsingField( Object value )
 140  
         throws ComponentConfigurationException
 141  
     {
 142  
         try
 143  
         {
 144  61
             boolean wasAccessible = field.isAccessible();
 145  
 
 146  61
             if ( !wasAccessible )
 147  
             {
 148  61
                 field.setAccessible( true );
 149  
             }
 150  
 
 151  61
             if ( listener != null )
 152  
             {
 153  0
                 listener.notifyFieldChangeUsingReflection( fieldName, value, object );
 154  
             }
 155  
 
 156  61
             field.set( object, value );
 157  
 
 158  61
             if ( !wasAccessible )
 159  
             {
 160  61
                 field.setAccessible( false );
 161  
             }
 162  
         }
 163  0
         catch ( IllegalAccessException e )
 164  
         {
 165  0
             throw new ComponentConfigurationException( "Cannot access field: " + field, e );
 166  
         }
 167  0
         catch ( IllegalArgumentException e )
 168  
         {
 169  0
             throw new ComponentConfigurationException( "Cannot assign value '" + value + "' (type: "
 170  
                 + value.getClass() + ") to " + field, e );
 171  61
         }
 172  61
     }
 173  
 
 174  
     private void setValueUsingSetter( Object value )
 175  
         throws ComponentConfigurationException
 176  
     {
 177  7
         if ( setterParamType == null || setter == null )
 178  
         {
 179  0
             throw new ComponentConfigurationException( "No setter found" );
 180  
         }
 181  
 
 182  7
         String exceptionInfo = object.getClass().getName() + "." + setter.getName() + "( " + setterParamType.getClass().getName() + " )";
 183  
 
 184  7
         if ( listener != null )
 185  
         {
 186  0
             listener.notifyFieldChangeUsingSetter( fieldName, value, object );
 187  
         }
 188  
 
 189  
         try
 190  
         {
 191  7
             setter.invoke( object, new Object[]{value} );
 192  
         }
 193  0
         catch ( IllegalAccessException e )
 194  
         {
 195  0
             throw new ComponentConfigurationException( "Cannot access method: " + exceptionInfo, e );
 196  
         }
 197  0
         catch ( IllegalArgumentException e )
 198  
         {
 199  0
             throw new ComponentConfigurationException(
 200  
                 "Invalid parameter supplied while setting '" + value + "' to " + exceptionInfo, e );
 201  
         }
 202  0
         catch ( InvocationTargetException e )
 203  
         {
 204  0
             throw new ComponentConfigurationException( "Setter " + exceptionInfo +
 205  
                 " threw exception when called with parameter '" + value + "': " + e.getTargetException().getMessage(),
 206  
                 e );
 207  7
         }
 208  7
     }
 209  
 
 210  
     public void configure( PlexusConfiguration config, ClassLoader classLoader, ExpressionEvaluator evaluator )
 211  
         throws ComponentConfigurationException
 212  
     {
 213  71
         Object value = null;
 214  
 
 215  
         // try setter converter + method first
 216  
 
 217  71
         if ( setterTypeConverter != null )
 218  
         {
 219  
             try
 220  
             {
 221  7
                 value = setterTypeConverter.fromConfiguration( lookup, config, setterParamType, object.getClass(), classLoader, evaluator, listener );
 222  
 
 223  7
                 if ( value != null )
 224  
                 {
 225  7
                     setValueUsingSetter( value );
 226  
 
 227  7
                     return;
 228  
                 }
 229  
             }
 230  0
             catch ( ComponentConfigurationException e )
 231  
             {
 232  0
                 if ( fieldTypeConverter == null || fieldTypeConverter.getClass().equals( setterTypeConverter.getClass() ) )
 233  
                 {
 234  0
                     throw e;
 235  
                 }
 236  0
             }
 237  
         }
 238  
 
 239  
         // try setting field using value found with method
 240  
         // converter, if present.
 241  
 
 242  64
         ComponentConfigurationException savedEx = null;
 243  
 
 244  64
         if ( value != null )
 245  
         {
 246  
             try
 247  
             {
 248  0
                 setValueUsingField( value );
 249  0
                 return;
 250  
             }
 251  0
             catch ( ComponentConfigurationException e )
 252  
             {
 253  0
                 savedEx = e;
 254  
             }
 255  
         }
 256  
 
 257  
         // either no value or setting went wrong. Try
 258  
         // new converter.
 259  
 
 260  64
         value = fieldTypeConverter.fromConfiguration( lookup, config, fieldType, object.getClass(), classLoader, evaluator, listener );
 261  
 
 262  63
         if ( value != null )
 263  
         {
 264  61
             setValueUsingField( value );
 265  
         }
 266  
         // FIXME: need this?
 267  2
         else if ( savedEx != null )
 268  
         {
 269  0
             throw savedEx;
 270  
         }
 271  63
     }
 272  
 
 273  
 }