Package org.xmlBlaster.contrib.scheduler

Source Code of org.xmlBlaster.contrib.scheduler.SchedulerPlugin$CronData

package org.xmlBlaster.contrib.scheduler;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.logging.Logger;

import org.quartz.Job;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.Trigger;
import org.quartz.TriggerUtils;
import org.xmlBlaster.contrib.GlobalInfo;
import org.xmlBlaster.contrib.InfoHelper;
import org.xmlBlaster.util.Global;
import org.xmlBlaster.util.XmlBlasterException;
import org.xmlBlaster.util.context.ContextNode;
import org.xmlBlaster.util.def.ErrorCode;
import org.xmlBlaster.util.plugin.PluginInfo;

public class SchedulerPlugin extends GlobalInfo implements SchedulerPluginMBean, Job {

   private final static String[] WEEK_NAMES = new String[] { "SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT" };
   private final static String[] MONTH_NAMES = new String[] { "___", "JAN", "FEB", "MAR", "APR", "MAY", "JUN",
                                                                 "JUL", "AUG", "SEP", "OCT", "NOV", "DEC" };

   private final static Logger log = Logger.getLogger(SchedulerPlugin.class.getName());
  
   /**
    *
    * The syntax for the configuration is as for crontab:
    *  http://www.adminschoice.com/docs/crontab.htm#Crontab%20file
    * 
    * .  *  *  *  *  *  command to be executed
    * .  -  -  -  -  -
    * .  |  |  |  |  |
    * .  |  |  |  |  +----- day of week (0 - 6) (Sunday=0)
    * .  |  |  |  +------- month (1 - 12)
    * .  |  |  +--------- day of month (1 - 31)
    * .  |  +----------- hour (0 - 23)
    * .  +------------- min (0 - 59)
    *  
   */
   public class CronData {
     
      private int min = -1;
      private int hour = -1;
      private int dayOfMonth = -1;
      private int dayOfWeek = -1;
      private int month = -1;
      private String command;
      private String[] arguments; // optional
      private final String name;
      private String rawText;
     
      public CronData(String name) {
         this.name = name;
      }
     
      private int getInt(StringTokenizer tokenizer) {
         try {
            String token = tokenizer.nextToken().trim();
            if ("*".equals(token))
               return -1;
            return Integer.parseInt(token);
         }
         catch (NumberFormatException ex) {
            ex.printStackTrace();
            return -1;
         }
      }
     
      private int getInt(StringTokenizer tokenizer, String[] names) {
         String token = tokenizer.nextToken().trim().toUpperCase();
         for (int i=0; i < names.length; i++) {
            if (token.startsWith(names[i]))
               return i;
         }
         try {
            if ("*".equals(token))
               return -1;
            return Integer.parseInt(token);
         }
         catch (NumberFormatException ex) {
            ex.printStackTrace();
            return -1;
         }
      }
     
      public void parse(String txt) throws XmlBlasterException {
         rawText = txt;
         StringTokenizer tokenizer = new StringTokenizer(txt, " ");
         int nmax = tokenizer.countTokens();
         if (nmax < 6)
            throw new XmlBlasterException(global, ErrorCode.RESOURCE, "SchedulerPlugin.doInit", "The string '" + txt + "' could not be parsed as a cron syntax");
         min = getInt(tokenizer);
         hour = getInt(tokenizer);
         dayOfMonth = getInt(tokenizer);
         month = getInt(tokenizer, MONTH_NAMES);
         dayOfWeek = getInt(tokenizer, WEEK_NAMES);
        
         command = tokenizer.nextToken().trim();
         int numArgs = nmax - 6;
         arguments = new String[numArgs];
         int i=0;
         while (tokenizer.hasMoreTokens()) {
            arguments[i] = tokenizer.nextToken().trim();
            i++;
         }
      }

      public String[] getArguments() {
         return arguments;
      }

      public String getCommand() {
         return command;
      }

      public int getDayOfWeek() {
         return dayOfWeek;
      }

      public int getDayOfMonth() {
         return dayOfMonth;
      }

      public int getHour() {
         return hour;
      }

      public int getMin() {
         return min;
      }

      public int getMonth() {
         return month;
      }
     
      public String getName() {
         return name;
      }
     
      public String getRawText() {
         return rawText;
      }
     
