[jboss-cvs] JBossAS SVN: r63625 - in branches/JBoss_4_0_3_SP1_JBAS-4497: common/src/main/org/jboss/util and 12 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Sat Jun 23 14:53:20 EDT 2007


Author: darran.lofthouse at jboss.com
Date: 2007-06-23 14:53:19 -0400 (Sat, 23 Jun 2007)
New Revision: 63625

Added:
   branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/main/org/jboss/test/jbossmx/compliance/timer/PeriodTestCase.java
   branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/main/org/jboss/test/scheduler/
   branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/main/org/jboss/test/scheduler/BaseTest.java
   branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/main/org/jboss/test/scheduler/ScheduleTask.java
   branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/main/org/jboss/test/scheduler/ScheduleTracker.java
   branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/main/org/jboss/test/scheduler/ScheduleTrackerMBean.java
   branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/main/org/jboss/test/scheduler/SchedulerDefaultTestCase.java
   branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/main/org/jboss/test/scheduler/SchedulerFixedDelayTestCase.java
   branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/main/org/jboss/test/scheduler/SchedulerFixedRateTestCase.java
   branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/resources/scheduler/
   branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/resources/scheduler/default/
   branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/resources/scheduler/default/jboss-service.xml
   branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/resources/scheduler/fixedDelay/
   branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/resources/scheduler/fixedDelay/jboss-service.xml
   branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/resources/scheduler/fixedRate/
   branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/resources/scheduler/fixedRate/jboss-service.xml
Modified:
   branches/JBoss_4_0_3_SP1_JBAS-4497/
   branches/JBoss_4_0_3_SP1_JBAS-4497/common/src/main/org/jboss/util/Classes.java
   branches/JBoss_4_0_3_SP1_JBAS-4497/jmx/src/main/javax/management/timer/Timer.java
   branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/imports/test-jars.xml
   branches/JBoss_4_0_3_SP1_JBAS-4497/varia/src/etc/schedule-manager-service.xml
   branches/JBoss_4_0_3_SP1_JBAS-4497/varia/src/etc/scheduler-service.xml
   branches/JBoss_4_0_3_SP1_JBAS-4497/varia/src/main/org/jboss/varia/scheduler/ScheduleManager.java
   branches/JBoss_4_0_3_SP1_JBAS-4497/varia/src/main/org/jboss/varia/scheduler/ScheduleManagerMBean.java
   branches/JBoss_4_0_3_SP1_JBAS-4497/varia/src/main/org/jboss/varia/scheduler/Scheduler.java
   branches/JBoss_4_0_3_SP1_JBAS-4497/varia/src/main/org/jboss/varia/scheduler/SchedulerMBean.java
Log:
JBAS-4497 - ScheduleManager MBean uses fixed-rate execution on Java 1.4 and fixed-delay execution on Java 5.0.


Property changes on: branches/JBoss_4_0_3_SP1_JBAS-4497
___________________________________________________________________
Name: svn:ignore
   + thirdparty
.metadata



Modified: branches/JBoss_4_0_3_SP1_JBAS-4497/common/src/main/org/jboss/util/Classes.java
===================================================================
--- branches/JBoss_4_0_3_SP1_JBAS-4497/common/src/main/org/jboss/util/Classes.java	2007-06-23 12:48:50 UTC (rev 63624)
+++ branches/JBoss_4_0_3_SP1_JBAS-4497/common/src/main/org/jboss/util/Classes.java	2007-06-23 18:53:19 UTC (rev 63625)
@@ -14,7 +14,10 @@
 import java.lang.reflect.Array;
 import java.lang.*;
 import java.lang.NoSuchMethodException;
+import java.net.URL;
 
+import java.security.CodeSource;
+import java.security.ProtectionDomain;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -38,6 +41,109 @@
    /** The default package name. */
    public static final String DEFAULT_PACKAGE_NAME = "<default>";
 
+   /** Format a string buffer containing the Class, Interfaces, CodeSource,
+    and ClassLoader information for the given object clazz.
+
+    @param clazz the Class
+    @param results - the buffer to write the info to
+    */
+   public static void displayClassInfo(Class clazz, StringBuffer results)
+   {
+      // Print out some codebase info for the clazz
+      ClassLoader cl = clazz.getClassLoader();
+      results.append("\n");
+      results.append(clazz.getName());
+      results.append("(");
+      results.append(Integer.toHexString(clazz.hashCode()));
+      results.append(").ClassLoader=");
+      results.append(cl);
+      ClassLoader parent = cl;
+      while (parent != null)
+      {
+         results.append("\n..");
+         results.append(parent);
+         URL[] urls = getClassLoaderURLs(parent);
+         int length = urls != null ? urls.length : 0;
+         for (int u = 0; u < length; u++)
+         {
+            results.append("\n....");
+            results.append(urls[u]);
+         }
+         if (parent != null)
+            parent = parent.getParent();
+      }
+      CodeSource clazzCS = clazz.getProtectionDomain().getCodeSource();
+      if (clazzCS != null)
+      {
+         results.append("\n++++CodeSource: ");
+         results.append(clazzCS);
+      }
+      else
+         results.append("\n++++Null CodeSource");
+
+      results.append("\nImplemented Interfaces:");
+      Class[] ifaces = clazz.getInterfaces();
+      for (int i = 0; i < ifaces.length; i++)
+      {
+         Class iface = ifaces[i];
+         results.append("\n++");
+         results.append(iface);
+         results.append("(");
+         results.append(Integer.toHexString(iface.hashCode()));
+         results.append(")");
+         ClassLoader loader = ifaces[i].getClassLoader();
+         results.append("\n++++ClassLoader: ");
+         results.append(loader);
+         ProtectionDomain pd = ifaces[i].getProtectionDomain();
+         CodeSource cs = pd.getCodeSource();
+         if (cs != null)
+         {
+            results.append("\n++++CodeSource: ");
+            results.append(cs);
+         }
+         else
+            results.append("\n++++Null CodeSource");
+      }
+   }
+
+   /** Use reflection to access a URL[] getURLs or URL[] getClasspath method so
+    that non-URLClassLoader class loaders, or class loaders that override
+    getURLs to return null or empty, can provide the true classpath info.
+    */
+   public static URL[] getClassLoaderURLs(ClassLoader cl)
+   {
+      URL[] urls =
+      {};
+      try
+      {
+         Class returnType = urls.getClass();
+         Class[] parameterTypes =
+         {};
+         Class clClass = cl.getClass();
+         Method getURLs = clClass.getMethod("getURLs", parameterTypes);
+         if (returnType.isAssignableFrom(getURLs.getReturnType()))
+         {
+            Object[] args =
+            {};
+            urls = (URL[]) getURLs.invoke(cl, args);
+         }
+         if (urls == null || urls.length == 0)
+         {
+            Method getCp = clClass.getMethod("getClasspath", parameterTypes);
+            if (returnType.isAssignableFrom(getCp.getReturnType()))
+            {
+               Object[] args =
+               {};
+               urls = (URL[]) getCp.invoke(cl, args);
+            }
+         }
+      }
+      catch (Exception ignore)
+      {
+      }
+      return urls;
+   }
+
    /**
     * Get the short name of the specified class by striping off the package
     * name.
@@ -113,16 +219,16 @@
    {
       if (type == null)
          throw new NullArgumentException("type");
-      
+
       // don't attempt to force primitives to load
-      if (type.isPrimitive()) return;
+      if (type.isPrimitive())
+         return;
 
       // don't attempt to force java.* classes to load
       String packageName = Classes.getPackageName(type);
       // System.out.println("package name: " + packageName);
 
-      if (packageName.startsWith("java.") ||
-         packageName.startsWith("javax."))
+      if (packageName.startsWith("java.") || packageName.startsWith("javax."))
       {
          return;
       }
@@ -158,14 +264,13 @@
       }
    }
 
-
    /////////////////////////////////////////////////////////////////////////
    //                               Primitives                            //
    /////////////////////////////////////////////////////////////////////////
 
    /** Primitive type name -> class map. */
    private static final Map PRIMITIVE_NAME_TYPE_MAP = new HashMap();
-   
+
    /** Setup the primitives map. */
    static
    {
@@ -196,16 +301,9 @@
    }
 
    /** Map of primitive types to their wrapper classes */
-   private static final Class[] PRIMITIVE_WRAPPER_MAP = {
-      Boolean.TYPE, Boolean.class,
-      Byte.TYPE, Byte.class,
-      Character.TYPE, Character.class,
-      Double.TYPE, Double.class,
-      Float.TYPE, Float.class,
-      Integer.TYPE, Integer.class,
-      Long.TYPE, Long.class,
-      Short.TYPE, Short.class,
-   };
+   private static final Class[] PRIMITIVE_WRAPPER_MAP =
+   {Boolean.TYPE, Boolean.class, Byte.TYPE, Byte.class, Character.TYPE, Character.class, Double.TYPE, Double.class,
+         Float.TYPE, Float.class, Integer.TYPE, Integer.class, Long.TYPE, Long.class, Short.TYPE, Short.class,};
 
    /**
     * Get the wrapper class for the given primitive type.
@@ -268,13 +366,14 @@
 
       return false;
    }
+
    /** Check type against boolean, byte, char, short, int, long, float, double.
     * @param type  The java type name
     * @return true if this is a primative type name.
-    */ 
+    */
    public static boolean isPrimitive(final String type)
    {
-      return PRIMITIVE_NAME_TYPE_MAP.containsKey(type); 
+      return PRIMITIVE_NAME_TYPE_MAP.containsKey(type);
    }
 
    /////////////////////////////////////////////////////////////////////////
@@ -312,8 +411,7 @@
     * @throws ClassNotFoundException when the <code>classLoader</code> can not
     * find the requested class
     */
-   public static Class loadClass(String className, ClassLoader classLoader)
-      throws ClassNotFoundException
+   public static Class loadClass(String className, ClassLoader classLoader) throws ClassNotFoundException
    {
       // ClassLoader.loadClass() does not handle primitive types:
       //
@@ -330,27 +428,36 @@
       if (className.length() == 1)
       {
          char type = className.charAt(0);
-         if (type == 'B') return Byte.TYPE;
-         if (type == 'C') return Character.TYPE;
-         if (type == 'D') return Double.TYPE;
-         if (type == 'F') return Float.TYPE;
-         if (type == 'I') return Integer.TYPE;
-         if (type == 'J') return Long.TYPE;
-         if (type == 'S') return Short.TYPE;
-         if (type == 'Z') return Boolean.TYPE;
-         if (type == 'V') return Void.TYPE;
+         if (type == 'B')
+            return Byte.TYPE;
+         if (type == 'C')
+            return Character.TYPE;
+         if (type == 'D')
+            return Double.TYPE;
+         if (type == 'F')
+            return Float.TYPE;
+         if (type == 'I')
+            return Integer.TYPE;
+         if (type == 'J')
+            return Long.TYPE;
+         if (type == 'S')
+            return Short.TYPE;
+         if (type == 'Z')
+            return Boolean.TYPE;
+         if (type == 'V')
+            return Void.TYPE;
          // else throw...
          throw new ClassNotFoundException(className);
       }
 
       // Check for a primative type
-      if( isPrimitive(className) == true )
+      if (isPrimitive(className) == true)
          return (Class) Classes.PRIMITIVE_NAME_TYPE_MAP.get(className);
 
       // Check for the internal vm format: Lclassname;
       if (className.charAt(0) == 'L' && className.charAt(className.length() - 1) == ';')
          return classLoader.loadClass(className.substring(1, className.length() - 1));
-      
+
       // first try - be optimistic
       // this will succeed for all non-array classes and array classes that have already been resolved
       //
@@ -364,17 +471,17 @@
          if (className.charAt(0) != '[')
             throw e;
       }
-   
+
       // we are now resolving array class for the first time
-      
+
       // count opening braces
       int arrayDimension = 0;
       while (className.charAt(arrayDimension) == '[')
          arrayDimension++;
-            
+
       // resolve component type - use recursion so that we can resolve primitive types also
       Class componentType = loadClass(className.substring(arrayDimension), classLoader);
-      
+
       // construct array class
       return Array.newInstance(componentType, new int[arrayDimension]).getClass();
    }
@@ -391,9 +498,7 @@
     * @throws ClassNotFoundException When a class could not be loaded from
     *         the specified ClassLoader
     */
-   public final static Class[] convertToJavaClasses(Iterator it,
-      ClassLoader cl)
-      throws ClassNotFoundException
+   public final static Class[] convertToJavaClasses(Iterator it, ClassLoader cl) throws ClassNotFoundException
    {
       ArrayList classes = new ArrayList();
       while (it.hasNext())
@@ -427,7 +532,8 @@
    public final static Method getAttributeSetter(Class cls, String attr, Class type) throws NoSuchMethodException
    {
       String setterName = "set" + Character.toUpperCase(attr.charAt(0)) + attr.substring(1);
-      return cls.getMethod(setterName, new Class[]{type});
+      return cls.getMethod(setterName, new Class[]
+      {type});
    }
 
    /**
@@ -441,9 +547,7 @@
     * @throws ClassNotFoundException When the class could not be found by
     *         the specified ClassLoader
     */
-   private final static Class convertToJavaClass(String name,
-      ClassLoader cl)
-      throws ClassNotFoundException
+   private final static Class convertToJavaClass(String name, ClassLoader cl) throws ClassNotFoundException
    {
       int arraySize = 0;
       while (name.endsWith("[]"))
@@ -464,8 +568,7 @@
          }
          catch (ClassNotFoundException cnfe)
          {
-            throw new ClassNotFoundException("Parameter class not found: " +
-               name);
+            throw new ClassNotFoundException("Parameter class not found: " + name);
          }
       }
 
@@ -486,5 +589,5 @@
 }
 
 /*
-vim:ts=3:sw=3:et
-*/
+ vim:ts=3:sw=3:et
+ */

Modified: branches/JBoss_4_0_3_SP1_JBAS-4497/jmx/src/main/javax/management/timer/Timer.java
===================================================================
--- branches/JBoss_4_0_3_SP1_JBAS-4497/jmx/src/main/javax/management/timer/Timer.java	2007-06-23 12:48:50 UTC (rev 63624)
+++ branches/JBoss_4_0_3_SP1_JBAS-4497/jmx/src/main/javax/management/timer/Timer.java	2007-06-23 18:53:19 UTC (rev 63625)
@@ -1,9 +1,25 @@
 /*
-* JBoss, the OpenSource EJB server
-*
-* Distributable under LGPL license.
-* See terms of license at gnu.org.
-*/
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
 package javax.management.timer;
 
 import java.util.Date;
@@ -17,184 +33,185 @@
 import javax.management.NotificationBroadcasterSupport;
 import javax.management.ObjectName;
 
+import org.jboss.logging.Logger;
 import org.jboss.mx.util.RunnableScheduler;
 import org.jboss.mx.util.SchedulableRunnable;
-import org.jboss.logging.Logger;
 
 /**
  * The timer service.
  *
  * @author <a href="mailto:Adrian.Brock at HappeningTimes.com">Adrian Brock</a>
+ * @author <a href="mailto:dimitris at jboss.org">Dimitris Andreadis</a>
  * @version $Revision$
  */
