You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by cz...@apache.org on 2013/10/14 18:40:53 UTC

svn commit: r1531972 - in /sling/trunk/bundles/extensions/event: ./ src/main/java/org/apache/sling/event/impl/jobs/ src/main/java/org/apache/sling/event/impl/jobs/console/ src/main/java/org/apache/sling/event/impl/support/ src/main/java/org/apache/slin...

Author: cziegeler
Date: Mon Oct 14 16:40:52 2013
New Revision: 1531972

URL: http://svn.apache.org/r1531972
Log:
SLING-3166  : Job Scheduling Possibilities

Modified:
    sling/trunk/bundles/extensions/event/pom.xml
    sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/JobBuilderImpl.java
    sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/JobSchedulerImpl.java
    sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/console/InventoryPlugin.java
    sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/console/WebConsolePlugin.java
    sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/support/ResourceHelper.java
    sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/support/ScheduleInfoImpl.java
    sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/jobs/JobBuilder.java
    sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/jobs/ScheduleInfo.java

Modified: sling/trunk/bundles/extensions/event/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/event/pom.xml?rev=1531972&r1=1531971&r2=1531972&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/event/pom.xml (original)
+++ sling/trunk/bundles/extensions/event/pom.xml Mon Oct 14 16:40:52 2013
@@ -75,7 +75,8 @@
                         </Sling-Namespaces>
                         <Embed-Dependency>
                             jackrabbit-jcr-commons;inline="org/apache/jackrabbit/util/ISO9075.*|org/apache/jackrabbit/util/ISO8601.*|org/apache/jackrabbit/util/XMLChar.*",
-                            org.apache.sling.commons.osgi;inline="org/apache/sling/commons/osgi/PropertiesUtil.*"
+                            org.apache.sling.commons.osgi;inline="org/apache/sling/commons/osgi/PropertiesUtil.*",
+                            quartz;inline="org/quartz/CronExpression.*"
                         </Embed-Dependency>
                     </instructions>
                 </configuration>
@@ -235,6 +236,12 @@
             <version>2.2.4</version>
             <scope>provided</scope>
         </dependency>
+        <dependency>
+            <groupId>org.quartz-scheduler</groupId>
+            <artifactId>quartz</artifactId>
+            <version>2.2.0</version>
+            <scope>provided</scope>
+        </dependency>
       <!-- Webconsole -->
         <dependency>
             <groupId>javax.servlet</groupId>

Modified: sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/JobBuilderImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/JobBuilderImpl.java?rev=1531972&r1=1531971&r2=1531972&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/JobBuilderImpl.java (original)
+++ sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/JobBuilderImpl.java Mon Oct 14 16:40:52 2013
@@ -66,8 +66,7 @@ public class JobBuilderImpl implements J
         return new ScheduleBuilderImpl(name);
     }
 
