Clover coverage report - gsbase - 2.0.1
Coverage timestamp: Sat Jan 1 2005 12:30:02 EST
file stats: LOC: 190   Methods: 5
NCLOC: 74   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
ReflectedAction.java 62.5% 83.3% 80% 79.1%
coverage coverage
 1    /*
 2    * Copyright (c) 1998, 2005 Gargoyle Software Inc. All rights reserved.
 3    *
 4    * Redistribution and use in source and binary forms, with or without
 5    * modification, are permitted provided that the following conditions are met:
 6    *
 7    * 1. Redistributions of source code must retain the above copyright notice,
 8    * this list of conditions and the following disclaimer.
 9    * 2. Redistributions in binary form must reproduce the above copyright notice,
 10    * this list of conditions and the following disclaimer in the documentation
 11    * and/or other materials provided with the distribution.
 12    * 3. The end-user documentation included with the redistribution, if any, must
 13    * include the following acknowledgment:
 14    *
 15    * "This product includes software developed by Gargoyle Software Inc.
 16    * (http://www.GargoyleSoftware.com/)."
 17    *
 18    * Alternately, this acknowledgment may appear in the software itself, if
 19    * and wherever such third-party acknowledgments normally appear.
 20    * 4. The name "Gargoyle Software" must not be used to endorse or promote
 21    * products derived from this software without prior written permission.
 22    * For written permission, please contact info@GargoyleSoftware.com.
 23    * 5. Products derived from this software may not be called "GSBase", nor may
 24    * "GSBase" appear in their name, without prior written permission of
 25    * Gargoyle Software Inc.
 26    *
 27    * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
 28    * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 29    * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GARGOYLE
 30    * SOFTWARE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 31    * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 32    * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 33    * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 34    * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 35    * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 36    * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 37    */
 38    package com.gargoylesoftware.base.gui;
 39   
 40    import com.gargoylesoftware.base.util.DetailedIllegalArgumentException;
 41    import com.gargoylesoftware.base.util.DetailedNullPointerException;
 42    import javax.swing.AbstractAction;
 43    import java.awt.event.ActionEvent;
 44    import java.lang.reflect.Method;
 45    import java.lang.reflect.InvocationTargetException;
 46   
 47    /**
 48    * A swing "action" that uses reflection to find and invoke a given target
 49    * method.<p>
 50    *
 51    * ReflectedAction is a Swing "action" that uses reflection to call a specific target
 52    * method when the action is fired. Actions are often implemented using inner classes which
 53    * can be very inefficient in terms of performance and deployment size. This action is a tiny
 54    * bit slower when it is actually fired but is smaller and generally faster otherwise due to
 55    * the fact that those inner classes are no longer needed.
 56    *
 57    * <pre>
 58    * Action searchAction = new ReflectedAction(this, "performSearch");
 59    * </pre>
 60    *
 61    * @version $Revision: 1.5 $
 62    * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
 63    */
 64    public class ReflectedAction extends AbstractAction {
 65   
 66    private static final long serialVersionUID = -3881811288492789994L;
 67    private final Object object_;
 68    private final String methodName_;
 69   
 70   
 71    /**
 72    * Create a reflected action with an object and the name of the method that
 73    * will be invoked on that object when the action is fired.
 74    *
 75    * @param object The object upon which we will invoke a method when
 76    * the action is fired
 77    * @param methodName The name of the method that we will invoke. This method
 78    * must take either no parameters or one parameter which is an ActionEvent.
 79    * @throws IllegalArgumentException if there are no matching methods.
 80    */
 81  10 public ReflectedAction( final Object object, final String methodName )
 82    throws IllegalArgumentException {
 83   
 84  10 assertNotNull("object", object);
 85  9 assertNotNull("methodName", methodName);
 86   
 87  8 findMethodOnObject(object, methodName);
 88   
 89  5 object_ = object;
 90  5 methodName_ = methodName;
 91    }
 92   
 93   
 94    /**
 95    * The action has been fired so now we use reflection to invoke the method that
 96    * was specified previously.
 97    *
 98    * @param event The ActionEvent
 99    */
 100  3 public void actionPerformed( final ActionEvent event ) {
 101  3 final Method method = findMethodOnObject(object_, methodName_);
 102  3 final Object parameters[];
 103  3 if( method.getParameterTypes().length == 0 ) {
 104  2 parameters = new Object[0];
 105    }
 106    else {
 107  1 parameters = new Object[]{event};
 108    }
 109   
 110  3 try {
 111  3 method.invoke(object_, parameters);
 112    }
 113    catch( final IllegalAccessException e ) {
 114  0 exceptionThrown(e);
 115    }
 116    catch( final InvocationTargetException e ) {
 117  1 exceptionThrown(e);
 118    }
 119    catch( final IllegalArgumentException e ) {
 120  0 exceptionThrown(e);
 121    }
 122    }
 123   
 124   
 125    /**
 126    * Return the Method object that corresponds to the specified method name.
 127    * The method may take either no arguments or may take an ActionEvent.
 128    *
 129    * @param object The object that contains the method
 130    * @param methodName The name of the method that we're looking for
 131    * @return The method that matches the specified name.
 132    * @throws IllegalArgumentException If there aren't any methods that match.
 133    * @throws SecurityException If we do not have access to this method.
 134    */
 135  11 private Method findMethodOnObject( final Object object, final String methodName ) {
 136  11 final Class clazz = object.getClass();
 137  11 Method method = null;
 138   
 139  11 try {
 140  11 method = clazz.getDeclaredMethod(methodName, new Class[0]);
 141    }
 142    catch( final NoSuchMethodException e ) {
 143  6 try {
 144  6 method = clazz.getDeclaredMethod(methodName, new Class[]{ActionEvent.class});
 145    }
 146    catch( final NoSuchMethodException ex ) {
 147  3 throw new DetailedIllegalArgumentException("methodName", methodName, "No such method");
 148    }
 149    }
 150   
 151    // If we wouldn't normally have access to this method then
 152    // request access now. If we are denied then a SecurityException
 153    // will be thrown.
 154  8 if( method.isAccessible() == false ) {
 155  8 method.setAccessible(true);
 156    }
 157  8 return method;
 158    }
 159   
 160   
 161    /**
 162    * Callback that will be invoked if an exception is thrown during the
 163    * reflected method call.<p>
 164    *
 165    * Override this to provide custom error handling. Default behaviour
 166    * is to print a stack trace.
 167    *
 168    * @param exception The exception
 169    */
 170  0 protected void exceptionThrown( final Exception exception ) {
 171  0 if( exception instanceof InvocationTargetException ) {
 172  0 ((InvocationTargetException)exception).getTargetException().printStackTrace();
 173    }
 174    else {
 175  0 exception.printStackTrace();
 176    }
 177    }
 178   
 179   
 180    /**
 181    * Throw an exception if the specified object is null
 182    * @param fieldName The name of the paremeter we are checking
 183    * @param object The value of the parameter we are checking
 184    */
 185  19 protected final void assertNotNull( final String fieldName, final Object object ) {
 186  19 if( object == null ) {
 187  2 throw new DetailedNullPointerException(fieldName);
 188    }
 189    }
 190    }