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 }