      public String toString() {
         StringBuffer buf = new StringBuffer(128);
         buf.append(name).append("\t");
         buf.append(rawText).append("\t(");
         if (min == -1)
            buf.append("* ");
         else
            buf.append(min);
         if (month != -1) {
            buf.append(" YEARLY TRIGGER NOT SUPPORTED");
            return buf.toString();
         }
         if (dayOfMonth != -1) {
            buf.append(" MONTLY ");
            buf.append(dayOfMonth).append(" ").append(hour).append(":").append(min);
         }
         else if (dayOfWeek != -1) {
            buf.append(" WEEKLY ");
            buf.append(WEEK_NAMES[dayOfWeek]).append(" ").append(hour).append(":").append(min);
         }
         else if (hour != -1) {
            buf.append(" DAILY ");
            buf.append(hour).append(":").append(min);

         }
         else if (min != -1) {
            buf.append(" HOURLY every hour at ");
            buf.append(min).append(" minute");
         }
         else {
            buf.append(" NOT SUPPORTED SINCE NOTHING CHOOSEN");
         }
         buf.append(")");
         return buf.toString();
      }
   }
  
   private Scheduler sched;
   private Map cronDataMap = new HashMap();
   private Object mbeanHandle;
  
   public SchedulerPlugin() {
      super((String[])null);
     
   }
  
   private void startSchedule(Scheduler sched, String name, CronData data) throws XmlBlasterException {
      try {
         log.info("Starting scheduler " + data.toString());
         Class clazz = Class.forName(data.getCommand());
         JobDetail jobDetail = new JobDetail(name, null, clazz);
         Object obj = global.getObjectEntry(ORIGINAL_ENGINE_GLOBAL);
         if (obj != null)
            jobDetail.getJobDataMap().put(ORIGINAL_ENGINE_GLOBAL, obj);
         else
            throw new XmlBlasterException(global, ErrorCode.INTERNAL, "SchedulerPlugin.doInit", "Could not find the ServerScope");
         String triggerName = name;
         Trigger trigger = null;
        
         if (data.getMonth() > -1)
            throw new XmlBlasterException(global, ErrorCode.USER_CONFIGURATION, "SchedulerPlugin.doInit", "Yearly Events are not implemented");

         int dayOfMonth = data.getDayOfMonth();
         int hour = data.getHour();
         int min = data.getMin();
         if (dayOfMonth > -1) { // monthly trigger
            if (hour < 0)
               throw new XmlBlasterException(this.global, ErrorCode.USER_CONFIGURATION, "SchedulerPlugin.doInit", "On monthly triggers the hour must be specified");
            if (min < 0)
               throw new XmlBlasterException(this.global, ErrorCode.USER_CONFIGURATION, "SchedulerPlugin.doInit", "On monthly triggers the min must be specified");
            trigger = TriggerUtils.makeMonthlyTrigger(triggerName, dayOfMonth, hour, min);
            trigger.setStartTime(new Date())// start now
         }
         else {
            int dayOfWeek = data.getDayOfWeek();
            if (dayOfWeek > -1) {
               if (hour < 0)
                  throw new XmlBlasterException(this.global, ErrorCode.USER_CONFIGURATION, "SchedulerPlugin.doInit", "On weekly triggers the hour must be specified");
               if (min < 0)
                  throw new XmlBlasterException(this.global, ErrorCode.USER_CONFIGURATION, "SchedulerPlugin.doInit", "On weekly triggers the min must be specified");
               trigger = TriggerUtils.makeWeeklyTrigger(triggerName, dayOfWeek+1, hour, min);
               trigger.setStartTime(new Date())// start now
            }
            else {
               if (hour > -1) {
                  if (min < 0)
                     throw new XmlBlasterException(this.global, ErrorCode.USER_CONFIGURATION, "SchedulerPlugin.doInit", "On daily triggers the min must be specified");
                  trigger = TriggerUtils.makeDailyTrigger(triggerName, hour, min);
                  trigger.setStartTime(new Date())// start now
               }
               else {
                  if (min > -1) {
                     trigger = TriggerUtils.makeHourlyTrigger(1);
                     trigger.setName(triggerName);
                     Date startTime = TriggerUtils.getNextGivenMinuteDate(new Date(), min);
                     trigger.setStartTime(startTime);
                  }
                  else {
                     throw new XmlBlasterException(global, ErrorCode.USER_CONFIGURATION, "SchedulerPlugin.doInit", "No time has been specified in the configuration");
                  }
               }
              
            }
         }
         String[] args = data.getArguments();
         for (int i=0; i < args.length; i++)
            jobDetail.getJobDataMap().put("arg" + i, args[i]);
         sched.scheduleJob(jobDetail, trigger);
         cronDataMap.put(name, data);
      }
      catch (ClassNotFoundException ex) {
         throw new XmlBlasterException(this.global, ErrorCode.RESOURCE, "", "SchedulerPlugin.doInit", ex);
      }
      catch (SchedulerException ex) {
         throw new XmlBlasterException(this.global, ErrorCode.RESOURCE, "", "SchedulerPlugin.doInit", ex);
      }
   }

