1   /**
2    *  Copyright 2003-2007 Greg Luck
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License");
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
15   */
16  
17  package net.sf.ehcache.constructs.asynchronous;
18  
19  import org.apache.commons.logging.Log;
20  import org.apache.commons.logging.LogFactory;
21  
22  import java.io.ByteArrayOutputStream;
23  import java.io.IOException;
24  import java.io.ObjectOutputStream;
25  import java.io.Serializable;
26  
27  
28  /**
29   * A test command
30   * @author <a href="mailto:gluck@thoughtworks.com">Greg Luck</a>
31   * @version $Id: ListAppenderCommand.java 512 2007-07-10 09:18:45Z gregluck $
32   */
33  class ListAppenderCommand implements Command {
34  
35      private static final Log LOG = LogFactory.getLog(ListAppenderCommand.class.getName());
36  
37      private static final int NUMBER_OF_ATTEMPTS = 3;
38      private static final int DELAY_IN_SECONDS = 1200;
39      private Serializable payload;
40      private long timeToCompleteInMs;
41      private Class exceptionOnExecute;
42  
43      /**
44       * Constructor
45       */
46      public ListAppenderCommand(Serializable payload, long timeToCompleteInMs, Class exceptionOnExecute) {
47          this.payload = payload;
48          this.timeToCompleteInMs = timeToCompleteInMs;
49          this.exceptionOnExecute = exceptionOnExecute;
50  
51      }
52  
53  
54      /**
55       * Executes the command. The command is successful if it does not throw an exception.
56       *
57       * @throws Throwable A command could do anything and could throw any {@link Exception} or {@link Error}
58       * @see #getThrowablesToRetryOn() to set {@link Throwable}s that should are expected
59       */
60      public void execute() throws Throwable {
61          LOG.debug("About to attempt execution");
62          checkSerializability(payload);
63          Thread.sleep(timeToCompleteInMs);
64          if (exceptionOnExecute != null) {
65              throw (Throwable) exceptionOnExecute.newInstance();
66          }
67          AsynchronousCommandExecutorTest.getMessages().add(payload);
68      }
69  
70      private void checkSerializability(Serializable payload) throws IOException {
71          ObjectOutputStream oout = new ObjectOutputStream(new ByteArrayOutputStream());
72          oout.writeObject(payload);
73      }
74  
75      /**
76       * The AsynchronousCommandExecutor may also be fault tolerant. This method returns a list of {@link Throwable}
77       * classes such that if one if thrown during an execute attempt the command will simply retry after an interval
78       * until it uses up all of its retry attempts. If a {@link Throwable} does occurs which is not in this list,
79       * an {@link AsynchronousCommandException} will be thrown and the command will be removed.
80       * <p/>
81       *
82       * @return a list of {@link Class}s. It only makes sense for the list to contain Classes which are subclasses
83       *         of Throwable
84       */
85      public Class[] getThrowablesToRetryOn() {
86          return new Class[]{Exception.class};
87      }
88  
89      /**
90       * @return the number of times the dispatcher should try to send the message. A non-zero value implies fault tolerance
91       *         and only makes sense if {@link #getThrowablesToRetryOn()} is non-null.
92       */
93      public int getNumberOfAttempts() {
94          return NUMBER_OF_ATTEMPTS;
95      }
96  
97      /**
98       * @return the delay between attempts, in seconds. A non-zero value implies fault tolerance
99       *         and only makes sense if {@link #getThrowablesToRetryOn()} is non-null.
100      */
101     public int getDelayBetweenAttemptsInSeconds() {
102         return DELAY_IN_SECONDS;
103     }
104 }
105