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.IOException; 19 import java.lang.reflect.InvocationTargetException; 20 import java.util.logging.Level; 21 import java.util.logging.Logger; 22 23 /** 24 * This class performs the retriable calls. 25 * 26 * @author smolloy 27 * 28 */ 29 public class RetryCaller implements Runnable { 30 /** 31 * Logger for this class 32 */ 33 private static final Logger logger = Logger.getLogger(RetryCaller.class.getName()); 34 35 /** Call to be retried. */ 36 private RetryableCall theCall; 37 38 /** Result of the call. */ 39 private Object theResult; 40 41 /** The RetryHandler. */ 42 private final RetryHandler theHandler; 43 44 /** 45 * Constructor. 46 * 47 * @param theCall 48 * The call to retry. 49 * @param theHandler 50 * The RetryHandler. 51 */ 52 public RetryCaller(final RetryableCall theCall, final RetryHandler theHandler) { 53 super(); 54 this.theCall = theCall; 55 this.theHandler = theHandler; 56 } 57 58 /** 59 * @return Returns the theCall. 60 */ 61 public RetryableCall getTheCall() { 62 return theCall; 63 } 64 65 /** 66 * @return Returns the theResult. 67 */ 68 public Object getTheResult() { 69 return theResult; 70 } 71 72 /** 73 * Will retry the call the specified number of times and will notify the instance when it reaches the maximum number 74 * of retries or it has a successful result. 75 * 76 * @see java.lang.Runnable#run() 77 */ 78 public void run() { 79 if (RetryCaller.logger.isLoggable(Level.FINER)) { 80 RetryCaller.logger.entering("RetryCaller", "run()", "start"); 81 } 82 83 Object[] args = null; 84 try { 85 args = theHandler.getArgs(theCall.getArgs()); 86 } catch (final IOException e1) { 87 if (RetryCaller.logger.isLoggable(Level.FINE)) { 88 RetryCaller.logger.logp(Level.FINE, "RetryCaller", "run()", "exception ignored", e1); 89 } 90 } 91 int maxRetryCode = IRetryable.KEEP_TRYING; 92 while (theResult == null && theCall.getNumRetries() <= theHandler.getMaximumRetries()) { 93 try { 94 Thread.sleep(theHandler.getRetryInterval()); 95 } catch (final InterruptedException e) { 96 if (RetryCaller.logger.isLoggable(Level.FINE)) { 97 RetryCaller.logger.logp(Level.FINE, "RetryCaller", "run()", "exception ignored", e); 98 } 99 } 100 try { 101 final IRetryable instance = theHandler.findInstance(theCall.getClassName()); 102 if (instance != null) { 103 if (theCall.getNumRetries() >= theHandler.getMaximumRetries()) { 104 final RetryableCallResult result = new RetryableCallResult(theCall, theResult, args); 105 maxRetryCode = instance.maxRetriesReached(result); 106 if (maxRetryCode == IRetryable.KEEP_TRYING) { 107 theCall.setNumRetries(0); 108 } else { 109 theCall.setNumRetries(theCall.getNumRetries() + 1); 110 } 111 } else { 112 theCall.setNumRetries(theCall.getNumRetries() + 1); 113 theResult = theCall.getMethod().invoke(instance, args); 114 final RetryableCallResult result = new RetryableCallResult(theCall, theResult, args); 115 instance.retryCallback(result); 116 } 117 } 118 } catch (final IllegalAccessException e) { 119 if (RetryCaller.logger.isLoggable(Level.FINE)) { 120 RetryCaller.logger.logp(Level.FINE, "RetryCaller", "run()", "exception ignored", e); 121 } 122 } catch (final IllegalArgumentException e) { 123 if (RetryCaller.logger.isLoggable(Level.FINE)) { 124 RetryCaller.logger.logp(Level.FINE, "RetryCaller", "run()", "exception ignored", e); 125 } 126 } catch (final InvocationTargetException e) { 127 if (RetryCaller.logger.isLoggable(Level.FINE)) { 128 RetryCaller.logger.logp(Level.FINE, "RetryCaller", "run()", "exception ignored", e); 129 } 130 } 131 } 132 if (maxRetryCode != IRetryable.TRY_NEXT_RUN) { 133 try { 134 theHandler.callDone(theCall); 135 } catch (final IOException e) { 136 if (RetryCaller.logger.isLoggable(Level.FINE)) { 137 RetryCaller.logger.logp(Level.FINE, "RetryCaller", "run()", "exception ignored", e); 138 } 139 } 140 } 141 142 if (RetryCaller.logger.isLoggable(Level.FINER)) { 143 RetryCaller.logger.exiting("RetryCaller", "run()", "end"); 144 } 145 } 146 147 /** 148 * @param theCall 149 * The theCall to set. 150 */ 151 public void setTheCall(final RetryableCall theCall) { 152 this.theCall = theCall; 153 } 154 155 /** 156 * @param theResult 157 * The theResult to set. 158 */ 159 public void setTheResult(final Object theResult) { 160 this.theResult = theResult; 161 } 162 163 }