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/11 14:38:55 UTC
svn commit: r1531274 - in
/sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event:
impl/jobs/ impl/jobs/config/ impl/jobs/console/ impl/support/ jobs/
Author: cziegeler
Date: Fri Oct 11 12:38:55 2013
New Revision: 1531274
URL: http://svn.apache.org/r1531274
Log:
SLING-3139 : Provide a way to schedule jobs
Added:
sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/config/ScheduledJobConfiguration.java (with props)
sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/config/ScheduledJobConfigurationManager.java (with props)
Modified:
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/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=1531274&r1=1531273&r2=1531274&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 Fri Oct 11 12:38:55 2013
@@ -94,8 +94,8 @@ public class JobBuilderImpl implements J
}
@Override
- public DayBuilder dayly(final int hour, final int minute) {
- schedules.add(ScheduleInfoImpl.DAYLY(hour, minute));
+ public DayBuilder daily(final int hour, final int minute) {
+ schedules.add(ScheduleInfoImpl.DAILY(hour, minute));
return this;
}
@@ -119,7 +119,7 @@ public class JobBuilderImpl implements J
@Override
public DayBuilder at(int hour, int minute) {
- schedules.add(ScheduleInfoImpl.DAYLY(hour, minute));
+ schedules.add(ScheduleInfoImpl.DAILY(hour, minute));
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=1531274&r1=1531273&r2=1531274&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 Fri Oct 11 12:38:55 2013
@@ -56,7 +56,6 @@ import org.apache.sling.event.impl.suppo
import org.apache.sling.event.impl.support.ScheduleInfoImpl;
import org.apache.sling.event.jobs.Job;
import org.apache.sling.event.jobs.JobBuilder;
-import org.apache.sling.event.jobs.JobUtil;
import org.apache.sling.event.jobs.ScheduleInfo;
import org.apache.sling.event.jobs.ScheduledJobInfo;
import org.osgi.service.event.Event;
@@ -272,7 +271,7 @@ public class JobSchedulerImpl
final String name = info.getSchedulerJobId() + "-" + String.valueOf(index);
ScheduleOptions options = null;
switch ( si.getType() ) {
- case DAYLY:
+ case DAILY:
case WEEKLY:
case HOURLY:
options = this.scheduler.EXPR(((ScheduleInfoImpl)si).getCronExpression());
Added: sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/config/ScheduledJobConfiguration.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/config/ScheduledJobConfiguration.java?rev=1531274&view=auto
==============================================================================
--- sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/config/ScheduledJobConfiguration.java (added)
+++ sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/config/ScheduledJobConfiguration.java Fri Oct 11 12:38:55 2013
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.event.impl.jobs.config;
+
+import java.util.Map;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.ConfigurationPolicy;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Properties;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.PropertyOption;
+import org.apache.felix.scr.annotations.PropertyUnbounded;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.event.impl.support.ResourceHelper;
+import org.osgi.framework.Constants;
+
+@Component(name="org.apache.sling.event.jobs.ScheduledJobConfiguration",
+ configurationFactory=true,policy=ConfigurationPolicy.REQUIRE,
+ metatype=true, label="Apache Sling Scheduled Job",
+ description="Configuration for a scheduled job.")
+@Service(value={ScheduledJobConfiguration.class})
+@Properties({
+ @Property(name=ResourceHelper.PROPERTY_SCHEDULE_NAME, label="Schedule Name", description="Unique schedule name", value=""),
+ @Property(name=ResourceHelper.PROPERTY_JOB_TOPIC, label="Job Topic", description="The topic of the scheduled job.", value=""),
+ @Property(name=ResourceHelper.PROPERTY_SCHEDULE_INFO_TYPE, label="Schedule Type", description="Define the schedule frequency.",
+ value="WEEKLY",
+ options={@PropertyOption(name="WEEKLY",value="Weekly"),
+ @PropertyOption(name="DAILY",value="Daily"),
+ @PropertyOption(name="HOURLY",value="Hourly")}),
+ @Property(name=ResourceHelper.PROPERTY_SCHEDULE_INFO, unbounded=PropertyUnbounded.ARRAY, value="",
+ label="Schedules", description="This value depends on the type. For a weekly schedule three numbers"
+ + " separated by a colon must be used for each schedule, the first number specifying the day (1-7)"
+ + " the second the hour (0-23) and the third the minute (0-59). For a daily schedule two numbers"
+ + " separated by a colon for hour and minute must be specified and for hourly a single number"
+ + " (0-59) for the minute is required."),
+ @Property(name=ResourceHelper.PROPERTY_SCHEDULE_SUSPENDED, boolValue=false,
+ label="Suspended", description="If this flag is set, the schedule is currently suspended (inactive)"),
+ @Property(name=Constants.SERVICE_RANKING, intValue=0, propertyPrivate=false,
+ label="Ranking", description="Configuration ranking - if there is more than one configuration"
+ +" with the same name, the one with the highest ranking is used.")
+})
+public class ScheduledJobConfiguration {
+
+
+ private Map<String, Object> configuration;
+
+ @Activate
+ protected void activate(final Map<String, Object> configuration) {
+ this.configuration = configuration;
+ }
+
+ @Deactivate
+ protected void deactivate() {
+ this.configuration = null;
+ }
+
+ public Map<String, Object> getConfiguration() {
+ return this.configuration;
+ }
+}
Propchange: sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/config/ScheduledJobConfiguration.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/config/ScheduledJobConfiguration.java
------------------------------------------------------------------------------
svn:keywords = author date id revision rev url
Propchange: sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/config/ScheduledJobConfiguration.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/config/ScheduledJobConfigurationManager.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/config/ScheduledJobConfigurationManager.java?rev=1531274&view=auto
==============================================================================
--- sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/config/ScheduledJobConfigurationManager.java (added)
+++ sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/config/ScheduledJobConfigurationManager.java Fri Oct 11 12:38:55 2013
@@ -0,0 +1,286 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.event.impl.jobs.config;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.ReferencePolicy;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.commons.osgi.PropertiesUtil;
+import org.apache.sling.discovery.TopologyEvent;
+import org.apache.sling.discovery.TopologyEvent.Type;
+import org.apache.sling.discovery.TopologyEventListener;
+import org.apache.sling.event.impl.jobs.JobManagerImpl;
+import org.apache.sling.event.impl.jobs.Utility;
+import org.apache.sling.event.impl.support.ResourceHelper;
+import org.apache.sling.event.impl.support.ScheduleInfoImpl;
+import org.apache.sling.event.jobs.JobManager;
+import org.apache.sling.event.jobs.ScheduleInfo;
+import org.apache.sling.event.jobs.ScheduledJobInfo;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Component handling scheduled job OSGi configurations
+ */
+@Component
+@Service(value=TopologyEventListener.class)
+@Reference(name="config", cardinality=ReferenceCardinality.OPTIONAL_MULTIPLE,
+ policy=ReferencePolicy.DYNAMIC, referenceInterface=ScheduledJobConfiguration.class)
+public class ScheduledJobConfigurationManager implements TopologyEventListener {
+
+ private final Logger logger = LoggerFactory.getLogger(this.getClass());
+
+ private final AtomicBoolean isLeader = new AtomicBoolean(false);
+
+ private final Map<String, List<Schedule>> configs = new HashMap<String, List<Schedule>>();
+
+ @Reference
+ private JobManager jobManager;
+
+ @Override
+ public void handleTopologyEvent(final TopologyEvent event) {
+ if ( event.getType() == Type.TOPOLOGY_CHANGED || event.getType() == Type.TOPOLOGY_INIT ) {
+ synchronized ( this.configs ) {
+ final boolean wasLeader = this.isLeader.get();
+ this.isLeader.set(event.getNewView().getLocalInstance().isLeader());
+ if ( !wasLeader && this.isLeader.get() ) {
+ this.updateSchedules();
+ }
+ }
+ }
+ }
+
+ /**
+ * Bind a new configuration
+ */
+ protected void bindConfig(final ScheduledJobConfiguration config, final Map<String, Object> properties) {
+ // create schedule
+ final Schedule schedule = new Schedule(config, properties);
+
+ if ( schedule.errors.size() > 0 ) {
+ logger.warn("Ignoring job schedule configuration: {}. Reason(s): {}", schedule,
+ schedule.errors);
+ return;
+ }
+
+ synchronized ( configs ) {
+ List<Schedule> schedules = this.configs.get(schedule.scheduleName);
+ if ( schedules == null ) {
+ schedules = new ArrayList<ScheduledJobConfigurationManager.Schedule>();
+ this.configs.put(schedule.scheduleName, schedules);
+ }
+ schedules.add(schedule);
+ Collections.sort(schedules);
+ if ( this.isLeader.get() && schedules.get(0) == schedule ) {
+ if ( schedules.size() > 1 ) {
+ this.stop(schedule.scheduleName);
+ }
+ }
+ }
+ }
+
+ /**
+ * Unbind a configuration
+ */
+ protected void unbindConfig(final ServiceReference ref) {
+ final String scheduleName = PropertiesUtil.toString(ref.getProperty(ResourceHelper.PROPERTY_SCHEDULE_NAME), null);
+ if ( scheduleName != null && scheduleName.length() > 0 ) {
+ final long serviceId = (Long)ref.getProperty(Constants.SERVICE_ID);
+ synchronized ( configs ) {
+ List<Schedule> schedules = this.configs.get(scheduleName);
+ if ( schedules != null ) {
+ boolean isFirst = true;
+ boolean update = false;
+ final Iterator<Schedule> i = schedules.iterator();
+ while ( i.hasNext() ) {
+ final Schedule current = i.next();
+ if ( current.serviceId == serviceId ) {
+ if ( isFirst ) {
+ update = true;
+ }
+ i.remove();
+ break;
+ }
+ isFirst = false;
+ }
+ if ( schedules.size() == 0 ) {
+ this.configs.remove(scheduleName);
+ }
+ if ( update && this.isLeader.get() ) {
+ this.stop(scheduleName);
+ if ( schedules.size() > 0 ) {
+ this.start(schedules.get(0));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private void start(final Schedule s) {
+ final List<String> errors = new ArrayList<String>();
+ ((JobManagerImpl)jobManager).addScheduledJob(s.jobTopic, null, s.jobProperties, s.scheduleName, s.suspended, s.scheduleInfos, errors);
+ if ( errors.size() > 0 ) {
+ logger.error("Unable to schedule job from configuration: {} : {}", errors, s);
+ }
+ }
+
+ private void stop(final String scheduleName) {
+ final ScheduledJobInfo info = this.jobManager.getScheduledJob(scheduleName);
+ if ( info != null ) {
+ info.unschedule();
+ }
+ }
+
+ private void updateSchedules() {
+ for(final List<Schedule> schedules : this.configs.values() ) {
+ final Schedule s = schedules.get(0);
+ this.start(s);
+ }
+ }
+
+ private static final class Schedule implements Comparable<Schedule> {
+
+ public final int ranking;
+ public final long serviceId;
+ public final ScheduleInfo.ScheduleType scheduleType;
+ public final String jobTopic;
+ public final String scheduleName;
+ public final boolean suspended;
+ public final Map<String, Object> jobProperties;
+ public final List<ScheduleInfoImpl> scheduleInfos = new ArrayList<ScheduleInfoImpl>();
+
+ public final List<String> errors = new ArrayList<String>();
+
+ public Schedule(final ScheduledJobConfiguration config, final Map<String, Object> properties) {
+ final Object sr = properties.get(Constants.SERVICE_RANKING);
+ if ( sr == null || !(sr instanceof Integer)) {
+ this.ranking = 0;
+ } else {
+ this.ranking = (Integer)sr;
+ }
+ this.serviceId = (Long)properties.get(Constants.SERVICE_ID);
+ final Map<String, Object> configProperties = config.getConfiguration();
+ // type
+ final String scheduleTypeString = PropertiesUtil.toString(configProperties.get(ResourceHelper.PROPERTY_SCHEDULE_INFO_TYPE), null);
+ ScheduleInfo.ScheduleType sType = null;
+ if ( scheduleTypeString != null ) {
+ try {
+ sType = ScheduleInfo.ScheduleType.valueOf(scheduleTypeString);
+ } catch ( final IllegalArgumentException iae) {
+ // ignore
+ }
+ }
+ this.scheduleType = sType;
+ if ( this.scheduleType == null ) {
+ this.errors.add("No valid schedule type set: " + scheduleTypeString);
+ } else {
+ // Schedule info
+ final String[] scheduleConfigs = PropertiesUtil.toStringArray(configProperties.get(ResourceHelper.PROPERTY_SCHEDULE_INFO), null);
+ if ( scheduleConfigs != null ) {
+ for(final String s : scheduleConfigs) {
+ final ScheduleInfoImpl info = ScheduleInfoImpl.deserialize(this.scheduleType, s.trim());
+ if ( info != null ) {
+ this.scheduleInfos.add(info);
+ }
+ }
+ }
+ if ( this.scheduleInfos.size() == 0 || this.scheduleInfos.size() < scheduleConfigs.length ) {
+ this.errors.add("Either no schedules or invalid schedules found: " + Arrays.toString(scheduleConfigs));
+ }
+ }
+ this.jobTopic = PropertiesUtil.toString(configProperties.get(ResourceHelper.PROPERTY_JOB_TOPIC), null);
+ this.scheduleName = PropertiesUtil.toString(configProperties.get(ResourceHelper.PROPERTY_SCHEDULE_NAME), null);
+ this.suspended = PropertiesUtil.toBoolean(configProperties.get(ResourceHelper.PROPERTY_SCHEDULE_SUSPENDED), false);
+ this.jobProperties = new HashMap<String, Object>(configProperties);
+ final Iterator<String> nameIter = this.jobProperties.keySet().iterator();
+ while ( nameIter.hasNext() ) {
+ final String name = nameIter.next();
+ if ( name.startsWith("service.")
+ || name.startsWith("component.")
+ || name.equals(ResourceHelper.PROPERTY_SCHEDULE_NAME)
+ || name.equals(ResourceHelper.PROPERTY_SCHEDULE_INFO)
+ || name.equals(ResourceHelper.PROPERTY_SCHEDULE_INFO_TYPE)
+ || name.equals(ResourceHelper.PROPERTY_SCHEDULE_SUSPENDED)
+ || name.equals(ResourceHelper.PROPERTY_JOB_TOPIC) ) {
+ nameIter.remove();
+ }
+ }
+
+ if ( this.scheduleName == null || this.scheduleName.trim().length() == 0 ) {
+ this.errors.add("Schedule name missign.");
+ return;
+ }
+ final String errorMessage = Utility.checkJob(this.jobTopic, this.jobProperties);
+ if ( errorMessage != null ) {
+ this.errors.add(errorMessage);
+ }
+ for(final ScheduleInfoImpl info : this.scheduleInfos) {
+ info.check(this.errors);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "Schedule [ranking=" + ranking + ", serviceId=" + serviceId
+ + ", scheduleType=" + scheduleType + ", jobTopic="
+ + jobTopic + ", scheduleName=" + scheduleName
+ + ", suspended=" + suspended + ", jobProperties="
+ + jobProperties + ", scheduleInfos=" + scheduleInfos + ", errors=" + errors
+ + "]";
+ }
+
+ @Override
+ public int compareTo(final Schedule o) {
+ if ( this.ranking < o.ranking ) {
+ return 1;
+ } else if (this.ranking > o.ranking ) {
+ return -1;
+ }
+ // If ranks are equal, then sort by service id in descending order.
+ return (this.serviceId < o.serviceId) ? -1 : 1;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if ( obj instanceof Schedule ) {
+ return ((Schedule)obj).serviceId == this.serviceId;
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return this.scheduleName.hashCode();
+ }
+ }
+}
Propchange: sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/config/ScheduledJobConfigurationManager.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/config/ScheduledJobConfigurationManager.java
------------------------------------------------------------------------------
svn:keywords = author date id revision rev url
Propchange: sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/config/ScheduledJobConfigurationManager.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
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=1531274&r1=1531273&r2=1531274&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 Fri Oct 11 12:38:55 2013
@@ -23,6 +23,7 @@ import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
@@ -44,6 +45,8 @@ import org.apache.sling.event.impl.jobs.
import org.apache.sling.event.jobs.JobManager;
import org.apache.sling.event.jobs.Queue;
import org.apache.sling.event.jobs.QueueConfiguration;
+import org.apache.sling.event.jobs.ScheduleInfo;
+import org.apache.sling.event.jobs.ScheduledJobInfo;
import org.apache.sling.event.jobs.Statistics;
import org.apache.sling.event.jobs.TopicStatistics;
@@ -184,6 +187,43 @@ public class InventoryPlugin implements
}
pw.println();
+ pw.println("Scheduled Jobs");
+ pw.println("<table class='nicetable'><tbody>");
+ final Collection<ScheduledJobInfo> infos = this.jobManager.getScheduledJobs();
+ if ( infos.size() == 0 ) {
+ pw.print("No jobs currently scheduled");
+ } else {
+ pw.println("<tr><th>Schedule</th><th>Job Topic</th><th>Job Name</th><th>Schedule Type</th><th>Schedules</th></tr>");
+ for(final ScheduledJobInfo info : infos) {
+ pw.printf("Schedule : %s%n", info.getName());
+ pw.printf("Job Topic< : %s%n", info.getJobTopic());
+ if ( info.getJobName() != null ) {
+ pw.printf("Schedule : %s%n", info.getJobName());
+ }
+ pw.printf("ScheduleType : %s%n", info.getSchedules().iterator().next().getType().name());
+ pw.print("Schedules : ");
+ boolean first = true;
+ for(final ScheduleInfo si : info.getSchedules() ) {
+ if ( !first ) {
+ pw.print(", ");
+ }
+ first = false;
+ switch ( si.getType() ) {
+ case WEEKLY : pw.printf("%s : %s:%s", si.getDayOfWeek(), si.getHourOfDay(), si.getMinuteOfHour());
+ break;
+ case DAILY : pw.printf("%s:%s", si.getHourOfDay(), si.getMinuteOfHour());
+ break;
+ case HOURLY : pw.printf("%s", si.getMinuteOfHour());
+ break;
+ default : pw.printf("%s", si.getAt());
+ }
+ }
+ pw.println();
+ pw.println();
+ }
+ }
+ pw.println();
+
boolean isEmpty = true;
for(final Queue q : this.jobManager.getQueues()) {
isEmpty = false;
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=1531274&r1=1531273&r2=1531274&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 Fri Oct 11 12:38:55 2013
@@ -22,6 +22,7 @@ import java.io.IOException;
import java.io.PrintWriter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
+import java.util.Collection;
import java.util.Date;
import java.util.Dictionary;
import java.util.Hashtable;
@@ -49,6 +50,8 @@ import org.apache.sling.event.jobs.JobMa
import org.apache.sling.event.jobs.JobUtil;
import org.apache.sling.event.jobs.Queue;
import org.apache.sling.event.jobs.QueueConfiguration;
+import org.apache.sling.event.jobs.ScheduleInfo;
+import org.apache.sling.event.jobs.ScheduledJobInfo;
import org.apache.sling.event.jobs.Statistics;
import org.apache.sling.event.jobs.TopicStatistics;
import org.osgi.service.event.Event;
@@ -267,6 +270,38 @@ public class WebConsolePlugin extends Ht
pw.println("</tbody></table>");
pw.println("<br/>");
+ pw.println("<p class='statline'>Scheduled Jobs</p>");
+ pw.println("<table class='nicetable'><tbody>");
+ final Collection<ScheduledJobInfo> infos = this.jobManager.getScheduledJobs();
+ 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>Job Name</th><th>Schedule Type</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>%s</td><td>",
+ info.getName(), info.getJobTopic(), info.getJobName(), info.getSchedules().iterator().next().getType().name());
+ boolean first = true;
+ for(final ScheduleInfo si : info.getSchedules() ) {
+ if ( !first ) {
+ pw.print("<br/>");
+ }
+ first = false;
+ switch ( si.getType() ) {
+ case WEEKLY : pw.printf("%s : %s:%s", si.getDayOfWeek(), si.getHourOfDay(), si.getMinuteOfHour());
+ break;
+ case DAILY : pw.printf("%s:%s", si.getHourOfDay(), si.getMinuteOfHour());
+ break;
+ case HOURLY : pw.printf("%s", si.getMinuteOfHour());
+ break;
+ default : pw.printf("%s", si.getAt());
+ }
+ }
+ pw.print("</td></tr>");
+ }
+ }
+ pw.println("</tbody></table>");
+ pw.println("<br/>");
+
boolean isEmpty = true;
for(final Queue q : this.jobManager.getQueues()) {
isEmpty = false;
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=1531274&r1=1531273&r2=1531274&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 Fri Oct 11 12:38:55 2013
@@ -59,6 +59,7 @@ public abstract class ResourceHelper {
public static final String PROPERTY_SCHEDULE_NAME = "slingevent:scheduleName";
public static final String PROPERTY_SCHEDULE_INFO = "slingevent:scheduleInfo";
+ public static final String PROPERTY_SCHEDULE_INFO_TYPE = "slingevent:scheduleInfoType";
public static final String PROPERTY_SCHEDULE_SUSPENDED = "slingevent:scheduleSuspended";
public static final String PROPERTY_JOB_ID = "slingevent:eventId";
@@ -88,6 +89,7 @@ public abstract class ResourceHelper {
Job.PROPERTY_RESULT_MESSAGE,
PROPERTY_SCHEDULE_INFO,
PROPERTY_SCHEDULE_NAME,
+ PROPERTY_SCHEDULE_INFO_TYPE,
PROPERTY_SCHEDULE_SUSPENDED
};
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=1531274&r1=1531273&r2=1531274&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 Fri Oct 11 12:38:55 2013
@@ -44,8 +44,8 @@ public class ScheduleInfoImpl implements
return new ScheduleInfoImpl(ScheduleType.WEEKLY, day, hour, minute, null);
}
- public static ScheduleInfoImpl DAYLY(final int hour, final int minute) {
- return new ScheduleInfoImpl(ScheduleType.DAYLY, -1, hour, minute, null);
+ public static ScheduleInfoImpl DAILY(final int hour, final int minute) {
+ return new ScheduleInfoImpl(ScheduleType.DAILY, -1, hour, minute, null);
}
private final ScheduleType scheduleType;
@@ -70,6 +70,43 @@ public class ScheduleInfoImpl implements
this.at = at;
}
+ public static ScheduleInfoImpl deserialize(final ScheduleType scheduleType, final String s) {
+ final String[] parts = s.split(":");
+ 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);
+ } catch ( final IllegalArgumentException iae) {
+ // ignore and return null
+ }
+ } else if ( scheduleType == ScheduleType.DAILY && parts.length == 2 ) {
+ try {
+ return new ScheduleInfoImpl(scheduleType,
+ -1,
+ Integer.parseInt(parts[0]),
+ Integer.parseInt(parts[1]),
+ null);
+ } catch ( final IllegalArgumentException iae) {
+ // ignore and return null
+ }
+ } else if ( scheduleType == ScheduleType.HOURLY && parts.length == 1 ) {
+ try {
+ return new ScheduleInfoImpl(scheduleType,
+ -1,
+ -1,
+ Integer.parseInt(parts[0]),
+ null);
+ } 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) ) {
@@ -85,6 +122,7 @@ public class ScheduleInfoImpl implements
}
return null;
}
+
public String getSerializedString() {
final StringBuilder sb = new StringBuilder();
sb.append(VERSION);
@@ -132,7 +170,7 @@ public class ScheduleInfoImpl implements
public void check(final List<String> errors) {
switch ( this.scheduleType ) {
- case DAYLY : if ( hourOfDay < 0 || hourOfDay > 23 || minuteOfHour < 0 || minuteOfHour > 59 ) {
+ case DAILY : if ( hourOfDay < 0 || hourOfDay > 23 || minuteOfHour < 0 || minuteOfHour > 59 ) {
errors.add("Wrong time information : " + minuteOfHour + ":" + minuteOfHour);
}
break;
@@ -158,7 +196,7 @@ public class ScheduleInfoImpl implements
final Calendar now = Calendar.getInstance();
switch ( this.scheduleType ) {
case DATE : return this.at;
- case DAYLY : final Calendar next = Calendar.getInstance();
+ case DAILY : final Calendar next = Calendar.getInstance();
next.set(Calendar.HOUR_OF_DAY, this.hourOfDay);
next.set(Calendar.MINUTE, this.minuteOfHour);
if ( next.before(now) ) {
@@ -187,7 +225,7 @@ public class ScheduleInfoImpl implements
* If the job is scheduled daily or weekly, return the cron expression
*/
public String getCronExpression() {
- if ( this.scheduleType == ScheduleType.DAYLY ) {
+ if ( this.scheduleType == ScheduleType.DAILY ) {
final StringBuilder sb = new StringBuilder("0 ");
sb.append(String.valueOf(this.minuteOfHour));
sb.append(' ');
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=1531274&r1=1531273&r2=1531274&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 Fri Oct 11 12:38:55 2013
@@ -109,7 +109,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 dayly(final int hour, final int minute);
+ DayBuilder daily(final int hour, final int minute);
/**
* Schedule the job weekly, the time needs to be specified in addition.
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=1531274&r1=1531273&r2=1531274&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 Fri Oct 11 12:38:55 2013
@@ -32,7 +32,7 @@ public interface ScheduleInfo {
enum ScheduleType {
DATE, // scheduled for a date
HOURLY, // scheduled hourly
- DAYLY, // scheduled once a day
+ DAILY, // scheduled once a day
WEEKLY // scheduled once a week
}