001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.ejb.txtimer;
023:
024: // $Id: DatabasePersistencePolicy.java 62317 2007-04-13 10:39:22Z dimitris@jboss.org $
025:
026: import java.io.Serializable;
027: import java.sql.SQLException;
028: import java.util.ArrayList;
029: import java.util.Date;
030: import java.util.List;
031:
032: import javax.ejb.TimerService;
033: import javax.management.ObjectName;
034:
035: import org.jboss.ejb.ContainerMBean;
036: import org.jboss.logging.Logger;
037: import org.jboss.mx.util.MBeanProxyExt;
038: import org.jboss.system.ServiceMBeanSupport;
039:
040: /**
041: * This service implements a PersistencePolicy that persistes the timer to a
042: * database.
043: *
044: * @author Thomas.Diesler@jboss.org
045: * @author Scott.Stark@jboss.org
046: * @author Dimitris.Andreadis@jboss.org
047: * @version $Revision: 62317 $
048: * @since 09-Sep-2004
049: */
050: public class DatabasePersistencePolicy extends ServiceMBeanSupport
051: implements DatabasePersistencePolicyMBean {
052: /** logging support */
053: private static Logger log = Logger
054: .getLogger(DatabasePersistencePolicy.class);
055:
056: /** The persistence plugin */
057: private DatabasePersistencePlugin dbpPlugin;
058:
059: /** The datasource */
060: private ObjectName dataSource;
061: /** The persistence plugin */
062: private String dbpPluginClassName;
063: /** The timers table */
064: private String timersTable = "TIMERS";
065:
066: /** The persisted timers seen on startup */
067: private List timersToRestore;
068:
069: /**
070: * Initializes this service.
071: */
072: public void startService() throws Exception {
073: // Get the persistence plugin
074: if (dbpPluginClassName != null) {
075: Class dbpPolicyClass = Thread.currentThread()
076: .getContextClassLoader().loadClass(
077: dbpPluginClassName);
078: dbpPlugin = (DatabasePersistencePlugin) dbpPolicyClass
079: .newInstance();
080: } else {
081: dbpPlugin = new GeneralPurposeDatabasePersistencePlugin();
082: }
083:
084: // init the plugin
085: if (dbpPlugin instanceof DatabasePersistencePluginExt) {
086: // if using the extended plugin interface, initialize the timers table name
087: ((DatabasePersistencePluginExt) dbpPlugin).init(server,
088: dataSource, timersTable);
089: } else {
090: dbpPlugin.init(server, dataSource);
091: }
092:
093: // warn if timers table cannot be set
094: if (dbpPlugin.getTableName().equals(timersTable) == false) {
095: log.warn("Database persistence plugin '"
096: + dbpPluginClassName
097: + "' uses hardcoded timers table name: '"
098: + dbpPlugin.getTableName());
099: }
100:
101: // create the table if needed
102: dbpPlugin.createTableIfNotExists();
103: }
104:
105: /**
106: * Creates the timer in persistent storage.
107: *
108: * @param timerId The timer id
109: * @param timedObjectId The timed object id
110: * @param firstEvent The point in time at which the first txtimer expiration must occur.
111: * @param intervalDuration The number of milliseconds that must elapse between txtimer expiration notifications.
112: * @param info A serializable handback object.
113: */
114: public void insertTimer(String timerId,
115: TimedObjectId timedObjectId, Date firstEvent,
116: long intervalDuration, Serializable info) {
117: try {
118: dbpPlugin.insertTimer(timerId, timedObjectId, firstEvent,
119: intervalDuration, info);
120: } catch (SQLException e) {
121: RuntimeException ex = new IllegalStateException(
122: "Unable to persist timer");
123: ex.initCause(e);
124: throw ex;
125: }
126: }
127:
128: /**
129: * Removes the timer from persistent storage.
130: *
131: * @param timerId The timer id
132: */
133: public void deleteTimer(String timerId, TimedObjectId timedObjectId) {
134: try {
135: dbpPlugin.deleteTimer(timerId, timedObjectId);
136: } catch (SQLException e) {
137: log.warn("Unable to delete timer", e);
138: }
139: }
140:
141: /**
142: * List the persisted timer handles for a particular container
143: *
144: * @param containerId The Container ObjectName
145: * @param loader The ClassLoader to use for loading the handles
146: * @return a list of TimerHandleImpl objects
147: */
148: public List listTimerHandles(ObjectName containerId,
149: ClassLoader loader) {
150: List list = new ArrayList();
151:
152: ClassLoader oldCl = Thread.currentThread()
153: .getContextClassLoader();
154: try {
155: if (loader != null) {
156: Thread.currentThread().setContextClassLoader(loader);
157: }
158: list.addAll(dbpPlugin.selectTimers(containerId));
159: } catch (SQLException e) {
160: log.warn("Unable to get timer handles for containerId: "
161: + containerId, e);
162: } finally {
163: // restore class loader
164: Thread.currentThread().setContextClassLoader(oldCl);
165: }
166: return list;
167: }
168:
169: /**
170: * Return a List of TimerHandle objects.
171: */
172: public List listTimerHandles() {
173: List list = new ArrayList();
174: try {
175: list.addAll(dbpPlugin.selectTimers(null));
176: } catch (SQLException e) {
177: log.warn("Unable to get timer handles", e);
178: }
179: return list;
180: }
181:
182: /**
183: * Restore the persistent timers seen during service startup
184: */
185: public void restoreTimers() {
186: if (timersToRestore != null && timersToRestore.size() > 0) {
187: log.debug("Restoring " + timersToRestore.size()
188: + " timer(s)");
189:
190: // recreate the timers
191: for (int i = 0; i < timersToRestore.size(); i++) {
192: TimerHandleImpl handle = (TimerHandleImpl) timersToRestore
193: .get(i);
194:
195: try {
196: TimedObjectId targetId = handle.getTimedObjectId();
197: ObjectName containerName = targetId
198: .getContainerId();
199: ContainerMBean container = (ContainerMBean) MBeanProxyExt
200: .create(ContainerMBean.class,
201: containerName, server);
202: TimerService timerService = container
203: .getTimerService(targetId.getInstancePk());
204: timerService.createTimer(handle.getFirstTime(),
205: handle.getPeriode(), handle.getInfo());
206: } catch (Exception e) {
207: log.warn("Unable to restore timer record: "
208: + handle);
209: }
210: }
211: timersToRestore.clear();
212: }
213: }
214:
215: /**
216: * Delete all persisted timers
217: */
218: public void clearTimers() {
219: try {
220: dbpPlugin.clearTimers();
221: } catch (SQLException e) {
222: log.warn("Unable to clear timers", e);
223: }
224: }
225:
226: /** Re-read the current persistent timers list, clear the db of timers,
227: * and restore the timers.
228: *
229: * @jmx.managed-operation
230: */
231: public void resetAndRestoreTimers() throws SQLException {
232: timersToRestore = dbpPlugin.selectTimers(null);
233: log.debug("Found " + timersToRestore.size() + " timer(s)");
234: if (timersToRestore.size() > 0) {
235: // delete all timers
236: clearTimers();
237: }
238: restoreTimers();
239: }
240:
241: // MBean attributes *************************************************************************************************\
242:
243: /**
244: * @jmx.managed-attribute
245: */
246: public ObjectName getDataSource() {
247: return dataSource;
248: }
249:
250: /**
251: * @jmx.managed-attribute
252: */
253: public void setDataSource(ObjectName dataSource) {
254: this .dataSource = dataSource;
255: }
256:
257: /**
258: * @jmx.managed-attribute
259: */
260: public String getDatabasePersistencePlugin() {
261: return dbpPluginClassName;
262: }
263:
264: /**
265: * @jmx.managed-attribute
266: */
267: public void setDatabasePersistencePlugin(String dbpPluginClass) {
268: this .dbpPluginClassName = dbpPluginClass;
269: }
270:
271: /**
272: * @jmx.managed-attribute
273: */
274: public String getTimersTable() {
275: return timersTable;
276: }
277:
278: /**
279: * @jmx.managed-attribute
280: */
281: public void setTimersTable(String timersTable) {
282: this.timersTable = timersTable;
283: }
284: }
|