User: schaefera
  Date: 01/06/10 00:50:58

  Added:       src/main/org/jboss/util Schedulable.java Scheduler.java
                        SchedulerMBean.java
  Log:
  Added a Scheduler Service for JBoss to let run a Task at a given date/time
  for a given number (also unlimited) of repeats.
  
  Revision  Changes    Path
  1.1                  jboss/src/main/org/jboss/util/Schedulable.java
  
  Index: Schedulable.java
  ===================================================================
  /*
   * JBoss, the OpenSource EJB server
   *
   * Distributable under LGPL license.
   * See terms of license at gnu.org.
   */
  package org.jboss.util;
  
  import java.util.Date;
  
  /**
   * This interface defines the manageable interface for a Scheduler Service
   * allowing the client to create a Schedulable instance which is then run
   * by this service at given times.
   *
   * @author Andreas Schaefer ([EMAIL PROTECTED])
   **/
  public interface Schedulable
  {
     // -------------------------------------------------------------------------
     // Constants
     // -------------------------------------------------------------------------  
  
     // -------------------------------------------------------------------------
     // Methods
     // -------------------------------------------------------------------------
  
     /**
      * This method is called from the Scheduler Service
      *
      * @param pTimeOfCall Date/Time of the scheduled call
      * @param pRemainingRepetitions Number of the remaining repetitions which
      *                              is -1 if there is an unlimited number of
      *                              repetitions.
      **/
     public void perform(
        Date pTimeOfCall,
        int pRemainingRepetitions
     );
  }
  
  
  
  1.1                  jboss/src/main/org/jboss/util/Scheduler.java
  
  Index: Scheduler.java
  ===================================================================
  /*
   * JBoss, the OpenSource EJB server
   *
   * Distributable under LGPL license.
   * See terms of license at gnu.org.
   */
  package org.jboss.util;
  
  import java.lang.reflect.Constructor;
  import java.security.InvalidParameterException;
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.Date;
  import java.util.Hashtable;
  import java.util.Iterator;
  import java.util.Map;
  
  import javax.management.MalformedObjectNameException;
  import javax.management.MBeanServer;
  import javax.management.Notification;
  import javax.management.NotificationListener;
  import javax.management.ObjectName;
  import javax.naming.Context;
  import javax.naming.InitialContext;
  import javax.naming.Name;
  import javax.naming.NamingException;
  import javax.naming.NameNotFoundException;
  import javax.naming.Reference;
  import javax.naming.StringRefAddr;
  
  import org.jboss.logging.Log;
  import org.jboss.naming.NonSerializableFactory;
  import org.jboss.util.ServiceMBeanSupport;
  
  import management.J2EEApplication;
  
  /**
   * Scheduler Instance to allow clients to run this as a
   * scheduling service for any Schedulable instances.
   *
   * @author Andreas Schaefer ([EMAIL PROTECTED])
   **/
  public class Scheduler
     extends ServiceMBeanSupport
     implements SchedulerMBean
  {
  
     // -------------------------------------------------------------------------
     // Constants
     // -------------------------------------------------------------------------  
  
     public static String JNDI_NAME = "scheduler:domain";
     public static String JMX_NAME = "scheduler";
  
     // -------------------------------------------------------------------------
     // Members
     // -------------------------------------------------------------------------  
  
     private MBeanServer mServer;
     private String mName;
     
     private long mSchedulePeriod;
     private int mRemainingRepetitions = 0;
     private int mActualSchedule = -1;
     private boolean mScheduleIsStarted = false;
     private boolean mWaitForNextCallToStop = false;
     private ObjectName mTimer;
     private Schedulable mSchedulable;
     
     private boolean mStartOnStart = false;
     private String mSchedulableClass;
     private Object[] mInitArguments;
     private String[] mInitTypes;
     private Date mStartDate;
     private long mPeriod;
     private int mRepetitions;
  
     // -------------------------------------------------------------------------
     // Constructors
     // -------------------------------------------------------------------------  
  
     /**
      * Default (no-args) Constructor
      **/
     public Scheduler()
     {
        mName = null;
     }
  
     /**
      * Constructor with the necessary attributes to be set
      *
      * @param pName Name of the MBean
      **/
     public Scheduler( String pName )
     {
        mName = pName;
     }
  
     /**
      * Constructor with the necessary attributes to be set
      *
      * @param pName Name of the MBean
      **/
     public Scheduler(
        String pName,
        String pSchedulableClass,
        String pInitArguments,
        String pInitTypes,
        long pInitialStartDate,
        long pSchedulePeriod,
        long pNumberOfRepetitions
     ) {
        mName = pName;
        mStartOnStart = true;
        mSchedulableClass = pSchedulableClass;
  //      if( pInitArguments == null || pInitArguments.equals( "" ) ) {
           mInitArguments = new Object[ 0 ];
  //      }
  //      if( pInitTypes == null || pInitTypes.equals( "" ) ) {
           mInitArguments = new String[ 0 ];
  //      }
        mStartDate = new Date( pInitialStartDate );
        mPeriod = pSchedulePeriod;
        mRepetitions = (int) pNumberOfRepetitions;
     }
  
     // -------------------------------------------------------------------------
     // SchedulerMBean Methods
     // -------------------------------------------------------------------------  
     
     public void startSchedule(
        String pSchedulableClass,
        Object[] pInitArguments,
        String[] pInitTypes,
        Date pInitialStartDate,
        long pSchedulePeriod,
        int pNumberOfRepetitions
     ) {
        // Check if not already started
        if( !isStarted() ) {
           try {
              // Try to load the Schedulable Class
              Class lSchedulableClass = 
Thread.currentThread().getContextClassLoader().loadClass( pSchedulableClass );
              // Create an instance of it
              if( pInitArguments == null ) {
                 pInitArguments = new Object[ 0 ];
              }
              if( pInitTypes == null ) {
                 pInitTypes = new String[ 0 ];
              }
              if( pInitArguments.length != pInitTypes.length ) {
                 throw new InvalidParameterException( "Constructor Arguments and Data 
Types does not match" );
              }
              Class[]  lInitTypes = new Class[ pInitTypes.length ];
              for( int i = 0; i < pInitTypes.length; i++ ) {
                 lInitTypes[ i ] = 
Thread.currentThread().getContextClassLoader().loadClass( pInitTypes[ i ] );
              }
              Constructor lSchedulableConstructor = lSchedulableClass.getConstructor( 
lInitTypes );
              mSchedulable = (Schedulable) lSchedulableConstructor.newInstance( 
pInitArguments );
              // Register the notificaiton listener at the MBeanServer
              mServer.addNotificationListener(
                 mTimer, 
                 new Listener( mSchedulable ),
                 // No filter
                 null,
                 // No object handback necessary
                 null
              );
              mRemainingRepetitions = pNumberOfRepetitions;
              mSchedulePeriod = pSchedulePeriod;
              // Register the Schedule at the Timer
              if( pInitialStartDate == null || pInitialStartDate.getTime() < new 
Date().getTime() ) {
                 pInitialStartDate = new Date( new Date().getTime() + 1000 );
                 // Start Schedule now
                 System.out.println( "Start regular Schedule with period: " + 
getSchedulePeriod() );
                 if( getRemainingRepetitions() > 0 ) {
                    System.out.println( "Start Schedule wtih " + 
getRemainingRepetitions() + " reps." );
                    mActualSchedule = ( (Integer) mServer.invoke(
                       mTimer,
                       "addNotification",
                       new Object[] {
                          "Schedule",
                          "Scheduler Notification",
                          null,
                          new Date( new Date().getTime() + 1000 ),
                          new Long( getSchedulePeriod() ),
                          new Long( (long) getRemainingRepetitions() )
                       },
                       new String[] {
                          "".getClass().getName(),
                          "".getClass().getName(),
                          "java.lang.Object",
                          Date.class.getName(),
                          Long.TYPE.getName(),
                          Long.TYPE.getName()
                       }
                    ) ).intValue();
                 }
                 else {
                    System.out.println( "Start Schedule with unlimited reps." );
                    mActualSchedule = ( (Integer) mServer.invoke(
                       mTimer,
                       "addNotification",
                       new Object[] {
                          "Schedule",
                          "Scheduler Notification",
                          null,
                          new Date( new Date().getTime() + 1000 ),
                          new Long( getSchedulePeriod() )
                       },
                       new String[] {
                          String.class.getName(),
                          String.class.getName(),
                          Object.class.getName(),
                          Date.class.getName(),
                          Long.TYPE.getName()
                       }
                    ) ).intValue();
                 }
              }
              else {
                 // Add an initial call
                 mActualSchedule = ( (Integer) mServer.invoke(
                    mTimer,
                    "addNotification",
                    new Object[] {
                       "Schedule",
                       "Scheduler Notification",
                       pInitialStartDate
                    },
                    new String[] {
                       "".getClass().getName(),
                       "".getClass().getName(),
                       Date.class.getName(),
                    }
                 ) ).intValue();
              }
              mScheduleIsStarted = true;
           }
           catch( Exception e ) {
              e.printStackTrace();
           }
        }
     }
     
     public void stopSchedule(
        boolean pDoItNow
     ) {
        try {
           if( pDoItNow ) {
              // Remove notification listener now
              mWaitForNextCallToStop = false;
              mServer.invoke(
                 mTimer,
                 "removeNotification",
                 new Object[] {
                    new Integer( mActualSchedule )
                 },
                 new String[] {
                    Integer.TYPE.getName(),
                 }
              );
              mActualSchedule = -1;
              mScheduleIsStarted = false;
           }
           else {
              mWaitForNextCallToStop = true;
           }
        }
        catch( Exception e ) {
           e.printStackTrace();
        }
     }
     
     public long getSchedulePeriod() {
        return mSchedulePeriod;
     }
     
     public int getRemainingRepetitions() {
        return mRemainingRepetitions;
     }
     
     public boolean isStarted() {
        return mScheduleIsStarted;
     }
  
     // -------------------------------------------------------------------------
     // Methods
     // -------------------------------------------------------------------------  
  
     public ObjectName getObjectName(
        MBeanServer pServer,
        ObjectName pName
     )
        throws MalformedObjectNameException
     {
        mServer = pServer;
        return pName;
     }
     
     public String getJNDIName() {
        if( mName != null ) {
           return JMX_NAME + ":" + mName;
        }
        else {
           return JMX_NAME;
        }
     }
     
     public String getName() {
        return "JBoss Scheduler MBean";
     }
     
     // -------------------------------------------------------------------------
     // ServiceMBean - Methods
     // -------------------------------------------------------------------------  
  
     protected void initService()
          throws Exception
     {
     }
     
     protected void startService()
          throws Exception
     {
        bind( this );
        try {
           // Create Timer MBean
           mTimer = new ObjectName( "DefaultDomain", "service", "Timer" );
           mServer.createMBean( "javax.management.timer.Timer", mTimer );
           // Now start the Timer
           mServer.invoke(
              mTimer,
              "start",
              new Object[] {},
              new String[] {}
           );
        }
        catch( Exception e ) {
           e.printStackTrace();
        }
        if( mStartOnStart ) {
           startSchedule(
              mSchedulableClass,
              mInitArguments,
              mInitTypes,
              mStartDate,
              mPeriod,
              mRepetitions
           );
        }
     }
     
     protected void stopService() {
        try {
           unbind();
        }
        catch( Exception e ) {
           log.exception( e );
        }
     }
  
     // -------------------------------------------------------------------------
     // Helper methods to bind/unbind the Management class
     // -------------------------------------------------------------------------
  
        private void bind( Scheduler pScheduler )
        throws
           NamingException
     {
                Context lContext = new InitialContext();
                String lJNDIName = getJNDIName();
  
                // Ah ! JBoss Server isn't serializable, so we use a helper class
                NonSerializableFactory.bind( lJNDIName, pScheduler );
  
        //AS Don't ask me what I am doing here
                Name lName = lContext.getNameParser("").parse( lJNDIName );
                while( lName.size() > 1 ) {
                        String lContextName = lName.get( 0 );
                        try {
                                lContext = (Context) lContext.lookup(lContextName);
                        }
                        catch( NameNotFoundException e )        {
                                lContext = lContext.createSubcontext(lContextName);
                        }
                        lName = lName.getSuffix( 1 );
                }
  
                // The helper class NonSerializableFactory uses address type nns, we 
go on to
                // use the helper class to bind the javax.mail.Session object in JNDI
                StringRefAddr lAddress = new StringRefAddr( "nns", lJNDIName );
                Reference lReference = new Reference(
           Scheduler.class.getName(),
           lAddress,
           NonSerializableFactory.class.getName(),
           null
        );
                lContext.bind( lName.get( 0 ), lReference );
  
                log.log( "JBoss Scheduler Service '" + getJNDIName() + "' bound to " + 
lJNDIName );
        }
  
        private void unbind() throws NamingException {
        String lJNDIName = getJNDIName();
  
        new InitialContext().unbind( lJNDIName );
        NonSerializableFactory.unbind( lJNDIName );
        log.log("JBoss Scheduler service '" + lJNDIName + "' removed from JNDI" );
        }
  
     // -------------------------------------------------------------------------
     // Inner Classes
     // -------------------------------------------------------------------------
  
     public class Listener
        implements NotificationListener
     {
        
        private Schedulable mDelegate;
        
        public Listener( Schedulable pDelegate ) {
           mDelegate = pDelegate;
        }
        
        public void handleNotification(
           Notification pNotification,
           Object pHandback 
        ) {
           System.out.println( "Listener.handleNotification(), notification: " + 
pNotification );
           try {
              // If schedule is started invoke the schedule method on the Schedulable 
instance
              if( isStarted() ) {
                 if( getRemainingRepetitions() > 0 || getRemainingRepetitions() < 0 ) {
                    mDelegate.perform(
                       new Date(),
                       getRemainingRepetitions()
                    );
                    if( mRemainingRepetitions > 0 ) {
                       mRemainingRepetitions--;
                    }
                    if( getRemainingRepetitions() == 0 || mWaitForNextCallToStop ) {
                       stopSchedule( true );
                    }
                    else {
                       if( "InitialCall".equals( pNotification.getType() ) ) {
                          // When Initial Call then setup the regular schedule
                          // By first removing the initial one and then adding the
                          // regular one.
                          mServer.invoke(
                             mTimer,
                             "removeNotification",
                             new Object[] {
                                new Integer( mActualSchedule )
                             },
                             new String[] {
                                Integer.TYPE.getName(),
                             }
                          );
                          // Add regular schedule
                          mActualSchedule = ( (Integer) mServer.invoke(
                             mTimer,
                             "addNotification",
                             new Object[] {
                                "Schedule",
                                "Scheduler Notification",
                                new Date( new Date().getTime() + 1000 ),
                                new Long( getSchedulePeriod() ),
                                new Long( getRemainingRepetitions() )
                             },
                             new String[] {
                                "".getClass().getName(),
                                "".getClass().getName(),
                                Date.class.getName(),
                                Long.TYPE.getName(),
                                Long.TYPE.getName()
                             }
                          ) ).intValue();
                       }
                    }
                 }
              }
              else {
                 // Schedule is stopped therefore remove the Schedule
                 mServer.invoke(
                    mTimer,
                    "removeNotification",
                    new Object[] {
                       new Integer( mActualSchedule )
                    },
                    new String[] {
                       Integer.TYPE.getName(),
                    }
                 );
                 mActualSchedule = -1;
              }
           }
           catch( Exception e ) {
              e.printStackTrace();
           }
        }
     }
     
     /**
      * A test class for a Schedulable Class
      **/
     public static class SchedulableExample
        implements Schedulable
     {
        
        /**
         * Just log the call
         **/
        public void perform(
           Date pTimeOfCall,
           int pRemainingRepetitions
        ) {
           System.out.println( "Schedulable Examples is called at: " + pTimeOfCall +
              ", remaining repetitions: " + pRemainingRepetitions );
        }
     }
  }
  
  
  
  1.1                  jboss/src/main/org/jboss/util/SchedulerMBean.java
  
  Index: SchedulerMBean.java
  ===================================================================
  /*
   * JBoss, the OpenSource EJB server
   *
   * Distributable under LGPL license.
   * See terms of license at gnu.org.
   */
  package org.jboss.util;
  
  import java.util.Date;
  
  import org.jboss.util.ServiceMBean;
  
  /**
   * This interface defines the manageable interface for a Scheduler Service
   * allowing the client to create a Schedulable instance which is then run
   * by this service at given times.
   *
   * @author Andreas Schaefer ([EMAIL PROTECTED])
   **/
  public interface SchedulerMBean
     extends ServiceMBean
  {
     // -------------------------------------------------------------------------
     // Constants
     // -------------------------------------------------------------------------  
  
     public static final String OBJECT_NAME = "DefaultDomain:service=Scheduler";
  
     // -------------------------------------------------------------------------
     // Methods
     // -------------------------------------------------------------------------
  
     /**
      * Starts the schedule if the schedule is stopped otherwise nothing will happen.
      * The scheduled is immediately set to started even the first call is in the
      * future.
      *
      * @param pSchedulableClass Full qaulified Class Name of the class implementing
      *                          the {@link org.jboss.util.Schedulable} interface.
      * @param pInitArguments Arrays of arguments for the constructor. It must have as
      *                       many elements as the Initial Types array. If null then
      *                       an empty array is assumed.
      * @param pInitTypes Arrays of data types to look up the constructor. It must have
      *                   as many elements as the Init Arguments array. If null then an
      *                   empty array is assumed.
      * @param pInitialStartDate Date when the schedule will be started initially. If
      *                          null of older than now it will started NOW.
      * @param pSchedulePeriod Time in Milliseconds between two scheduled calls after
      *                        the initial call.
      * @param pNumberOfRepetitions Number of repetitions this schedule is suppossed to
      *                             call. If less or equal than 0 it will repeat
      *                             unlimited.
      **/
     public void startSchedule(
        String pSchedulableClass,
        Object[] pInitArguments,
        String[] pInitTypes,
        Date pInitialStartDate,
        long pSchedulePeriod,
        int pNumberOfRepetitions
     );
     
     /**
      * Stops the schedule because it is either not used anymore or to restart it with
      * new values.
      *
      * @param pDoItNow If true the schedule will be stopped without waiting for the 
next
      *                 scheduled call otherwise the next call will be performed before
      *                 the schedule is stopped.
      **/
     public void stopSchedule(
        boolean pDoItNow
     );
     
     /**
      * @return Schedule Period between two scheduled calls in Milliseconds. It will 
always
      *         be bigger than 0 except it returns -1 then the schedule is stopped.
      **/
     public long getSchedulePeriod();
     
     /**
      * @return Number of remaining repetitions. If -1 then there is no limit.
      **/
     public int getRemainingRepetitions();
     
     /**
      * @return True if the schedule is up and running. If you want to start the 
schedule
      *         with another values by using {@ #startSchedule} you have to stop the 
schedule
      *         first with {@ #stopSchedule} and wait until this method returns false.
      **/
     public boolean isStarted();
  
  }
  
  
  

_______________________________________________
Jboss-development mailing list
[EMAIL PROTECTED]
http://lists.sourceforge.net/lists/listinfo/jboss-development

Reply via email to