KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > varia > scheduler > ScheduleManager


1 /*
2  * JBoss, Home of Professional Open Source
3  * Copyright 2005, JBoss Inc., and individual contributors as indicated
4  * by the @authors tag. See the copyright.txt in the distribution for a
5  * full listing of individual contributors.
6  *
7  * This is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU Lesser General Public License as
9  * published by the Free Software Foundation; either version 2.1 of
10  * the License, or (at your option) any later version.
11  *
12  * This software is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this software; if not, write to the Free
19  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21  */

22 package org.jboss.varia.scheduler;
23
24 import java.util.ArrayList JavaDoc;
25 import java.util.Arrays JavaDoc;
26 import java.util.Collections JavaDoc;
27 import java.util.List JavaDoc;
28 import java.util.Date JavaDoc;
29 import java.util.Iterator JavaDoc;
30 import java.util.Map JavaDoc;
31
32 import javax.management.InstanceNotFoundException JavaDoc;
33 import javax.management.JMException JavaDoc;
34 import javax.management.MBeanException JavaDoc;
35 import javax.management.MBeanServer JavaDoc;
36 import javax.management.MBeanServerInvocationHandler JavaDoc;
37 import javax.management.MalformedObjectNameException JavaDoc;
38 import javax.management.Notification JavaDoc;
39 import javax.management.NotificationListener JavaDoc;
40 import javax.management.NotificationEmitter JavaDoc;
41 import javax.management.ObjectName JavaDoc;
42 import javax.management.timer.TimerNotification JavaDoc;
43 import javax.management.timer.TimerMBean JavaDoc;
44 import javax.management.timer.Timer JavaDoc;
45
46 import EDU.oswego.cs.dl.util.concurrent.SynchronizedInt;
47 import EDU.oswego.cs.dl.util.concurrent.SynchronizedBoolean;
48 import EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap;
49 import org.jboss.logging.Logger;
50 import org.jboss.system.ServiceMBeanSupport;
51
52 /**
53  * ScheduleManager manages multiple scheduled timer listeners.
54  * These are registered using the {@link #addSchedule} operation.
55  * Providers (basically MBean lifecycle listeners) can be registered using the
56  * {@link #registerProvider} operation.
57  *
58  * Because of the way the JBoss deployment model works (no way to readily
59  * invoke operations at deployment time), prefer to use the {@link Scheduler}
60  * MBean instead.
61  *
62  * @author <a HREF="mailto:andreas@jboss.org">Andreas Schaefer</a>
63  * @author <a HREF="mailto:dimitris@jboss.org">Dimitris Andreadis</a>
64  * @version $Revision: 58158 $
65  */

