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/07 17:54:44 UTC

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

Author: cziegeler
Date: Mon Oct  7 15:54:43 2013
New Revision: 1529984

URL: http://svn.apache.org/r1529984
Log:
SLING-3139 : Provide a way to schedule jobs
SLING-3138 : Add fluent api to create new jobs

Modified:
    sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/EventPropertiesMap.java
    sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/JobProcessor.java
    sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/JobStatusProvider.java
    sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/JobsIterator.java
    sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/TimedEventStatusProvider.java
    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/JobManagerImpl.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/ScheduledJobInfoImpl.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/jobs/JobBuilder.java
    sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/jobs/ScheduledJobInfo.java

Modified: sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/EventPropertiesMap.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/EventPropertiesMap.java?rev=1529984&r1=1529983&r2=1529984&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/EventPropertiesMap.java (original)
+++ sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/EventPropertiesMap.java Mon Oct  7 15:54:43 2013
@@ -33,7 +33,9 @@ import org.osgi.service.event.Event;
  * An implementation of a map that helps in dealing with properties
  * of an OSGi event.
  * This map implements both, the map and the dictionary interfaces.
+ * @deprecated EventAdmin supports creating events with maps now as well.
  */
+@Deprecated
 public class EventPropertiesMap
     extends Dictionary<String, Object>
     implements Map<String, Object>, Serializable {

Modified: sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/JobProcessor.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/JobProcessor.java?rev=1529984&r1=1529983&r2=1529984&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/JobProcessor.java (original)
+++ sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/JobProcessor.java Mon Oct  7 15:54:43 2013
@@ -20,12 +20,15 @@ package org.apache.sling.event;
 
 import org.osgi.service.event.Event;
 
+import aQute.bnd.annotation.ConsumerType;
+
 /**
  * A job processor processes a job in the background.
  * It is used by {@link EventUtil#processJob(Event, JobProcessor)}.
  * @deprecated Use org.apache.sling.event.jobs.JobProcessor
  */
 @Deprecated
+@ConsumerType
 public interface JobProcessor extends org.apache.sling.event.jobs.JobProcessor {
 
     // just for compatibility

Modified: sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/JobStatusProvider.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/JobStatusProvider.java?rev=1529984&r1=1529983&r2=1529984&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/JobStatusProvider.java (original)
+++ sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/JobStatusProvider.java Mon Oct  7 15:54:43 2013
@@ -23,11 +23,14 @@ import java.util.Map;
 
 import org.osgi.service.event.Event;
 
+import aQute.bnd.annotation.ProviderType;
+
 /**
  * This service provides the current job processing status.
  * @deprecated
  */
 @Deprecated
+@ProviderType
 public interface JobStatusProvider {
 
     /**

Modified: sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/JobsIterator.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/JobsIterator.java?rev=1529984&r1=1529983&r2=1529984&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/JobsIterator.java (original)
+++ sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/JobsIterator.java Mon Oct  7 15:54:43 2013
@@ -20,6 +20,8 @@ package org.apache.sling.event;
 
 import org.osgi.service.event.Event;
 
+import aQute.bnd.annotation.ProviderType;
+
 /**
  * This <code>Iterator</code> allows to iterate over {@link Event}s.
  * In addition to an iterator it might return the number of elements
@@ -30,6 +32,7 @@ import org.osgi.service.event.Event;
  * @deprecated
  */
 @Deprecated
+@ProviderType
 public interface JobsIterator extends org.apache.sling.event.jobs.JobsIterator {
 
     /**

Modified: sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/TimedEventStatusProvider.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/TimedEventStatusProvider.java?rev=1529984&r1=1529983&r2=1529984&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/TimedEventStatusProvider.java (original)
+++ sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/TimedEventStatusProvider.java Mon Oct  7 15:54:43 2013
@@ -23,11 +23,14 @@ import java.util.Map;
 
 import org.osgi.service.event.Event;
 
+import aQute.bnd.annotation.ProviderType;
+
 /**
  * This service provides the current timed events status.
  * @deprecated Use scheduled jobs instead
  */
 @Deprecated
+@ProviderType
 public interface TimedEventStatusProvider {
 
     /**

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=1529984&r1=1529983&r2=1529984&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  7 15:54:43 2013
@@ -74,6 +74,8 @@ public class JobBuilderImpl implements J
 
         private final String scheduleName;
 
+        private boolean suspend = false;
+
         public ScheduleBuilderImpl(final String name) {
             this.scheduleName = name;
         }
@@ -96,7 +98,7 @@ public class JobBuilderImpl implements J
             if ( check() ) {
                 if ( minutes > 0 ) {
                     final ScheduleInfo info = ScheduleInfo.PERIODIC(minutes);
-                    return jobManager.addScheduledJob(topic, name, properties, scheduleName, info);
+                    return jobManager.addScheduledJob(topic, name, properties, scheduleName, suspend, info);
                 }
                 logger.warn("Discarding scheduled job - period must be higher than 0 : {}", minutes);
             }
@@ -118,13 +120,19 @@ public class JobBuilderImpl implements J
             if ( check() ) {
                 if ( date != null && date.getTime() > System.currentTimeMillis() ) {
                     final ScheduleInfo info = ScheduleInfo.AT(date);
-                    return jobManager.addScheduledJob(topic, name, properties, scheduleName, info);
+                    return jobManager.addScheduledJob(topic, name, properties, scheduleName, suspend, info);
                 }
                 logger.warn("Discarding scheduled job - date must be in the future : {}", date);
             }
             return false;
         }
 
+        @Override
+        public ScheduleBuilder suspend(final boolean flag) {
+            this.suspend = flag;
+            return this;
+        }
+
         public final class TimeBuilderImpl implements TimeBuilder {
 
             private final ScheduledJobInfo.ScheduleType scheduleType;
@@ -154,7 +162,7 @@ public class JobBuilderImpl implements J
                             } else {
                                 info = ScheduleInfo.DAYLY(hour, minute);
                             }
-                            return jobManager.addScheduledJob(topic, name, properties, scheduleName, info);
+                            return jobManager.addScheduledJob(topic, name, properties, scheduleName, suspend, info);
                         }
                         logger.warn("Discarding scheduled job - wrong time information : {}…{}", hour, minute);
                     }

Modified: sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/JobManagerImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/JobManagerImpl.java?rev=1529984&r1=1529983&r2=1529984&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/JobManagerImpl.java (original)
+++ sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/JobManagerImpl.java Mon Oct  7 15:54:43 2013
@@ -1461,9 +1461,10 @@ public class JobManagerImpl
             final String jobName,
             final Map<String, Object> properties,
             final String scheduleName,
+            final boolean isSuspended,
             final ScheduleInfo scheduleInfo) {
         try {
-            return this.jobScheduler.writeJob(topic, jobName, properties, scheduleName, scheduleInfo);
+            return this.jobScheduler.writeJob(topic, jobName, properties, scheduleName, isSuspended, scheduleInfo);
         } catch ( final PersistenceException pe) {
             logger.warn("Unable to persist scheduled job", pe);
         }

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=1529984&r1=1529983&r2=1529984&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  7 15:54:43 2013
@@ -38,6 +38,7 @@ import org.apache.jackrabbit.util.ISO860
 import org.apache.jackrabbit.util.ISO9075;
 import org.apache.sling.api.SlingConstants;
 import org.apache.sling.api.resource.LoginException;
+import org.apache.sling.api.resource.ModifiableValueMap;
 import org.apache.sling.api.resource.PersistenceException;
 import org.apache.sling.api.resource.QuerySyntaxException;
 import org.apache.sling.api.resource.Resource;
@@ -196,12 +197,19 @@ public class JobSchedulerImpl
                     final String jobTopic = (String) properties.remove(JobUtil.PROPERTY_JOB_TOPIC);
                     final String jobName = (String) properties.remove(JobUtil.PROPERTY_JOB_NAME);
                     final String schedulerName = (String) properties.remove(ResourceHelper.PROPERTY_SCHEDULER_NAME);
-                    final ScheduleInfo scheduleInfo = (ScheduleInfo)  properties.remove(ResourceHelper.PROPERTY_SCHEDULER_INFO);
-
+                    final ScheduleInfo scheduleInfo = (ScheduleInfo) properties.remove(ResourceHelper.PROPERTY_SCHEDULER_INFO);
+                    final boolean isSuspended = properties.remove(ResourceHelper.PROPERTY_SCHEDULER_SUSPENDED) != null;
                     // and now schedule
-                    final ScheduledJobInfoImpl info = new ScheduledJobInfoImpl(this, jobTopic, jobName, properties, schedulerName, scheduleInfo);
+                    final String key = ResourceHelper.filterName(schedulerName);
+                    ScheduledJobInfoImpl info;
                     synchronized ( this.scheduledJobs ) {
-                        this.scheduledJobs.put(ResourceHelper.filterName(schedulerName), info);
+                        info = this.scheduledJobs.get(key);
+                        if ( info == null ) {
+                            info = new ScheduledJobInfoImpl(this, jobTopic, jobName,
+                                    properties, schedulerName);
+                            this.scheduledJobs.put(key, info);
+                        }
+                        info.update(isSuspended, scheduleInfo);
                     }
                     if ( this.active ) {
                         this.startScheduledJob(info);
@@ -257,27 +265,29 @@ public class JobSchedulerImpl
     }
 
     private void startScheduledJob(final ScheduledJobInfoImpl info) {
-        // Create configuration for scheduled job
-        final Map<String, Serializable> config = new HashMap<String, Serializable>();
-        config.put(PROPERTY_READ_JOB, info);
+        if ( !info.isSuspended() ) {
+            // Create configuration for scheduled job
+            final Map<String, Serializable> config = new HashMap<String, Serializable>();
+            config.put(PROPERTY_READ_JOB, info);
 
-        logger.debug("Adding scheduled job: {}", info.getName());
-        try {
-            switch ( info.getScheduleType() ) {
-                case DAILY:
-                case WEEKLY:
-                    this.scheduler.addJob(info.getSchedulerJobId(), this, config, info.getCronExpression(), false);
-                    break;
-                case DATE:
-                    this.scheduler.fireJobAt(info.getSchedulerJobId(), this, config, info.getNextScheduledExecution());
-                    break;
-                case PERIODICALLY:
-                    this.scheduler.addPeriodicJob(info.getSchedulerJobId(), this, config, info.getPeriod() * 1000, false);
-                    break;
-                }
-        } catch (final Exception e) {
-            // we ignore it if scheduled fails...
-            this.ignoreException(e);
+            logger.debug("Adding scheduled job: {}", info.getName());
+            try {
+                switch ( info.getScheduleType() ) {
+                    case DAILY:
+                    case WEEKLY:
+                        this.scheduler.addJob(info.getSchedulerJobId(), this, config, info.getCronExpression(), false);
+                        break;
+                    case DATE:
+                        this.scheduler.fireJobAt(info.getSchedulerJobId(), this, config, info.getNextScheduledExecution());
+                        break;
+                    case PERIODICALLY:
+                        this.scheduler.addPeriodicJob(info.getSchedulerJobId(), this, config, info.getPeriod() * 1000, false);
+                        break;
+                    }
+            } catch (final Exception e) {
+                // we ignore it if scheduled fails...
+                this.ignoreException(e);
+            }
         }
     }
 
@@ -497,6 +507,7 @@ public class JobSchedulerImpl
             final String jobName,
             final Map<String, Object> jobProperties,
             final String schedulerName,
+            final boolean suspend,
             final ScheduleInfo scheduleInfo)
     throws PersistenceException {
         ResourceResolver resolver = null;
@@ -525,6 +536,9 @@ public class JobSchedulerImpl
             // put scheduler name and scheduler info
             properties.put(ResourceHelper.PROPERTY_SCHEDULER_NAME, schedulerName);
             properties.put(ResourceHelper.PROPERTY_SCHEDULER_INFO, scheduleInfo);
+            if ( suspend ) {
+                properties.put(ResourceHelper.PROPERTY_SCHEDULER_SUSPENDED, Boolean.TRUE);
+            }
 
             // create path and resource
             properties.put(ResourceResolver.PROPERTY_RESOURCE_TYPE, ResourceHelper.RESOURCE_TYPE_SCHEDULED_JOB);
@@ -590,7 +604,8 @@ public class JobSchedulerImpl
 
     public JobBuilder.ScheduleBuilder createJobBuilder(final ScheduledJobInfoImpl info) {
         final JobBuilder builder = this.jobManager.createJob(info.getJobTopic()).name(info.getJobTopic()).properties(info.getJobProperties());
-        return builder.schedule(info.getName());
+        final JobBuilder.ScheduleBuilder sb = builder.schedule(info.getName());
+        return sb.suspend(info.isSuspended());
     }
 
     public Collection<ScheduledJobInfo> getScheduledJobs() {
@@ -608,4 +623,35 @@ public class JobSchedulerImpl
             return this.scheduledJobs.get(ResourceHelper.filterName(name));
         }
     }
+
+    public void setSuspended(final ScheduledJobInfoImpl info, final boolean flag) {
+        ResourceResolver resolver = null;
+        try {
+            resolver = this.resourceResolverFactory.getAdministrativeResourceResolver(null);
+            final StringBuilder sb = new StringBuilder(this.config.getScheduledJobsPathWithSlash());
+            sb.append('/');
+            sb.append(ResourceHelper.filterName(info.getName()));
+            final String path = sb.toString();
+
+            final Resource eventResource = resolver.getResource(path);
+            if ( eventResource != null ) {
+                final ModifiableValueMap mvm = eventResource.adaptTo(ModifiableValueMap.class);
+                if ( flag ) {
+                    mvm.put(ResourceHelper.PROPERTY_SCHEDULER_SUSPENDED, Boolean.TRUE);
+                } else {
+                    mvm.remove(ResourceHelper.PROPERTY_SCHEDULER_SUSPENDED);
+                }
+                resolver.commit();
+            }
+        } catch (final LoginException le) {
+            this.ignoreException(le);
+        } catch (final PersistenceException pe) {
+            // we ignore the exception if removing fails
+            ignoreException(pe);
+        } finally {
+            if ( resolver != null ) {
+                resolver.close();
+            }
+        }
+    }
 }

Modified: sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/ScheduledJobInfoImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/ScheduledJobInfoImpl.java?rev=1529984&r1=1529983&r2=1529984&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/ScheduledJobInfoImpl.java (original)
+++ sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/ScheduledJobInfoImpl.java Mon Oct  7 15:54:43 2013
@@ -19,8 +19,10 @@
 package org.apache.sling.event.impl.jobs;
 
 import java.io.Serializable;
+import java.util.Calendar;
 import java.util.Date;
 import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.apache.sling.event.impl.support.ScheduleInfo;
 import org.apache.sling.event.jobs.Job;
@@ -39,88 +41,177 @@ public class ScheduledJobInfoImpl implem
 
     private final Map<String, Object> jobProperties;
 
-    private final ScheduleInfo scheduleInfo;
-
     private final JobSchedulerImpl jobScheduler;
 
+    private ScheduleInfo scheduleInfo;
+
+    private AtomicBoolean isSuspended;
+
     public ScheduledJobInfoImpl(final JobSchedulerImpl jobScheduler,
             final String jobTopic,
             final String jobName,
             final Map<String, Object> jobProperties,
-            final String scheduleName,
-            final ScheduleInfo scheduleInfo) {
+            final String scheduleName) {
         this.jobScheduler = jobScheduler;
         this.scheduleName = scheduleName;
         this.jobName = jobName;
         this.jobTopic = jobTopic;
         this.jobProperties = jobProperties;
+    }
+
+    public void update(final boolean isSuspended,
+            final ScheduleInfo scheduleInfo) {
         this.scheduleInfo = scheduleInfo;
+        this.isSuspended = new AtomicBoolean(isSuspended);
     }
 
+    /**
+     * @see org.apache.sling.event.jobs.ScheduledJobInfo#getName()
+     */
     @Override
     public String getName() {
         return this.scheduleName;
     }
 
+    /**
+     * @see org.apache.sling.event.jobs.ScheduledJobInfo#getScheduleType()
+     */
     @Override
     public ScheduleType getScheduleType() {
         return this.scheduleInfo.getScheduleType();
     }
 
+    /**
+     * @see org.apache.sling.event.jobs.ScheduledJobInfo#getNextScheduledExecution()
+     */
     @Override
     public Date getNextScheduledExecution() {
-        if ( this.scheduleInfo.getScheduleType() == ScheduleType.DATE ) {
-            return this.scheduleInfo.getAt();
+        final Calendar now = Calendar.getInstance();
+        switch ( this.scheduleInfo.getScheduleType() ) {
+            case DATE : return this.scheduleInfo.getAt();
+            case DAILY : final Calendar next = Calendar.getInstance();
+                         next.set(Calendar.HOUR_OF_DAY, this.getHourOfDay());
+                         next.set(Calendar.MINUTE, this.getMinuteOfHour());
+                         if ( next.before(now) ) {
+                             next.add(Calendar.DAY_OF_WEEK, 1);
+                         }
+                         return next.getTime();
+            case WEEKLY : final Calendar nextW = Calendar.getInstance();
+                          nextW.set(Calendar.HOUR_OF_DAY, this.getHourOfDay());
+                          nextW.set(Calendar.MINUTE, this.getMinuteOfHour());
+                          nextW.set(Calendar.DAY_OF_WEEK, this.getDayOfWeek());
+                          if ( nextW.before(now) ) {
+                              nextW.add(Calendar.WEEK_OF_YEAR, 1);
+                          }
+                          return nextW.getTime();
+            case PERIODICALLY : final Calendar nextP = Calendar.getInstance();
+                                nextP.add(Calendar.MINUTE, this.getPeriod()); // TODO - this is not correct
+                                return nextP.getTime();
         }
         return null;
     }
 
+    /**
+     * @see org.apache.sling.event.jobs.ScheduledJobInfo#getDayOfWeek()
+     */
     @Override
     public int getDayOfWeek() {
         return this.scheduleInfo.getDayOfWeek();
     }
 
+    /**
+     * @see org.apache.sling.event.jobs.ScheduledJobInfo#getHourOfDay()
+     */
     @Override
     public int getHourOfDay() {
         return this.scheduleInfo.getHourOfDay();
     }
 
+    /**
+     * @see org.apache.sling.event.jobs.ScheduledJobInfo#getMinuteOfHour()
+     */
     @Override
     public int getMinuteOfHour() {
         return this.scheduleInfo.getPeriod();
     }
 
+    /**
+     * @see org.apache.sling.event.jobs.ScheduledJobInfo#getPeriod()
+     */
     @Override
     public int getPeriod() {
         return this.scheduleInfo.getPeriod();
     }
 
+    /**
+     * @see org.apache.sling.event.jobs.ScheduledJobInfo#getJobTopic()
+     */
     @Override
     public String getJobTopic() {
         return this.jobTopic;
     }
 
+    /**
+     * @see org.apache.sling.event.jobs.ScheduledJobInfo#getJobName()
+     */
     @Override
     public String getJobName() {
         return this.jobName;
     }
 
+    /**
+     * @see org.apache.sling.event.jobs.ScheduledJobInfo#getJobProperties()
+     */
     @Override
     public Map<String, Object> getJobProperties() {
         return this.jobProperties;
     }
 
+    /**
+     * @see org.apache.sling.event.jobs.ScheduledJobInfo#unschedule()
+     */
     @Override
     public void unschedule() {
         this.jobScheduler.unschedule(this);
     }
 
+    /**
+     * @see org.apache.sling.event.jobs.ScheduledJobInfo#reschedule()
+     */
     @Override
     public ScheduleBuilder reschedule() {
         return this.jobScheduler.createJobBuilder(this);
     }
 
     /**
+     * @see org.apache.sling.event.jobs.ScheduledJobInfo#suspend()
+     */
+    @Override
+    public void suspend() {
+        if ( this.isSuspended.compareAndSet(false, true) ) {
+            this.jobScheduler.setSuspended(this, true);
+        }
+    }
+
+    /**
+     * @see org.apache.sling.event.jobs.ScheduledJobInfo#resume()
+     */
+    @Override
+    public void resume() {
+        if ( this.isSuspended.compareAndSet(true, false) ) {
+            this.jobScheduler.setSuspended(this, false);
+        }
+    }
+
+    /**
+     * @see org.apache.sling.event.jobs.ScheduledJobInfo#isSuspended()
+     */
+    @Override
+    public boolean isSuspended() {
+        return this.isSuspended.get();
+    }
+
+    /**
      * Get the scheduler job id
      */
     public String getSchedulerJobId() {

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=1529984&r1=1529983&r2=1529984&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  7 15:54:43 2013
@@ -58,6 +58,7 @@ public abstract class ResourceHelper {
 
     public static final String PROPERTY_SCHEDULER_NAME = "slingevent:schedulerName";
     public static final String PROPERTY_SCHEDULER_INFO = "slingevent:schedulerInfo";
+    public static final String PROPERTY_SCHEDULER_SUSPENDED = "slingevent:schedulerSuspended";
 
     /** List of ignored properties to write to the repository. */
     @SuppressWarnings("deprecation")
@@ -81,7 +82,8 @@ public abstract class ResourceHelper {
         JobImpl.PROPERTY_FINISHED_STATE,
         Job.PROPERTY_RESULT_MESSAGE,
         PROPERTY_SCHEDULER_INFO,
-        PROPERTY_SCHEDULER_NAME
+        PROPERTY_SCHEDULER_NAME,
+        PROPERTY_SCHEDULER_SUSPENDED
     };
 
     /**

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=1529984&r1=1529983&r2=1529984&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  7 15:54:43 2013
@@ -65,6 +65,11 @@ public interface JobBuilder {
     public interface ScheduleBuilder {
 
         /**
+         * Suspend this scheduling by default
+         */
+        ScheduleBuilder suspend(final boolean flag);
+
+        /**
          * Schedule the job periodically every N minutes.
          * If the minutes argument is less than 1, the job can't be scheduled.
          * @param minutes Positive number of minutes

Modified: sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/jobs/ScheduledJobInfo.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/jobs/ScheduledJobInfo.java?rev=1529984&r1=1529983&r2=1529984&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/jobs/ScheduledJobInfo.java (original)
+++ sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/jobs/ScheduledJobInfo.java Mon Oct  7 15:54:43 2013
@@ -103,7 +103,26 @@ public interface ScheduledJobInfo {
 
     /**
      * Reschedule this job with a new rescheduling information.
-     * If rescheduling fails, the job will be unscheduled.
+     * If rescheduling fails (due to wrong arguments), the job
+     * schedule is left as is.
      */
     JobBuilder.ScheduleBuilder reschedule();
+
+    /**
+     * Suspend this job scheduling.
+     * Job scheduling can be resumed with {@link #resume()}.
+     * This information is persisted and survives a restart.
+     */
+    void suspend();
+
+    /**
+     * Resume job processing. {@link #suspend()}. If the queue is not
+     * suspended, calling this method has no effect.
+     */
+    void resume();
+
+    /**
+     * Is the processing currently suspended?
+     */
+    boolean isSuspended();
 }