-public class Timer
-  extends NotificationBroadcasterSupport
-  implements TimerMBean, MBeanRegistration
+public class Timer extends NotificationBroadcasterSupport implements TimerMBean, MBeanRegistration
 {
    // logging support
    private static Logger log = Logger.getLogger(Timer.class);
 
-  // Constants -----------------------------------------------------
+   // Constants -----------------------------------------------------
 
-  /**
-   * The number of milliseconds in one second.
-   */
-  public static final long ONE_SECOND = 1000;
+   /** The number of milliseconds in one second. */
+   public static final long ONE_SECOND = 1000;
 
-  /**
-   * The number of milliseconds in one minute.
-   */
-  public static final long ONE_MINUTE = ONE_SECOND * 60;
+   /** The number of milliseconds in one minute. */
+   public static final long ONE_MINUTE = ONE_SECOND * 60;
 
-  /**
-   * The number of milliseconds in one hour.
-   */
-  public static final long ONE_HOUR = ONE_MINUTE * 60;
+   /** The number of milliseconds in one hour. */
+   public static final long ONE_HOUR = ONE_MINUTE * 60;
 
-  /**
-   * The number of milliseconds in one day.
-   */
-  public static final long ONE_DAY = ONE_HOUR * 24;
+   /** The number of milliseconds in one day. */
+   public static final long ONE_DAY = ONE_HOUR * 24;
 
-  /**
-   * The number of milliseconds in one week.
-   */
-  public static final long ONE_WEEK = ONE_DAY * 7;
+   /** The number of milliseconds in one week. */
+   public static final long ONE_WEEK = ONE_DAY * 7;
 
-  /**
-   * Don't send notifications at initial start up.
-   */
-  private static final int SEND_NO = 0;
+   /** Don't send notifications at initial start up. */
+   private static final int SEND_NO = 0;
 
-  /**
-   * Send all past notifications at initial start up.
-   */
-  private static final int SEND_START = 1;
+   /** Send all past notifications at initial start up. */
+   private static final int SEND_START = 1;
 
-  /**
-   * Normal operation sending
-   */
-  private static final int SEND_NORMAL = 2;
+   /** Normal operation sending */
+   private static final int SEND_NORMAL = 2;
 
-  // Attributes ----------------------------------------------------
+   // Attributes ----------------------------------------------------
 
-  /**
-   * The next notification id.
-   */
-  int nextId = 0;
+   /** The next notification id. */
+   int nextId = 0;
 
-  /**
-   * The next notification sequence number.
-   */
-  long sequenceNumber = 0;
+   /** The next notification sequence number. */
+   long sequenceNumber = 0;
 
-  /**
-   * The send past events attribute.
-   */
-  boolean sendPastNotifications = false;
+   /** The send past events attribute. */
+   boolean sendPastNotifications = false;
 
-  /**
-   * Whether the service is active.
-   */
-  boolean active = false;
+   /** Whether the service is active. */
+   boolean active = false;
 
-  /**
-   * Our object name.
-   */
-  ObjectName objectName;
+   /** Our object name. */
+   ObjectName objectName;
 
-  /**
-   * The registered notifications.
-   */
-  HashMap notifications = new HashMap();
+   /** The registered notifications. */
+   HashMap notifications = new HashMap();
 
-  /**
-   * The scheduler
-   */
-  private RunnableScheduler scheduler = new RunnableScheduler();
+   /** The scheduler */
+   private RunnableScheduler scheduler = new RunnableScheduler();
 
-  // Static --------------------------------------------------------
+   /** When addNotification is called without specifying fixedRate should we default to fixedDelay? */
+   private boolean defaultFixedDelay = false;
 
-  // Constructors --------------------------------------------------
+   // Static --------------------------------------------------------
 
-  // Public --------------------------------------------------------
+   // Constructors --------------------------------------------------
+   public Timer()
+   {
+      String fixedDelayProperty = System
+            .getProperty("jboss.jmx.timer.fixed_delay", Boolean.toString(defaultFixedDelay));
+      defaultFixedDelay = Boolean.valueOf(fixedDelayProperty).booleanValue();
+   }
 
-  // TimerMBean implementation -------------------------------------
+   // Public --------------------------------------------------------
 
-  public Integer addNotification(String type, String message, Object userData,
-                                 Date date)
-    throws IllegalArgumentException
-  {
-    return addNotification(type, message, userData, date, 0);
-  }
+   // TimerMBean implementation -------------------------------------
 
-  public Integer addNotification(String type, String message, Object userData,
-                                 Date date, long period)
-    throws IllegalArgumentException
-  {
-    return addNotification(type, message, userData, date, period, 0);
-  }
+   public Integer addNotification(String type, String message, Object userData, Date date)
+         throws IllegalArgumentException
+   {
+      return addNotification(type, message, userData, date, 0);
+   }
 
-  public Integer addNotification(String type, String message,
-                Object userData, Date date, long period, long occurences)
-    throws IllegalArgumentException
-  {
-     // Generate the next id.
-    int newId = 0;
-    newId = ++nextId;
-    Integer id = new Integer(newId);
+   public Integer addNotification(String type, String message, Object userData, Date date, long period)
+         throws IllegalArgumentException
+   {
+      return addNotification(type, message, userData, date, period, 0);
+   }
 
-    // Validate and create the registration.
-    RegisteredNotification rn =
-      new RegisteredNotification(id, type, message, userData, date, period,
-                                 occurences);
+   public Integer addNotification(String type, String message, Object userData, Date date, long period, long occurences)
+         throws IllegalArgumentException
+   {
+      return addNotification(type, message, userData, date, period, occurences, !defaultFixedDelay);
+   }
 
-    // Add the registration.
-    synchronized(notifications)
-    {
-       notifications.put(id, rn);
-       rn.setNextRun(rn.nextDate);
-       rn.setScheduler(scheduler);
-    }
+   /**
+    * Creates a new timer notification with the specified type, message and userData and inserts it into the list of notifications with a given date, period and number of occurences.
+    * <p/>
+    * If the timer notification to be inserted has a date that is before the current date, the method behaves as if the specified date were the current date.
+    * For once-off notifications, the notification is delivered immediately.
+    * For periodic notifications, the first notification is delivered immediately and the subsequent ones are spaced as specified by the period parameter.
+    * <p/>
+    * Note that once the timer notification has been added into the list of notifications, its associated date, period and number of occurences cannot be updated.
+    * <p/>
+    * In the case of a periodic notification, the value of parameter fixedRate is used to specify the execution scheme, as specified in Timer.
+    *
+    * @param type         The timer notification type.
+    * @param message      The timer notification detailed message.
+    * @param userData     The timer notification user data object.
+    * @param date         The date when the notification occurs.
+    * @param period       The period of the timer notification (in milliseconds).
+    * @param nbOccurences The total number the timer notification will be emitted.
+    * @param fixedRate    If true and if the notification is periodic, the notification is scheduled with a fixed-rate execution scheme. If false and if the notification is periodic, the notification is scheduled with a fixed-delay execution scheme. Ignored if the notification is not periodic.
+    * @return The identifier of the new created timer notification.
+    * @throws IllegalArgumentException The period or the number of occurences is negative
+    */
+   public Integer addNotification(String type, String message, Object userData, Date date, long period,
+         long nbOccurences, boolean fixedRate) throws IllegalArgumentException
+   {
+      // Generate the next id.
+      int newId = 0;
+      newId = ++nextId;
+      Integer id = new Integer(newId);
 
-    return id;
-  }
+      // Validate and create the registration.
+      RegisteredNotification rn = new RegisteredNotification(id, type, message, userData, date, period, nbOccurences,
+            fixedRate);
 
-  public Vector getAllNotificationIDs()
-  {
-     synchronized(notifications)
-     {
-        return new Vector(notifications.keySet());
-     }
-  }
+      // Add the registration.
+      synchronized (notifications)
+      {
+         notifications.put(id, rn);
+         rn.setNextRun(rn.nextDate);
+         rn.setScheduler(scheduler);
+      }
 
-  public Date getDate(Integer id)
-  {
-    // Make sure there is a registration
-    RegisteredNotification rn = (RegisteredNotification) notifications.get(id);
-    if (rn == null)
-      return null;
+      return id;
+   }
 
-    // Return a copy of the date.
-    return new Date(rn.startDate);
-  }
+   public Vector getAllNotificationIDs()
+   {
+      synchronized (notifications)
+      {
+         return new Vector(notifications.keySet());
+      }
+   }
 
-  public int getNbNotifications()
-  {
-    return notifications.size();
-  }
+   public Date getDate(Integer id)
+   {
+      // Make sure there is a registration
+      RegisteredNotification rn = (RegisteredNotification) notifications.get(id);
+      if (rn == null)
+         return null;
 
-  public Long getNbOccurences(Integer id)
-  {
-    // Make sure there is a registration
-    RegisteredNotification rn = (RegisteredNotification) notifications.get(id);
-    if (rn == null)
-      return null;
+      // Return a copy of the date.
+      return new Date(rn.startDate);
+   }
 
-    // Return a copy of the occurences.
-    return new Long(rn.occurences);
-  }
+   public int getNbNotifications()
+   {
+      return notifications.size();
+   }
 
+   public Long getNbOccurences(Integer id)
+   {
+      // Make sure there is a registration
+      RegisteredNotification rn = (RegisteredNotification) notifications.get(id);
+      if (rn == null)
+         return null;
+
+      // Return a copy of the occurences.
+      return new Long(rn.occurences);
+   }
+
    /**
     * Gets a copy of the flag indicating whether a peridic notification is executed at fixed-delay or at fixed-rate.
     *
@@ -203,158 +220,159 @@
     */
    public Boolean getFixedRate(Integer id)
    {
-      //[todo] implement getFixedRate
-      throw new RuntimeException("NYI");
+      // Make sure there is a registration
+      RegisteredNotification rn = (RegisteredNotification) notifications.get(id);
+      if (rn == null)
+         return null;
+
+      // Return a copy of the fixedRate
+      return new Boolean(rn.fixedRate);
    }
 
    public Vector getNotificationIDs(String type)
-  {
-    Vector result = new Vector();
+   {
+      Vector result = new Vector();
 
-    // Loop through the notifications looking for the passed type.
-    synchronized (notifications)
-    {
-       Iterator iterator = notifications.values().iterator();
-       while (iterator.hasNext())
-       {
-          RegisteredNotification rn = (RegisteredNotification) iterator.next();
-          if (rn.type.equals(type))
-             result.add(rn.id);
-       }
-    }
-      
-    return result;
-  }
+      // Loop through the notifications looking for the passed type.
+      synchronized (notifications)
+      {
+         Iterator iterator = notifications.values().iterator();
+         while (iterator.hasNext())
+         {
+            RegisteredNotification rn = (RegisteredNotification) iterator.next();
+            if (rn.type.equals(type))
+               result.add(rn.id);
+         }
+      }
 
-  public String getNotificationMessage(Integer id)
-  {
-    // Make sure there is a registration
-    RegisteredNotification rn = (RegisteredNotification) notifications.get(id);
-    if (rn == null)
-      return null;
+      return result;
+   }
 
-    // Return the message
-    return rn.message;
-  }
+   public String getNotificationMessage(Integer id)
+   {
+      // Make sure there is a registration
+      RegisteredNotification rn = (RegisteredNotification) notifications.get(id);
+      if (rn == null)
+         return null;
 
-  public String getNotificationType(Integer id)
-  {
-    // Make sure there is a registration
-    RegisteredNotification rn = (RegisteredNotification) notifications.get(id);
-    if (rn == null)
-      return null;
+      // Return the message
+      return rn.message;
+   }
 
-    // Return the type.
-    return rn.type;
-  }
+   public String getNotificationType(Integer id)
+   {
+      // Make sure there is a registration
+      RegisteredNotification rn = (RegisteredNotification) notifications.get(id);
+      if (rn == null)
+         return null;
 
-  public Object getNotificationUserData(Integer id)
-  {
-    // Make sure there is a registration
-    RegisteredNotification rn = (RegisteredNotification) notifications.get(id);
-    if (rn == null)
-      return null;
+      // Return the type.
+      return rn.type;
+   }
 
-    // Return the user data.
-    return rn.userData;
-  }
+   public Object getNotificationUserData(Integer id)
+   {
+      // Make sure there is a registration
+      RegisteredNotification rn = (RegisteredNotification) notifications.get(id);
+      if (rn == null)
+         return null;
 
-  public Long getPeriod(Integer id)
-  {
-    // Make sure there is a registration
-    RegisteredNotification rn = (RegisteredNotification) notifications.get(id);
-    if (rn == null)
-      return null;
+      // Return the user data.
+      return rn.userData;
+   }
 
-    // Return a copy of the period
-    return new Long(rn.period);
-  }
+   public Long getPeriod(Integer id)
+   {
+      // Make sure there is a registration
+      RegisteredNotification rn = (RegisteredNotification) notifications.get(id);
+      if (rn == null)
+         return null;
 
-  public boolean getSendPastNotifications()
-  {
-    return sendPastNotifications;
-  }
+      // Return a copy of the period
+      return new Long(rn.period);
+   }
 
-  public boolean isActive()
-  {
-    return active;
-  }
+   public boolean getSendPastNotifications()
+   {
+      return sendPastNotifications;
+   }
 
-  public boolean isEmpty()
-  {
-    return notifications.isEmpty();
-  }
+   public boolean isActive()
+   {
+      return active;
+   }
 
-  public void removeAllNotifications()
-  {
-    // Remove the notifications
-    synchronized(notifications)
-    {
-       Iterator iterator = notifications.values().iterator();
-       while (iterator.hasNext())
-       {
-          RegisteredNotification rn = (RegisteredNotification) iterator.next();
-          rn.setScheduler(null);
-          iterator.remove();
-       }
-    }
+   public boolean isEmpty()
+   {
+      return notifications.isEmpty();
+   }
 
-    // The spec says to reset the identifiers, seems like a bad idea to me
-    synchronized (this)
-    {
-       nextId = 0;
-    }
-  }
+   public void removeAllNotifications()
+   {
+      // Remove the notifications
+      synchronized (notifications)
+      {
+         Iterator iterator = notifications.values().iterator();
+         while (iterator.hasNext())
+         {
+            RegisteredNotification rn = (RegisteredNotification) iterator.next();
+            rn.setScheduler(null);
+            iterator.remove();
+         }
+      }
 
-  public void removeNotification(Integer id)
-    throws InstanceNotFoundException
-  {
+      // The spec says to reset the identifiers, seems like a bad idea to me
+      synchronized (this)
+      {
+         nextId = 0;
+      }
+   }
 
-     log.debug("removeNotification: " + objectName + ",id=" + id);
+   public void removeNotification(Integer id) throws InstanceNotFoundException
+   {
 
-    // Check if there is a notification.
-    synchronized(notifications)
-    {
-       RegisteredNotification rn = (RegisteredNotification) notifications.get(id);
-       if (rn == null)
-         throw new InstanceNotFoundException("No notification id : " +
-                                          id.toString());
+      log.debug("removeNotification: " + objectName + ",id=" + id);
 
-       // Remove the notification
-       rn.setScheduler(null);
-       notifications.remove(id);
-    }
-  }
+      // Check if there is a notification.
+      synchronized (notifications)
+      {
+         RegisteredNotification rn = (RegisteredNotification) notifications.get(id);
+         if (rn == null)
+            throw new InstanceNotFoundException("No notification id : " + id.toString());
 
-  public void removeNotifications(String type)
-    throws InstanceNotFoundException
-  {
-    boolean found = false;
+         // Remove the notification
+         rn.setScheduler(null);
+         notifications.remove(id);
+      }
+   }
 
-     log.debug("removeNotifications: " + objectName + ",type=" + type);
+   public void removeNotifications(String type) throws InstanceNotFoundException
+   {
+      boolean found = false;
 
-    // Loop through the notifications removing the passed type.
-    synchronized(notifications)
-    {
-       Iterator iterator = notifications.values().iterator();
-       while (iterator.hasNext())
-       {
-          RegisteredNotification rn = (RegisteredNotification) iterator.next();
-          if (rn.type.equals(type))
-          {
-             rn.setScheduler(null);
-             iterator.remove();
-             found = true;
-          }
-       }
-    }
+      log.debug("removeNotifications: " + objectName + ",type=" + type);
 
-    // The spec says to through an exception when nothing removed.
-    if (found == false)
-      throw new InstanceNotFoundException("Nothing registered for type: " +
-                                          type);
-  }
+      // Loop through the notifications removing the passed type.
+      synchronized (notifications)
+      {
+         Iterator iterator = notifications.values().iterator();
+         while (iterator.hasNext())
+         {
+            RegisteredNotification rn = (RegisteredNotification) iterator.next();
+            if (rn.type.equals(type))
+            {
+               rn.setScheduler(null);
+               iterator.remove();
+               found = true;
+            }
+         }
+      }
 
+      // The spec says to through an exception when nothing removed.
+      if (found == false)
+         throw new InstanceNotFoundException("Nothing registered for type: " + type);
+   }
+
    public void setSendPastNotifications(boolean value)
    {
       log.debug("setSendPastNotifications: " + objectName + ",value=" + value);
@@ -391,284 +409,248 @@
       scheduler.start();
    }
 
-  public synchronized void stop()
-  {
-    // Ignore if not active
-    if (active == false)
-      return;
+   public synchronized void stop()
+   {
+      // Ignore if not active
+      if (active == false)
+         return;
 
-     log.debug("stop: " + objectName + ",now=" + new Date());
+      log.debug("stop: " + objectName + ",now=" + new Date());
 
-    // Stop the threads
-    active = false;
-    scheduler.stop();
-  }
-
-   /**
-    * Creates a new timer notification with the specified type, message and userData and inserts it into the list of notifications with a given date, period and number of occurences.
-    * <p/>
-    * If the timer notification to be inserted has a date that is before the current date, the method behaves as if the specified date were the current date.
-    * For once-off notifications, the notification is delivered immediately.
-    * For periodic notifications, the first notification is delivered immediately and the subsequent ones are spaced as specified by the period parameter.
-    * <p/>
-    * Note that once the timer notification has been added into the list of notifications, its associated date, period and number of occurences cannot be updated.
-    * <p/>
-    * In the case of a periodic notification, the value of parameter fixedRate is used to specify the execution scheme, as specified in Timer.
-    *
-    * @param type         The timer notification type.
-    * @param message      The timer notification detailed message.
-    * @param userData     The timer notification user data object.
-    * @param date         The date when the notification occurs.
-    * @param period       The period of the timer notification (in milliseconds).
-    * @param nbOccurences The total number the timer notification will be emitted.
-    * @param fixedRate    If true and if the notification is periodic, the notification is scheduled with a fixed-rate execution scheme. If false and if the notification is periodic, the notification is scheduled with a fixed-delay execution scheme. Ignored if the notification is not periodic.
-    * @return The identifier of the new created timer notification.
-    * @throws IllegalArgumentException The period or the number of occurences is negative
-    */
-   public Integer addNotification(String type, String message, Object userData, Date date, long period, long nbOccurences, boolean fixedRate) throws IllegalArgumentException
-   {
-      // [todo] implement addNotification
-      throw new RuntimeException("NYI");
+      // Stop the threads
+      active = false;
+      scheduler.stop();
    }
 
    // MBeanRegistrationImplementation overrides ---------------------
 
-  public ObjectName preRegister(MBeanServer server, ObjectName objectName)
-    throws Exception
-  {
-    // Save the object name
-    this.objectName = objectName;
+   public ObjectName preRegister(MBeanServer server, ObjectName objectName) throws Exception
+   {
+      // Save the object name
+      this.objectName = objectName;
 
-    // Use the passed object name.
-    return objectName;
-  }
+      // Use the passed object name.
+      return objectName;
+   }
 
-  public void postRegister(Boolean registrationDone)
-  {
-  }
+   public void postRegister(Boolean registrationDone)
+   {
+   }
 
-  public void preDeregister()
-    throws Exception
-  {
-    // Stop the timer before deregistration.
-    stop();
-  }
+   public void preDeregister() throws Exception
+   {
+      // Stop the timer before deregistration.
+      stop();
+   }
 
-  public void postDeregister()
-  {
-  }
+   public void postDeregister()
+   {
+   }
 
-  // Package protected ---------------------------------------------
+   // Package protected ---------------------------------------------
 
-  // Protected -----------------------------------------------------
+   // Protected -----------------------------------------------------
 
-  // Private -------------------------------------------------------
+   // Private -------------------------------------------------------
 
-  /**
-   * Send any outstanding notifications.
-   *
-   * @param rn the registered notification to send.
-   */
-  private void sendNotifications(RegisteredNotification rn)
-  {
-     // Keep going until we have done all outstanding notifications.
-     // The loop ends when not active, or there are no outstanding
-     // notifications.
-     // REVIEW: In practice for normal operation it never loops. We
-     // ignore sends that we have missed. This avoids problems where
-     // the notification takes longer than the period. Correct???
-     while (isActive() && rn.nextDate != 0
-             && rn.nextDate <= System.currentTimeMillis())
-     {
-        // Do we actually send it?
-        // Yes, unless start and not sending past notifications.
-        if (rn.sendType != SEND_NO)
-        {
-           long seq = 0;
-           synchronized (this)
-           {
-              seq = ++sequenceNumber;
-           }
+   /**
+    * Send any outstanding notifications.
+    *
+    * @param rn the registered notification to send.
+    */
+   private void sendNotifications(RegisteredNotification rn)
+   {
+      // Keep going until we have done all outstanding notifications.
+      // The loop ends when not active, or there are no outstanding
+      // notifications.
+      // REVIEW: In practice for normal operation it never loops. We
+      // ignore sends that we have missed. This avoids problems where
+      // the notification takes longer than the period. Correct???
+      while (isActive() && rn.nextDate != 0 && rn.nextDate <= System.currentTimeMillis())
+      {
+         // Do we actually send it?
+         // Yes, unless start and not sending past notifications.
+         if (rn.sendType != SEND_NO)
+         {
+            long seq = 0;
+            synchronized (this)
+            {
+               seq = ++sequenceNumber;
+            }
 
-           log.debug("sendNotification: " + rn);
-           TimerNotification tn = new TimerNotification(rn.type, objectName,
-              seq, rn.nextDate, rn.message, rn.id);
-           tn.setUserData(rn.userData);
-           sendNotification(tn);
-        }
-        // Calculate the next date.
-        // Except for when we are sending past notifications at start up,
-        // it cannot be in the future.
-        do
-        {
-           // If no next run, remove it sets the next date to zero.
-           if (rn.calcNextDate() == false)
-           {
-              synchronized (notifications)
-              {
-                 log.debug("remove: " + rn);
-                 notifications.remove(rn.id);
-              }
-           }
-        }
-        while (isActive() && rn.sendType != SEND_START && rn.nextDate != 0
-                && rn.occurences == 0 && rn.nextDate < System.currentTimeMillis());
-     }
+            log.debug("sendNotification: " + rn);
+            TimerNotification tn = new TimerNotification(rn.type, objectName, seq, rn.nextDate, rn.message, rn.id);
+            tn.setUserData(rn.userData);
+            sendNotification(tn);
+         }
+         // Calculate the next date.
+         // Except for when we are sending past notifications at start up,
+         // it cannot be in the future.
+         do
+         {
+            // If no next run, remove it sets the next date to zero.
+            if (rn.calcNextDate() == false)
+            {
+               synchronized (notifications)
+               {
+                  log.debug("remove: " + rn);
+                  notifications.remove(rn.id);
+               }
+            }
+         }
+         while (isActive() && rn.sendType != SEND_START && rn.nextDate != 0 && rn.occurences == 0
+               && rn.nextDate < System.currentTimeMillis());
+      }
 
-     if (rn.nextDate != 0)
-        rn.setNextRun(rn.nextDate);
-  }
+      if (rn.nextDate != 0)
+         rn.setNextRun(rn.nextDate);
+   }
 
-  // Inner classes -------------------------------------------------
+   // Inner classes -------------------------------------------------
 
-  /**
-   * A registered notification. These run as separate threads.
-   */
-  private class RegisteredNotification
-    extends SchedulableRunnable
-  {
-    // Attributes ----------------------------------------------------
+   /**
+    * A registered notification. These run as separate threads.
+    */
+   private class RegisteredNotification extends SchedulableRunnable
+   {
+      // Attributes ----------------------------------------------------
 
-    /**
-     * The notification id.
-     */
-    public Integer id;
+      /** The notification id. */
+      public Integer id;
 
-    /**
-     * The notification type.
-     */
-    public String type;
+      /** The notification type. */
+      public String type;
 
-    /**
-     * The message.
-     */
-    public String message;
+      /** The message. */
+      public String message;
 
-    /**
-     * The user data.
-     */
-    public Object userData;
+      /** The user data. */
+      public Object userData;
 
-    /**
-     * The start date.
-     */
-    public long startDate;
+      /** The start date. */
+      public long startDate;
 
-    /**
-     * The period.
-     */
-    public long period;
+      /** The period. */
+      public long period;
 
-    /**
-     * The maximum number of occurences.
-     */
-    public long occurences;
+      /** The maximum number of occurences. */
+      public long occurences;
 
-    /**
-     * The send type, no send, past notifications or normal
-     */
-    public int sendType = SEND_NORMAL;
+      /** The flag to indicate fixedRate notifications, or fixedDelay (default) */
+      public boolean fixedRate;
 
-    /**
-     * The next run date
-     */
-    public long nextDate = 0;
+      /** The send type, no send, past notifications or normal */
+      public int sendType = SEND_NORMAL;
 
-    // Constructors --------------------------------------------------
+      /** The next run date */
+      public long nextDate = 0;
 
-    /**
-     * The default constructor.
-     *
-     * @param id the notification id.
-     * @param type the notification type.
-     * @param message the notification's message string.
-     * @param userData the notification's user data.
-     * @param startDate the date/time the notification will occur.
-     * @param period the repeat period in milli-seconds. Passing zero means
-     *        no repeat.
-     * @param occurences the maximum number of repeats. When the period is not
-     *        zero and this parameter is zero, it will repeat indefinitely.
-     * @exception IllegalArgumentException when the date is before the current
-     *        date, the period is negative or the number of repeats is
-     *        negative.
-     */
-    public RegisteredNotification(Integer id, String type, String message, Object userData, Date startDate, long period, long occurences)
-            throws IllegalArgumentException
-    {
-       // Basic validation
-       if (startDate == null)
-          throw new IllegalArgumentException("Null Date");
-       if (period < 0)
-          throw new IllegalArgumentException("Negative Period");
-       if (occurences < 0)
-          throw new IllegalArgumentException("Negative Occurences");
+      // Constructors --------------------------------------------------
 
-       this.startDate = startDate.getTime();
-       if (startDate.getTime() < System.currentTimeMillis())
-       {
-          log.warn("startDate [" + startDate + "] in the past, set to now");
-          this.startDate = System.currentTimeMillis();
-       }
+      /**
+       * The default constructor.
+       *
+       * @param id the notification id.
+       * @param type the notification type.
+       * @param message the notification's message string.
+       * @param userData the notification's user data.
+       * @param startDate the date/time the notification will occur.
+       * @param period the repeat period in milli-seconds. Passing zero means
+       *        no repeat.
+       * @param occurences the maximum number of repeats. When the period is not
+       *        zero and this parameter is zero, it will repeat indefinitely.
+       * @param fixedRate If true and if the notification is periodic, the notification
+       *        is scheduled with a fixed-rate execution scheme. If false and if the notification
+       *        is periodic, the notification is scheduled with a fixed-delay execution scheme.
+       *        Ignored if the notification is not periodic.
+       *
+       * @exception IllegalArgumentException when the date is before the current
+       *        date, the period is negative or the number of repeats is
+       *        negative.
+       */
+      public RegisteredNotification(Integer id, String type, String message, Object userData, Date startDate,
+            long period, long occurences, boolean fixedRate) throws IllegalArgumentException
+      {
+         // Basic validation
+         if (startDate == null)
+            throw new IllegalArgumentException("Null Date");
+         if (period < 0)
+            throw new IllegalArgumentException("Negative Period");
+         if (occurences < 0)
+            throw new IllegalArgumentException("Negative Occurences");
 
-       // Remember the values
-       this.id = id;
-       this.type = type;
-       this.message = message;
-       this.userData = userData;
-       this.period = period;
-       this.occurences = occurences;
+         this.startDate = startDate.getTime();
+         if (startDate.getTime() < System.currentTimeMillis())
+         {
+            log.debug("startDate [" + startDate + "] in the past, set to now");
+            this.startDate = System.currentTimeMillis();
+         }
 
-       this.nextDate = this.startDate;
+         // Remember the values
+         this.id = id;
+         this.type = type;
+         this.message = message;
+         this.userData = userData;
+         this.period = period;
+         this.occurences = occurences;
+         this.fixedRate = fixedRate;
 
-       String msgStr = "new " + this.toString();
-       log.debug(msgStr);
-    }
+         this.nextDate = this.startDate;
 
-     // Public --------------------------------------------------------
+         String msgStr = "new " + this.toString();
+         log.debug(msgStr);
+      }
 
-     /**
-      * Calculate the next notification date. Add on the period until
-      * the number of occurences is exhausted.
-      *
-      * @return false when there are no more occurences, true otherwise.
-      */
-     boolean calcNextDate()
-     {
-        // No period, we've finished
-        if (period == 0)
-        {
-           nextDate = 0;
-           return false;
-        }
+      // Public --------------------------------------------------------
 
-        // Limited number of repeats have we finished?
-        if (occurences != 0 && --occurences == 0)
-        {
-           nextDate = 0;
-           return false;
-        }
+      /**
+       * Calculate the next notification date. Add on the period until
+       * the number of occurences is exhausted.
+       *
+       * @return false when there are no more occurences, true otherwise.
+       */
+      boolean calcNextDate()
+      {
+         // No period, we've finished
+         if (period == 0)
+         {
+            nextDate = 0;
+            return false;
+         }
 
-        // Calculate the next occurence
-        nextDate += period;
+         // Limited number of repeats have we finished?
+         if (occurences != 0 && --occurences == 0)
+         {
+            nextDate = 0;
+            return false;
+         }
 
-        return true;
-     }
+         // Calculate the next occurence
+         if (fixedRate)
+            nextDate += period;
+         else
+            // fixed delay
+            nextDate = System.currentTimeMillis() + period;
 
-     // SchedulableRunnable overrides ---------------------------------
+         return true;
+      }
 
-     /**
-      * Send the notifications.
-      */
-     public void doRun()
-     {
-        // Send any notifications
-        sendNotifications(this);
-     }
+      // SchedulableRunnable overrides ---------------------------------
 
-     public String toString()
-     {
-        return " RegisteredNotification: [timer=" + objectName + ",id=" + id + ",startDate=" + new Date(startDate) +
-                ",periode=" + period + ",occurences=" + occurences + ",nextDate=" + new Date(nextDate) + "]";
-     }
-  }
+      /**
+       * Send the notifications.
+       */
+      public void doRun()
+      {
+         // Send any notifications
+         sendNotifications(this);
+      }
+
+      public String toString()
+      {
+         return " RegisteredNotification: [timer=" + objectName + ",id=" + id + ",startDate=" + new Date(startDate)
+               + ",period=" + period + ",occurences=" + occurences + ",fixedRate=" + fixedRate + ",nextDate="
+               + new Date(nextDate) + "]";
+      }
+   }
 }

Modified: branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/imports/test-jars.xml
===================================================================
--- branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/imports/test-jars.xml	2007-06-23 12:48:50 UTC (rev 63624)
+++ branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/imports/test-jars.xml	2007-06-23 18:53:19 UTC (rev 63625)
@@ -61,6 +61,7 @@
       _jars-proxycompiler,
       _jars-readahead,
       _jars-retry,
+      _jars-scheduler,
       _jars-security,
       _jars-testbean,
       _jars-testbeancluster,
@@ -4273,6 +4274,43 @@
     </jar>
   </target>
 
+  <!-- scheduler test -->
+  <target name="_jars-scheduler">
+	
+  	<!-- JBAS-4497 -->
+  	<jar destfile="${build.lib}/scheduler-fixeddelay.sar">
+      <metainf dir="${build.resources}/scheduler/fixedDelay">
+        <include name="jboss-service.xml"/>     
+      </metainf>
+      <fileset dir="${build.classes}">
+        <include name="org/jboss/test/scheduler/ScheduleTask.class"/>
+        <include name="org/jboss/test/scheduler/ScheduleTracker.class"/>
+        <include name="org/jboss/test/scheduler/ScheduleTrackerMBean.class"/>
+      </fileset>  	  	
+  	</jar>
+  	<jar destfile="${build.lib}/scheduler-fixedrate.sar">
+      <metainf dir="${build.resources}/scheduler/fixedRate">
+        <include name="jboss-service.xml"/>     
+      </metainf>
+      <fileset dir="${build.classes}">
+        <include name="org/jboss/test/scheduler/ScheduleTask.class"/>
+        <include name="org/jboss/test/scheduler/ScheduleTracker.class"/>
+        <include name="org/jboss/test/scheduler/ScheduleTrackerMBean.class"/>
+      </fileset>  	  	
+  	</jar>
+  	<jar destfile="${build.lib}/scheduler-default.sar">
+  	  <metainf dir="${build.resources}/scheduler/default">
+  	    <include name="jboss-service.xml"/>     
+  	  </metainf>
+  	  <fileset dir="${build.classes}">
+  	    <include name="org/jboss/test/scheduler/ScheduleTask.class"/>
+  	    <include name="org/jboss/test/scheduler/ScheduleTracker.class"/>
+  	    <include name="org/jboss/test/scheduler/ScheduleTrackerMBean.class"/>
+  	  </fileset>  	  	
+  	</jar>  	
+      	
+  </target>
+	
   <!-- security test -->
   <target name="_jars-security">
     <mkdir dir="${build.lib}"/>

Copied: branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/main/org/jboss/test/jbossmx/compliance/timer/PeriodTestCase.java (from rev 46245, branches/Branch_4_0/jbosstest/src/main/org/jboss/test/jbossmx/compliance/timer/PeriodTestCase.java)
===================================================================
--- branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/main/org/jboss/test/jbossmx/compliance/timer/PeriodTestCase.java	                        (rev 0)
+++ branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/main/org/jboss/test/jbossmx/compliance/timer/PeriodTestCase.java	2007-06-23 18:53:19 UTC (rev 63625)
@@ -0,0 +1,316 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.test.jbossmx.compliance.timer;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Properties;
+
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.MBeanServerInvocationHandler;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+import javax.management.timer.TimerMBean;
+
+import org.jboss.test.jbossmx.compliance.TestCase;
+
+/**
+ * Test fixed-delay/fixed-rate timer execution modes.
+ * 
+ * Program a JMX timer to produce TIMES notifications, every PERIOD msces,
+ * with the initial notification after PERIOD msecs.
+ * 
+ * Introduce a fixed DELAY (<PERIOD) in the reception of the timer notification
+ * to slow it down. Measure the total time in both fixed-rate & fixed-delay
+ * scenarios and compare it with an expected value +/- an allowed percentage
+ * difference.
+ * 
+ * In fixed-rate mode the delay does not affect the periodic execution (because
+ * it's less than the period), so the expected total time is the number of repeatitions
+ * times the period, plus the final delay (because that one doesn't overlap with a period).
+ * 
+ * In fixed-delay mode things are simpler. The total execution time is prolonged because
+ * the period doesn't overlap with the execution/delay time, so the total time is
+ * period plus delay times the number of repeatitions.
+ * 
+ * The choice of numbers below makes sure that even with a 15% allowed difference
+ * there won't be any overlap in the fixed-rate/fixed-delay execution modes
+ * (i.e. one cannot be confused with the other)
+ * 
+ * @author Dimitris.Andreadis at jboss.org
+ * @version $Revision$
+ */
+public class PeriodTestCase extends TestCase implements NotificationListener
+{
+   private final long PERIOD = 300;
+
+   private final long DELAY = 200;
+
+   private final long TIMES = 5;
+
+   private final long FIXED_RATE_TOTAL = PERIOD * TIMES + DELAY;
+
+   private final long FIXED_DELAY_TOTAL = (PERIOD + DELAY) * TIMES;
+
+   private final long ALLOWED_DIFFERENCE = 15;
+
+   /** The object name of the timer service */
+   private ObjectName timerName;
+
+   /** The MBean server */
+   private MBeanServer server;
+
+   /** Test start time */
+   private long startTime;
+
+   /** The received notifications */
+   private ArrayList receivedNotifications = new ArrayList();
+
+   // Constructor ---------------------------------------------------------------
+
+   public PeriodTestCase(String s)
+   {
+      super(s);
+   }
+
+   // Tests ---------------------------------------------------------------------
+
+   /**
+    * By default to prevent breaking existing applications that depend on the incorrect behaviour under
+    * Java 1.4 this should be fixed rate but under Java 5.0 it should be fixed delay.
+    */
+   public void testDefaultDelay() throws Exception
+   {
+      try
+      {
+         startTimerService();
+         TimerMBean timer = (TimerMBean) MBeanServerInvocationHandler.newProxyInstance(server, timerName,
+               TimerMBean.class, false);
+
+         // calculate all times from now
+         startTime = System.currentTimeMillis();
+
+         timer.addNotification("timer.notification", null, null, new Date(startTime + PERIOD), PERIOD, TIMES);
+
+         long expectedDuration = FIXED_DELAY_TOTAL;
+         String javaVersion = System.getProperty("java.specification.version");
+
+         // Under Java 1.4 the test should pass with the old (faulty) default of fixed rate.
+         if ("1.4".equals(javaVersion))
+         {
+            expectedDuration = FIXED_RATE_TOTAL;
+         }
+
+         waitForNotifications(TIMES, expectedDuration * 2);
+
+         long testDuration = System.currentTimeMillis() - startTime;
+         checkTimeDifference(expectedDuration, testDuration, ALLOWED_DIFFERENCE);
+      }
+      finally
+      {
+         stopTimerService();
+      }
+   }
+
+   /**
+    * Test the jboss.jmx.timer.fixed_delay property that enables the new correct behaviour.
+    */
+   public void testFixedDelayProperty() throws Exception
+   {
+      try
+      {
+         System.setProperty("jboss.jmx.timer.fixed_delay", "true");
+         startTimerService();
+         
+         TimerMBean timer = (TimerMBean) MBeanServerInvocationHandler.newProxyInstance(server, timerName,
+               TimerMBean.class, false);
+
+         // calculate all times from now
+         startTime = System.currentTimeMillis();
+
+         timer.addNotification("timer.notification", null, null, new Date(startTime + PERIOD), PERIOD, TIMES);
+
+         long expectedDuration = FIXED_DELAY_TOTAL;
+         String javaVersion = System.getProperty("java.specification.version");
+
+         waitForNotifications(TIMES, expectedDuration * 2);
+
+         long testDuration = System.currentTimeMillis() - startTime;
+         checkTimeDifference(expectedDuration, testDuration, ALLOWED_DIFFERENCE);
+      }
+      finally
+      {
+         Properties props = System.getProperties();
+         props.remove("jboss.jmx.timer.fixed_delay");
+         System.setProperties(props);
+         stopTimerService();
+      }
+   }
+
+   /**
+    * Test the fixed-delay timer execution mode
+    */
+   public void testFixedDelay() throws Exception
+   {
+      try
+      {
+         startTimerService();
+         TimerMBean timer = (TimerMBean) MBeanServerInvocationHandler.newProxyInstance(server, timerName,
+               TimerMBean.class, false);
+
+         // calculate all times from now
+         startTime = System.currentTimeMillis();
+
+         // This must cause a fixed-delay timer notification production
+         // with TIMES notification produced, spaced at PERIOD msecs, starting in now+PERIOD 
+         timer.addNotification("timer.notification", null, null, new Date(startTime + PERIOD), PERIOD, TIMES, false);
+
+         long expectedDuration = FIXED_DELAY_TOTAL;
+         waitForNotifications(TIMES, expectedDuration * 2);
+
+         long testDuration = System.currentTimeMillis() - startTime;
+         checkTimeDifference(expectedDuration, testDuration, ALLOWED_DIFFERENCE);
+      }
+      finally
+      {
+         stopTimerService();
+      }
+   }
+
+   /**
+    * Test the fixed-rate timer execution mode
+    */
+   public void testFixedRate() throws Exception
+   {
+      try
+      {
+         startTimerService();
+         TimerMBean timer = (TimerMBean) MBeanServerInvocationHandler.newProxyInstance(server, timerName,
+               TimerMBean.class, false);
+
+         // calculate all times from now
+         startTime = System.currentTimeMillis();
+
+         // This must cause a fixed-rate timer notification production
+         // with TIMES notification produced, spaced at PERIOD msecs, starting in now+PERIOD 
+         timer.addNotification("timer.notification", null, null, new Date(startTime + PERIOD), PERIOD, TIMES, true);
+
+         long expectedDuration = FIXED_RATE_TOTAL;
+         waitForNotifications(TIMES, expectedDuration * 2);
+
+         long testDuration = System.currentTimeMillis() - startTime;
+         checkTimeDifference(expectedDuration, testDuration, ALLOWED_DIFFERENCE);
+      }
+      finally
+      {
+         stopTimerService();
+      }
+   }
+
+   public void handleNotification(Notification notification, Object handback)
+   {
+      try
+      {
+         long time = notification.getTimeStamp() - startTime;
+         long seqNo = notification.getSequenceNumber();
+         log.debug("#" + seqNo + " (" + time + "ms) - " + notification);
+
+         // cause an artifical delay
+         Thread.sleep(DELAY);
+      }
+      catch (InterruptedException ignore)
+      {
+      }
+
+      synchronized (receivedNotifications)
+      {
+         receivedNotifications.add(notification);
+
+         // Notify test completion
+         if (receivedNotifications.size() >= TIMES)
+            receivedNotifications.notifyAll();
+      }
+   }
+
+   // Support functions ---------------------------------------------------------
+
+   private void checkTimeDifference(long expected, long actual, long percentage)
+   {
+      long actualDiff = (actual - expected) * 100 / expected;
+      log.debug("Actual time: " + actual + " msec, expected time: " + expected + " msecs");
+      log.debug("Actual difference: " + actualDiff + "%, allowed: +/-" + percentage + "%");
+
+      long diff = Math.abs(expected - actual);
+      long maxDeviation = expected / percentage;
+
+      if (diff > maxDeviation)
+         fail("Time difference larger than " + percentage + "%");
+   }
+
+   private void waitForNotifications(long totalExpected, long wait) throws Exception
+   {
+      synchronized (receivedNotifications)
+      {
+         if (receivedNotifications.size() > totalExpected)
+            fail("too many notifications " + receivedNotifications.size());
+
+         if (receivedNotifications.size() < totalExpected)
+            receivedNotifications.wait(wait);
+      }
+      assertEquals(totalExpected, receivedNotifications.size());
+   }
+
+   /**
+    * Get an MBeanServer, install the timer service and a notification
+    * listener.
+    */
+   private void startTimerService() throws Exception
+   {
+      server = MBeanServerFactory.createMBeanServer("Timer");
+      timerName = new ObjectName("Timer:type=TimerService");
+      server.createMBean("javax.management.timer.Timer", timerName, new Object[0], new String[0]);
+      server.invoke(timerName, "start", new Object[0], new String[0]);
+      server.addNotificationListener(timerName, this, null, null);
+      receivedNotifications.clear();
+   }
+
+   /**
+    * Remove everything used by this test.
+    */
+   private void stopTimerService()
+   {
+      try
+      {
+         server.invoke(timerName, "removeAllNotifications", new Object[0], new String[0]);
+         server.invoke(timerName, "stop", new Object[0], new String[0]);
+         server.unregisterMBean(timerName);
+         MBeanServerFactory.releaseMBeanServer(server);
+         receivedNotifications.clear();
+      }
+      catch (Exception ignored)
+      {
+      }
+   }
+
+}
\ No newline at end of file

Added: branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/main/org/jboss/test/scheduler/BaseTest.java
===================================================================
--- branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/main/org/jboss/test/scheduler/BaseTest.java	                        (rev 0)
+++ branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/main/org/jboss/test/scheduler/BaseTest.java	2007-06-23 18:53:19 UTC (rev 63625)
@@ -0,0 +1,130 @@
+/* 
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.test.scheduler;
+
+import javax.management.MBeanServerConnection;
+import javax.management.MBeanServerInvocationHandler;
+import javax.management.ObjectName;
+
+import org.jboss.mq.selectors.ISelectorParser;
+import org.jboss.test.JBossTestCase;
+
+/**
+ * Base test case.
+ * 
+ * These test cases borrow from the PeriodTestCase written by Dimitris Andreadis
+ *
+ * @author <a href="mailto:darran.lofthouse at jboss.com">Darran Lofthouse</a>
+ * @version $Revision$
+ */
+public abstract class BaseTest extends JBossTestCase
+{
+
+   private static final long WAIT_TIME = 500L;
+
+   private final long PERIOD = 300;
+
+   private final long DELAY = 200;
+
+   private final long TIMES = 5;
+
+   private final long FIXED_RATE_TOTAL = PERIOD * (TIMES - 1);
+
+   private final long FIXED_DELAY_TOTAL = (PERIOD + DELAY) * (TIMES - 1);
+
+   private final long ALLOWED_DIFFERENCE = 15;
+
+   public BaseTest(String name)
+   {
+      super(name);
+   }
+
+   public ScheduleTrackerMBean getScheduleTracker() throws Exception
+   {
+      MBeanServerConnection server = getServer();
+      ObjectName trackerName = new ObjectName("test:name=ScheduleTracker");
+      return (ScheduleTrackerMBean) MBeanServerInvocationHandler.newProxyInstance(server, trackerName,
+            ScheduleTrackerMBean.class, false);
+   }
+
+   /**
+    * The test should wait until the timer has been called 3 times
+    * then check the time difference between the first and last calls
+    * to ensure it was either fixed rate or fixed  
+    */
+   public void testTimer() throws Exception
+   {
+      ScheduleTrackerMBean tracker = getScheduleTracker();
+
+      waitForInvocations(tracker);
+
+      long invocationDuration = tracker.getCallGap();
+
+      long expectedWait = getExpectedWaitTime();
+      checkTimeDifference(expectedWait, invocationDuration, ALLOWED_DIFFERENCE);
+
+   }
+
+   private void checkTimeDifference(long expected, long actual, long percentage)
+   {
+      long actualDiff = (actual - expected) * 100 / expected;
+      log.debug("Actual time: " + actual + " msec, expected time: " + expected + " msecs");
+      log.debug("Actual difference: " + actualDiff + "%, allowed: +/-" + percentage + "%");
+
+      long diff = Math.abs(expected - actual);
+      long maxDeviation = expected / percentage;
+
+      if (diff > maxDeviation)
+         fail("Time difference larger than " + percentage + "%");
+   }
+
+   private long getExpectedWaitTime() throws Exception
+   {
+      if (isTestFixedDelay())
+      {
+         return FIXED_DELAY_TOTAL;
+      }
+
+      return FIXED_RATE_TOTAL;
+   }
+
+   private void waitForInvocations(final ScheduleTrackerMBean tracker) throws Exception
+   {
+      int invocations = 0;
+      int loopCount = 0;
+      while (invocations < TIMES)
+      {
+         invocations = tracker.getInvocationCount();
+         Thread.sleep(WAIT_TIME);
+
+         if (loopCount++ > TIMES * 2)
+         {
+            throw new Exception("Waited too long for the invocations!!");
+         }
+      }
+
+   }
+
+   public abstract boolean isTestFixedDelay() throws Exception;
+
+}


Property changes on: branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/main/org/jboss/test/scheduler/BaseTest.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Added: branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/main/org/jboss/test/scheduler/ScheduleTask.java
===================================================================
--- branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/main/org/jboss/test/scheduler/ScheduleTask.java	                        (rev 0)
+++ branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/main/org/jboss/test/scheduler/ScheduleTask.java	2007-06-23 18:53:19 UTC (rev 63625)
@@ -0,0 +1,66 @@
+/* 
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.test.scheduler;
+
+import java.util.Date;
+
+import javax.management.MBeanServer;
+import javax.management.MBeanServerInvocationHandler;
+import javax.management.ObjectName;
+
+import org.jboss.logging.Logger;
+import org.jboss.mx.util.MBeanServerLocator;
+import org.jboss.varia.scheduler.Schedulable;
+
+/**
+ * The class to be called from the scheduler.
+ * 
+ * This class will be called 3 times in a test, this calls another MBean
+ * that will track the time between the calls and introduce a small delay 
+ * to test the difference between fixed rate and fixed delay.
+ *
+ * @author <a href="mailto:darran.lofthouse at jboss.com">Darran Lofthouse</a>
+ * @version $Revision$
+ */
+public class ScheduleTask implements Schedulable
+{
+
+   private static final Logger log = Logger.getLogger(ScheduleTask.class);
+
+   public void perform(Date pTimeOfCall, long pRemainingRepetitions)
+   {
+      try
+      {
+         MBeanServer server = MBeanServerLocator.locateJBoss();
+         ObjectName trackerName = new ObjectName("test:name=ScheduleTracker");
+         ScheduleTrackerMBean tracker = (ScheduleTrackerMBean) MBeanServerInvocationHandler.newProxyInstance(server,
+               trackerName, ScheduleTrackerMBean.class, false);
+         tracker.perform();
+      }
+      catch (Exception e)
+      {
+         log.error("Error in perform", e);
+      }
+   }
+
+}


Property changes on: branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/main/org/jboss/test/scheduler/ScheduleTask.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Added: branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/main/org/jboss/test/scheduler/ScheduleTracker.java
===================================================================
--- branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/main/org/jboss/test/scheduler/ScheduleTracker.java	                        (rev 0)
+++ branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/main/org/jboss/test/scheduler/ScheduleTracker.java	2007-06-23 18:53:19 UTC (rev 63625)
@@ -0,0 +1,92 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.test.scheduler;
+
+import org.jboss.logging.Logger;
+
+/**
+ * An MBean to track the invocations.
+ * 
+ * @author <a href="mailto:darran.lofthouse at jboss.com">Darran Lofthouse</a>
+ * @version $Revision$
+ */
+public class ScheduleTracker implements ScheduleTrackerMBean
+{
+
+   private static final long DELAY = 200;
+
+   private static final Logger log = Logger.getLogger(ScheduleTracker.class);
+
+   private int invocationCount = 0;
+
+   private long firstCall = -1;
+
+   private long lastCall = -1;
+
+   public int getInvocationCount()
+   {
+      log.debug("Invocation Count = " + invocationCount);
+      return invocationCount;
+   }
+
+   public long getCallGap()
+   {
+      long callGap = lastCall - firstCall;
+      log.debug("Call Gap = " + callGap);
+      return callGap;
+   }
+
+   public void perform()
+   {
+      log.debug("perform start");
+      invocationCount++;
+      lastCall = System.currentTimeMillis();
+      if (firstCall == -1)
+      {
+         firstCall = lastCall;
+      }
+      delay();
+      log.debug("invocationCount=" + invocationCount + ", firstCall=" + firstCall + ", lastCall=" + lastCall);
+      log.debug("perform end");
+   }
+
+   private void delay()
+   {
+      try
+      {
+         Thread.sleep(DELAY);
+      }
+      catch (InterruptedException e)
+      {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      }
+   }
+
+   public boolean isJava14()
+   {
+      boolean java14 = "1.4".equals(System.getProperty("java.specification.version"));
+      log.debug("isJava14=" + java14);
+      return java14;
+   }
+}


Property changes on: branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/main/org/jboss/test/scheduler/ScheduleTracker.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Added: branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/main/org/jboss/test/scheduler/ScheduleTrackerMBean.java
===================================================================
--- branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/main/org/jboss/test/scheduler/ScheduleTrackerMBean.java	                        (rev 0)
+++ branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/main/org/jboss/test/scheduler/ScheduleTrackerMBean.java	2007-06-23 18:53:19 UTC (rev 63625)
@@ -0,0 +1,46 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.test.scheduler;
+
+/**
+ * An MBean to track the invocations.
+ * 
+ * @author <a href="mailto:darran.lofthouse at jboss.com">Darran Lofthouse</a>
+ * @version $Revision$
+ */
+public interface ScheduleTrackerMBean
+{
+
+   /** Called from the scheduled task. */
+   public void perform();
+
+   /** The number of times this has been called. */
+   public int getInvocationCount();
+
+   /** The time between the first and last calls. */
+   public long getCallGap();
+
+   /**  Return true if this is Java14 */
+   public boolean isJava14();
+
+}


Property changes on: branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/main/org/jboss/test/scheduler/ScheduleTrackerMBean.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Added: branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/main/org/jboss/test/scheduler/SchedulerDefaultTestCase.java
===================================================================
--- branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/main/org/jboss/test/scheduler/SchedulerDefaultTestCase.java	                        (rev 0)
+++ branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/main/org/jboss/test/scheduler/SchedulerDefaultTestCase.java	2007-06-23 18:53:19 UTC (rev 63625)
@@ -0,0 +1,53 @@
+/* 
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.test.scheduler;
+
+import junit.framework.Test;
+
+/**
+ * When JBOSS (Not the test itself) is running under Java 1.4 this tests that it is
+ * fixed rate, when running under Java 5.0 this tests that it is fixed delay.
+ *
+ * @author <a href="mailto:darran.lofthouse at jboss.com">Darran Lofthouse</a>
+ * @version $Revision$
+ */
+public class SchedulerDefaultTestCase extends BaseTest
+{
+
+   public SchedulerDefaultTestCase(String name)
+   {
+      super(name);
+   }
+
+   public boolean isTestFixedDelay() throws Exception
+   {
+      return getScheduleTracker().isJava14() == false;
+   }
+   
+   public static Test suite() throws Exception
+   {
+      Test t1 = getDeploySetup(SchedulerDefaultTestCase.class, "scheduler-default.sar");
+      return t1;
+   }    
+
+}


Property changes on: branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/main/org/jboss/test/scheduler/SchedulerDefaultTestCase.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Added: branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/main/org/jboss/test/scheduler/SchedulerFixedDelayTestCase.java
===================================================================
--- branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/main/org/jboss/test/scheduler/SchedulerFixedDelayTestCase.java	                        (rev 0)
+++ branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/main/org/jboss/test/scheduler/SchedulerFixedDelayTestCase.java	2007-06-23 18:53:19 UTC (rev 63625)
@@ -0,0 +1,51 @@
+/* 
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.test.scheduler;
+
+import junit.framework.Test;
+
+/**
+ * Test case to test deploying a schedulable class with a fixed delay.
+ *
+ * @author <a href="mailto:darran.lofthouse at jboss.com">Darran Lofthouse</a>
+ * @version $Revision$
+ */
+public class SchedulerFixedDelayTestCase extends BaseTest
+{
+
+   public SchedulerFixedDelayTestCase(String name)
+   {
+      super(name);
+   }
+
+   public boolean isTestFixedDelay()
+   {
+      return true;
+   }
+
+   public static Test suite() throws Exception
+   {
+      Test t1 = getDeploySetup(SchedulerFixedDelayTestCase.class, "scheduler-fixeddelay.sar");
+      return t1;
+   }
+}


Property changes on: branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/main/org/jboss/test/scheduler/SchedulerFixedDelayTestCase.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Added: branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/main/org/jboss/test/scheduler/SchedulerFixedRateTestCase.java
===================================================================
--- branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/main/org/jboss/test/scheduler/SchedulerFixedRateTestCase.java	                        (rev 0)
+++ branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/main/org/jboss/test/scheduler/SchedulerFixedRateTestCase.java	2007-06-23 18:53:19 UTC (rev 63625)
@@ -0,0 +1,52 @@
+/* 
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.test.scheduler;
+
+import junit.framework.Test;
+
+/**
+ * Test case to test deploying a schedulable class with a fixed rate.
+ *
+ * @author <a href="mailto:darran.lofthouse at jboss.com">Darran Lofthouse</a>
+ * @version $Revision$
+ */
+public class SchedulerFixedRateTestCase extends BaseTest
+{
+
+   public SchedulerFixedRateTestCase(String name)
+   {
+      super(name);
+   }
+
+   public boolean isTestFixedDelay()
+   {
+      return false;
+   }
+   
+   public static Test suite() throws Exception
+   {
+      Test t1 = getDeploySetup(SchedulerFixedRateTestCase.class, "scheduler-fixedrate.sar");
+      return t1;
+   }   
+
+}


Property changes on: branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/main/org/jboss/test/scheduler/SchedulerFixedRateTestCase.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Added: branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/resources/scheduler/default/jboss-service.xml
===================================================================
--- branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/resources/scheduler/default/jboss-service.xml	                        (rev 0)
+++ branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/resources/scheduler/default/jboss-service.xml	2007-06-23 18:53:19 UTC (rev 63625)
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<server>
+
+  <mbean code="org.jboss.test.scheduler.ScheduleTracker"
+	 name="test:name=ScheduleTracker"/>
+
+  <mbean code="org.jboss.varia.scheduler.Scheduler"
+         name="test:service=Scheduler">
+    <attribute name="StartAtStartup">true</attribute>
+    <attribute name="SchedulableClass">org.jboss.test.scheduler.ScheduleTask</attribute>
+    <attribute name="InitialStartDate">NOW</attribute>
+    <attribute name="SchedulePeriod">300</attribute>
+    <attribute name="InitialRepetitions">5</attribute>
+    <depends>
+      <mbean code="javax.management.timer.Timer"
+             name="jboss:service=Timer"/>
+    </depends>
+  </mbean>
+
+</server>
\ No newline at end of file


Property changes on: branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/resources/scheduler/default/jboss-service.xml
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Added: branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/resources/scheduler/fixedDelay/jboss-service.xml
===================================================================
--- branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/resources/scheduler/fixedDelay/jboss-service.xml	                        (rev 0)
+++ branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/resources/scheduler/fixedDelay/jboss-service.xml	2007-06-23 18:53:19 UTC (rev 63625)
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<server>
+
+  <mbean code="org.jboss.test.scheduler.ScheduleTracker"
+	 name="test:name=ScheduleTracker"/>
+
+  <mbean code="org.jboss.varia.scheduler.Scheduler"
+         name="test:service=Scheduler">
+    <attribute name="StartAtStartup">true</attribute>
+    <attribute name="SchedulableClass">org.jboss.test.scheduler.ScheduleTask</attribute>
+    <attribute name="InitialStartDate">NOW</attribute>
+    <attribute name="SchedulePeriod">300</attribute>
+    <attribute name="InitialRepetitions">5</attribute>
+    <attribute name="FixedRate">false</attribute>    
+    <depends>
+      <mbean code="javax.management.timer.Timer"
+             name="jboss:service=Timer"/>
+    </depends>
+  </mbean>
+
+</server>
\ No newline at end of file


Property changes on: branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/resources/scheduler/fixedDelay/jboss-service.xml
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Added: branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/resources/scheduler/fixedRate/jboss-service.xml
===================================================================
--- branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/resources/scheduler/fixedRate/jboss-service.xml	                        (rev 0)
+++ branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/resources/scheduler/fixedRate/jboss-service.xml	2007-06-23 18:53:19 UTC (rev 63625)
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<server>
+
+  <mbean code="org.jboss.test.scheduler.ScheduleTracker"
+	 name="test:name=ScheduleTracker"/>
+
+  <mbean code="org.jboss.varia.scheduler.Scheduler"
+         name="test:service=Scheduler">
+    <attribute name="StartAtStartup">true</attribute>
+    <attribute name="SchedulableClass">org.jboss.test.scheduler.ScheduleTask</attribute>
+    <attribute name="InitialStartDate">NOW</attribute>
+    <attribute name="SchedulePeriod">300</attribute>
+    <attribute name="InitialRepetitions">5</attribute>
+    <attribute name="FixedRate">true</attribute>    
+    <depends>
+      <mbean code="javax.management.timer.Timer"
+             name="jboss:service=Timer"/>
+    </depends>
+  </mbean>
+
+</server>
\ No newline at end of file


Property changes on: branches/JBoss_4_0_3_SP1_JBAS-4497/testsuite/src/resources/scheduler/fixedRate/jboss-service.xml
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Modified: branches/JBoss_4_0_3_SP1_JBAS-4497/varia/src/etc/schedule-manager-service.xml
===================================================================
--- branches/JBoss_4_0_3_SP1_JBAS-4497/varia/src/etc/schedule-manager-service.xml	2007-06-23 12:48:50 UTC (rev 63624)
+++ branches/JBoss_4_0_3_SP1_JBAS-4497/varia/src/etc/schedule-manager-service.xml	2007-06-23 18:53:19 UTC (rev 63625)
@@ -18,11 +18,15 @@
    
    <!--
     | The Schedule Manager has to be started whenever
-    | schedules are needed
+    | schedules are needed.
+    |
+    | The default JMX Timer scheduling behaviour of FixedDelay execution
+    | (as of JDK5 or JBoss v4.0.5) is overriden below using FixedRate true
     - ->
    <mbean code="org.jboss.varia.scheduler.ScheduleManager"
           name="jboss:service=ScheduleManager">
       <attribute name="StartAtStartup">true</attribute>
+      <attribute name="FixedRate">true</attribute>
    </mbean>
    <!- - -->
    

Modified: branches/JBoss_4_0_3_SP1_JBAS-4497/varia/src/etc/scheduler-service.xml
===================================================================
--- branches/JBoss_4_0_3_SP1_JBAS-4497/varia/src/etc/scheduler-service.xml	2007-06-23 12:48:50 UTC (rev 63624)
+++ branches/JBoss_4_0_3_SP1_JBAS-4497/varia/src/etc/scheduler-service.xml	2007-06-23 18:53:19 UTC (rev 63625)
@@ -20,6 +20,7 @@
     <attribute name="InitialStartDate">0</attribute>
     <attribute name="SchedulePeriod">10000</attribute>
     <attribute name="InitialRepetitions">-1</attribute>
+    <attribute name="FixedRate">true</attribute>    
   </mbean>
 
   -->
@@ -45,6 +46,7 @@
     <attribute name="InitialStartDate">NOW</attribute>
     <attribute name="SchedulePeriod">10000</attribute>
     <attribute name="InitialRepetitions">10</attribute>
+    <attribute name="FixedRate">true</attribute>
   </mbean>
 
   -->

Modified: branches/JBoss_4_0_3_SP1_JBAS-4497/varia/src/main/org/jboss/varia/scheduler/ScheduleManager.java
===================================================================
--- branches/JBoss_4_0_3_SP1_JBAS-4497/varia/src/main/org/jboss/varia/scheduler/ScheduleManager.java	2007-06-23 12:48:50 UTC (rev 63624)
+++ branches/JBoss_4_0_3_SP1_JBAS-4497/varia/src/main/org/jboss/varia/scheduler/ScheduleManager.java	2007-06-23 18:53:19 UTC (rev 63625)
@@ -36,11 +36,10 @@
  *            extends="org.jboss.system.ServiceMBean"
  *
  * @author <a href="mailto:andreas at jboss.org">Andreas Schaefer</a>
+ * @author <a href="mailto:dimitris at jboss.org">Dimitris Andreadis</a>
  * @version $Revision$
  */
-public class ScheduleManager
-        extends ServiceMBeanSupport
-        implements ScheduleManagerMBean
+public class ScheduleManager extends ServiceMBeanSupport implements ScheduleManagerMBean
 {
 
    // -------------------------------------------------------------------------
@@ -54,11 +53,17 @@
    private static int sCounter = 0;
 
    private static final int NOTIFICATION = 0;
+
    private static final int DATE = 1;
+
    private static final int REPETITIONS = 2;
+
    private static final int SCHEDULER_NAME = 3;
+
    private static final int NULL = 4;
+
    private static final int ID = 5;
+
    private static final int NEXT_DATE = 6;
 
    // -------------------------------------------------------------------------
@@ -66,11 +71,15 @@
    // -------------------------------------------------------------------------
 
    private String mTimerName = DEFAULT_TIMER_NAME;
+
    private ObjectName mTimer;
 
-   private boolean mScheduleIsStarted = false;
    private boolean mWaitForNextCallToStop = false;
+
    private boolean mStartOnStart = false;
+
+   private boolean mFixedRate = false;
+
    private boolean mIsPaused = false;
 
    /**
@@ -78,7 +87,8 @@
     * Schedule is stop / started or destroyed
     **/
    private ArrayList mProviders = new ArrayList();
-   /** List of added Schedules **/
+
+   /** List of added Schedules */
    private Hashtable mSchedules = new Hashtable();
 
    // -------------------------------------------------------------------------
@@ -90,6 +100,15 @@
     **/
    public ScheduleManager()
    {
+      String javaVersion = System.getProperty("java.specification.version");
+
+      // The previous inconsistency was that when running under Java 1.4 the scheduler
+      // would be fixed-rate but under Java 5.0 is would be fixed delay.
+      if ("1.4".equals(javaVersion))
+      {
+         // Java 1.4 so revert to previous behaviour.
+         mFixedRate = true;
+      }
    }
 
    // -------------------------------------------------------------------------
@@ -121,7 +140,6 @@
             }
          }
       }
