KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ejbca > core > ejb > services > ServiceTimerSessionBean


1 /*************************************************************************
2  * *
3  * EJBCA: The OpenSource Certificate Authority *
4  * *
5  * This software is free software; you can redistribute it and/or *
6  * modify it under the terms of the GNU Lesser General Public *
7  * License as published by the Free Software Foundation; either *
8  * version 2.1 of the License, or any later version. *
9  * *
10  * See terms of license at gnu.org. *
11  * *
12  *************************************************************************/

13
14 package org.ejbca.core.ejb.services;
15
16 import java.io.Serializable JavaDoc;
17 import java.util.Collection JavaDoc;
18 import java.util.Date JavaDoc;
19 import java.util.HashMap JavaDoc;
20 import java.util.HashSet JavaDoc;
21 import java.util.Iterator JavaDoc;
22
23 import javax.ejb.CreateException JavaDoc;
24 import javax.ejb.EJBException JavaDoc;
25 import javax.ejb.Timer JavaDoc;
26
27 import org.apache.commons.lang.StringUtils;
28 import org.ejbca.core.ejb.BaseSessionBean;
29 import org.ejbca.core.ejb.log.ILogSessionLocal;
30 import org.ejbca.core.ejb.log.ILogSessionLocalHome;
31 import org.ejbca.core.model.InternalResources;
32 import org.ejbca.core.model.log.Admin;
33 import org.ejbca.core.model.log.LogEntry;
34 import org.ejbca.core.model.services.IInterval;
35 import org.ejbca.core.model.services.IWorker;
36 import org.ejbca.core.model.services.ServiceConfiguration;
37 import org.ejbca.core.model.services.ServiceExecutionFailedException;
38
39
40 /**
41  * Uses JNDI name for datasource as defined in env 'Datasource' in ejb-jar.xml.
42  *
43  * @ejb.bean description="Timed Object Session bean running the services"
44  * display-name="ServiceTimerSessionSB"
45  * name="ServiceTimerSession"
46  * jndi-name="ServiceTimerSession"
47  * local-jndi-name="ServiceTimerSessionLocal"
48  * view-type="both"
49  * type="Stateless"
50  * transaction-type="Bean"
51  *
52  * @weblogic.enable-call-by-reference True
53  *
54  * @ejb.transaction type="Supports"
55  *
56  * @ejb.env-entry name="DataSource"
57  * type="java.lang.String"
58  * value="${datasource.jndi-name-prefix}${datasource.jndi-name}"
59  *
60  *
61  * @ejb.env-entry
62  * description="Defines the JNDI name of the mail service used"
63  * name="MailJNDIName"
64  * type="java.lang.String"
65  * value="${mail.jndi-name}"
66  *
67  * @ejb.home extends="javax.ejb.EJBHome"
68  * local-extends="javax.ejb.EJBLocalHome"
69  * local-class="org.ejbca.core.ejb.services.IServiceTimerSessionLocalHome"
70  * remote-class="org.ejbca.core.ejb.services.IServiceTimerSessionHome"
71  *
72  * @ejb.interface extends="javax.ejb.EJBObject"
73  * local-extends="javax.ejb.EJBLocalObject"
74  * local-class="org.ejbca.core.ejb.services.IServiceTimerSessionLocal"
75  * remote-class="org.ejbca.core.ejb.services.IServiceTimerSessionRemote"
76  *
77  * @ejb.ejb-external-ref description="The Service session bean"
78  * view-type="local"
79  * ref-name="ejb/ServiceSessionLocal"
80  * type="Session"
81  * home="org.ejbca.core.ejb.services.IServiceSessionLocalHome"
82  * business="org.ejbca.core.ejb.services.IServiceSessionLocal"
83  * link="ServiceSession"
84  *
85  * @ejb.ejb-external-ref description="The Certificate entity bean used to store and fetch certificates"
86  * view-type="local"
87  * ref-name="ejb/CertificateDataLocal"
88  * type="Entity"
89  * home="org.ejbca.core.ejb.ca.store.CertificateDataLocalHome"
90  * business="org.ejbca.core.ejb.ca.store.CertificateDataLocal"
91  * link="CertificateData"
92  *
93  * @ejb.ejb-external-ref description="The Authorization Session Bean"
94  * view-type="local"
95  * ref-name="ejb/AuthorizationSessionLocal"
96  * type="Session"
97  * home="org.ejbca.core.ejb.authorization.IAuthorizationSessionLocalHome"
98  * business="org.ejbca.core.ejb.authorization.IAuthorizationSessionLocal"
99  * link="AuthorizationSession"
100  *
101  * @ejb.ejb-external-ref description="The User Admin Session Bean"
102  * view-type="local"
103  * ref-name="ejb/UserAdminSessionLocal"
104  * type="Session"
105  * home="org.ejbca.core.ejb.ra.IUserAdminSessionLocalHome"
106  * business="org.ejbca.core.ejb.ra.IUserAdminSessionLocal"
107  * link="UserAdminSession"
108  *
109  *
110  * @ejb.ejb-external-ref description="The log session bean"
111  * view-type="local"
112  * ref-name="ejb/LogSessionLocal"
113  * type="Session"
114  * home="org.ejbca.core.ejb.log.ILogSessionLocalHome"
115  * business="org.ejbca.core.ejb.log.ILogSessionLocal"
116  * link="LogSession"
117  *
118  * @ejb.ejb-external-ref description="The CAAdmin Session Bean"
119  * view-type="local"
120  * ref-name="ejb/CAAdminSessionLocal"
121  * type="Session"
122  * home="org.ejbca.core.ejb.ca.caadmin.ICAAdminSessionLocalHome"
123  * business="org.ejbca.core.ejb.ca.caadmin.ICAAdminSessionLocal"
124  * link="CAAdminSession"
125  *
126  * @ejb.ejb-external-ref description="The CRL Create bean"
127  * view-type="local"
128  * ref-name="ejb/CreateCRLSessionLocal"
129  * type="Session"
130  * home="org.ejbca.core.ejb.ca.crl.ICreateCRLSessionLocalHome"
131  * business="org.ejbca.core.ejb.ca.crl.ICreateCRLSessionLocal"
132  * link="CreateCRLSession"
133  *
134  * @jonas.bean ejb-name="ServiceTimerSession"
135  *
136  * @version $Id: ServiceTimerSessionBean.java,v 1.10.2.6 2007/07/19 12:09:34 anatom Exp $
137  */

