View Javadoc

1   /**
2    *
3    *  Licensed to the Apache Software Foundation (ASF) under one or more
4    *  contributor license agreements.  See the NOTICE file distributed with
5    *  this work for additional information regarding copyright ownership.
6    *  The ASF licenses this file to You under the Apache License, Version 2.0
7    *  (the "License"); you may not use this file except in compliance with
8    *  the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing, software
13   *  distributed under the License is distributed on an "AS IS" BASIS,
14   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   *  See the License for the specific language governing permissions and
16   *  limitations under the License.
17   */
18  
19  package org.apache.geronimo.timer;
20  
21  import java.util.TimerTask;
22  
23  import javax.transaction.RollbackException;
24  import javax.transaction.SystemException;
25  import javax.transaction.Synchronization;
26  import javax.transaction.Status;
27  
28  import org.apache.commons.logging.Log;
29  import org.apache.commons.logging.LogFactory;
30  
31  /**
32   *
33   *
34   * @version $Rev: 470597 $ $Date: 2006-11-02 15:30:55 -0800 (Thu, 02 Nov 2006) $
35   *
36   * */
37  public class ExecutorFeedingTimerTask extends TimerTask {
38  
39      private static final Log log = LogFactory.getLog(ExecutorFeedingTimerTask.class);
40  
41      private final WorkInfo workInfo;
42      private final ThreadPooledTimer threadPooledTimer;
43      boolean cancelled = false;
44  
45      public ExecutorFeedingTimerTask(WorkInfo workInfo, ThreadPooledTimer threadPooledTimer) {
46          this.workInfo = workInfo;
47          this.threadPooledTimer = threadPooledTimer;
48      }
49  
50      public void run() {
51          threadPooledTimer.getExecutor().execute(workInfo.getExecutorTask());
52      }
53  
54      public boolean cancel() {
55          threadPooledTimer.removeWorkInfo(workInfo);
56          try {
57              threadPooledTimer.registerSynchronization(new CancelSynchronization(this));
58          } catch (RollbackException e) {
59              log.warn("Exception canceling task", e);
60              throw (IllegalStateException) new IllegalStateException("RollbackException when trying to register Cancel Synchronization").initCause(e);
61          } catch (SystemException e) {
62              log.warn("Exception canceling task", e);
63              throw (IllegalStateException) new IllegalStateException("SystemException when trying to register Cancel Synchronization").initCause(e);
64          }
65          // One cancels the task at this specific time. If the transaction is
66          // rolled-back, one will recreate it.
67          cancelled = true;
68          return super.cancel();
69      }
70  
71      public boolean isCancelled() {
72          return cancelled;
73      }
74  
75      private void doCancel() {
76          try {
77              // Impacts the timer storage only if the timer is cancelled
78              // in the scope of a committed transactions.
79              threadPooledTimer.getWorkerPersistence().cancel(workInfo.getId());
80          } catch (PersistenceException e) {
81              log.warn("Exception canceling task", e);
82          }
83      }
84  
85      private void rollbackCancel() {
86          threadPooledTimer.addWorkInfo(workInfo);
87          
88          // The transaction has been rolled-back, we need to restore the
89          // task as if cancel has been called.
90          if ( workInfo.isOneTime() ) {
91              threadPooledTimer.getTimer().schedule(
92                  new ExecutorFeedingTimerTask(workInfo, threadPooledTimer), 
93                  workInfo.getTime());
94          } else if ( workInfo.getAtFixedRate() ) {
95              threadPooledTimer.getTimer().scheduleAtFixedRate(
96                  new ExecutorFeedingTimerTask(workInfo, threadPooledTimer), 
97                  workInfo.getTime(), workInfo.getPeriod().longValue());
98          } else {
99              threadPooledTimer.getTimer().schedule(
100                 new ExecutorFeedingTimerTask(workInfo, threadPooledTimer),
101                 workInfo.getTime(), workInfo.getPeriod().longValue());
102         }
103     }
104     
105     private static class CancelSynchronization implements Synchronization {
106 
107         private final ExecutorFeedingTimerTask worker;
108 
109         public CancelSynchronization(ExecutorFeedingTimerTask worker) {
110             this.worker = worker;
111         }
112 
113         public void beforeCompletion() {
114         }
115 
116         public void afterCompletion(int status) {
117             if (status == Status.STATUS_COMMITTED) {
118                 worker.doCancel();
119             } else if (status == Status.STATUS_ROLLEDBACK) {
120                 worker.rollbackCancel();
121             }
122         }
123 
124     }
125 
126 }