-      mScheduleIsStarted = true;
    }
 
    /**
@@ -156,7 +174,6 @@
             }
          }
       }
-      mScheduleIsStarted = false;
    }
 
    /**
@@ -197,13 +214,10 @@
       try
       {
          ObjectName lProviderName = new ObjectName(pProviderObjectName);
-//AS         log.info( "Start Providing on: " + lProviderName + ", based on: " + pProviderObjectName );
-         server.invoke(
-                 lProviderName,
-                 "startProviding",
-                 new Object[]{},
-                 new String[]{}
-         );
+         //AS         log.info( "Start Providing on: " + lProviderName + ", based on: " + pProviderObjectName );
+         server.invoke(lProviderName, "startProviding", new Object[]
+         {}, new String[]
+         {});
       }
       catch (JMException jme)
       {
@@ -232,12 +246,9 @@
       try
       {
          ObjectName lProviderName = new ObjectName(pProviderObjectName);
-         server.invoke(
-                 lProviderName,
-                 "stopProviding",
-                 new Object[]{},
-                 new String[]{}
-         );
+         server.invoke(lProviderName, "stopProviding", new Object[]
+         {}, new String[]
+         {});
       }
       catch (JMException jme)
       {
@@ -266,31 +277,17 @@
     *
     * @jmx:managed-operation
     **/