66 public class ScheduleManager extends ServiceMBeanSupport
67    implements ScheduleManagerMBean
68 {
69
70    // -------------------------------------------------------------------------
71
// Constants
72
// -------------------------------------------------------------------------
73

74    /**
75     * Default Timer Object Name
76     */

77    public static String JavaDoc DEFAULT_TIMER_NAME = "jboss:service=Timer";
78
79    /**
80     * Counter for the number of scheduled instances.
81     */

82    private static SynchronizedInt sCounter = new SynchronizedInt(0);
83
84    private static final int NOTIFICATION = 0;
85    private static final int DATE = 1;
86    private static final int REPETITIONS = 2;
87    private static final int SCHEDULER_NAME = 3;
88    private static final int NULL = 4;
89    private static final int ID = 5;
90    private static final int NEXT_DATE = 6;
91
92    // -------------------------------------------------------------------------
93
// Members
94
// -------------------------------------------------------------------------
95

96    private String JavaDoc mTimerName = DEFAULT_TIMER_NAME;
97    private ObjectName JavaDoc mTimerObjectName;
98    private TimerMBean JavaDoc mTimer;
99    private NotificationEmitter JavaDoc mTimerEmitter;
100
101    private boolean mStartOnStart = true;
102    private boolean mFixedRate = false;
103    private SynchronizedBoolean mIsPaused = new SynchronizedBoolean(false);
104
105    /**
106     * List of registered AbstractScheduleProvider ObjectNames to inform
107     * when the this manager is stop or started.
108     */

109    private List JavaDoc mProviders = Collections.synchronizedList(new ArrayList JavaDoc());
110    
111    /**
112     * Maps Integer to registered ScheduleInstance.
113     */

114    private Map JavaDoc mSchedules = new ConcurrentReaderHashMap();
115
116    // -------------------------------------------------------------------------
117
// Constructors
118
// -------------------------------------------------------------------------
119

120    /**
121     * Default (no-args) Constructor
122     */

123    public ScheduleManager()
124    {
125    }
126
127    // -------------------------------------------------------------------------
128
// SchedulerMBean Methods
129
// -------------------------------------------------------------------------
130

131    /**
132     * Starts all the registered Schedules
133     *
134     * @jmx:managed-operation
135     */

136    public void startSchedules()
137    {
138       log.debug("startSchedules()");
139       // Check if not already started
140
if (!isStarted())
141       {
142          // Loop over all available Schedule Instance and start them now
143
Iterator JavaDoc i = mSchedules.values().iterator();
144          while (i.hasNext())
145          {
146             ScheduleInstance lInstance = (ScheduleInstance) i.next();
147             try
148             {
149                lInstance.start();
150             }
151             catch (JMException JavaDoc e)
152             {
153                log.error("Could not start: " + lInstance, e);
154             }
155          }
156       }
157    }
158
159    /**
160     * Stops all the registered Schedules
161     *
162     * @jmx:managed-operation
163     *
164     * @param pDoItNow If true the schedule will be stopped without waiting for the next
165     * scheduled call otherwise the next call will be performed before
166     * the schedule is stopped.
167     */

168    public void stopSchedules(boolean pDoItNow)
169    {
170       // Check if it is already started
171
if (isStarted())
172       {
173          // Loop over all available Schedule Instance and start them now
174
Iterator JavaDoc i = mSchedules.values().iterator();
175          while (i.hasNext())
176          {
177             ScheduleInstance lInstance = (ScheduleInstance) i.next();
178             try
179             {
180                lInstance.stop();
181             }
182             catch (JMException JavaDoc e)
183             {
184                log.error("Could not stop: " + lInstance, e);
185             }
186          }
187       }
188    }
189
190    /**
191     * Stops existing schedules immediately and restarts them right away.
192     *
193     * @jmx:managed-operation
194     */

195    public void restartSchedule()
196    {
197       stopSchedules(true);
198       startSchedules();
199    }
200
201    /**
202     * Register a Provider to make it available. In turn this
203     * method calls "startProviding()" method on the Provider
204     * to indicate that the Provider can start adding Schedules.
205     *
206     * @param pProviderObjectName Object Name of the Provider
207     *
208     * @jmx:managed-operation
209     */

210    public void registerProvider(String JavaDoc pProviderObjectName)
211    {
212       try
213       {
214          registerProvider(new ObjectName JavaDoc(pProviderObjectName));
215       }
216       catch (JMException JavaDoc jme)
217       {
218          log.error("Could not call startProviding() on " + pProviderObjectName, jme);
219       }
220    }
221
222    /**
223     * Register a Provider to make it available. In turn this
224     * method calls "startProviding()" method on the Provider
225     * to indicate that the Provider can start adding Schedules.
226     *
227     * @param pProviderObjectName Object Name of the Provider
228     *
229     * @jmx:managed-operation
230     */

231    public void registerProvider(ObjectName JavaDoc pProviderObjectName)
232       throws JMException JavaDoc
233    {
234       if (pProviderObjectName == null)
235       {
236          throw new MalformedObjectNameException JavaDoc("Provider must not be null");
237       }
238       synchronized (mProviders) {
239          if (mProviders.contains(pProviderObjectName))
240             throw new JMException JavaDoc("Already registered: " + pProviderObjectName);
241          mProviders.add(pProviderObjectName);
242       }
243       server.invoke(
244               pProviderObjectName,
245               "startProviding",
246               new Object JavaDoc[]{},
247               new String JavaDoc[]{}
248       );
249    }
250
251    /**
252     * Unregister a Provider which in turn calls "stopProviding()"
253     * indicating to the Provider to remove all the Schedules.
254     *
255     * @param pProviderObjectName Object Name of the Provider
256     *
257     * @jmx:managed-operation
258     */

259    public void unregisterProvider(String JavaDoc pProviderObjectName)
260    {
261       try
262       {
263          unregisterProvider(new ObjectName JavaDoc(pProviderObjectName));
264       }
265       catch (JMException JavaDoc jme)
266       {
267          log.error("Could not call stopProviding() on " + pProviderObjectName, jme);
268       }
269    }
270
271    /**
272     * Unregister a Provider which in turn calls "stopProviding()"
273     * indicating to the Provider to remove all the Schedules.
274     *
275     * @param pProviderObjectName Object Name of the Provider
276     *
277     * @jmx:managed-operation
278     */

279    public void unregisterProvider(ObjectName JavaDoc pProviderObjectName)
280       throws JMException JavaDoc
281    {
282       if (!mProviders.remove(pProviderObjectName))
283          return;
284       server.invoke(
285               pProviderObjectName,
286               "stopProviding",
287               new Object JavaDoc[]{},
288               new String JavaDoc[]{}
289       );
290    }
291
292    /**
293     * Adds a new Schedule to the Scheduler
294     *
295     * @param pTarget Object Name of the Target MBean
296     * @param pMethodName Name of the method to be called
297     * @param pMethodSignature List of Attributes of the method to be called
298     * where ...
299     * @param pStartDate Date when the schedule is started
300     * @param pRepetitions Initial Number of repetitions
301     *
302     * @return Identification of the Schedule used later to remove it
303     * if necessary
304     *
305     * @jmx:managed-operation
306     */

307    public int addSchedule(
308            ObjectName JavaDoc pProvider,
309            ObjectName JavaDoc pTarget,
310            String JavaDoc pMethodName,
311            String JavaDoc[] pMethodSignature,
312            Date JavaDoc pStartDate,
313            long pPeriod,
314            int pRepetitions
315            )
316    {
317       ScheduleInstance lInstance = new ScheduleInstance(
318               pProvider,
319               pTarget,
320               pMethodName,
321               pMethodSignature,
322               pStartDate,
323               pRepetitions,
324               pPeriod
325       );
326       if (isStarted())
327       {
328          try
329          {
330             lInstance.start();
331          }
332          catch (JMException JavaDoc jme)
333          {
334             log.error("Could not start " + lInstance, jme);
335          }
336       }
337       int lID = lInstance.getID();
338       mSchedules.put(new Integer JavaDoc(lID), lInstance);
339       return lID;
340    }
341
342    /**
343     * Removes a Schedule so that no notification is sent anymore
344     *
345     * @param pIdentification Identification returned by {@link #addSchedule
346     * addSchedule()} or {@link #getSchedules
347     * getSchedules()}.
348     *
349     * @jmx:managed-operation
350     */

351    public void removeSchedule(int pIdentification)
352    {
353       ScheduleInstance lInstance = (ScheduleInstance) mSchedules.get(new Integer JavaDoc(pIdentification));
354       try
355       {
356          if (lInstance == null)
357             throw new InstanceNotFoundException JavaDoc();
358          lInstance.stop();
359       }
360       catch (JMException JavaDoc e)
361       {
362          log.error("Could not stop " + lInstance, e);
363       }
364       mSchedules.remove(new Integer JavaDoc(pIdentification));
365    }
366
367    /**
368     * Returns a list of the ids of all registered schedules
369     *
370     * @return List of Ids separated by a ","
371     */

372    public String JavaDoc getSchedules()
373    {
374       Iterator JavaDoc i = mSchedules.values().iterator();
375       StringBuffer JavaDoc lReturn = new StringBuffer JavaDoc();
376       boolean lFirst = true;
377       while (i.hasNext())
378       {
379          ScheduleInstance lInstance = (ScheduleInstance) i.next();
380          if (lFirst)
381          {
382             lReturn.append(lInstance.mIdentification);
383             lFirst = false;
384          }
385          else
386          {
387             lReturn.append(",").append(lInstance.mIdentification);
388          }
389       }
390       return lReturn.toString();
391    }
392
393    /**
394     * @return True if all the Schedules are paused meaning that even when the notifications
395     * are sent to the listener they are ignored. ATTENTION: this applies to all registered
396     * Schedules and any notifications are lost during pausing
397     */

398    public boolean isPaused()
399    {
400       return mIsPaused.get();
401    }
402
403    /**
404     * Pauses or restarts the Schedules which either suspends the
405     * notifications or start transfering them to the target
406     *
407     * @param pIsPaused True when the Schedules are paused or false when they resume
408     */

409    public void setPaused(boolean pIsPaused)
410    {
411       mIsPaused.set(pIsPaused);
412    }
413
414    /**
415     * @return true if the Schedule Manager is started
416     */

417    public boolean isStarted()
418    {
419       return getState() == STARTED;
420    }
421
422    // -------------------------------------------------------------------------
423
// SchedulerManagerMBean Attributes
424
// -------------------------------------------------------------------------
425

426    /**
427     * Set the scheduler to start when MBean started or not. Note that this method only
428     * affects when the {@link #startService startService()} gets called (normally at
429     * startup time.
430     *
431     * @jmx:managed-attribute
432     *
433     * @param pStartAtStartup if the scheduler should be started upon MBean start or not
434     */

435    public void setStartAtStartup(boolean pStartAtStartup)
436    {
437       mStartOnStart = pStartAtStartup;
438    }
439
440    /**
441     * @jmx:managed-attribute
442     *
443     * @return true if the scheduler should be started upon MBean start or not
444     */

445    public boolean isStartAtStartup()
446    {
447       return mStartOnStart;
448    }
449    
450    /**
451     * @jmx:managed-attribute
452     *
453     * @param pTimerName Object Name of the Timer MBean to
454     * be used. If null or not a valid ObjectName
455     * the default will be used
456     */

457    public void setTimerName(String JavaDoc pTimerName)
458    {
459       mTimerName = pTimerName;
460    }
461    
462    /**
463     * @jmx:managed-attribute
464     *
465     * @return Name of the Timer MBean used in here
466     */

467    public String JavaDoc getTimerName()
468    {
469       return mTimerName;
470    }
471
472    /**
473     * @jmx:managed-attribute
474     *
475     * @param fixedRate the default scheduling to use, fixed-rate or fixed-delay (false, default)
476     */

477    public void setFixedRate(boolean fixedRate)
478    {
479       mFixedRate = fixedRate;
480    }
481    
482    /**
483     * @jmx:managed-attribute
484     *
485     * @return the default scheduling to use
486     */

487    public boolean getFixedRate()
488    {
489       return mFixedRate;
490    }
491    
492    // -------------------------------------------------------------------------
493
// ServiceMBeanSupport overrides
494
// -------------------------------------------------------------------------
495

496    public ObjectName JavaDoc getObjectName(MBeanServer JavaDoc pServer, ObjectName JavaDoc pName)
497       throws MalformedObjectNameException JavaDoc
498    {
499       return pName == null ? OBJECT_NAME : pName;
500    }
501
502    /**
503     * Creates the requested Timer if not already available
504     * and start all added Schedules.
505     * ATTENTION: the start of the schedules is not necessary when
506     * the service is started but this method is also called when
507     * the service is restarted and therefore schedules can be
508     * available.
509     */

510    protected void startService() throws Exception JavaDoc
511    {
512       mTimerObjectName = new ObjectName JavaDoc(mTimerName);
513       if (!getServer().isRegistered(mTimerObjectName))
514       {
515          getServer().createMBean(Timer JavaDoc.class.getName(), mTimerObjectName);
516       }
517       mTimer = (TimerMBean JavaDoc)MBeanServerInvocationHandler.newProxyInstance(getServer(),
518             mTimerObjectName, TimerMBean JavaDoc.class, true);
519       mTimerEmitter = (NotificationEmitter JavaDoc)mTimer;
520       if (!mTimer.isActive())
521       {
522          mTimer.start();
523       }
524       startSchedules();
525    }
526
527    /**
528     * Stops all Schedules.
529     */

530    protected void stopService()
531    {
532       stopSchedules(true);
533    }
534
535    /**
536     * When Service is destroyed it will call the "unregisterProvider()"
537     * on all register Providers to let them remove their Schedules and
538     * being notified that they should stop providing.
539     */

540    protected void destroyService()
541    {
542       // Unregister all providers
543
Iterator JavaDoc i = mSchedules.values().iterator();
544       while (i.hasNext())
545       {
546          ScheduleInstance lInstance = (ScheduleInstance) i.next();
547          unregisterProvider(lInstance.mProvider.toString());
548       }
549    }
550    
551    // -------------------------------------------------------------------------
552
// Inner Classes
553
// -------------------------------------------------------------------------
554

555    /**
556     * This listener is waiting for its Timer Notification and call the
557     * appropriate method on the given Target (MBean) and count down the
558     * number of remaining repetitions.
559     */

560    public class MBeanListener implements NotificationListener JavaDoc
561    {
562       private final Logger log = Logger.getLogger(MBeanListener.class);
563
564       private ScheduleInstance mSchedule;
565
566       public MBeanListener(ScheduleInstance pSchedule)
567       {
568          mSchedule = pSchedule;
569       }
570
571       public void handleNotification(Notification JavaDoc pNotification, Object JavaDoc pHandback)
572       {
573          boolean trace = log.isTraceEnabled();
574          if (trace) {
575             log.trace("MBeanListener.handleNotification: " + pNotification);
576          }
577
578          try
579          {
580             if (!isStarted()) {
581                log.trace("Scheduler not started");
582                mSchedule.stop();
583                return;
584             }
585             if (mSchedule.mRemainingRepetitions == 0)
586             {
587                log.trace("No more repetitions");
588                mSchedule.stop();
589                return;
590             }
591             if (mIsPaused.get())
592             {
593                log.trace("Paused");
594                return;
595             }
596             if (mSchedule.mRemainingRepetitions > 0)
597             {
598                mSchedule.mRemainingRepetitions--;
599                if (trace)
600                   log.trace("Remaining repetitions: " + mSchedule.mRemainingRepetitions);
601             }
602             Object JavaDoc[] lArguments = getArguments(pNotification);
603             if (trace)
604             {
605                log.trace("invoke " + mSchedule);
606                log.trace("arguments are: " + Arrays.asList(lArguments));
607             }
608             
609             ObjectName JavaDoc on = mSchedule.mTarget;
610             String JavaDoc mn = mSchedule.mMethodName;
611             getServer().invoke(on, mn, lArguments,
612                     mSchedule.mSchedulableMBeanArgumentTypes
613             );
614          }
615          catch (Exception JavaDoc e)
616          {
617             log.error("Invoke failed: " + mSchedule.getTargetString(), e);
618          }
619       }
620
621       private Object JavaDoc[] getArguments(Notification JavaDoc pNotification)
622       {
623          Object JavaDoc[] lArguments = new Object JavaDoc[mSchedule.mSchedulableMBeanArguments.length];
624          Date JavaDoc lTimeStamp = new Date JavaDoc(pNotification.getTimeStamp());
625          for (int i = 0; i < lArguments.length; i++)
626          {
627             switch (mSchedule.mSchedulableMBeanArguments[i])
628             {
629                case ID:
630                   lArguments[i] = pNotification.getUserData();
631                   break;
632                case NOTIFICATION:
633                   lArguments[i] = pNotification;
634                   break;
635                case DATE:
636                   lArguments[i] = lTimeStamp;
637                   break;
638                case REPETITIONS:
639                   lArguments[i] = new Long JavaDoc(mSchedule.mRemainingRepetitions);
640                   break;
641                case SCHEDULER_NAME:
642                   lArguments[i] = getServiceName();
643                   break;
644                case NEXT_DATE:
645                   lArguments[i] = new Date JavaDoc(lTimeStamp.getTime() + mSchedule.mPeriod);
646                   break;
647                default:
648                   lArguments[i] = null;
649             }
650          }
651          return lArguments;
652       }
653
654    }
655
656    /**
657     * Filter to ensure that each Scheduler only gets notified when it is supposed to.
658     */

659    static class IdNotificationFilter implements javax.management.NotificationFilter JavaDoc
660    {
661       private static final Logger log = Logger.getLogger(IdNotificationFilter.class);
662
663       private Integer JavaDoc filterId;
664
665       /**
666        * Create a Filter.
667        * @param pId the Scheduler id
668        */

669       public IdNotificationFilter(int filterId)
670       {
671          this.filterId = new Integer JavaDoc(filterId);
672       }
673
674       /**
675        * Determine if the notification should be sent to this Scheduler
676        */

677       public boolean isNotificationEnabled(Notification JavaDoc pNotification)
678       {
679          if (!(pNotification instanceof TimerNotification JavaDoc))
680             return false;
681          TimerNotification JavaDoc lTimerNotification = (TimerNotification JavaDoc) pNotification;
682          if (log.isTraceEnabled())
683             log.trace("isNotificationEnabled(), filterId=" + filterId +
684                ", notification=" + pNotification +
685                ", notificationId=" + lTimerNotification.getNotificationID() +
686                ", timestamp=" + lTimerNotification.getTimeStamp() +
687                ", message=" + lTimerNotification.getMessage()
688             );
689          return lTimerNotification.getNotificationID().equals(filterId);
690       }
691    }
692
693    /**
694     * Represents a single Schedule which can be started and stopped
695     * if necessary.
696     */

697    private class ScheduleInstance
698    {
699
700       private final Logger log = Logger.getLogger(ScheduleInstance.class);
701       private int mIdentification;
702       private MBeanListener mListener;
703
704       public int mNotificationID;
705       public ObjectName JavaDoc mProvider;
706       public ObjectName JavaDoc mTarget;
707       public int mInitialRepetitions;
708       public int mRemainingRepetitions = 0;
709       public Date JavaDoc mStartDate;
710       public long mPeriod;
711       public String JavaDoc mMethodName;
712       public int[] mSchedulableMBeanArguments;
713       public String JavaDoc[] mSchedulableMBeanArgumentTypes;
714
715       public ScheduleInstance(
716               ObjectName JavaDoc pProvider,
717               ObjectName JavaDoc pTarget,
718               String JavaDoc pMethodName,
719               String JavaDoc[] pMethodArguments,
720               Date JavaDoc pStartDate,
721               int pRepetitions,
722               long pPeriod
723               )
724       {
725          mProvider = pProvider;
726          mTarget = pTarget;
727          mInitialRepetitions = pRepetitions;
728          mStartDate = pStartDate;
729          mPeriod = pPeriod;
730          mMethodName = pMethodName;
731          mSchedulableMBeanArguments = new int[pMethodArguments.length];
732          mSchedulableMBeanArgumentTypes = new String JavaDoc[pMethodArguments.length];
733          for (int i = 0; i < pMethodArguments.length; i++)
734          {
735             String JavaDoc lToken = pMethodArguments[i];
736             if (lToken.equals("ID"))
737             {
738                mSchedulableMBeanArguments[i] = ID;
739                mSchedulableMBeanArgumentTypes[i] = Integer JavaDoc.class.getName();
740             }
741             else if (lToken.equals("NOTIFICATION"))
742             {
743                mSchedulableMBeanArguments[i] = NOTIFICATION;
744                mSchedulableMBeanArgumentTypes[i] = Notification JavaDoc.class.getName();
745             }
746             else if (lToken.equals("NEXT_DATE"))
747             {
748                mSchedulableMBeanArguments[i] = NEXT_DATE;
749                mSchedulableMBeanArgumentTypes[i] = Date JavaDoc.class.getName();
750             }
751             else if (lToken.equals("DATE"))
752             {
753                mSchedulableMBeanArguments[i] = DATE;
754                mSchedulableMBeanArgumentTypes[i] = Date JavaDoc.class.getName();
755             }
756             else if (lToken.equals("REPETITIONS"))
757             {
758                mSchedulableMBeanArguments[i] = REPETITIONS;
759                mSchedulableMBeanArgumentTypes[i] = Long.TYPE.getName();
760             }
761             else if (lToken.equals("SCHEDULER_NAME"))
762             {
763                mSchedulableMBeanArguments[i] = SCHEDULER_NAME;
764                mSchedulableMBeanArgumentTypes[i] = ObjectName JavaDoc.class.getName();
765             }
766             else
767             {
768                mSchedulableMBeanArguments[i] = NULL;
769                //AS ToDo: maybe later to check if this class exists !
770
mSchedulableMBeanArgumentTypes[i] = lToken;
771             }
772          }
773          mIdentification = sCounter.increment();
774       }
775
776       /**
777        * Starts the Schedule by adding itself to the timer
778        * and registering its listener to get the notifications
779        * and hand over to the target
780        **/

781       public void start() throws JMException JavaDoc
782       {
783          Date JavaDoc lStartDate = null;
784          // Check if initial start date is in the past
785
if (mStartDate.getTime() < new Date JavaDoc().getTime() && mPeriod > 0)
786          {
787             // If then first check if a repetition is in the future
788
long lNow = new Date JavaDoc().getTime() + 100;
789             int lSkipRepeats = (int) ((lNow - mStartDate.getTime()) / mPeriod) + 1;
790             log.debug("Old start date: " + mStartDate + ", now: " + new Date JavaDoc(lNow) + ", Skip repeats: " + lSkipRepeats);
791             if (mInitialRepetitions > 0)
792             {
793                // If not infinit loop
794
if (lSkipRepeats >= mInitialRepetitions)
795                {
796                   // No repetition left -> exit
797
log.warn("No repetitions left because start date is in the past and could " +
798                           "not be reached by Initial Repetitions * Schedule Period");
799                   return;
800                }
801                else
802                {
803                   // Reduce the missed hits
804
mRemainingRepetitions = mInitialRepetitions - lSkipRepeats;
805                }
806             }
807             else
808             {
809                if (mInitialRepetitions == 0)
810                {
811                   mRemainingRepetitions = 0;
812                }
813                else
814                {
815                   mRemainingRepetitions = -1;
816                }
817             }
818             lStartDate = new Date JavaDoc(mStartDate.getTime() + (lSkipRepeats * mPeriod));
819          }
820          else
821          {
822             lStartDate = mStartDate;
823             mRemainingRepetitions = mInitialRepetitions;
824          }
825          mNotificationID = mTimer.addNotification(
826                "Schedule", "Scheduler Notification",
827                new Integer JavaDoc(getID()), // User Object
828
lStartDate,
829                new Long JavaDoc(mPeriod),
830                mRemainingRepetitions < 0 ? new Long JavaDoc(0) : new Long JavaDoc(mRemainingRepetitions),
831                Boolean.valueOf(mFixedRate)
832          );
833          mListener = new MBeanListener(this);
834          mTimerEmitter.addNotificationListener(
835                mListener,
836                new IdNotificationFilter(mNotificationID),
837                // No object handback necessary
838
null
839          );
840          log.debug("start(), add Notification to Timer with ID: " + mNotificationID);
841       }
842
843       /**
844        * Stops the Schedule by remove itself from the timer
845        * and removing the listener
846        **/

847       public void stop()
848               throws JMException JavaDoc
849       {
850          log.debug("stopSchedule(), notification id: " + mNotificationID);
851          mTimerEmitter.removeNotificationListener(mListener);
852          try
853          {
854             mTimer.removeNotification(mNotificationID);
855          }
856          catch (InstanceNotFoundException JavaDoc e)
857          {
858              log.trace(e);
859          }
860       }
861
862       public int getID()
863       {
864          return mIdentification;
865       }
866
867       public String JavaDoc toString()
868       {
869          return "Schedule target=" + getTargetString();
870       }
871
872       public String JavaDoc getTargetString()
873       {
874          return mTarget + " " + mMethodName + "" + Arrays.asList(mSchedulableMBeanArgumentTypes);
875       }
876
877    }
878 }
879
Popular Tags