-    public final class ScheduleBuilderImpl implements ScheduleBuilder,
-        WeekBuilder, DayBuilder, MinuteBuilder, DateBuilder, ScheduleBuilderAdder {
+    public final class ScheduleBuilderImpl implements ScheduleBuilder {
 
         private final String scheduleName;
 
@@ -80,44 +79,44 @@ public class JobBuilderImpl implements J
         }
 
         @Override
-        public WeekBuilder weekly(final int day, final int hour, final int minute) {
+        public ScheduleBuilder weekly(final int day, final int hour, final int minute) {
             schedules.add(ScheduleInfoImpl.WEEKLY(day, hour, minute));
             return this;
         }
 
         @Override
-        public DayBuilder daily(final int hour, final int minute) {
+        public ScheduleBuilder daily(final int hour, final int minute) {
             schedules.add(ScheduleInfoImpl.DAILY(hour, minute));
             return this;
         }
 
         @Override
-        public MinuteBuilder hourly(final int minute) {
+        public ScheduleBuilder hourly(final int minute) {
             schedules.add(ScheduleInfoImpl.HOURLY(minute));
             return this;
         }
 
         @Override
-        public DateBuilder at(final Date date) {
+        public ScheduleBuilder at(final Date date) {
             schedules.add(ScheduleInfoImpl.AT(date));
             return this;
         }
 
         @Override
-        public MinuteBuilder at(int minute) {
-            schedules.add(ScheduleInfoImpl.HOURLY(minute));
+        public ScheduleBuilder monthly(final int day, final int hour, final int minute) {
+            schedules.add(ScheduleInfoImpl.MONTHLY(day, hour, minute));
             return this;
         }
 
         @Override
-        public DayBuilder at(int hour, int minute) {
-            schedules.add(ScheduleInfoImpl.DAILY(hour, minute));
+        public ScheduleBuilder yearly(final int month, final int day, final int hour, final int minute) {
+            schedules.add(ScheduleInfoImpl.YEARLY(month, day, hour, minute));
             return this;
         }
 
         @Override
-        public WeekBuilder at(int day, int hour, int minute) {
-            schedules.add(ScheduleInfoImpl.WEEKLY(day, hour, minute));
+        public ScheduleBuilder cron(final String expression) {
+            schedules.add(ScheduleInfoImpl.CRON(expression));
             return this;
         }
 

Modified: sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/JobSchedulerImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/JobSchedulerImpl.java?rev=1531972&r1=1531971&r2=1531972&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/JobSchedulerImpl.java (original)
+++ sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/JobSchedulerImpl.java Mon Oct 14 16:40:52 2013
@@ -273,6 +273,9 @@ public class JobSchedulerImpl
                     case DAILY:
                     case WEEKLY:
                     case HOURLY:
+                    case MONTHLY:
+                    case YEARLY:
+                    case CRON:
                         options = this.scheduler.EXPR(((ScheduleInfoImpl)si).getCronExpression());
 
                         break;

Modified: sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/console/InventoryPlugin.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/console/InventoryPlugin.java?rev=1531972&r1=1531971&r2=1531972&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/console/InventoryPlugin.java (original)
+++ sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/console/InventoryPlugin.java Mon Oct 14 16:40:52 2013
@@ -196,7 +196,6 @@ public class InventoryPlugin implements 
             for(final ScheduledJobInfo info : infos) {
                 pw.printf("Schedule : %s%n", info.getName());
                 pw.printf("Job Topic< : %s%n", info.getJobTopic());
-                pw.printf("ScheduleType : %s%n", info.getSchedules().iterator().next().getType().name());
                 pw.print("Schedules : ");
                 boolean first = true;
                 for(final ScheduleInfo si : info.getSchedules() ) {
@@ -205,13 +204,19 @@ public class InventoryPlugin implements 
                     }
                     first = false;
                     switch ( si.getType() ) {
-                    case WEEKLY : pw.printf("%s : %s:%s", si.getDayOfWeek(), si.getHourOfDay(), si.getMinuteOfHour());
+                    case YEARLY : pw.printf("YEARLY %s %s : %s:%s", si.getMonthOfYear(), si.getDayOfMonth(), si.getHourOfDay(), si.getMinuteOfHour());
                                   break;
-                    case DAILY : pw.printf("%s:%s", si.getHourOfDay(), si.getMinuteOfHour());
+                    case MONTHLY : pw.printf("MONTHLY %s : %s:%s", si.getDayOfMonth(), si.getHourOfDay(), si.getMinuteOfHour());
+                                  break;
+                    case WEEKLY : pw.printf("WEEKLY %s : %s:%s", si.getDayOfWeek(), si.getHourOfDay(), si.getMinuteOfHour());
+                                  break;
+                    case DAILY : pw.printf("DAILY %s:%s", si.getHourOfDay(), si.getMinuteOfHour());
+                                 break;
+                    case HOURLY : pw.printf("HOURLY %s", si.getMinuteOfHour());
                                  break;
-                    case HOURLY : pw.printf("%s", si.getMinuteOfHour());
+                    case CRON : pw.printf("CRON %s", si.getExpression());
                                  break;
-                    default : pw.printf("%s", si.getAt());
+                    default : pw.printf("AT %s", si.getAt());
                     }
                 }
                 pw.println();

Modified: sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/console/WebConsolePlugin.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/console/WebConsolePlugin.java?rev=1531972&r1=1531971&r2=1531972&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/console/WebConsolePlugin.java (original)
+++ sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/console/WebConsolePlugin.java Mon Oct 14 16:40:52 2013
@@ -262,10 +262,10 @@ public class WebConsolePlugin extends Ht
         if ( infos.size() == 0 ) {
             pw.print("<tr><td colspan='5'>No jobs currently scheduled.</td></tr>");
         } else {
-            pw.println("<tr><th>Schedule</th><th>Job Topic</th><th>Schedule Type</th><th>Schedules</th></tr>");
+            pw.println("<tr><th>Schedule</th><th>Job Topic</th><th>Schedules</th></tr>");
             for(final ScheduledJobInfo info : infos) {
-                pw.printf("<tr><td><b>%s</b></td><td>%s</td><td>%s</td><td>",
-                        info.getName(), info.getJobTopic(), info.getSchedules().iterator().next().getType().name());
+                pw.printf("<tr><td><b>%s</b></td><td>%s</td><td>",
+                        info.getName(), info.getJobTopic());
                 boolean first = true;
                 for(final ScheduleInfo si : info.getSchedules() ) {
                     if ( !first ) {
@@ -273,13 +273,19 @@ public class WebConsolePlugin extends Ht
                     }
                     first = false;
                     switch ( si.getType() ) {
-                    case WEEKLY : pw.printf("%s : %s:%s", si.getDayOfWeek(), si.getHourOfDay(), si.getMinuteOfHour());
+                    case YEARLY : pw.printf("YEARLY %s %s : %s:%s", si.getMonthOfYear(), si.getDayOfMonth(), si.getHourOfDay(), si.getMinuteOfHour());
                                   break;
-                    case DAILY : pw.printf("%s:%s", si.getHourOfDay(), si.getMinuteOfHour());
+                    case MONTHLY : pw.printf("MONTHLY %s : %s:%s", si.getDayOfMonth(), si.getHourOfDay(), si.getMinuteOfHour());
+                                  break;
+                    case WEEKLY : pw.printf("WEEKLY %s : %s:%s", si.getDayOfWeek(), si.getHourOfDay(), si.getMinuteOfHour());
+                                  break;
+                    case DAILY : pw.printf("DAILY %s:%s", si.getHourOfDay(), si.getMinuteOfHour());
                                  break;
-                    case HOURLY : pw.printf("%s", si.getMinuteOfHour());
+                    case HOURLY : pw.printf("HOURLY %s", si.getMinuteOfHour());
                                  break;
-                    default : pw.printf("%s", si.getAt());
+                    case CRON : pw.printf("CRON %s", si.getExpression());
+                                  break;
+                    default : pw.printf("AT %s", si.getAt());
                     }
                 }
                 pw.print("</td></tr>");

Modified: sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/support/ResourceHelper.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/support/ResourceHelper.java?rev=1531972&r1=1531971&r2=1531972&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/support/ResourceHelper.java (original)
+++ sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/support/ResourceHelper.java Mon Oct 14 16:40:52 2013
@@ -23,6 +23,7 @@ import java.io.InputStream;
 import java.io.ObjectInputStream;
 import java.io.Serializable;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.BitSet;
 import java.util.HashMap;
 import java.util.List;
@@ -170,7 +171,10 @@ public abstract class ResourceHelper {
                 if ( entry.getKey().equals(PROPERTY_SCHEDULE_INFO) ) {
                     final String[] infoArray = vm.get(entry.getKey(), String[].class);
                     if ( infoArray == null || infoArray.length == 0 ) {
-                        hasReadError.add(new Exception("Unable to deserialize property '" + entry.getKey() + "'"));
+                        if ( hasReadError == null ) {
+                            hasReadError = new ArrayList<Exception>();
+                        }
+                        hasReadError.add(new Exception("Unable to deserialize property '" + entry.getKey() + "' : " + entry.getValue()));
                     } else {
                         final List<ScheduleInfo> infos = new ArrayList<ScheduleInfo>();
                         for(final String i : infoArray) {
@@ -180,7 +184,10 @@ public abstract class ResourceHelper {
                             }
                         }
                         if ( infos.size() < infoArray.length ) {
-                            hasReadError.add(new Exception("Unable to deserialize property '" + entry.getKey() + "'"));
+                            if ( hasReadError == null ) {
+                                hasReadError = new ArrayList<Exception>();
+                            }
+                            hasReadError.add(new Exception("Unable to deserialize property '" + entry.getKey() + "' : " + Arrays.toString(infoArray)));
                         } else {
                             entry.setValue(infos);
                         }

Modified: sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/support/ScheduleInfoImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/support/ScheduleInfoImpl.java?rev=1531972&r1=1531971&r2=1531972&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/support/ScheduleInfoImpl.java (original)
+++ sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/support/ScheduleInfoImpl.java Mon Oct 14 16:40:52 2013
@@ -19,11 +19,13 @@
 package org.apache.sling.event.impl.support;
 
 import java.io.Serializable;
+import java.text.ParseException;
 import java.util.Calendar;
 import java.util.Date;
 import java.util.List;
 
 import org.apache.sling.event.jobs.ScheduleInfo;
+import org.quartz.CronExpression;
 
 public class ScheduleInfoImpl implements ScheduleInfo, Serializable {
 
@@ -33,19 +35,31 @@ public class ScheduleInfoImpl implements
     private static final String VERSION = "1";
 
     public static ScheduleInfoImpl HOURLY(final int minutes) {
-        return new ScheduleInfoImpl(ScheduleType.HOURLY, -1, -1, minutes, null);
+        return new ScheduleInfoImpl(ScheduleType.HOURLY, -1, -1, minutes, null, -1, null);
+    }
+
+    public static ScheduleInfoImpl CRON(final String expr) {
+        return new ScheduleInfoImpl(ScheduleType.CRON, -1, -1, -1, null, -1, expr);
     }
 
     public static ScheduleInfoImpl AT(final Date at) {
-        return new ScheduleInfoImpl(ScheduleType.DATE, -1, -1, -1, at);
+        return new ScheduleInfoImpl(ScheduleType.DATE, -1, -1, -1, at, -1, null);
+    }
+
+    public static ScheduleInfoImpl YEARLY(final int month, final int day, final int hour, final int minute) {
+        return new ScheduleInfoImpl(ScheduleType.YEARLY, day, hour, minute, null, month, null);
+    }
+
+    public static ScheduleInfoImpl MONTHLY(final int day, final int hour, final int minute) {
+        return new ScheduleInfoImpl(ScheduleType.MONTHLY, day, hour, minute, null, -1, null);
     }
 
     public static ScheduleInfoImpl WEEKLY(final int day, final int hour, final int minute) {
-        return new ScheduleInfoImpl(ScheduleType.WEEKLY, day, hour, minute, null);
+        return new ScheduleInfoImpl(ScheduleType.WEEKLY, day, hour, minute, null, -1, null);
     }
 
     public static ScheduleInfoImpl DAILY(final int hour, final int minute) {
-        return new ScheduleInfoImpl(ScheduleType.DAILY, -1, hour, minute, null);
+        return new ScheduleInfoImpl(ScheduleType.DAILY, -1, hour, minute, null, -1, null);
     }
 
     private final ScheduleType scheduleType;
@@ -58,26 +72,60 @@ public class ScheduleInfoImpl implements
 
     private final Date at;
 
+    private final int monthOfYear;
+
+    private final String expression;
+
     private ScheduleInfoImpl(final ScheduleType scheduleType,
             final int dayOfWeek,
             final int hourOfDay,
             final int minuteOfHour,
-            final Date at) {
+            final Date at,
+            final int monthOfYear,
+            final String expression) {
         this.scheduleType = scheduleType;
         this.dayOfWeek = dayOfWeek;
         this.hourOfDay = hourOfDay;
         this.minuteOfHour = minuteOfHour;
         this.at = at;
+        this.monthOfYear = monthOfYear;
+        this.expression = expression;
     }
 
     public static ScheduleInfoImpl deserialize(final ScheduleType scheduleType, final String s) {
-        final String[] parts = s.split(":");
-        if ( scheduleType == ScheduleType.WEEKLY && parts.length == 3 ) {
+        final String[] parts = s.split("|");
+        if ( scheduleType == ScheduleType.YEARLY && parts.length == 4 ) {
             try {
                 return new ScheduleInfoImpl(scheduleType,
                         Integer.parseInt(parts[0]),
                         Integer.parseInt(parts[1]),
                         Integer.parseInt(parts[2]),
+                        null,
+                        Integer.parseInt(parts[3]),
+                        null);
+            } catch ( final IllegalArgumentException iae) {
+                // ignore and return null
+            }
+        } else if ( scheduleType == ScheduleType.MONTHLY && parts.length == 3 ) {
+            try {
+                return new ScheduleInfoImpl(scheduleType,
+                        Integer.parseInt(parts[0]),
+                        Integer.parseInt(parts[1]),
+                        Integer.parseInt(parts[2]),
+                        null,
+                        -1,
+                        null);
+            } catch ( final IllegalArgumentException iae) {
+                // ignore and return null
+            }
+        } else if ( scheduleType == ScheduleType.WEEKLY && parts.length == 3 ) {
+            try {
+                return new ScheduleInfoImpl(scheduleType,
+                        Integer.parseInt(parts[0]),
+                        Integer.parseInt(parts[1]),
+                        Integer.parseInt(parts[2]),
+                        null,
+                        -1,
                         null);
             } catch ( final IllegalArgumentException iae) {
                 // ignore and return null
@@ -88,6 +136,8 @@ public class ScheduleInfoImpl implements
                         -1,
                         Integer.parseInt(parts[0]),
                         Integer.parseInt(parts[1]),
+                        null,
+                        -1,
                         null);
             } catch ( final IllegalArgumentException iae) {
                 // ignore and return null
@@ -98,24 +148,41 @@ public class ScheduleInfoImpl implements
                         -1,
                         -1,
                         Integer.parseInt(parts[0]),
+                        null,
+                        -1,
                         null);
             } catch ( final IllegalArgumentException iae) {
                 // ignore and return null
             }
+        } else if ( scheduleType == ScheduleType.CRON && parts.length == 1 ) {
+            try {
+                return new ScheduleInfoImpl(scheduleType,
+                        -1,
+                        -1,
+                        -1,
+                        null,
+                        -1,
+                        parts[0]);
+            } catch ( final IllegalArgumentException iae) {
+                // ignore and return null
+            }
         }
 
         return null;
     }
 
     public static ScheduleInfoImpl deserialize(final String s) {
-        final String[] parts = s.split(":");
-        if ( parts.length == 6 && parts[0].equals(VERSION) ) {
+        final String[] parts = s.split("\\|");
+        if ( parts.length == 8 && parts[0].equals(VERSION) ) {
             try {
                 return new ScheduleInfoImpl(ScheduleType.valueOf(parts[1]),
                         Integer.parseInt(parts[2]),
                         Integer.parseInt(parts[3]),
                         Integer.parseInt(parts[4]),
-                        (parts[5].equals("null") ? null : new Date(Long.parseLong(parts[5]))));
+                        (parts[5].equals("null") ? null : new Date(Long.parseLong(parts[5]))),
+                        Integer.parseInt(parts[6]),
+                        (parts[7].equals("null") ? null : parts[7])
+                        );
             } catch ( final IllegalArgumentException iae) {
                 // ignore and return null
             }
@@ -126,20 +193,28 @@ public class ScheduleInfoImpl implements
     public String getSerializedString() {
         final StringBuilder sb = new StringBuilder();
         sb.append(VERSION);
-        sb.append(":");
+        sb.append("|");
         sb.append(this.scheduleType.name());
-        sb.append(":");
+        sb.append("|");
         sb.append(String.valueOf(this.dayOfWeek));
-        sb.append(":");
+        sb.append("|");
         sb.append(String.valueOf(this.hourOfDay));
-        sb.append(":");
+        sb.append("|");
         sb.append(String.valueOf(this.minuteOfHour));
-        sb.append(":");
+        sb.append("|");
         if ( at == null ) {
             sb.append("null");
         } else {
             sb.append(String.valueOf(at.getTime()));
         }
+        sb.append("|");
+        sb.append(String.valueOf(this.monthOfYear));
+        sb.append("|");
+        if ( expression == null ) {
+            sb.append("null");
+        } else {
+            sb.append(String.valueOf(expression));
+        }
         return sb.toString();
     }
 
@@ -155,7 +230,7 @@ public class ScheduleInfoImpl implements
 
     @Override
     public int getDayOfWeek() {
-        return this.dayOfWeek;
+        return (this.scheduleType == ScheduleType.WEEKLY ? this.dayOfWeek : -1);
     }
 
     @Override
@@ -168,6 +243,22 @@ public class ScheduleInfoImpl implements
         return this.minuteOfHour;
     }
 
+    @Override
+    public String getExpression() {
+        return this.expression;
+    }
+
+    @Override
+    public int getMonthOfYear() {
+        return this.monthOfYear;
+    }
+
+    @Override
+    public int getDayOfMonth() {
+        return (this.scheduleType == ScheduleType.MONTHLY
+                || this.scheduleType == ScheduleType.YEARLY ? this.dayOfWeek : -1);
+    }
+
     public void check(final List<String> errors) {
         switch ( this.scheduleType ) {
         case DAILY : if ( hourOfDay < 0 || hourOfDay > 23 || minuteOfHour < 0 || minuteOfHour > 59 ) {
@@ -189,6 +280,31 @@ public class ScheduleInfoImpl implements
                           errors.add("Day must be between 1 and 7 : " + dayOfWeek);
                       }
                       break;
+        case MONTHLY : if ( hourOfDay < 0 || hourOfDay > 23 || minuteOfHour < 0 || minuteOfHour > 59 ) {
+                           errors.add("Wrong time information : " + minuteOfHour + ":" + minuteOfHour);
+                       }
+                       if ( dayOfWeek < 1 || dayOfWeek > 28 ) {
+                           errors.add("Day must be between 1 and 28 : " + dayOfWeek);
+                       }
+                       break;
+        case YEARLY : if ( hourOfDay < 0 || hourOfDay > 23 || minuteOfHour < 0 || minuteOfHour > 59 ) {
+                          errors.add("Wrong time information : " + minuteOfHour + ":" + minuteOfHour);
+                      }
+                      if ( dayOfWeek < 1 || dayOfWeek > 28 ) {
+                          errors.add("Day must be between 1 and 28 : " + dayOfWeek);
+                      }
+                      if ( monthOfYear < 1 || monthOfYear > 12 ) {
+                          errors.add("Month must be between 1 and 12 : " + dayOfWeek);
+                      }
+                      break;
+        case CRON : if ( expression == null ) {
+                         errors.add("Expression must be specified.");
+                    }
+                    try {
+                        new CronExpression(this.expression);
+                    } catch (final ParseException e) {
+                        errors.add("Expression must be valid: " + this.expression);
+                    }
         }
     }
 
@@ -217,6 +333,29 @@ public class ScheduleInfoImpl implements
                               nextH.add(Calendar.HOUR_OF_DAY, 1);
                           }
                           return nextH.getTime();
+            case MONTHLY : final Calendar nextM = Calendar.getInstance();
+                           nextM.set(Calendar.HOUR_OF_DAY, this.hourOfDay);
+                           nextM.set(Calendar.MINUTE, this.minuteOfHour);
+                           nextM.set(Calendar.DAY_OF_MONTH, this.dayOfWeek);
+                           if ( nextM.before(now) ) {
+                               nextM.add(Calendar.MONTH, 1);
+                           }
+                           return nextM.getTime();
+            case YEARLY : final Calendar nextY = Calendar.getInstance();
+                          nextY.set(Calendar.HOUR_OF_DAY, this.hourOfDay);
+                          nextY.set(Calendar.MINUTE, this.minuteOfHour);
+                          nextY.set(Calendar.DAY_OF_MONTH, this.dayOfWeek);
+                          nextY.set(Calendar.MONTH, this.monthOfYear - 1);
+                          if ( nextY.before(now) ) {
+                              nextY.add(Calendar.YEAR, 1);
+                          }
+                          return nextY.getTime();
+            case CRON : try {
+                            final CronExpression exp = new CronExpression(this.expression);
+                            return exp.getNextValidTimeAfter(new Date());
+                        } catch (final ParseException e) {
+                            // as we check the expression in check() everything should be fine here
+                        }
         }
         return null;
     }
@@ -245,6 +384,28 @@ public class ScheduleInfoImpl implements
             sb.append(String.valueOf(this.minuteOfHour));
             sb.append(" * * * *");
             return sb.toString();
+        } else if ( this.scheduleType == ScheduleType.MONTHLY ) {
+            final StringBuilder sb = new StringBuilder("0 ");
+            sb.append(String.valueOf(this.minuteOfHour));
+            sb.append(' ');
+            sb.append(String.valueOf(this.hourOfDay));
+            sb.append(' ');
+            sb.append(String.valueOf(this.dayOfWeek));
+            sb.append(" * *");
+            return sb.toString();
+        } else if ( this.scheduleType == ScheduleType.YEARLY ) {
+            final StringBuilder sb = new StringBuilder("0 ");
+            sb.append(String.valueOf(this.minuteOfHour));
+            sb.append(' ');
+            sb.append(String.valueOf(this.hourOfDay));
+            sb.append(' ');
+            sb.append(String.valueOf(this.dayOfWeek));
+            sb.append(' ');
+            sb.append(String.valueOf(this.monthOfYear));
+            sb.append(" *");
+            return sb.toString();
+        } else if ( this.scheduleType == ScheduleType.CRON ) {
+            return this.expression;
         }
         return null;
     }

Modified: sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/jobs/JobBuilder.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/jobs/JobBuilder.java?rev=1531972&r1=1531971&r2=1531972&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/jobs/JobBuilder.java (original)
+++ sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/jobs/JobBuilder.java Mon Oct 14 16:40:52 2013
@@ -63,22 +63,6 @@ public interface JobBuilder {
      */
     ScheduleBuilder schedule(final String name);
 
-    public interface ScheduleBuilderAdder {
-
-        /**
-         * Finally add the job to the schedule
-         * @return Returns the info object if the job could be scheduled, <code>null</code>otherwise.
-         */
-        ScheduledJobInfo add();
-
-        /**
-         * Finally add the job to the schedule
-         * @param errors Optional list which will be filled with error messages.
-         * @return Returns the info object if the job could be scheduled, <code>null</code>otherwise.
-         */
-        ScheduledJobInfo add(final List<String> errors);
-    }
-
     /**
      * This is a builder interface for creating schedule information
      */
@@ -95,7 +79,7 @@ public interface JobBuilder {
          * If the minutes argument is less than 0 or higher than 59, the job can't be scheduled.
          * @param minute Between 0 and 59.
          */
-        MinuteBuilder hourly(final int minute);
+        ScheduleBuilder hourly(final int minute);
 
         /**
          * Schedule the job daily at the given time.
@@ -104,7 +88,7 @@ public interface JobBuilder {
          * @param hour  Hour of the day ranging from 0 to 23.
          * @param minute Minute of the hour ranging from 0 to 59.
          */
-        DayBuilder daily(final int hour, final int minute);
+        ScheduleBuilder daily(final int hour, final int minute);
 
         /**
          * Schedule the job weekly, the time needs to be specified in addition.
@@ -115,59 +99,57 @@ public interface JobBuilder {
          * @param hour  Hour of the day ranging from 0 to 23.
          * @param minute Minute of the hour ranging from 0 to 59.
          */
-        WeekBuilder weekly(final int day, final int hour, final int minute);
-
-        /**
-         * Schedule the job for a specific date.
-         * If no date or a a date in the past is provided, the job can't be scheduled.
-         * @param date The date
-         */
-        DateBuilder at(final Date date);
-    }
-
-    public interface WeekBuilder extends ScheduleBuilderAdder {
+        ScheduleBuilder weekly(final int day, final int hour, final int minute);
 
         /**
-         * Schedule the job for the given day, hour and minute.
-         * If a value lower than 1 or higher than 7 is used for the day, the job can't be scheduled.
+         * Schedule the job monthly, the time needs to be specified in addition.
+         * If a value lower than 1 or higher than 28 is used for the day, the job can't be scheduled.
          * If a value less than zero for hour or minute is specified or a value higher than 23 for hour or
          * a value higher than 59 for minute than the job can't be scheduled.
-         * @param day Day of the week, 1:Sunday, 2:Monday, ... 7:Saturday.
+         * @param day Day of the month from 1 to 28.
          * @param hour  Hour of the day ranging from 0 to 23.
          * @param minute Minute of the hour ranging from 0 to 59.
          */
-        WeekBuilder at(final int day, final int hour, final int minute);
-    }
-
-    public interface DayBuilder extends ScheduleBuilderAdder  {
+        ScheduleBuilder monthly(final int day, final int hour, final int minute);
 
         /**
-         * Schedule the job for the given hour and minute.
+         * Schedule the job yearly, the time needs to be specified in addition.
+         * If a value lower than 1 or higher than 12 is used for the month, the job can't be scheduled.
+         * If a value lower than 1 or higher than 28 is used for the day, the job can't be scheduled.
          * If a value less than zero for hour or minute is specified or a value higher than 23 for hour or
          * a value higher than 59 for minute than the job can't be scheduled.
+         * @param month Month of the year from 1 to 12.
+         * @param day Day of the month from 1 to 28.
          * @param hour  Hour of the day ranging from 0 to 23.
          * @param minute Minute of the hour ranging from 0 to 59.
          */
-        DayBuilder at(final int hour, final int minute);
-    }
-
-    public interface DateBuilder extends ScheduleBuilderAdder {
+        ScheduleBuilder yearly(final int month, final int day, final int hour, final int minute);
 
         /**
          * Schedule the job for a specific date.
          * If no date or a a date in the past is provided, the job can't be scheduled.
          * @param date The date
          */
-        DateBuilder at(final Date date);
-    }
+        ScheduleBuilder at(final Date date);
 
-    public interface MinuteBuilder extends ScheduleBuilderAdder {
+        /**
+         * Schedule the job for according to the cron expression.
+         * If no expression is specified, the job can't be scheduled.
+         * @param date The date
+         */
+        ScheduleBuilder cron(final String expression);
 
         /**
-         * Schedule the job hourly at the given minute.
-         * If the minutes argument is less than 0 or higher than 59, the job can't be scheduled.
-         * @param minute Between 0 and 59.
+         * Finally add the job to the schedule
+         * @return Returns the info object if the job could be scheduled, <code>null</code>otherwise.
          */
-        MinuteBuilder at(final int minute);
+        ScheduledJobInfo add();
+
+        /**
+         * Finally add the job to the schedule
+         * @param errors Optional list which will be filled with error messages.
+         * @return Returns the info object if the job could be scheduled, <code>null</code>otherwise.
+         */
+        ScheduledJobInfo add(final List<String> errors);
     }
 }
\ No newline at end of file

Modified: sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/jobs/ScheduleInfo.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/jobs/ScheduleInfo.java?rev=1531972&r1=1531971&r2=1531972&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/jobs/ScheduleInfo.java (original)
+++ sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/jobs/ScheduleInfo.java Mon Oct 14 16:40:52 2013
@@ -33,7 +33,10 @@ public interface ScheduleInfo {
         DATE,         // scheduled for a date
         HOURLY,       // scheduled hourly
         DAILY,        // scheduled once a day
-        WEEKLY        // scheduled once a week
+        WEEKLY,       // scheduled once a week
+        MONTHLY,      // scheduled once a month
+        YEARLY,       // scheduled once a year,
+        CRON          // scheduled according to the cron expression
     }
 
     /**
@@ -48,6 +51,24 @@ public interface ScheduleInfo {
     Date getAt();
 
     /**
+     * If the schedule is a cron expression, return the expression.
+     * @return The cron expression or <code>null</code>
+     */
+    String getExpression();
+
+    /**
+     * If the job is scheduled yearly, returns the month of the year
+     * @return The day of the year (from 1 to 12) or -1
+     */
+    int getMonthOfYear();
+
+    /**
+     * If the job is scheduled monthly, returns the day of the month
+     * @return The day of the month (from 1 to 28) or -1
+     */
+    int getDayOfMonth();
+
+    /**
      * If the job is scheduled weekly, returns the day of the week
      * @return The day of the week (from 1 to 7) or -1
      */