-   public int addSchedule(
-           ObjectName pProvider,
-           ObjectName pTarget,
-           String pMethodName,
-           String[] pMethodSignature,
-           Date pStartDate,
-           long pPeriod,
-           int pRepetitions
-           )
+   public int addSchedule(ObjectName pProvider, ObjectName pTarget, String pMethodName, String[] pMethodSignature,
+         Date pStartDate, long pPeriod, int pRepetitions)
    {
       /*
-      String sig = "{";
-      for (int i = 0; i < pMethodSignature.length; i++) sig += pMethodSignature[i];
-      sig += "}";
-      log.info( "ScheduleManager.addScheduler(" + pProvider + ", " + pTarget + ", " + pMethodName + ","  + sig + ", " + pStartDate + ", " + pPeriod + ", " + pRepetitions);
-      */
-      ScheduleInstance lInstance = new ScheduleInstance(
-              pProvider,
-              pTarget,
-              pMethodName,
-              pMethodSignature,
-              pStartDate,
-              pRepetitions,
-              pPeriod
-      );
+       String sig = "{";
+       for (int i = 0; i < pMethodSignature.length; i++) sig += pMethodSignature[i];
+       sig += "}";
+       log.info( "ScheduleManager.addScheduler(" + pProvider + ", " + pTarget + ", " + pMethodName + ","  + sig + ", " + pStartDate + ", " + pPeriod + ", " + pRepetitions);
+       */
+      ScheduleInstance lInstance = new ScheduleInstance(pProvider, pTarget, pMethodName, pMethodSignature, pStartDate,
+            pRepetitions, pPeriod);
       // Only start it know when the Schedule Manager is started
       if (isStarted())
       {
@@ -388,15 +385,9 @@
       return getState() == STARTED;
    }
 
-   /**
-    * @jmx:managed-attribute
-    *
-    * @return True if the Schedule when the Scheduler is started
-    */
-   public boolean isStartAtStartup()
-   {
-      return mStartOnStart;
-   }
+   // -------------------------------------------------------------------------
+   // SchedulerManagerMBean Attributes
+   // -------------------------------------------------------------------------
 
    /**
     * Set the scheduler to start when MBean started or not. Note that this method only
@@ -415,11 +406,11 @@
    /**
     * @jmx:managed-attribute
     *
-    * @return Name of the Timer MBean used in here
+    * @return true if the scheduler should be started upon MBean start or not
     */
-   public String getTimerName()
+   public boolean isStartAtStartup()
    {
-      return mTimerName;
+      return mStartOnStart;
    }
 
    /**
@@ -434,15 +425,41 @@
       mTimerName = pTimerName;
    }
 
+   /**
+    * @jmx:managed-attribute
+    *
+    * @return Name of the Timer MBean used in here
+    */
+   public String getTimerName()
+   {
+      return mTimerName;
+   }
+
+   /**
+    * @jmx:managed-attribute
+    * 
+    * @param fixedRate the default scheduling to use, fixed-rate or fixed-delay (false, default)
+    */
+   public void setFixedRate(boolean fixedRate)
+   {
+      mFixedRate = fixedRate;
+   }
+
+   /**
+    * @jmx:managed-attribute
+    * 
+    * @return the default scheduling to use
+    */
+   public boolean getFixedRate()
+   {
+      return mFixedRate;
+   }
+
    // -------------------------------------------------------------------------
    // Methods
    // -------------------------------------------------------------------------
 
-   public ObjectName getObjectName(
-           MBeanServer pServer,
-           ObjectName pName
-           )
-           throws MalformedObjectNameException
+   public ObjectName getObjectName(MBeanServer pServer, ObjectName pName) throws MalformedObjectNameException
    {
       return pName == null ? OBJECT_NAME : pName;
    }
@@ -475,8 +492,7 @@
     * the service is restarted and therefore schedules can be
     * available.
     **/
-   protected void startService()
-           throws Exception
+   protected void startService() throws Exception
    {
       // Create Timer MBean if need be
 
@@ -496,12 +512,9 @@
       if (!((Boolean) getServer().getAttribute(mTimer, "Active")).booleanValue())
       {
          // Now start the Timer
-         getServer().invoke(
-                 mTimer,
-                 "start",
-                 new Object[]{},
-                 new String[]{}
-         );
+         getServer().invoke(mTimer, "start", new Object[]
+         {}, new String[]
+         {});
       }
       log.debug("Start Schedules when Service is (re) started");
       startSchedules();
@@ -525,8 +538,7 @@
     * appropriate method on the given Target (MBean) and count down the
     * number of remaining repetitions.
     **/
-   public class MBeanListener
-           implements NotificationListener
+   public class MBeanListener implements NotificationListener
    {
       private final Logger log = Logger.getLogger(MBeanListener.class);
 
@@ -537,10 +549,7 @@
          mSchedule = pSchedule;
       }
 
-      public void handleNotification(
-              Notification pNotification,
-              Object pHandback
-              )
+      public void handleNotification(Notification pNotification, Object pHandback)
       {
          log.debug("MBeanListener.handleNotification(), notification: " + pNotification);
          try
@@ -563,39 +572,36 @@
                      {
                         switch (mSchedule.mSchedulableMBeanArguments[i])
                         {
-                           case ID:
+                           case ID :
                               lArguments[i] = pNotification.getUserData();
                               break;
-                           case NOTIFICATION:
+                           case NOTIFICATION :
                               lArguments[i] = pNotification;
                               break;
-                           case DATE:
+                           case DATE :
                               lArguments[i] = lTimeStamp;
                               break;
-                           case REPETITIONS:
+                           case REPETITIONS :
                               lArguments[i] = new Long(mSchedule.mRemainingRepetitions);
                               break;
-                           case SCHEDULER_NAME:
+                           case SCHEDULER_NAME :
                               lArguments[i] = getServiceName();
                               break;
-                           case NEXT_DATE:
+                           case NEXT_DATE :
                               lArguments[i] = new Date(lTimeStamp.getTime() + mSchedule.mPeriod);
                               break;
-                           default:
+                           default :
                               lArguments[i] = null;
                         }
                      }
                      log.debug("MBean Arguments are: " + java.util.Arrays.asList(lArguments));
-                     log.debug("MBean Arguments Types are: " + java.util.Arrays.asList(mSchedule.mSchedulableMBeanArgumentTypes));
+                     log.debug("MBean Arguments Types are: "
+                           + java.util.Arrays.asList(mSchedule.mSchedulableMBeanArgumentTypes));
                      try
                      {
                         log.debug("invoke(" + mSchedule.mTarget + ", " + mSchedule.mMethodName);
-                        getServer().invoke(
-                                mSchedule.mTarget,
-                                mSchedule.mMethodName,
-                                lArguments,
-                                mSchedule.mSchedulableMBeanArgumentTypes
-                        );
+                        getServer().invoke(mSchedule.mTarget, mSchedule.mMethodName, lArguments,
+                              mSchedule.mSchedulableMBeanArgumentTypes);
                      }
                      catch (javax.management.JMRuntimeException jmre)
                      {
@@ -605,8 +611,8 @@
                      {
                         log.error("Invoke of the Schedulable MBean failed", jme);
                      }
-                     log.debug("Remaining Repititions: " + mSchedule.mRemainingRepetitions +
-                             ", wait for next call to stop: " + mWaitForNextCallToStop);
+                     log.debug("Remaining Repititions: " + mSchedule.mRemainingRepetitions
+                           + ", wait for next call to stop: " + mWaitForNextCallToStop);
                      if (mSchedule.mRemainingRepetitions == 0 || mWaitForNextCallToStop)
                      {
                         mSchedule.stop();
@@ -658,36 +664,40 @@
    }
 
    /**
-    * Represents a single Schedule which can be started and stop
+    * Represents a single Schedule which can be started and stopped
     * if necessary.
     **/
    private class ScheduleInstance
    {
 
       private final Logger log = Logger.getLogger(ScheduleInstance.class);
+
       private int mIdentification;
+
       private MBeanListener mListener;
 
       public int mNotificationID;
+
       public ObjectName mProvider;
+
       public ObjectName mTarget;
+
       public int mInitialRepetitions;
+
       public int mRemainingRepetitions = 0;
+
       public Date mStartDate;
+
       public long mPeriod;
+
       public String mMethodName;
+
       public int[] mSchedulableMBeanArguments;
+
       public String[] mSchedulableMBeanArgumentTypes;
 
-      public ScheduleInstance(
-              ObjectName pProvider,
-              ObjectName pTarget,
-              String pMethodName,
-              String[] pMethodArguments,
-              Date pStartDate,
-              int pRepetitions,
-              long pPeriod
-              )
+      public ScheduleInstance(ObjectName pProvider, ObjectName pTarget, String pMethodName, String[] pMethodArguments,
+            Date pStartDate, int pRepetitions, long pPeriod)
       {
          mProvider = pProvider;
          mTarget = pTarget;
@@ -745,8 +755,7 @@
        * and registering its listener to get the notifications
        * and hand over to the target
        **/
-      public void start()
-              throws JMException
+      public void start() throws JMException
       {
          Date lStartDate = null;
          // Check if initial start date is in the past
@@ -762,8 +771,8 @@
                if (lSkipRepeats >= mInitialRepetitions)
                {
                   // No repetition left -> exit
-                  log.warn("No repetitions left because start date is in the past and could " +
-                          "not be reached by Initial Repetitions * Schedule Period");
+                  log.warn("No repetitions left because start date is in the past and could "
+                        + "not be reached by Initial Repetitions * Schedule Period");
                   return;
                }
                else
@@ -791,36 +800,23 @@
             mRemainingRepetitions = mInitialRepetitions;
          }
          mNotificationID = ((Integer) getServer().invoke(
-                 mTimer,
-                 "addNotification",
-                 new Object[]{
-                    "Schedule",
-                    "Scheduler Notification",
-                    new Integer(getID()), // User Object
-                    lStartDate,
-                    new Long(mPeriod),
-                    mRemainingRepetitions < 0 ?
-                 new Long(0) :
-                 new Long(mRemainingRepetitions)
-                 },
-                 new String[]{
-                    String.class.getName(),
-                    String.class.getName(),
-                    Object.class.getName(),
-                    Date.class.getName(),
-                    Long.TYPE.getName(),
-                    Long.TYPE.getName()
-                 }
-         )).intValue();
+               mTimer,
+               "addNotification",
+               new Object[]
+               {"Schedule", "Scheduler Notification",
+                     new Integer(getID()), // User Object
+                     lStartDate, new Long(mPeriod),
+                     mRemainingRepetitions < 0 ? new Long(0) : new Long(mRemainingRepetitions), new Boolean(mFixedRate)
+
+               },
+               new String[]
+               {String.class.getName(), String.class.getName(), Object.class.getName(), Date.class.getName(),
+                     Long.TYPE.getName(), Long.TYPE.getName(), Boolean.TYPE.getName()})).intValue();
          // Register the notification listener at the MBeanServer
          mListener = new MBeanListener(this);
-         getServer().addNotificationListener(
-                 mTimer,
-                 mListener,
-                 new NotificationFilter(new Integer(mNotificationID)),
-                 // No object handback necessary
-                 null
-         );
+         getServer().addNotificationListener(mTimer, mListener, new NotificationFilter(new Integer(mNotificationID)),
+         // No object handback necessary
+               null);
          log.debug("start(), add Notification to Timer with ID: " + mNotificationID);
       }
 
@@ -828,26 +824,15 @@
        * Stops the Schedule by remove itself from the timer
        * and removing the listener
        **/
-      public void stop()
-              throws JMException
+      public void stop() throws JMException
       {
          log.debug("stopSchedule(), notification id: " + mNotificationID);
-         getServer().removeNotificationListener(
-                 mTimer,
-                 mListener
-         );
+         getServer().removeNotificationListener(mTimer, mListener);
          try
          {
-            getServer().invoke(
-                    mTimer,
-                    "removeNotification",
-                    new Object[]{
-                       new Integer(mNotificationID)
-                    },
-                    new String[]{
-                       Integer.class.getName()
-                    }
-            );
+            getServer().invoke(mTimer, "removeNotification", new Object[]
+            {new Integer(mNotificationID)}, new String[]
+            {Integer.class.getName()});
          }
          catch (MBeanException mbe)
          {

Modified: branches/JBoss_4_0_3_SP1_JBAS-4497/varia/src/main/org/jboss/varia/scheduler/ScheduleManagerMBean.java
===================================================================
--- branches/JBoss_4_0_3_SP1_JBAS-4497/varia/src/main/org/jboss/varia/scheduler/ScheduleManagerMBean.java	2007-06-23 12:48:50 UTC (rev 63624)
+++ branches/JBoss_4_0_3_SP1_JBAS-4497/varia/src/main/org/jboss/varia/scheduler/ScheduleManagerMBean.java	2007-06-23 18:53:19 UTC (rev 63625)
@@ -16,6 +16,17 @@
    public static final javax.management.ObjectName OBJECT_NAME = org.jboss.mx.util.ObjectNameFactory
          .create("jboss:service=ScheduleMBean");
 
+
+   /** The JMX timer to use for the actual scheduling */
+   void setTimerName(String timerObjectName);
+   String getTimerName();
+   
+   /** The default scheduling to use, fixed-rate or fixed-delay (false, default) */
+   void setFixedRate(boolean fixedRate);
+   boolean getFixedRate();
+   
+   // Operations ----------------------------------------------------
+   
    /**
     * Starts all the containing Schedules
     */
@@ -70,8 +81,4 @@
     * @param pStartAtStartup True if Schedule has to be started at startup time    */
    void setStartAtStartup(boolean pStartAtStartup);
 
-   java.lang.String getTimerName();
-
-   void setTimerName(java.lang.String pTimerName);
-
 }

Modified: branches/JBoss_4_0_3_SP1_JBAS-4497/varia/src/main/org/jboss/varia/scheduler/Scheduler.java
===================================================================
--- branches/JBoss_4_0_3_SP1_JBAS-4497/varia/src/main/org/jboss/varia/scheduler/Scheduler.java	2007-06-23 12:48:50 UTC (rev 63624)
+++ branches/JBoss_4_0_3_SP1_JBAS-4497/varia/src/main/org/jboss/varia/scheduler/Scheduler.java	2007-06-23 18:53:19 UTC (rev 63625)
@@ -1,28 +1,43 @@
 /*
- * JBoss, the OpenSource EJB server
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
  *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  */
 
 package org.jboss.varia.scheduler;
 
 import java.lang.reflect.Constructor;
-import java.text.SimpleDateFormat;
 import java.security.InvalidParameterException;
+import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.StringTokenizer;
 import java.util.Vector;
 
 import javax.management.MalformedObjectNameException;
 import javax.management.Notification;
-import javax.management.timer.TimerNotification;
 import javax.management.NotificationListener;
 import javax.management.ObjectName;
+import javax.management.timer.TimerNotification;
 
 import org.jboss.logging.Logger;
 import org.jboss.system.ServiceMBeanSupport;
-import org.jboss.mx.loading.ClassLoaderUtils;
+import org.jboss.util.Classes;
 
 /**
  * Scheduler Instance to allow clients to run this as a scheduling service for
@@ -34,16 +49,11 @@
  * :service=Scheduler,schedule=<you schedule name><br>
  * This way you should not run into a name conflict.
  *
- * @jmx:mbean name="jboss:service=Scheduler"
- *            extends="org.jboss.system.ServiceMBean"
- *
  * @author <a href="mailto:andreas at jboss.org">Andreas Schaefer</a>
  * @author Cameron (camtabor)
  * @version $Revision$
  */
-public class Scheduler
-   extends ServiceMBeanSupport
-   implements SchedulerMBean
+public class Scheduler extends ServiceMBeanSupport implements SchedulerMBean
 {
 
    // -------------------------------------------------------------------------
@@ -51,14 +61,20 @@
    // -------------------------------------------------------------------------
 
    public static String JNDI_NAME = "scheduler:domain";
+
    public static String JMX_NAME = "scheduler";
+
    /** Default Timer Object Name **/
    public static String DEFAULT_TIMER_NAME = "jboss:service=Timer";
 
    private static final int NOTIFICATION = 0;
+
    private static final int DATE = 1;
+
    private static final int REPETITIONS = 2;
+
    private static final int SCHEDULER_NAME = 3;
+
    private static final int NULL = 4;
 
    // -------------------------------------------------------------------------
@@ -66,40 +82,62 @@
    // -------------------------------------------------------------------------
 
    private long mActualSchedulePeriod;
+
    private long mRemainingRepetitions = 0;
+
    private int mActualSchedule = -1;
+
    private String mTimerName = DEFAULT_TIMER_NAME;
+
    private ObjectName mTimer;
+
    private Schedulable mSchedulable;
-//as   private Object mSchedulableMBeanObjectName;
 
    private boolean mScheduleIsStarted = false;
+
    private boolean mWaitForNextCallToStop = false;
+
    private boolean mStartOnStart = false;
+
    private boolean mIsRestartPending = true;
 
    // Pending values which can be different to the actual ones
    private boolean mUseMBean = false;
 
    private Class mSchedulableClass;
+
    private String mSchedulableArguments;
+
    private String[] mSchedulableArgumentList = new String[0];
+
    private String mSchedulableArgumentTypes;
+
    private Class[] mSchedulableArgumentTypeList = new Class[0];
 
    private ObjectName mSchedulableMBean;
+
    private String mSchedulableMBeanMethod;
+
    private String mSchedulableMBeanMethodName;
+
    private int[] mSchedulableMBeanArguments = new int[0];
+
    private String[] mSchedulableMBeanArgumentTypes = new String[0];
 
    private SimpleDateFormat mDateFormatter;
+
    private Date mStartDate;
+
    private String mStartDateString;
+
    private boolean mStartDateIsNow;
+
    private long mSchedulePeriod;
+
    private long mInitialRepetitions;
 
+   private boolean mFixedRate = false;
+
    private NotificationListener listener;
 
    // -------------------------------------------------------------------------
@@ -111,6 +149,15 @@
     **/
    public Scheduler()
    {
+      String javaVersion = System.getProperty("java.specification.version");
+
+      // The previous inconsistency was that when running under Java 1.4 the scheduler
+      // would be fixed-rate but under Java 5.0 is would be fixed delay.
+      if ("1.4".equals(javaVersion))
+      {
+         // Java 1.4 so revert to previous behaviour.
+         mFixedRate = true;
+      }
    }
 
    /**
@@ -121,14 +168,9 @@
     * @param pInitialStartDate
     * @param pSchedulePeriod
     * @param pNumberOfRepetitions
-    */ 
-   public Scheduler(String pSchedulableClass,
-      String pInitArguments,
-      String pInitTypes,
-      String pInitialStartDate,
-      long pSchedulePeriod,
-      long pNumberOfRepetitions
-      )
+    */
+   public Scheduler(String pSchedulableClass, String pInitArguments, String pInitTypes, String pInitialStartDate,
+         long pSchedulePeriod, long pNumberOfRepetitions)
    {
       setStartAtStartup(true);
       setSchedulableClass(pSchedulableClass);
@@ -148,16 +190,9 @@
     * @param pInitialStartDate
     * @param pSchedulePeriod
     * @param pNumberOfRepetitions
-    */ 
-   public Scheduler(
-      String pSchedulableClass,
-      String pInitArguments,
-      String pInitTypes,
-      String pDateFormat,
-      String pInitialStartDate,
-      long pSchedulePeriod,
-      long pNumberOfRepetitions
-      )
+    */
+   public Scheduler(String pSchedulableClass, String pInitArguments, String pInitTypes, String pDateFormat,
+         String pInitialStartDate, long pSchedulePeriod, long pNumberOfRepetitions)
    {
       setStartAtStartup(true);
       setSchedulableClass(pSchedulableClass);
@@ -197,18 +232,15 @@
                if (mSchedulableMBean == null)
                {
                   log.debug("Schedulable MBean Object Name is not set");
-                  throw new InvalidParameterException(
-                     "Schedulable MBean must be set"
-                  );
+                  throw new InvalidParameterException("Schedulable MBean must be set");
                }
                if (mSchedulableMBeanMethodName == null)
                {
                   mSchedulableMBeanMethodName = "perform";
-                  mSchedulableMBeanArguments = new int[]{DATE, REPETITIONS};
-                  mSchedulableMBeanArgumentTypes = new String[]{
-                     Date.class.getName(),
-                     Integer.TYPE.getName()
-                  };
+                  mSchedulableMBeanArguments = new int[]
+                  {DATE, REPETITIONS};
+                  mSchedulableMBeanArgumentTypes = new String[]
+                  {Date.class.getName(), Integer.TYPE.getName()};
                }
             }
             else
@@ -216,24 +248,18 @@
                if (mSchedulableClass == null)
                {
                   log.debug("Schedulable Class is not set");
-                  throw new InvalidParameterException(
-                     "Schedulable Class must be set"
-                  );
+                  throw new InvalidParameterException("Schedulable Class must be set");
                }
                if (mSchedulableArgumentList.length != mSchedulableArgumentTypeList.length)
                {
                   log.debug("Schedulable Class Arguments and Types do not match in length");
-                  throw new InvalidParameterException(
-                     "Schedulable Class Arguments and Types do not match in length"
-                  );
+                  throw new InvalidParameterException("Schedulable Class Arguments and Types do not match in length");
                }
             }
             if (mSchedulePeriod <= 0)
             {
                log.debug("Schedule Period is less than 0 (ms)");
-               throw new InvalidParameterException(
-                  "Schedule Period must be set and greater than 0 (ms)"
-               );
+               throw new InvalidParameterException("Schedule Period must be set and greater than 0 (ms)");
             }
             if (!mUseMBean)
             {
@@ -278,8 +304,10 @@
                      }
                      else
                      {
-                        Constructor lConstructor = lClass.getConstructor(new Class[]{String.class});
-                        lArgumentList[i] = lConstructor.newInstance(new Object[]{mSchedulableArgumentList[i]});
+                        Constructor lConstructor = lClass.getConstructor(new Class[]
+                        {String.class});
+                        lArgumentList[i] = lConstructor.newInstance(new Object[]
+                        {mSchedulableArgumentList[i]});
                      }
                   }
                }
@@ -298,7 +326,8 @@
                catch (Exception e)
                {
                   log.error("Could not find the constructor or create Schedulable instance", e);
-                  throw new InvalidParameterException("Could not find the constructor or create the Schedulable Instance");
+                  throw new InvalidParameterException(
+                        "Could not find the constructor or create the Schedulable Instance");
                }
             }
 
@@ -320,15 +349,16 @@
                   // If then first check if a repetition is in the future
                   long lNow = new Date().getTime() + 100;
                   long lSkipRepeats = ((lNow - mStartDate.getTime()) / mActualSchedulePeriod) + 1;
-                  log.debug("Old start date: " + mStartDate + ", now: " + new Date(lNow) + ", Skip repeats: " + lSkipRepeats);
+                  log.debug("Old start date: " + mStartDate + ", now: " + new Date(lNow) + ", Skip repeats: "
+                        + lSkipRepeats);
                   if (mRemainingRepetitions > 0)
                   {
                      // If not infinit loop
                      if (lSkipRepeats >= mRemainingRepetitions)
                      {
                         // No repetition left -> exit
-                        log.info("No repetitions left because start date is in the past and could " +
-                           "not be reached by Initial Repetitions * Schedule Period");
+                        log.info("No repetitions left because start date is in the past and could "
+                              + "not be reached by Initial Repetitions * Schedule Period");
                         return;
                      }
                      else
@@ -347,27 +377,18 @@
             log.debug("Schedule initial call to: " + lStartDate + ", remaining repetitions: " + mRemainingRepetitions);
             // Add an initial call
             mActualSchedule = ((Integer) getServer().invoke(
-               mTimer,
-               "addNotification",
-               new Object[]{
-                  "Schedule",
-                  "Scheduler Notification",
-                  null, // User Object
-                  lStartDate,
-                  new Long(mActualSchedulePeriod),
-                  mRemainingRepetitions < 0 ?
-               new Long(0) :
-               new Long(mRemainingRepetitions)
-               },
-               new String[]{
-                  String.class.getName(),
-                  String.class.getName(),
-                  Object.class.getName(),
-                  Date.class.getName(),
-                  Long.TYPE.getName(),
-                  Long.TYPE.getName()
-               }
-            )).intValue();
+                  mTimer,
+                  "addNotification",
+                  new Object[]
+                  {"Schedule",
+                        "Scheduler Notification",
+                        null, // User Object
+                        lStartDate, new Long(mActualSchedulePeriod),
+                        mRemainingRepetitions < 0 ? new Long(0) : new Long(mRemainingRepetitions),
+                        new Boolean(mFixedRate)},
+                  new String[]
+                  {String.class.getName(), String.class.getName(), Object.class.getName(), Date.class.getName(),
+                        Long.TYPE.getName(), Long.TYPE.getName(), Boolean.TYPE.getName()})).intValue();
             if (mUseMBean)
             {
                listener = new MBeanListener(mSchedulableMBean);
@@ -377,13 +398,10 @@
                listener = new Listener(mSchedulable);
             }
             // Register the notification listener at the MBeanServer
-            getServer().addNotificationListener(
-               mTimer,
-               listener,
-               new Scheduler.NotificationFilter(new Integer(mActualSchedule)),
-               // No object handback necessary
-               null
-            );
+            getServer().addNotificationListener(mTimer, listener,
+                  new Scheduler.NotificationFilter(new Integer(mActualSchedule)),
+                  // No object handback necessary
+                  null);
             mScheduleIsStarted = true;
             mIsRestartPending = false;
          }