138 public class ServiceTimerSessionBean extends BaseSessionBean implements javax.ejb.TimedObject JavaDoc {
139
140
141
142     /**
143      * The remote interface of log session bean
144      */

145     private transient ILogSessionLocal logsession = null;
146     
147     /** Internal localization of logs and errors */
148     private static final InternalResources intres = InternalResources.getInstance();
149
150
151     /**
152      * The administrator that the services should be runned as.
153      */

154     Admin intAdmin = new Admin(Admin.TYPE_INTERNALUSER);
155     
156     
157     
158     /**
159      * Default create for SessionBean without any creation Arguments.
160      *
161      * @throws CreateException if bean instance can't be created
162      */

163     public void ejbCreate() throws CreateException JavaDoc {
164         
165     }
166     
167     /**
168      * Constant indicating the Id of the "service loader" service.
169      * Used in a clustered environment to perodically load available
170      * services
171      */

172     private static final Integer JavaDoc SERVICELOADER_ID = Integer.valueOf(0);
173     
174     private static final long SERVICELOADER_PERIOD = 5 * 60 * 1000;
175
176     /**
177      * Method implemented from the TimerObject and is the main method of this
178      * session bean. It calls the work object for each object.
179      *
180      * @param timer
181      */

182     public void ejbTimeout(Timer JavaDoc timer) {
183         debug(">ejbTimeout");
184         Integer JavaDoc timerInfo = (Integer JavaDoc) timer.getInfo();
185         if(timerInfo.equals(SERVICELOADER_ID)){
186             log.debug("Running the internal Service loader.");
187             load();
188         }else{
189             ServiceConfiguration serviceData = null;
190             IWorker worker = null;
191             String JavaDoc serviceName = null;
192             boolean run = false;
193             try{
194                 serviceData = getServiceSession().getServiceConfiguration(intAdmin, timerInfo.intValue());
195                 if(serviceData != null){
196                     serviceName = getServiceSession().getServiceName(intAdmin, timerInfo.intValue());
197                     worker = getWorker(serviceData,serviceName);
198                     run = checkAndUpdateServiceTimeout(worker.getNextInterval(), timerInfo, serviceData, serviceName);
199                 }
200             } catch (Exception JavaDoc e) {
201                 // We need to catch wide here in order to continue even if there is some error
202
log.error(e);
203             }
204             if(run){
205                 if(serviceData != null){
206                     try{
207                         if(serviceData.isActive() && worker.getNextInterval() != IInterval.DONT_EXECUTE){
208                             worker.work();
209                             getLogSession().log(intAdmin, intAdmin.getCaId(), LogEntry.MODULE_SERVICES, new java.util.Date JavaDoc(), null, null, LogEntry.EVENT_INFO_SERVICEEXECUTED, intres.getLocalizedMessage("services.serviceexecuted", serviceName));
210                         }
211                     }catch (ServiceExecutionFailedException e) {
212                         getLogSession().log(intAdmin, intAdmin.getCaId(), LogEntry.MODULE_SERVICES, new java.util.Date JavaDoc(), null, null, LogEntry.EVENT_ERROR_SERVICEEXECUTED, intres.getLocalizedMessage("services.serviceexecutionfailed", serviceName));
213                     }
214                 } else {
215                     getLogSession().log(intAdmin, intAdmin.getCaId(), LogEntry.MODULE_SERVICES, new java.util.Date JavaDoc(), null, null, LogEntry.EVENT_ERROR_SERVICEEXECUTED, intres.getLocalizedMessage("services.servicenotfound", timerInfo));
216                 }
217             }else{
218                 getLogSession().log(intAdmin, intAdmin.getCaId(), LogEntry.MODULE_SERVICES, new java.util.Date JavaDoc(), null, null, LogEntry.EVENT_INFO_SERVICEEXECUTED, intres.getLocalizedMessage("services.servicerunonothernode", timerInfo));
219             }
220         }
221         debug("<ejbTimeout");
222     }
223     /**
224      * Internal method should not be called from external classes, method is public to get automatic transaction handling.
225      *
226      * This method need "RequiresNew" transaction handling, because we want to make sure that the timer
227      * runs the next time even if the execution fails.
228      *
229      * @ejb.transaction type="RequiresNew"
230      */

231     public boolean checkAndUpdateServiceTimeout(long nextInterval, int timerInfo, ServiceConfiguration serviceData, String JavaDoc serviceName) {
232         boolean ret = false;
233         getSessionContext().getTimerService().createTimer(nextInterval*1000, timerInfo);
234         Date JavaDoc nextRunDate = serviceData.getNextRunTimestamp();
235         Date JavaDoc currentDate = new Date JavaDoc();
236         if(currentDate.after(nextRunDate)){
237             nextRunDate = new Date JavaDoc(currentDate.getTime() + nextInterval);
238             serviceData.setNextRunTimestamp(nextRunDate);
239             getServiceSession().changeService(intAdmin, serviceName, serviceData);
240             ret=true;
241         }
242         return ret;
243     }
244
245     /**
246      * Loads and activates all the services from database that are active
247      *
248      * @throws EJBException if a communication or other error occurs.
249      * @ejb.interface-method view-type="both"
250      */

251     public void load(){
252         // Get all services
253

254         Collection JavaDoc currentTimers = getSessionContext().getTimerService().getTimers();
255         Iterator JavaDoc iter = currentTimers.iterator();
256         HashSet JavaDoc existingTimers = new HashSet JavaDoc();
257         while(iter.hasNext()){
258             Timer JavaDoc timer = (Timer JavaDoc) iter.next();
259             try {
260                 Serializable JavaDoc info = timer.getInfo();
261                 existingTimers.add(info);
262             } catch (Throwable JavaDoc e) {
263                 // We need this try because weblogic seems to suck...
264
log.debug("Error invoking timer.getInfo(): ", e);
265             }
266         }
267
268         HashMap JavaDoc idToNameMap = getServiceSession().getServiceIdToNameMap(intAdmin);
269         Collection JavaDoc allServices = idToNameMap.keySet();
270         iter = allServices.iterator();
271         while(iter.hasNext()){
272             Integer JavaDoc id = (Integer JavaDoc) iter.next();
273             ServiceConfiguration serviceConfiguration = getServiceSession().getServiceConfiguration(intAdmin, id.intValue());
274             if(!existingTimers.contains(id)){
275                 IWorker worker = getWorker(serviceConfiguration, (String JavaDoc) idToNameMap.get(id));
276                 if(worker != null && serviceConfiguration.isActive() && worker.getNextInterval() != IInterval.DONT_EXECUTE){
277                     getSessionContext().getTimerService().createTimer((worker.getNextInterval()) *1000, id);
278                 }
279             }
280         }
281
282         if(!existingTimers.contains(SERVICELOADER_ID)){
283             // load the service timer
284
getSessionContext().getTimerService().createTimer(SERVICELOADER_PERIOD, SERVICELOADER_ID);
285         }
286     }
287     
288     /**
289      * Cancels all existing timers a unload
290      *
291      * @throws EJBException if a communication or other error occurs.
292      * @ejb.interface-method view-type="both"
293      */

294     public void unload(){
295         // Get all servicess
296
Collection JavaDoc currentTimers = getSessionContext().getTimerService().getTimers();
297         Iterator JavaDoc iter = currentTimers.iterator();
298         while(iter.hasNext()){
299             Timer JavaDoc timer = (Timer JavaDoc) iter.next();
300             timer.cancel();
301         }
302     }
303     
304     
305     /**
306      * Adds a timer to the bean, and cancels all existing timeouts for this id.
307      *
308      * @param id the id of the timer
309      * @throws EJBException if a communication or other error occurs.
310      * @ejb.interface-method view-type="both"
311      */

312     public void addTimer(long interval, Integer JavaDoc id){
313         // Cancel old timers before adding new one
314
cancelTimer(id);
315         getSessionContext().getTimerService().createTimer(interval, id);
316     }
317     
318     /**
319      * cancels a timer with the given Id
320      *
321      * @throws EJBException if a communication or other error occurs.
322      * @ejb.interface-method view-type="both"
323      */

324     public void cancelTimer(Integer JavaDoc id){
325           Collection JavaDoc timers = getSessionContext().getTimerService().getTimers();
326           Iterator JavaDoc iter = timers.iterator();
327           while(iter.hasNext()){
328               Timer JavaDoc next = (Timer JavaDoc) iter.next();
329               if(id.equals(next.getInfo())){
330                   next.cancel();
331               }
332           }
333     }
334     
335     
336
337    /**
338     * Method that creates a worker from the service configuration.
339     *
340     * @param serviceConfiguration
341     * @param serviceName
342     * @return a worker object or null if the worker is missconfigured.
343     */

344     private IWorker getWorker(ServiceConfiguration serviceConfiguration, String JavaDoc serviceName) {
345         IWorker worker = null;
346         try {
347             String JavaDoc clazz = serviceConfiguration.getWorkerClassPath();
348             if (StringUtils.isNotEmpty(clazz)) {
349                 worker = (IWorker) this.getClass().getClassLoader().loadClass(clazz).newInstance();
350                 worker.init(intAdmin, serviceConfiguration, serviceName);
351             } else {
352                 log.info("Worker has empty classpath for service "+serviceName);
353             }
354         } catch (Exception JavaDoc e) {
355             log.error("Worker is missconfigured, check the classpath",e);
356         }
357         
358         return worker;
359     }
360
361
362
363     /**
364      * Gets connection to log session bean
365      *
366      * @return Connection
367      */

368     private ILogSessionLocal getLogSession() {
369         if (logsession == null) {
370             try {
371                 ILogSessionLocalHome logsessionhome = (ILogSessionLocalHome) getLocator().getLocalHome(ILogSessionLocalHome.COMP_NAME);
372                 logsession = logsessionhome.create();
373             } catch (CreateException JavaDoc e) {
374                 throw new EJBException JavaDoc(e);
375             }
376         }
377         return logsession;
378     } //getLogSession
379

380
381
382
383     /**
384      * Gets connection a service session, used for timed services
385      *
386      * @return Connection
387      */

388     private IServiceSessionLocal getServiceSession() {
389         IServiceSessionLocal servicesession = null;
390         try {
391             IServiceSessionLocalHome servicesessionhome = (IServiceSessionLocalHome) getLocator().getLocalHome(IServiceSessionLocalHome.COMP_NAME);
392             servicesession = servicesessionhome.create();
393         } catch (CreateException JavaDoc e) {
394             throw new EJBException JavaDoc(e);
395         }
396
397         return servicesession ;
398     } //getServiceSession
399

400
401
402
403
404 } // LocalServiceSessionBean
405
Popular Tags