   private synchronized CronData addSchedulerWithEx(String name, String value) throws SchedulerException, XmlBlasterException {
      CronData data = new CronData(name);
      data.parse(value);
      startSchedule(sched, name, data);
      return data;
   }
  
   public synchronized String removeScheduler(String name) {
      try {
         boolean ret = sched.deleteJob(name, null);
         String val = null;
         if (ret)
            val = "Scheduler '" + name + "' successfully removed";
         else
            val = "Scheduler '" + name + "' could not be removed: are you sure it existed ?";
         cronDataMap.remove(name);
         return val;
      }
      catch (SchedulerException ex) {
         ex.printStackTrace();
         return new String("Could not remove scheduler '" + name + "' because of exception : " + ex.getMessage());
      }
   }
  
   protected void doInit(Global glob, PluginInfo plugInfo) throws XmlBlasterException {
      SchedulerFactory schedFact = new org.quartz.impl.StdSchedulerFactory();
      try {
         String instanceName = getType();
         ContextNode contextNode = new ContextNode(ContextNode.SERVICE_MARKER_TAG, instanceName,
               this.global.getContextNode());
         if (!this.global.isRegisteredMBean(contextNode))
            this.mbeanHandle = this.global.registerMBean(contextNode, this);
        
         sched = schedFact.getScheduler();
         sched.start();
         String prefix = "scheduler.";
         Map map = InfoHelper.getPropertiesStartingWith(prefix, this, null);
         String[] keys = (String[])map.keySet().toArray( new String[map.size()]);
         for (int i=0; i < keys.length; i++) {
            String value = get("scheduler." + keys[i], "").trim();
            addSchedulerWithEx(keys[i], value);
         }
      }
      catch (SchedulerException ex) {
         throw new XmlBlasterException(this.global, ErrorCode.RESOURCE, "", "SchedulerPlugin.doInit", ex);
      }

   }
 
   public void execute(JobExecutionContext context) throws JobExecutionException {
      String jobName = context.getJobDetail().getName();
      String triggerName = context.getTrigger().getName();
      Date date = context.getFireTime();
     
      log.severe("");
      log.severe("SCHEDULER: FIRING trigger='" + triggerName + "' jobName='" + jobName + "' on date '" + date + "'");
      log.severe("");
   }
  
   public void shutdown() throws XmlBlasterException {
      try {
         global.unregisterMBean(mbeanHandle);
         sched.shutdown();
      }
      catch (SchedulerException ex) {
         ex.printStackTrace();
      }
      super.shutdown();
   }
  
   public String getSchedulerList() {
      StringBuffer buf = new StringBuffer(1024);
      CronData[] datas = null;
      synchronized(this) {
         datas = (CronData[])cronDataMap.values().toArray(new CronData[cronDataMap.size()]);
      }
      for (int i=0; i < datas.length; i++) {
         buf.append(datas[i].toString()).append("\n");
      }
      return buf.toString();
   }
  
   public String addScheduler(String name, String value) {
      try {
         removeScheduler(name); // make sure it removes it if it already exists
         CronData data = addSchedulerWithEx(name, value);
         return "Successfully added scheduler : " + data.toString();
      }
      catch (SchedulerException ex) {
         ex.printStackTrace();
         return "addScheduler failed because of an exception: "  + ex.getMessage();
      }
      catch (XmlBlasterException ex) {
         ex.printStackTrace();
         return "addScheduler failed because of an exception: "  + ex.getMessage();
      }
   }
  
   public String getJobNames() throws SchedulerException {
      String[] names = this.sched.getJobNames(null);
      StringBuffer buf = new StringBuffer(128);
      for (int i=0; i < names.length; i++)
         buf.append(names[i]).append(" ");
      return buf.toString();
   }
  
}
TOP

Related Classes of org.xmlBlaster.contrib.scheduler.SchedulerPlugin$CronData

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.