@@ -420,23 +438,13 @@
             // Remove notification listener now
             if (listener != null)
             {
-               getServer().removeNotificationListener(
-                  mTimer,
-                  listener
-               );
+               getServer().removeNotificationListener(mTimer, listener);
                listener = null;
             }
             log.debug("stopSchedule(), schedule id: " + mActualSchedule);
-            getServer().invoke(
-               mTimer,
-               "removeNotification",
-               new Object[]{
-                  new Integer(mActualSchedule)
-               },
-               new String[]{
-                  Integer.class.getName()
-               }
-            );
+            getServer().invoke(mTimer, "removeNotification", new Object[]
+            {new Integer(mActualSchedule)}, new String[]
+            {Integer.class.getName()});
             log.debug("stopSchedule(), removed schedule id: " + mActualSchedule);
             mActualSchedule = -1;
             mScheduleIsStarted = false;
@@ -491,8 +499,7 @@
     *                                   be loaded by the Scheduler or is not of instance
     *                                   Schedulable.
     */
-   public void setSchedulableClass(String pSchedulableClass)
-      throws InvalidParameterException
+   public void setSchedulableClass(String pSchedulableClass) throws InvalidParameterException
    {
       if (pSchedulableClass == null || pSchedulableClass.equals(""))
       {
@@ -509,19 +516,17 @@
             String msg = "Given class " + pSchedulableClass + " is not instance of Schedulable";
             StringBuffer info = new StringBuffer(msg);
             info.append("\nThe SchedulableClass info:");
-            ClassLoaderUtils.displayClassInfo(mSchedulableClass, info);
+            Classes.displayClassInfo(mSchedulableClass, info);
             info.append("\nSchedulable.class info:");
-            ClassLoaderUtils.displayClassInfo(Schedulable.class, info);
+            Classes.displayClassInfo(Schedulable.class, info);
             log.debug(info.toString());
             throw new InvalidParameterException(msg);
          }
       }
       catch (ClassNotFoundException e)
       {
-         log.info("Failed to find: "+pSchedulableClass, e);
-         throw new InvalidParameterException(
-            "Given class " + pSchedulableClass + " is not  not found"
-         );
+         log.info("Failed to find: " + pSchedulableClass, e);
+         throw new InvalidParameterException("Given class " + pSchedulableClass + " is not  not found");
       }
       mIsRestartPending = true;
       mUseMBean = false;
