1 /** 2 * Copyright 2005 Steve Molloy 3 * 4 * This file is part of OV4J. 5 * 6 * OV4J is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as 7 * published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. 8 * 9 * OV4J is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty 10 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 11 * 12 * You should have received a copy of the GNU General Public License along with OV4J; if not, write to the Free Software 13 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 14 * 15 */ 16 package org.ov4j.cache; 17 18 import java.lang.reflect.Method; 19 import java.util.Timer; 20 import java.util.TimerTask; 21 import java.util.logging.Level; 22 import java.util.logging.Logger; 23 24 /** 25 * This class performs the method calls. 26 * 27 * @author smolloy 28 * 29 */ 30 public class MethodCaller { 31 /** 32 * Logger for this class 33 */ 34 private static final Logger logger = Logger.getLogger(MethodCaller.class.getName()); 35 36 /** Method to call. */ 37 private final Method theMethod; 38 39 /** Object on which to call the method. */ 40 private final Object theObj; 41 42 /** Arguments to pass to the method. */ 43 private Object[] theArgs; 44 45 /** result of the call. */ 46 private Object theResult; 47 48 /** Flag to indicate if the call has timedout. */ 49 private boolean timedout = false; 50 51 /** Exception caught while calling the method. */ 52 private Exception error; 53 54 /** Thread doing the call. */ 55 private final Runnable theCaller = new Runnable() { 56 public void run() { 57 invokeMethod(); 58 } 59 }; 60 61 /** Task setting timeout flag after the timeout period. */ 62 protected TimerTask theTimer = new TimerTask() { 63 @Override 64 public void run() { 65 setTimedout(true); 66 } 67 }; 68 69 /** 70 * Constructor. 71 * 72 * @param theMethod 73 * The method to call. 74 * @param theObj 75 * The object on which to call it. 76 * @param theArgs 77 * The arguments to pass to the method call. 78 */ 79 public MethodCaller(final Method theMethod, final Object theObj, final Object... theArgs) { 80 this.theMethod = theMethod; 81 this.theObj = theObj; 82 if (theArgs == null) { 83 this.theArgs = null; 84 } else { 85 this.theArgs = new Object[theArgs.length]; 86 System.arraycopy(theArgs, 0, this.theArgs, 0, theArgs.length); 87 } 88 } 89 90 /** 91 * Start the threads to perform the call. 92 * 93 * @param timeout 94 * Timeout period. 95 */ 96 public void call(final long timeout) { 97 if (MethodCaller.logger.isLoggable(Level.FINER)) { 98 MethodCaller.logger.entering("MethodCaller", "call(long=" + timeout + ")", "start"); 99 } 100 101 final Timer timer = new Timer(); 102 final Thread t = new Thread(theCaller); 103 timer.schedule(theTimer, timeout); 104 t.start(); 105 while (!timedout && error == null && theResult == null) { 106 try { 107 Thread.sleep(1000); 108 } catch (final InterruptedException e) { 109 if (MethodCaller.logger.isLoggable(Level.FINE)) { 110 MethodCaller.logger.logp(Level.FINE, "MethodCaller", "call(long=" + timeout + ")", 111 "exception ignored", e); 112 } 113 } 114 } 115 timer.cancel(); 116 117 if (MethodCaller.logger.isLoggable(Level.FINER)) { 118 MethodCaller.logger.exiting("MethodCaller", "call(long=" + timeout + ")", "end"); 119 } 120 } 121 122 /** 123 * @return Returns the error. 124 */ 125 public Exception getError() { 126 return error; 127 } 128 129 /** 130 * @return Returns the theResult. 131 */ 132 public Object getTheResult() { 133 return theResult; 134 } 135 136 /** 137 * @return Returns true if an error occured while trying to call the method. 138 */ 139 public boolean hasFailed() { 140 return (error != null); 141 } 142 143 /** 144 * @return Returns the timedout. 145 */ 146 public boolean hasTimedout() { 147 return timedout; 148 } 149 150 /** 151 * Invoke the method. 152 * 153 */ 154 public void invokeMethod() { 155 if (MethodCaller.logger.isLoggable(Level.FINER)) { 156 MethodCaller.logger.entering("MethodCaller", "invokeMethod()", "start"); 157 } 158 159 try { 160 theResult = theMethod.invoke(theObj, theArgs); 161 } catch (final Exception e) { 162 if (MethodCaller.logger.isLoggable(Level.FINE)) { 163 MethodCaller.logger.logp(Level.FINE, "MethodCaller", "invokeMethod()", "Exception caught", e); 164 } 165 166 error = e; 167 } 168 169 if (MethodCaller.logger.isLoggable(Level.FINER)) { 170 MethodCaller.logger.exiting("MethodCaller", "invokeMethod()", "end"); 171 } 172 } 173 174 /** 175 * @param timedout 176 * The timedout to set. 177 */ 178 public void setTimedout(final boolean timedout) { 179 this.timedout = timedout; 180 } 181 }