001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     * 
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     * 
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */ 
017    package org.apache.commons.betwixt.expression;
018    
019    
020    import java.lang.reflect.Method;
021    
022    import org.apache.commons.logging.Log;
023    import org.apache.commons.logging.LogFactory;
024    
025    /** <p><code>MethodUpdater</code> updates the current bean context 
026      * by calling a WriteMethod with the String value from the XML attribute 
027      * or element.</p>
028      *
029      * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
030      * @version $Revision: 438373 $
031      */
032    public class MethodUpdater extends TypedUpdater {
033    
034        /** Logger */
035        private static Log log = LogFactory.getLog( MethodUpdater.class );
036    
037        /** 
038         * Programmatically set log 
039         * @param aLog the implementation to which this class should log
040         */
041        public static void setLog( Log aLog ) {
042            log = aLog;
043        }
044        
045        /** The method to call on the bean */
046        private Method method;
047        /** Base constructor */
048        public MethodUpdater() {
049        }
050        
051        /** 
052         * Convenience constructor sets method property 
053         * @param method the Method to be invoked on the context's bean in the update
054         */
055        public MethodUpdater(Method method) {
056            setMethod( method );
057        }
058    
059        /** 
060         * Gets the method which will be invoked by the update
061         *
062         * @return the Method to be invoked by the update
063         */
064        public Method getMethod() {
065            return method;
066        }
067        
068        /** 
069         * Sets the constant value of this expression 
070         * @param method the Method to be invoked by the update
071         */
072        public void setMethod(Method method) {
073            this.method = method;
074            Class[] types = method.getParameterTypes();
075            if ( types == null || types.length <= 0 ) {
076                throw new IllegalArgumentException( "The Method must have at least one parameter" );
077            }
078            setValueType(types[0]);
079        }
080        
081        // Implementation methods
082        //-------------------------------------------------------------------------    
083        
084        
085        
086        /**
087         * Returns something useful for logging.
088         * @return something useful for logging
089         */
090        public String toString() {
091            return "MethodUpdater [method=" + method + "]";
092        }
093    
094        /**
095         * Updates the bean by method invocation.    
096         * @since 0.7
097         */
098        protected void executeUpdate(Context context, Object bean, Object newValue) throws Exception {
099            if ( log.isDebugEnabled() ) {
100                log.debug( 
101                    "Calling setter method: " + method.getName() + " on bean: " + bean 
102                    + " with new value: " + newValue 
103                );
104            }
105            Object[] arguments = { newValue };
106            try
107            {
108                method.invoke( bean, arguments );
109            }
110            catch (IllegalAccessException e)
111            {
112                method.setAccessible(true);
113                method.invoke( bean, arguments );
114            }
115        }
116    }