@@ -603,8 +608,7 @@
     *
     * @throws InvalidParameterException If the given list contains a unknow datat type.
     */
-   public void setSchedulableArgumentTypes(String pTypeList)
-      throws InvalidParameterException
+   public void setSchedulableArgumentTypes(String pTypeList) throws InvalidParameterException
    {
       if (pTypeList == null || pTypeList.equals(""))
       {
@@ -661,9 +665,8 @@
                }
                catch (ClassNotFoundException cnfe)
                {
-                  throw new InvalidParameterException(
-                     "The argument type: " + lToken + " is not a valid class or could not be found"
-                  );
+                  throw new InvalidParameterException("The argument type: " + lToken
+                        + " is not a valid class or could not be found");
                }
             }
             lList.add(lClass);
@@ -681,9 +684,7 @@
     */
    public String getSchedulableMBean()
    {
-      return mSchedulableMBean == null ?
-         null :
-         mSchedulableMBean.toString();
+      return mSchedulableMBean == null ? null : mSchedulableMBean.toString();
    }
 
    /**
@@ -703,8 +704,7 @@
     *
     * @throws InvalidParameterException If the given value is an valid Object Name.
     */
-   public void setSchedulableMBean(String pSchedulableMBean)
-      throws InvalidParameterException
+   public void setSchedulableMBean(String pSchedulableMBean) throws InvalidParameterException
    {
       if (pSchedulableMBean == null)
       {
@@ -761,8 +761,7 @@
     * @throws InvalidParameterException If the given value is not of the right
     *                                   format
     */
-   public void setSchedulableMBeanMethod(String pSchedulableMBeanMethod)
-      throws InvalidParameterException
+   public void setSchedulableMBeanMethod(String pSchedulableMBeanMethod) throws InvalidParameterException
    {
       if (pSchedulableMBeanMethod == null)
       {
@@ -790,7 +789,8 @@
          int lIndex2 = pSchedulableMBeanMethod.indexOf(')');
          if (lIndex2 < lIndex)
          {
-            throw new InvalidParameterException("Schedulable MBean Method: closing bracket must be after opening bracket");
+            throw new InvalidParameterException(
+                  "Schedulable MBean Method: closing bracket must be after opening bracket");
          }
          if (lIndex2 < pSchedulableMBeanMethod.length() - 1)
          {
@@ -1114,6 +1114,26 @@
       mTimerName = pTimerName;
    }
 
+   /**
+    * @jmx:managed-attribute
+    * 
+    * @param fixedRate the default scheduling to use, fixed-rate or fixed-delay (false, default)
+    */
+   public void setFixedRate(boolean fixedRate)
+   {
+      mFixedRate = fixedRate;
+   }
+
+   /**
+    * @jmx:managed-attribute
+    * 
+    * @return the default scheduling to use
+    */
+   public boolean getFixedRate()
+   {
+      return mFixedRate;
+   }
+
    // -------------------------------------------------------------------------
    // Methods
    // -------------------------------------------------------------------------
@@ -1122,8 +1142,7 @@
    // ServiceMBean - Methods
    // -------------------------------------------------------------------------
 
-   protected void startService()
-      throws Exception
+   protected void startService() throws Exception
    {
       // Create Timer MBean if need be
 
@@ -1143,12 +1162,9 @@
       if (!((Boolean) getServer().getAttribute(mTimer, "Active")).booleanValue())
       {
          // Now start the Timer
-         getServer().invoke(
-            mTimer,
-            "start",
-            new Object[]{},
-            new String[]{}
-         );
+         getServer().invoke(mTimer, "start", new Object[]
+         {}, new String[]
+         {});
       }
 
       if (mStartOnStart)
@@ -1179,7 +1195,7 @@
             }
          }
          c = c.getSuperclass();
-      } 
+      }
       while (c != null && !lFound);
       return lFound;
    }
