View Javadoc

1   /*
2    * Copyright 2001-2004 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */ 
16  package org.apache.commons.betwixt.expression;
17  
18  import java.lang.reflect.Method;
19  
20  import org.apache.commons.logging.Log;
21  import org.apache.commons.logging.LogFactory;
22  
23  /*** <p><code>MethodUpdater</code> updates the current bean context 
24    * by calling a WriteMethod with the String value from the XML attribute 
25    * or element.</p>
26    *
27    * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
28    * @version $Revision: 1.12 $
29    */
30  public class MethodUpdater implements Updater {
31  
32      /*** Logger */
33      private static Log log = LogFactory.getLog( MethodUpdater.class );
34  
35      /*** 
36       * Programmatically set log 
37       * @param aLog the implementation to which this class should log
38       */
39      public static void setLog( Log aLog ) {
40          log = aLog;
41      }
42      
43      /*** The method to call on the bean */
44      private Method method;
45      /*** The type of the first parameter of the method */
46      private Class valueType;
47      
48      /*** Base constructor */
49      public MethodUpdater() {
50      }
51      
52      /*** 
53       * Convenience constructor sets method property 
54       * @param method the Method to be invoked on the context's bean in the update
55       */
56      public MethodUpdater(Method method) {
57          setMethod( method );
58      }
59  
60      /*** 
61       * Updates the current bean context with the given String value 
62       * @param context the Context to be updated
63       * @param newValue the update to this new value 
64       */
65      public void update(Context context, Object newValue) {
66          Object bean = context.getBean();
67          if ( bean != null ) {
68              if ( newValue instanceof String ) {
69                  // try to convert into primitive types
70                  if ( log.isTraceEnabled() ) {
71                      log.trace("Converting primitive to " + valueType);
72                  }
73                  newValue = context.getObjectStringConverter()
74                      .stringToObject( (String) newValue, valueType, null, context );
75              }
76              if ( newValue != null ) {
77                  // check that it is of the correct type
78  /*                
79                  if ( ! valueType.isAssignableFrom( newValue.getClass() ) ) {
80                      log.warn( 
81                          "Cannot call setter method: " + method.getName() + " on bean: " + bean
82                          + " with type: " + bean.getClass().getName() 
83                          + " as parameter should be of type: " + valueType.getName() 
84                          + " but is: " + newValue.getClass().getName() 
85                      );
86                      return;
87                  }
88  */                
89              }                    
90              Object[] arguments = { newValue };
91              try {
92                  if ( log.isDebugEnabled() ) {
93                      log.debug( 
94                          "Calling setter method: " + method.getName() + " on bean: " + bean 
95                          + " with new value: " + newValue 
96                      );
97                  }
98                  method.invoke( bean, arguments );
99                  
100             } catch (Exception e) {
101                 String valueTypeName = (newValue != null) ? newValue.getClass().getName() : "null";
102                 log.warn( 
103                     "Cannot evaluate method: " + method.getName() + " on bean: " + bean 
104                     + " of type: " + bean.getClass().getName() + " with value: " + newValue 
105                     + " of type: " + valueTypeName 
106                 );
107                 handleException(context, e);
108             }
109         }
110     }
111 
112     /*** 
113      * Gets the method which will be invoked by the update
114      *
115      * @return the Method to be invoked by the update
116      */
117     public Method getMethod() {
118         return method;
119     }
120     
121     /*** 
122      * Sets the constant value of this expression 
123      * @param method the Method to be invoked by the update
124      */
125     public void setMethod(Method method) {
126         this.method = method;
127         Class[] types = method.getParameterTypes();
128         if ( types == null || types.length <= 0 ) {
129             throw new IllegalArgumentException( "The Method must have at least one parameter" );
130         }
131         this.valueType = types[0];
132     }
133     
134     // Implementation methods
135     //-------------------------------------------------------------------------    
136     
137     /*** 
138      * Strategy method to allow derivations to handle exceptions differently.
139      * @param context the Context being updated when this exception occured
140      * @param e the Exception that occured during the update
141      */
142     protected void handleException(Context context, Exception e) {
143         log.info( "Caught exception: " + e, e );
144     }
145     
146     /***
147      * Returns something useful for logging.
148      * @return something useful for logging
149      */
150     public String toString() {
151         return "MethodUpdater [method=" + method + "]";
152     }
153 }