001: package org.sakaiproject.component.app.scheduler;
002:
003: import java.util.Date;
004: import java.util.List;
005:
006: import org.apache.commons.logging.Log;
007: import org.apache.commons.logging.LogFactory;
008: import org.quartz.Job;
009: import org.quartz.JobDetail;
010: import org.quartz.SchedulerException;
011: import org.quartz.SimpleTrigger;
012: import org.quartz.Trigger;
013: import org.sakaiproject.api.app.scheduler.DelayedInvocation;
014: import org.sakaiproject.api.app.scheduler.ScheduledInvocationManager;
015: import org.sakaiproject.api.app.scheduler.SchedulerManager;
016: import org.sakaiproject.component.api.ServerConfigurationService;
017: import org.sakaiproject.component.app.scheduler.jobs.ScheduledInvocationRunner;
018: import org.sakaiproject.db.api.SqlService;
019: import org.sakaiproject.id.api.IdManager;
020: import org.sakaiproject.time.api.Time;
021:
022: public class ScheduledInvocationManagerImpl implements
023: ScheduledInvocationManager {
024:
025: private static final Log LOG = LogFactory
026: .getLog(ScheduledInvocationManagerImpl.class);
027:
028: private static final String SCHEDULED_INVOCATION_RUNNER_DEFAULT_INTERVAL_PROPERTY = "jobscheduler.invocation.interval";
029:
030: private static final int SCHEDULED_INVOCATION_RUNNER_DEFAULT_INTERVAL = 600; //default: time in seconds, run every 10 mins
031:
032: /** Dependency: IdManager */
033: protected IdManager m_idManager = null;
034:
035: public void setIdManager(IdManager service) {
036: m_idManager = service;
037: }
038:
039: /** Dependency: SqlService */
040: protected SqlService m_sqlService = null;
041:
042: public void setSqlService(SqlService service) {
043: m_sqlService = service;
044: }
045:
046: /** Dependency: SchedulerManager */
047: protected SchedulerManager m_schedulerManager = null;
048:
049: public void setSchedulerManager(SchedulerManager service) {
050: m_schedulerManager = service;
051: }
052:
053: /** Dependency: ServerConfigurationService */
054: protected ServerConfigurationService m_serverConfigurationService = null;
055:
056: public void setServerConfigurationService(
057: ServerConfigurationService service) {
058: m_serverConfigurationService = service;
059: }
060:
061: public void init() {
062: LOG.info("init()");
063: try {
064: registerScheduledInvocationRunner();
065: } catch (SchedulerException e) {
066: LOG.error(
067: "failed to schedule ScheduledInvocationRunner job",
068: e);
069: }
070: }
071:
072: public void destroy() {
073: LOG.info("destroy()");
074: }
075:
076: protected void registerScheduledInvocationRunner()
077: throws SchedulerException {
078:
079: //trigger will not start immediately, wait until interval has passed before 1st run
080: long startTime = System.currentTimeMillis()
081: + getScheduledInvocationRunnerInterval();
082:
083: JobDetail detail = new JobDetail(
084: "org.sakaiproject.component.app.scheduler.ScheduledInvocationManagerImpl.runner",
085: "org.sakaiproject.component.app.scheduler.ScheduledInvocationManagerImpl",
086: ScheduledInvocationRunner.class);
087:
088: Trigger trigger = new SimpleTrigger(
089: "org.sakaiproject.component.app.scheduler.ScheduledInvocationManagerImpl.runner",
090: "org.sakaiproject.component.app.scheduler.ScheduledInvocationManagerImpl",
091: new Date(startTime), null,
092: SimpleTrigger.REPEAT_INDEFINITELY,
093: getScheduledInvocationRunnerInterval());
094:
095: m_schedulerManager.getScheduler().unscheduleJob(
096: trigger.getName(), trigger.getGroup());
097: m_schedulerManager.getScheduler().scheduleJob(detail, trigger);
098: }
099:
100: protected int getScheduledInvocationRunnerInterval() {
101:
102: // convert seconds to millis
103: return 1000 * m_serverConfigurationService.getInt(
104: SCHEDULED_INVOCATION_RUNNER_DEFAULT_INTERVAL_PROPERTY,
105: SCHEDULED_INVOCATION_RUNNER_DEFAULT_INTERVAL);
106:
107: }
108:
109: /* (non-Javadoc)
110: * @see org.sakaiproject.api.app.scheduler.ScheduledInvocationManager#createDelayedInvocation(org.sakaiproject.time.api.Time, java.lang.String, java.lang.String)
111: */
112: public String createDelayedInvocation(Time time,
113: String componentId, String opaqueContext) {
114:
115: String uuid = m_idManager.createUuid();
116:
117: LOG.debug("Creating new Delayed Invocation: " + uuid);
118: String sql = "INSERT INTO SCHEDULER_DELAYED_INVOCATION VALUES(?,?,?,?)";
119:
120: Object[] fields = new Object[4];
121:
122: fields[0] = uuid;
123: fields[1] = time;
124: fields[2] = componentId;
125: fields[3] = opaqueContext;
126:
127: LOG.debug("SQL: " + sql);
128: if (m_sqlService.dbWrite(sql, fields)) {
129: LOG.info("Created new Delayed Invocation: uuid=" + uuid);
130: return uuid;
131: } else {
132: LOG
133: .error("Failed to create new Delayed Invocation: componentId="
134: + componentId
135: + ", opaqueContext="
136: + opaqueContext);
137: return null;
138: }
139:
140: }
141:
142: /* (non-Javadoc)
143: * @see org.sakaiproject.api.app.scheduler.ScheduledInvocationManager#deleteDelayedInvocation(java.lang.String)
144: */
145: public void deleteDelayedInvocation(String uuid) {
146:
147: LOG.debug("Removing Delayed Invocation: " + uuid);
148: String sql = "DELETE FROM SCHEDULER_DELAYED_INVOCATION WHERE INVOCATION_ID = ?";
149:
150: Object[] fields = new Object[1];
151: fields[0] = uuid;
152:
153: LOG.debug("SQL: " + sql);
154: m_sqlService.dbWrite(sql, fields);
155:
156: }
157:
158: /* (non-Javadoc)
159: * @see org.sakaiproject.api.app.scheduler.ScheduledInvocationManager#deleteDelayedInvocation(java.lang.String, java.lang.String)
160: */
161: public void deleteDelayedInvocation(String componentId,
162: String opaqueContext) {
163: LOG.debug("componentId=" + componentId + ", opaqueContext="
164: + opaqueContext);
165:
166: //String sql = "DELETE FROM SCHEDULER_DELAYED_INVOCATION WHERE COMPONENT = ? AND CONTEXT = ?";
167: String sql = "DELETE FROM SCHEDULER_DELAYED_INVOCATION";
168:
169: Object[] fields = new Object[0];
170: if (componentId.length() > 0 && opaqueContext.length() > 0) {
171: // both non-blank
172: sql += " WHERE COMPONENT = ? AND CONTEXT = ?";
173: fields = new Object[2];
174: fields[0] = componentId;
175: fields[1] = opaqueContext;
176: } else if (componentId.length() > 0) {
177: // context blank
178: sql += " WHERE COMPONENT = ?";
179: fields = new Object[1];
180: fields[0] = componentId;
181: } else if (opaqueContext.length() > 0) {
182: // component blank
183: sql += " WHERE CONTEXT = ?";
184: fields = new Object[1];
185: fields[0] = opaqueContext;
186: } else {
187: // both blank
188: }
189:
190: LOG.debug("SQL: " + sql);
191: if (m_sqlService.dbWrite(sql, fields)) {
192: LOG
193: .info("Removed all scheduled invocations matching: componentId="
194: + componentId
195: + ", opaqueContext="
196: + opaqueContext);
197: } else {
198: LOG
199: .error("Failure while attempting to remove invocations matching: componentId="
200: + componentId
201: + ", opaqueContext="
202: + opaqueContext);
203: }
204:
205: }
206:
207: /* (non-Javadoc)
208: * @see org.sakaiproject.api.app.scheduler.ScheduledInvocationManager#findDelayedInvocations(java.lang.String, java.lang.String)
209: */
210: public DelayedInvocation[] findDelayedInvocations(
211: String componentId, String opaqueContext) {
212: LOG.debug("componentId=" + componentId + ", opaqueContext="
213: + opaqueContext);
214:
215: //String sql = "SELECT * FROM SCHEDULER_DELAYED_INVOCATION WHERE COMPONENT = ? AND CONTEXT = ?";
216: String sql = "SELECT * FROM SCHEDULER_DELAYED_INVOCATION";
217:
218: Object[] fields = new Object[0];
219: if (componentId.length() > 0 && opaqueContext.length() > 0) {
220: // both non-blank
221: sql += " WHERE COMPONENT = ? AND CONTEXT = ?";
222: fields = new Object[2];
223: fields[0] = componentId;
224: fields[1] = opaqueContext;
225: } else if (componentId.length() > 0) {
226: // context blank
227: sql += " WHERE COMPONENT = ?";
228: fields = new Object[1];
229: fields[0] = componentId;
230: } else if (opaqueContext.length() > 0) {
231: // component blank
232: sql += " WHERE CONTEXT = ?";
233: fields = new Object[1];
234: fields[0] = opaqueContext;
235: } else {
236: // both blank
237: }
238:
239: List invocations = m_sqlService.dbRead(sql, fields,
240: new DelayedInvocationReader());
241: return (DelayedInvocation[]) invocations
242: .toArray(new DelayedInvocation[] {});
243: }
244:
245: }
|