@@ -1188,10 +1204,10 @@
    // Inner Classes
    // -------------------------------------------------------------------------
 
-   public class Listener
-      implements NotificationListener
+   public class Listener implements NotificationListener
    {
       private final Logger log = Logger.getLogger(Listener.class);
+
       private Schedulable mDelegate;
 
       public Listener(Schedulable pDelegate)
@@ -1199,7 +1215,7 @@
          mDelegate = pDelegate;
       }
 
-      public void handleNotification(Notification notification,Object handback)
+      public void handleNotification(Notification notification, Object handback)
       {
          log.debug("Listener.handleNotification(), notification: " + notification);
          ClassLoader currentTCL = TCLActions.getContextClassLoader();
@@ -1218,12 +1234,9 @@
                   {
                      mRemainingRepetitions--;
                   }
-                  mDelegate.perform(
-                     lTimeStamp,
-                     getRemainingRepetitions()
-                  );
-                  log.debug("Remaining Repititions: " + getRemainingRepetitions() +
-                     ", wait for next call to stop: " + mWaitForNextCallToStop);
+                  mDelegate.perform(lTimeStamp, getRemainingRepetitions());
+                  log.debug("Remaining Repititions: " + getRemainingRepetitions() + ", wait for next call to stop: "
+                        + mWaitForNextCallToStop);
                   if (getRemainingRepetitions() == 0 || mWaitForNextCallToStop)
                   {
                      stopSchedule(true);
@@ -1233,16 +1246,9 @@
             else
             {
                // Schedule is stopped therefore remove the Schedule
-               getServer().invoke(
-                  mTimer,
-                  "removeNotification",
-                  new Object[]{
-                     new Integer(mActualSchedule)
-                  },
-                  new String[]{
-                     Integer.class.getName()
-                  }
-               );
+               getServer().invoke(mTimer, "removeNotification", new Object[]
+               {new Integer(mActualSchedule)}, new String[]
+               {Integer.class.getName()});
                mActualSchedule = -1;
             }
          }
@@ -1257,8 +1263,7 @@
       }
    }
 
-   public class MBeanListener
-      implements NotificationListener
+   public class MBeanListener implements NotificationListener
    {
       private final Logger log = Logger.getLogger(Listener.class);
 
@@ -1269,10 +1274,7 @@
          mDelegate = pDelegate;
       }
 
