001: /***************************************************************
002: * This file is part of the [fleXive](R) project.
003: *
004: * Copyright (c) 1999-2008
005: * UCS - unique computing solutions gmbh (http://www.ucs.at)
006: * All rights reserved
007: *
008: * The [fleXive](R) project is free software; you can redistribute
009: * it and/or modify it under the terms of the GNU General Public
010: * License as published by the Free Software Foundation;
011: * either version 2 of the License, or (at your option) any
012: * later version.
013: *
014: * The GNU General Public License can be found at
015: * http://www.gnu.org/copyleft/gpl.html.
016: * A copy is found in the textfile GPL.txt and important notices to the
017: * license from the author are found in LICENSE.txt distributed with
018: * these libraries.
019: *
020: * This library is distributed in the hope that it will be useful,
021: * but WITHOUT ANY WARRANTY; without even the implied warranty of
022: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
023: * GNU General Public License for more details.
024: *
025: * For further information about UCS - unique computing solutions gmbh,
026: * please see the company website: http://www.ucs.at
027: *
028: * For further information about [fleXive](R), please see the
029: * project website: http://www.flexive.org
030: *
031: *
032: * This copyright notice MUST APPEAR in all copies of the file!
033: ***************************************************************/package com.flexive.ejb.beans;
034:
035: import com.flexive.core.Database;
036: import com.flexive.core.storage.StorageManager;
037: import com.flexive.shared.EJBLookup;
038: import com.flexive.shared.configuration.DivisionData;
039: import com.flexive.shared.exceptions.FxApplicationException;
040: import com.flexive.shared.interfaces.FxTimerService;
041: import com.flexive.shared.interfaces.FxTimerServiceLocal;
042: import com.flexive.shared.structure.TypeStorageMode;
043: import org.apache.commons.logging.Log;
044: import org.apache.commons.logging.LogFactory;
045:
046: import javax.annotation.Resource;
047: import javax.ejb.*;
048: import javax.naming.InitialContext;
049: import javax.sql.DataSource;
050: import java.sql.Connection;
051: import java.util.Collection;
052:
053: /**
054: * Periodical timer service
055: *
056: * @author Markus Plesser (markus.plesser@flexive.com), UCS - unique computing solutions gmbh (http://www.ucs.at)
057: */
058: @Stateless(name="FxTimerService")
059: @TransactionAttribute(TransactionAttributeType.REQUIRED)
060: @TransactionManagement(TransactionManagementType.CONTAINER)
061: public class FxTimerServiceBean implements FxTimerService,
062: FxTimerServiceLocal {
063:
064: private static transient Log LOG = LogFactory
065: .getLog(FxTimerServiceBean.class);
066:
067: /**
068: * timer interval in minutes
069: */
070: private static int INTERVAL = 10;
071:
072: /**
073: * Signature used to check if the timer is installed
074: */
075: private final static String TIMER_SIGNATURE = "FxTimer";
076:
077: @Resource
078: SessionContext ctx;
079:
080: /**
081: * {@inheritDoc}
082: */
083: public boolean install() {
084: //install a timer that runs every minute
085: if (ctx != null && ctx.getTimerService() != null) {
086: ctx.getTimerService().createTimer(1000L * 60 * INTERVAL,
087: 1000L * 60 * INTERVAL, TIMER_SIGNATURE);
088: return true;
089: } else {
090: if (ctx != null)
091: LOG
092: .fatal("TimerService is not available! (Still an alpha build?)");
093: else
094: LOG
095: .fatal("@Resource injection failed! (Wrong package?)");
096: }
097: LOG
098: .warn("Performing timer maintenance on startup due to failed service!");
099: perform(null);
100: return false;
101: }
102:
103: /**
104: * {@inheritDoc}
105: */
106: @SuppressWarnings("unchecked")
107: public void uninstall() {
108: try {
109: if (ctx != null && ctx.getTimerService() != null) {
110: for (Timer t : (Collection<Timer>) ctx
111: .getTimerService().getTimers()) {
112: if (t.getInfo().equals(TIMER_SIGNATURE)) {
113: t.cancel();
114: LOG.info(TIMER_SIGNATURE + " canceled!");
115: }
116: }
117: }
118: } catch (Exception e) {
119: LOG.error(e.getClass().getSimpleName() + ": "
120: + e.getMessage(), e);
121: }
122: }
123:
124: /**
125: * {@inheritDoc}
126: */
127: @SuppressWarnings("unchecked")
128: public boolean isInstalled() {
129: try {
130: if (ctx != null && ctx.getTimerService() != null) {
131: for (Timer t : (Collection<Timer>) ctx
132: .getTimerService().getTimers()) {
133: if (t.getInfo().equals(TIMER_SIGNATURE))
134: return true;
135: }
136: }
137: } catch (Exception e) {
138: LOG.error(e.getClass().getSimpleName() + ": "
139: + e.getMessage(), e);
140: }
141: return false;
142: }
143:
144: /**
145: * Timer function, calls periodical tasks for all active divisions
146: *
147: * @param timer the timer
148: */
149: @Timeout
150: @TransactionAttribute(TransactionAttributeType.REQUIRED)
151: public void perform(Timer timer) {
152: //place periodic maintenance code here ...
153: try {
154: for (DivisionData dd : EJBLookup
155: .getGlobalConfigurationEngine().getDivisions()) {
156: if (dd.getId() <= 0 || !dd.isAvailable())
157: continue;
158: Connection con = null;
159: try {
160: con = ((DataSource) new InitialContext().lookup(dd
161: .getDataSource())).getConnection();
162: for (TypeStorageMode mode : TypeStorageMode
163: .values()) {
164: if (!mode.isSupported())
165: continue;
166: StorageManager.getContentStorage(dd, mode)
167: .maintenance(con);
168: }
169: } catch (Exception e) {
170: LOG.error(
171: "Failed to perform maintenance for division #"
172: + dd.getId() + ": "
173: + e.getMessage(), e);
174: } finally {
175: Database.closeObjects(FxTimerServiceBean.class,
176: con, null);
177: }
178: }
179: } catch (FxApplicationException e) {
180: LOG.error("Maintenance error: " + e.getMessage(), e);
181: }
182: }
183: }
|