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.openejb.core.timer;
017:
018: import org.apache.openejb.util.LogCategory;
019: import org.apache.openejb.util.Logger;
020:
021: import javax.ejb.Timer;
022: import javax.transaction.Synchronization;
023: import javax.transaction.Status;
024: import javax.transaction.Transaction;
025: import java.util.Date;
026: import java.util.TimerTask;
027:
028: public class TimerData {
029: private static final Logger log = Logger.getInstance(
030: LogCategory.TIMER, "org.apache.openejb.util.resources");
031: private final long id;
032: private final EjbTimerServiceImpl timerService;
033: private final String deploymentId;
034: private final Object primaryKey;
035: private final Object info;
036: private final long intervalDuration;
037: private Date expiration;
038:
039: // EJB Timer object given to user code
040: private final Timer timer;
041:
042: // TimerTask object registered with the java.util.timer
043: private TimerTask timerTask;
044:
045: /**
046: * Is this a new timer? A new timer must be scheduled with the java.util.Timer
047: * when the transaction commits.
048: */
049: private boolean newTimer = false;
050:
051: /**
052: * Has this timer been cancelled? A canceled timer must be rescheduled with the
053: * java.util.Timer if the transaction is rolled back
054: */
055: private boolean cancelled = false;
056:
057: /**
058: * Has this timer been registered with the transaction for callbacks? We remember
059: * when we are registered to avoid multiple registrations.
060: */
061: private boolean synchronizationRegistered = false;
062:
063: public TimerData(long id, EjbTimerServiceImpl timerService,
064: String deploymentId, Object primaryKey, Object info,
065: Date expiration, long intervalDuration) {
066: this .id = id;
067: this .timerService = timerService;
068: this .deploymentId = deploymentId;
069: this .primaryKey = primaryKey;
070: this .info = info;
071: this .expiration = expiration;
072: this .intervalDuration = intervalDuration;
073: this .timer = new TimerImpl(this );
074: }
075:
076: public void stop() {
077: if (timerTask != null) {
078: timerTask.cancel();
079: timerTask = null;
080: }
081: cancelled = true;
082: }
083:
084: public long getId() {
085: return id;
086: }
087:
088: public String getDeploymentId() {
089: return deploymentId;
090: }
091:
092: public Object getPrimaryKey() {
093: return primaryKey;
094: }
095:
096: public Object getInfo() {
097: return info;
098: }
099:
100: public Date getExpiration() {
101: return expiration;
102: }
103:
104: public long getIntervalDuration() {
105: return intervalDuration;
106: }
107:
108: public TimerTask getTimerTask() {
109: return timerTask;
110: }
111:
112: public void setTimerTask(TimerTask timerTask) {
113: this .timerTask = timerTask;
114: }
115:
116: public Timer getTimer() {
117: return timer;
118: }
119:
120: public boolean isOneTime() {
121: return intervalDuration <= 0;
122: }
123:
124: void nextTime() {
125: if (isOneTime()) {
126: throw new IllegalStateException(
127: "This is a one-time timerTask");
128: }
129: expiration = new Date(expiration.getTime() + intervalDuration);
130: }
131:
132: public boolean isNewTimer() {
133: return newTimer;
134: }
135:
136: public void newTimer() {
137: newTimer = true;
138: registerTimerDataSynchronization();
139: }
140:
141: public boolean isCancelled() {
142: return cancelled;
143: }
144:
145: public void cancel() {
146: timerService.cancelled(TimerData.this );
147: if (timerTask != null) {
148: timerTask.cancel();
149: timerTask = null;
150: }
151: cancelled = true;
152: registerTimerDataSynchronization();
153: }
154:
155: private void transactionComplete(boolean committed) {
156: if (newTimer) {
157: // you are only a new timer once no matter what
158: newTimer = false;
159:
160: // if our new timer was not canceled and the transaction committed
161: if (!isCancelled() && committed) {
162: // schedule the timer with the java.util.Timer
163: timerService.schedule(TimerData.this );
164: }
165: } else {
166: // if the tx was rolled back, reschedule the timer with the java.util.Timer
167: if (!committed) {
168: cancelled = false;
169: timerService.addTimerData(TimerData.this );
170: timerService.schedule(TimerData.this );
171: }
172: }
173: }
174:
175: private void registerTimerDataSynchronization() {
176: if (synchronizationRegistered)
177: return;
178:
179: try {
180: Transaction transaction = timerService
181: .getTransactionManager().getTransaction();
182: int status = transaction == null ? Status.STATUS_NO_TRANSACTION
183: : transaction.getStatus();
184:
185: if (transaction != null && status == Status.STATUS_ACTIVE
186: || status == Status.STATUS_MARKED_ROLLBACK) {
187: transaction
188: .registerSynchronization(new TimerDataSynchronization());
189: synchronizationRegistered = true;
190: return;
191: }
192: } catch (Exception e) {
193: log
194: .warning(
195: "Unable to register timer data transaction synchronization",
196: e);
197: }
198:
199: // there either wasn't a transaction or registration failed... call transactionComplete directly
200: transactionComplete(true);
201: }
202:
203: private class TimerDataSynchronization implements Synchronization {
204: public void beforeCompletion() {
205: }
206:
207: public void afterCompletion(int status) {
208: synchronizationRegistered = false;
209: transactionComplete(status == Status.STATUS_COMMITTED);
210: }
211: }
212: }
|