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.retry; 17 18 import java.io.Serializable; 19 import java.lang.reflect.Method; 20 import java.util.logging.Level; 21 import java.util.logging.Logger; 22 23 /** 24 * This class holds information about a call which can be retried. 25 * 26 * @author smolloy 27 * 28 */ 29 public class RetryableCall implements Comparable<RetryableCall>, Serializable { 30 /** 31 * Logger for this class 32 */ 33 private static final Logger logger = Logger.getLogger(RetryableCall.class.getName()); 34 35 /** Serial UID */ 36 private static final long serialVersionUID = 3307958120152660595L; 37 38 /** Name of the class to use. */ 39 private String className; 40 41 /** Name of the method to call. */ 42 private String methodName; 43 44 /** Array of names of classes to use as arguments for the call. */ 45 private String[] argClassNames; 46 47 /** Unique ID to the stored arguments. */ 48 private Long args; 49 50 /** Number of times to retry the call. */ 51 private int numRetries = 0; 52 53 /** 54 * Constructor. 55 * 56 */ 57 public RetryableCall() { 58 } 59 60 /** 61 * @see java.lang.Comparable#compareTo(T) 62 */ 63 public int compareTo(final RetryableCall o) { 64 if (RetryableCall.logger.isLoggable(Level.FINEST)) { 65 RetryableCall.logger.entering("RetryableCall", "compareTo(RetryableCall=" + o + ")", "start"); 66 } 67 68 if (o == null) { 69 if (RetryableCall.logger.isLoggable(Level.FINEST)) { 70 RetryableCall.logger.exiting("RetryableCall", "compareTo(RetryableCall=null)", 71 "end - return value=" + 1); 72 } 73 return 1; 74 } 75 76 int res = ((className == null) ? "" : className).compareTo((o.getClassName() == null) ? "" : o.getClassName()); 77 if (res == 0) { 78 res = 79 ((methodName == null) ? "" : methodName).compareTo((o.getMethod() == null) ? "" : o.getMethod() 80 .getName()); 81 if (res == 0) { 82 if (args == null) { 83 res = (o.getArgs() == null) ? 0 : -1; 84 } else { 85 res = args.compareTo(o.getArgs()); 86 } 87 } 88 } 89 90 if (RetryableCall.logger.isLoggable(Level.FINEST)) { 91 RetryableCall.logger.exiting("RetryableCall", "compareTo(RetryableCall=" + o + ")", "end - return value=" 92 + res); 93 } 94 return res; 95 } 96 97 /** 98 * @see java.lang.Object#equals(java.lang.Object) 99 */ 100 @Override 101 public boolean equals(final Object obj) { 102 if (RetryableCall.logger.isLoggable(Level.FINEST)) { 103 RetryableCall.logger.entering("RetryableCall", "equals(Object=" + obj + ")", "start"); 104 } 105 106 final boolean returnboolean = (obj instanceof RetryableCall && compareTo((RetryableCall) obj) == 0); 107 108 if (RetryableCall.logger.isLoggable(Level.FINEST)) { 109 RetryableCall.logger.exiting("RetryableCall", "equals(Object=" + obj + ")", "end - return value=" 110 + returnboolean); 111 } 112 return returnboolean; 113 } 114 115 /** 116 * @return Returns the args. 117 */ 118 public Long getArgs() { 119 return args; 120 } 121 122 /** 123 * @return Returns the className. 124 */ 125 public String getClassName() { 126 return className; 127 } 128 129 /** 130 * @return Returns the methodName. 131 */ 132 public Method getMethod() { 133 if (RetryableCall.logger.isLoggable(Level.FINEST)) { 134 RetryableCall.logger.entering("RetryableCall", "getMethod()", "start"); 135 } 136 137 Method method = null; 138 try { 139 final Class<?>[] argClasses = new Class<?>[argClassNames.length]; 140 for (int i = 0; i < argClasses.length; i++) { 141 if (argClassNames[i].equals("boolean")) { 142 argClasses[i] = Boolean.TYPE; 143 } else if (argClassNames[i].equals("char")) { 144 argClasses[i] = Character.TYPE; 145 } else if (argClassNames[i].equals("byte")) { 146 argClasses[i] = Byte.TYPE; 147 } else if (argClassNames[i].equals("short")) { 148 argClasses[i] = Short.TYPE; 149 } else if (argClassNames[i].equals("int")) { 150 argClasses[i] = Integer.TYPE; 151 } else if (argClassNames[i].equals("long")) { 152 argClasses[i] = Long.TYPE; 153 } else if (argClassNames[i].equals("float")) { 154 argClasses[i] = Float.TYPE; 155 } else if (argClassNames[i].equals("double")) { 156 argClasses[i] = Double.TYPE; 157 } else if (argClassNames[i].equals("void")) { 158 argClasses[i] = Void.TYPE; 159 } else { 160 argClasses[i] = Class.forName(argClassNames[i]); 161 } 162 } 163 method = Class.forName(className).getMethod(methodName, argClasses); 164 } catch (final ClassNotFoundException e) { 165 if (RetryableCall.logger.isLoggable(Level.FINE)) { 166 RetryableCall.logger.logp(Level.FINE, "RetryableCall", "getMethod()", "exception ignored", e); 167 } 168 } catch (final SecurityException e) { 169 if (RetryableCall.logger.isLoggable(Level.FINE)) { 170 RetryableCall.logger.logp(Level.FINE, "RetryableCall", "getMethod()", "exception ignored", e); 171 } 172 } catch (final NoSuchMethodException e) { 173 if (RetryableCall.logger.isLoggable(Level.FINE)) { 174 RetryableCall.logger.logp(Level.FINE, "RetryableCall", "getMethod()", "exception ignored", e); 175 } 176 } 177 178 if (RetryableCall.logger.isLoggable(Level.FINEST)) { 179 RetryableCall.logger.exiting("RetryableCall", "getMethod()", "end - return value=" + method); 180 } 181 return method; 182 } 183 184 /** 185 * @return Returns the numRetries. 186 */ 187 public int getNumRetries() { 188 return numRetries; 189 } 190 191 /** 192 * @see java.lang.Object#hashCode() 193 */ 194 @Override 195 public int hashCode() { 196 return (className == null ? 0 : className.hashCode()) + (methodName == null ? 0 : methodName.hashCode()) 197 + (args == null ? 0 : args.hashCode()); 198 } 199 200 /** 201 * @param args 202 * The args to set. 203 */ 204 public void setArgs(final Long args) { 205 this.args = args; 206 } 207 208 /** 209 * @param className 210 * The className to set. 211 */ 212 public void setClassName(final String className) { 213 this.className = className; 214 } 215 216 /** 217 * @param methodName 218 * The methodName to set. 219 */ 220 public void setMethod(final Method method) { 221 if (RetryableCall.logger.isLoggable(Level.FINEST)) { 222 RetryableCall.logger.entering("RetryableCall", "setMethod(Method=" + method + ")", "start"); 223 } 224 225 methodName = method.getName(); 226 final Class<?>[] args = method.getParameterTypes(); 227 argClassNames = new String[args.length]; 228 for (int i = 0; i < argClassNames.length; i++) { 229 argClassNames[i] = args[i].getName(); 230 } 231 232 if (RetryableCall.logger.isLoggable(Level.FINEST)) { 233 RetryableCall.logger.exiting("RetryableCall", "setMethod(Method=" + method + ")", "end"); 234 } 235 } 236 237 /** 238 * @param numRetries 239 * The numRetries to set. 240 */ 241 public void setNumRetries(final int numRetries) { 242 this.numRetries = numRetries; 243 } 244 245 /** 246 * @see java.lang.Object#toString() 247 */ 248 @Override 249 public String toString() { 250 return "RetryableCall(Class: " + className + ", Method: " + methodName + ", Args: " + args + ")"; 251 } 252 }