001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */package org.apache.geronimo.timer;
017:
018: import java.util.TimerTask;
019:
020: import javax.transaction.RollbackException;
021: import javax.transaction.SystemException;
022: import javax.transaction.Synchronization;
023: import javax.transaction.Status;
024:
025: import org.apache.commons.logging.Log;
026: import org.apache.commons.logging.LogFactory;
027:
028: /**
029: *
030: *
031: * @version $Rev: 514870 $ $Date: 2007-03-05 13:18:26 -0800 (Mon, 05 Mar 2007) $
032: *
033: * */
034: public class ExecutorFeedingTimerTask extends TimerTask {
035:
036: private static final Log log = LogFactory
037: .getLog(ExecutorFeedingTimerTask.class);
038:
039: private final WorkInfo workInfo;
040: private final ThreadPooledTimer threadPooledTimer;
041: boolean cancelled = false;
042:
043: public ExecutorFeedingTimerTask(WorkInfo workInfo,
044: ThreadPooledTimer threadPooledTimer) {
045: this .workInfo = workInfo;
046: this .threadPooledTimer = threadPooledTimer;
047: }
048:
049: public void run() {
050: try {
051: threadPooledTimer.getExecutor().execute(
052: workInfo.getExecutorTask());
053: } catch (Throwable t) {
054: log
055: .error(
056: "Error occurred during execution of ExpirationMonitor TimerTask",
057: t);
058: }
059: }
060:
061: public boolean cancel() {
062: threadPooledTimer.removeWorkInfo(workInfo);
063: try {
064: threadPooledTimer
065: .registerSynchronization(new CancelSynchronization(
066: this ));
067: } catch (RollbackException e) {
068: log.warn("Exception canceling task", e);
069: throw (IllegalStateException) new IllegalStateException(
070: "RollbackException when trying to register Cancel Synchronization")
071: .initCause(e);
072: } catch (SystemException e) {
073: log.warn("Exception canceling task", e);
074: throw (IllegalStateException) new IllegalStateException(
075: "SystemException when trying to register Cancel Synchronization")
076: .initCause(e);
077: }
078: // One cancels the task at this specific time. If the transaction is
079: // rolled-back, one will recreate it.
080: cancelled = true;
081: return super .cancel();
082: }
083:
084: public boolean isCancelled() {
085: return cancelled;
086: }
087:
088: private void doCancel() {
089: try {
090: // Impacts the timer storage only if the timer is cancelled
091: // in the scope of a committed transactions.
092: threadPooledTimer.getWorkerPersistence().cancel(
093: workInfo.getId());
094: } catch (PersistenceException e) {
095: log.warn("Exception canceling task", e);
096: }
097: }
098:
099: private void rollbackCancel() {
100: threadPooledTimer.addWorkInfo(workInfo);
101:
102: // The transaction has been rolled-back, we need to restore the
103: // task as if cancel has been called.
104: if (workInfo.isOneTime()) {
105: threadPooledTimer.getTimer().schedule(
106: new ExecutorFeedingTimerTask(workInfo,
107: threadPooledTimer), workInfo.getTime());
108: } else if (workInfo.getAtFixedRate()) {
109: threadPooledTimer.getTimer().scheduleAtFixedRate(
110: new ExecutorFeedingTimerTask(workInfo,
111: threadPooledTimer), workInfo.getTime(),
112: workInfo.getPeriod().longValue());
113: } else {
114: threadPooledTimer.getTimer().schedule(
115: new ExecutorFeedingTimerTask(workInfo,
116: threadPooledTimer), workInfo.getTime(),
117: workInfo.getPeriod().longValue());
118: }
119: }
120:
121: private static class CancelSynchronization implements
122: Synchronization {
123:
124: private final ExecutorFeedingTimerTask worker;
125:
126: public CancelSynchronization(ExecutorFeedingTimerTask worker) {
127: this .worker = worker;
128: }
129:
130: public void beforeCompletion() {
131: }
132:
133: public void afterCompletion(int status) {
134: if (status == Status.STATUS_COMMITTED) {
135: worker.doCancel();
136: } else if (status == Status.STATUS_ROLLEDBACK) {
137: worker.rollbackCancel();
138: }
139: }
140:
141: }
142:
143: }
|