-      public void handleNotification(
-         Notification notification,
-         Object handback
-         )
+      public void handleNotification(Notification notification, Object handback)
       {
          log.debug("MBeanListener.handleNotification(), notification: " + notification);
          try
@@ -1293,19 +1295,19 @@
                   {
                      switch (mSchedulableMBeanArguments[i])
                      {
-                        case NOTIFICATION:
+                        case NOTIFICATION :
                            lArguments[i] = notification;
                            break;
-                        case DATE:
+                        case DATE :
                            lArguments[i] = lTimeStamp;
                            break;
-                        case REPETITIONS:
+                        case REPETITIONS :
                            lArguments[i] = new Long(mRemainingRepetitions);
                            break;
-                        case SCHEDULER_NAME:
+                        case SCHEDULER_NAME :
                            lArguments[i] = getServiceName();
                            break;
-                        default:
+                        default :
                            lArguments[i] = null;
                      }
                   }
@@ -1313,12 +1315,8 @@
                   log.debug("MBean Arguments Types are: " + java.util.Arrays.asList(mSchedulableMBeanArgumentTypes));
                   try
                   {
-                     getServer().invoke(
-                        mDelegate,
-                        mSchedulableMBeanMethodName,
-                        lArguments,
-                        mSchedulableMBeanArgumentTypes
-                     );
+                     getServer().invoke(mDelegate, mSchedulableMBeanMethodName, lArguments,
+                           mSchedulableMBeanArgumentTypes);
                   }
                   catch (javax.management.JMRuntimeException jmre)
                   {
@@ -1328,8 +1326,8 @@
                   {
                      log.error("Invoke of the Schedulable MBean failed", jme);
                   }
-                  log.debug("Remaining Repititions: " + getRemainingRepetitions() +
-                     ", wait for next call to stop: " + mWaitForNextCallToStop);
+                  log.debug("Remaining Repititions: " + getRemainingRepetitions() + ", wait for next call to stop: "
+                        + mWaitForNextCallToStop);
                   if (getRemainingRepetitions() == 0 || mWaitForNextCallToStop)
                   {
                      stopSchedule(true);
@@ -1339,16 +1337,9 @@
             else
             {
                // Schedule is stopped therefore remove the Schedule
-               getServer().invoke(
-                  mTimer,
-                  "removeNotification",
-                  new Object[]{
-                     new Integer(mActualSchedule)
-                  },
-                  new String[]{
-                     Integer.class.getName()
-                  }
-               );
+               getServer().invoke(mTimer, "removeNotification", new Object[]
+               {new Integer(mActualSchedule)}, new String[]
+               {Integer.class.getName()});
                mActualSchedule = -1;
             }
          }
@@ -1388,12 +1379,9 @@
          {
             TimerNotification lTimerNotification = (TimerNotification) notification;
             if (log.isTraceEnabled())
-               log.trace("Scheduler.NotificationFilter.isNotificationEnabled(), Id: " + mId +
-                  ", notification: " + notification +
-                  ", notification Id: " + lTimerNotification.getNotificationID() +
-                  ", timestamp: " + lTimerNotification.getTimeStamp() +
-                  ", message: " + lTimerNotification.getMessage()
-               );
+               log.trace("Scheduler.NotificationFilter.isNotificationEnabled(), Id: " + mId + ", notification: "
+                     + notification + ", notification Id: " + lTimerNotification.getNotificationID() + ", timestamp: "
+                     + lTimerNotification.getTimeStamp() + ", message: " + lTimerNotification.getMessage());
             return lTimerNotification.getNotificationID().equals(mId);
          }
          return false;
@@ -1403,20 +1391,17 @@
    /**
     * A test class for a Schedulable Class
     **/
-   public static class SchedulableExample
-      implements Schedulable
+   public static class SchedulableExample implements Schedulable
    {
 
       /** Class logger. */
       private static final Logger log = Logger.getLogger(Scheduler.SchedulableExample.class);
 
       private String mName;
+
       private int mValue;
 
-      public SchedulableExample(
-         String pName,
-         int pValue
-         )
+      public SchedulableExample(String pName, int pValue)
       {
          mName = pName;
          mValue = pValue;
@@ -1425,14 +1410,10 @@
       /**
        * Just log the call
        **/
-      public void perform(
-         Date pTimeOfCall,
-         long pRemainingRepetitions
-         )
+      public void perform(Date pTimeOfCall, long pRemainingRepetitions)
       {
-         log.info("Schedulable Examples is called at: " + pTimeOfCall +
-            ", remaining repetitions: " + pRemainingRepetitions +
-            ", test, name: " + mName + ", value: " + mValue);
+         log.info("Schedulable Examples is called at: " + pTimeOfCall + ", remaining repetitions: "
+               + pRemainingRepetitions + ", test, name: " + mName + ", value: " + mValue);
       }
    }
 }

Modified: branches/JBoss_4_0_3_SP1_JBAS-4497/varia/src/main/org/jboss/varia/scheduler/SchedulerMBean.java
===================================================================
--- branches/JBoss_4_0_3_SP1_JBAS-4497/varia/src/main/org/jboss/varia/scheduler/SchedulerMBean.java	2007-06-23 12:48:50 UTC (rev 63624)
+++ branches/JBoss_4_0_3_SP1_JBAS-4497/varia/src/main/org/jboss/varia/scheduler/SchedulerMBean.java	2007-06-23 18:53:19 UTC (rev 63625)
@@ -1,120 +1,171 @@
 /*
- * JBoss, the OpenSource J2EE webOS
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
  *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  */
+
 package org.jboss.varia.scheduler;
 
+import java.security.InvalidParameterException;
+
+import javax.management.ObjectName;
+
+import org.jboss.mx.util.ObjectNameFactory;
+import org.jboss.system.ServiceMBean;
+
 /**
- * MBean interface.
+ * ScheduleMBean interface.
+ * 
+ * @author <a href="mailto:andreas at jboss.org">Andreas Schaefer</a>
+ * @author <a href="mailto:dimitris at jboss.org">Dimitris Andreadis</a>
+ * @version $Revision$
  */
-public interface SchedulerMBean extends org.jboss.system.ServiceMBean
+public interface SchedulerMBean extends ServiceMBean
 {
+   /** The default ObjectName */
+   ObjectName OBJECT_NAME = ObjectNameFactory.create("jboss:service=Scheduler");
 
-   //default object name
-   public static final javax.management.ObjectName OBJECT_NAME = org.jboss.mx.util.ObjectNameFactory
-         .create("jboss:service=Scheduler");
+   // Attributes ----------------------------------------------------
 
+   /** 
+    * The first scheduled call
+    * 
+    * - NOW: date will be the current date (new Date()) plus 1 seconds
+    * - Date as String able to be parsed by SimpleDateFormat with default format
+    * - Date as String parsed using the date format attribute
+    * - Milliseconds since 1/1/1970
+    * 
+    * If the date is in the past the Scheduler will search a start date in the future
+    * with respect to the initial repetitions and the period between calls.
+    * This means that when you restart the MBean (restarting JBoss etc.) it will start
+    * at the next scheduled time. When no start date is available in the future the
+    * Scheduler will not start.
+    * 
+    * Example: if you start your Schedulable everyday at Noon and you restart your JBoss
+    * server then it will start at the next Noon (the same if started before Noon or the
+    * next day if start after Noon).
+    */
+   void setInitialStartDate(String startDate);
+   String getInitialStartDate();
+   
+   /** The date format used to parse date/times - when empty or null the locale is used to parse dates */
+   void setDateFormat(String dateFormat);
+   String getDateFormat();
+   
+   /** The Schedule Period between two scheduled call (in msecs) */
+   void setSchedulePeriod(long period);
+   long getSchedulePeriod();
+   
+   /** The number of scheduled calls */
+   void setInitialRepetitions(long numberOfCalls);
+   long getInitialRepetitions();
+   
+   /** The fully qualified Class name of the Schedulable Class being called by the Scheduler. */
+   void setSchedulableClass(String schedulableClass) throws java.security.InvalidParameterException;
+   String getSchedulableClass(); 
+   
+   /** The arguments to pass to the schedule */
+   void setSchedulableArguments(String argumentList);
+   String getSchedulableArguments();   
+   
    /**
-    * Starts the schedule if the schedule is stopped otherwise nothing will happen. The Schedule is immediately set to started even the first call is in the future.
-    * @throws InvalidParameterException If any of the necessary values are not set or invalid (especially for the Schedulable class attributes).    */
+    * The comma seperated list of argument types for the Schedulable class.
+    * This will be used to find the right constructor and to created the right
+    * instances to call the constructor with. This list must have as many elements
+    * as the Schedulable Arguments list otherwise the start of the Scheduler will fail.
+    * Right now only basic data types, String and Classes with a Constructor with a
+    * String as only argument are supported.
+    * 
+    * If the list is null or empty then the no-args constructor is used.
+    */
+   void setSchedulableArgumentTypes(String typeList) throws java.security.InvalidParameterException;
+   String getSchedulableArgumentTypes();
+   
+   /** The fully qualified JMX MBean name of the Schedulable MBean to be called.
+    * Attention: if set the values set by {@link #setSchedulableClass},
+    * {@link #setSchedulableArguments} and {@link #setSchedulableArgumentTypes}
+    * are cleared and not used anymore. Therefore only use either Schedulable Class
+    * or Schedulable MBean. If {@link #setSchedulableMBeanMethod} is not set then
+    * the schedule method as in the {@link Schedulable#perform} will be called with
+    * the same arguments. Also note that the Object Name will not be checked if the
+    * MBean is available. If the MBean is not available it will not be called but the
+    * remaining repetitions will be decreased. */
+   void setSchedulableMBean(String schedulableMBean) throws java.security.InvalidParameterException;
+   String getSchedulableMBean();
+   
+   /**
+    * The method name to be called on the Schedulable MBean. It can optionally be
+    * followed by an opening bracket, list of attributes (see below) and a closing bracket.
+    * The list of attributes can contain:
+    * - NOTIFICATION which will be replaced by the timers notification instance (javax.management.Notification)
+    * - DATE which will be replaced by the date of the notification call (java.util.Date)
+    * - REPETITIONS which will be replaced by the number of remaining repetitions (long)
+    * - SCHEDULER_NAME which will be replaced by the Object Name of the Scheduler (javax.management.ObjectName)
+    * - any full qualified Class name which the Scheduler will be set a "null" value for it
+    * 
+    * An example could be: "doSomething( NOTIFICATION, REPETITIONS, String )" where the Scheduler
+    * will pass the timer's notification instance, the remaining repetitions as int and a null to
+    * the MBean's doSomething() method which must have the following signature:
+    * doSomething( javax.management.Notification, long, String ).
+    */
+   void setSchedulableMBeanMethod(String schedulableMBeanMethod) throws java.security.InvalidParameterException;
+   String getSchedulableMBeanMethod();
+   
+   /** The default scheduling to use, fixed-rate or fixed-delay (false, default) */
+   void setFixedRate(boolean fixedRate);
+   boolean getFixedRate();
+
+   /** Start the scheduler when the MBean started or not. */
+   void setStartAtStartup(boolean startAtStartup);
+   boolean isStartAtStartup();
+   
+   /** The JMX Timer to use (or create if not there) */
+   void setTimerName(String timerName);    
+   String getTimerName();
+   
+   // Informative Attributes ----------------------------------------
+   
+   long getRemainingRepetitions();   
+   boolean isActive();   
+   boolean isStarted();
+   boolean isRestartPending();
+   boolean isUsingMBean();
+   
+   // Operations ----------------------------------------------------
+   
+   /**
+    * Starts the schedule if the schedule is stopped otherwise nothing will happen.
+    * The Schedule is immediately set to started even the first call is in the future.
+    * @throws InvalidParameterException If any of the necessary values are not set or invalid
+    * (especially for the Schedulable class attributes).
+    */
    void startSchedule();
 
    /**
     * 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.    */
-   void stopSchedule(boolean pDoItNow);
+    * @param doItNow 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.
+    */
+   void stopSchedule(boolean doItNow);
 
    /**
     * Stops the server right now and starts it right now.
     */
    void restartSchedule();
-
-   java.lang.String getSchedulableClass();
-
-   /**
-    * Sets the fully qualified Class name of the Schedulable Class being called by the Scheduler. Must be set before the Schedule is started. Please also set the {@link #setSchedulableArguments} and {@link #setSchedulableArgumentTypes}.
-    * @param pSchedulableClass Fully Qualified Schedulable Class.
-    * @throws InvalidParameterException If the given value is not a valid class or cannot be loaded by the Scheduler or is not of instance Schedulable.    */
-   void setSchedulableClass(java.lang.String pSchedulableClass) throws java.security.InvalidParameterException;
-
-   java.lang.String getSchedulableArguments();
-
-   void setSchedulableArguments(java.lang.String pArgumentList);
-
-   java.lang.String getSchedulableArgumentTypes();
-
-   /**
-    * Sets the comma seperated list of argument types for the Schedulable class. This will be used to find the right constructor and to created the right instances to call the constructor with. This list must have as many elements as the Schedulable Arguments list otherwise the start of the Scheduler will fail. Right now only basic data types, String and Classes with a Constructor with a String as only argument are supported.
-    * @param pTypeList List of arguments used to create the Schedulable intance. If the list is null or empty then the no-args constructor is used.
-    * @throws InvalidParameterException If the given list contains a unknow datat type.    */
-   void setSchedulableArgumentTypes(java.lang.String pTypeList) throws java.security.InvalidParameterException;
-
-   java.lang.String getSchedulableMBean();
-
-   /**
-    * Sets the fully qualified JMX MBean name of the Schedulable MBean to be called. <b>Attention: </b>if set the all values set by {@link #setSchedulableClass}, {@link #setSchedulableArguments} and {@link #setSchedulableArgumentTypes} are cleared and not used anymore. Therefore only use either Schedulable Class or Schedulable MBean. If {@link #setSchedulableMBeanMethod} is not set then the schedule method as in the {@link Schedulable#perform} will be called with the same arguments. Also note that the Object Name will not be checked if the MBean is available. If the MBean is not available it will not be called but the remaining repetitions will be decreased.
-    * @param pSchedulableMBean JMX MBean Object Name which should be called.
-    * @throws InvalidParameterException If the given value is an valid Object Name.    */
-   void setSchedulableMBean(java.lang.String pSchedulableMBean) throws java.security.InvalidParameterException;
-
-   /**
-    * Sets the method name to be called on the Schedulable MBean. It can optionally be followed by an opening bracket, list of attributes (see below) and a closing bracket. The list of attributes can contain: <ul> <li>NOTIFICATION which will be replaced by the timers notification instance (javax.management.Notification)</li> <li>DATE which will be replaced by the date of the notification call (java.util.Date)</li> <li>REPETITIONS which will be replaced by the number of remaining repetitions (long)</li> <li>SCHEDULER_NAME which will be replaced by the Object Name of the Scheduler (javax.management.ObjectName)</li> <li>any full qualified Class name which the Scheduler will be set a "null" value for it</li> </ul> <br> An example could be: "doSomething( NOTIFICATION, REPETITIONS, java.lang.String )" where the Scheduler will pass the timer's notification instance, the remaining repetitions as int and a null to the MBean's doSomething() method which must have the following signat!
 ure: doSomething( javax.management.Notification, long, java.lang.String ).
-    * @param pSchedulableMBeanMethod Name of the method to be called optional followed by method arguments (see above).
-    * @throws InvalidParameterException If the given value is not of the right format    */
-   void setSchedulableMBeanMethod(java.lang.String pSchedulableMBeanMethod)
-         throws java.security.InvalidParameterException;
-
-   boolean isUsingMBean();
-
-   long getSchedulePeriod();
-
-   /**
-    * Sets the Schedule Period between two scheduled call.
-    * @param pPeriod Time between to scheduled calls (after the initial call) in Milliseconds. This value must be bigger than 0.
-    * @throws InvalidParameterException If the given value is less or equal than 0    */
-   void setSchedulePeriod(long pPeriod);
-
-   java.lang.String getDateFormat();
-
-   /**
-    * Sets the date format used to parse date/times
-    * @param dateFormat The date format when empty or null the locale is used to parse dates    */
-   void setDateFormat(java.lang.String dateFormat);
-
-   java.lang.String getInitialStartDate();
-
-   /**
-    * Sets the first scheduled call. If the date is in the past the scheduler tries to find the next available start date.
-    * @param pStartDate Date when the initial call is scheduled. It can be either: <ul> <li> NOW: date will be the current date (new Date()) plus 1 seconds </li><li> Date as String able to be parsed by SimpleDateFormat with default format </li><li> Date as String parsed using the date format attribute </li><li> Milliseconds since 1/1/1970 </li> </ul> If the date is in the past the Scheduler will search a start date in the future with respect to the initial repe- titions and the period between calls. This means that when you restart the MBean (restarting JBoss etc.) it will start at the next scheduled time. When no start date is available in the future the Scheduler will not start.<br> Example: if you start your Schedulable everyday at Noon and you restart your JBoss server then it will start at the next Noon (the same if started before Noon or the next day if start after Noon).    */
-   void setInitialStartDate(java.lang.String pStartDate);
-
-   long getInitialRepetitions();
-
-   /**
-    * Sets the initial number of scheduled calls.
-    * @param pNumberOfCalls Initial Number of scheduled calls. If -1 then the number is unlimted.
-    * @throws InvalidParameterException If the given value is less or equal than 0    */
-   void setInitialRepetitions(long pNumberOfCalls);
-
-   long getRemainingRepetitions();
-
-   boolean isStarted();
-
-   boolean isRestartPending();
-
-   boolean isStartAtStartup();
-
-   /**
-    * Set the scheduler to start when MBean started or not. Note that this method only affects when the {@link #startService startService()} gets called (normally at startup time.
-    * @param pStartAtStartup True if Schedule has to be started at startup time    */
-   void setStartAtStartup(boolean pStartAtStartup);
-
-   boolean isActive();
-
-   java.lang.String getTimerName();
-
-   void setTimerName(java.lang.String pTimerName);
-
 }




More information about the jboss-cvs-commits mailing list