001: /*
002: * Copyright 2001-2007 Geert Bevin <gbevin[remove] at uwyn dot com>
003: * Distributed under the terms of either:
004: * - the common development and distribution license (CDDL), v1.0; or
005: * - the GNU Lesser General Public License, v2.1 or later
006: * $Id: Xml2MemoryScheduler.java 3714 2007-04-08 02:57:38Z gbevin $
007: */
008: package com.uwyn.rife.scheduler.schedulermanagers;
009:
010: import com.uwyn.rife.config.Config;
011: import com.uwyn.rife.config.RifeConfig;
012: import com.uwyn.rife.scheduler.Executor;
013: import com.uwyn.rife.scheduler.Scheduler;
014: import com.uwyn.rife.scheduler.Task;
015: import com.uwyn.rife.scheduler.Taskoption;
016: import com.uwyn.rife.scheduler.exceptions.FrequencyException;
017: import com.uwyn.rife.scheduler.exceptions.SchedulerException;
018: import com.uwyn.rife.scheduler.exceptions.TaskManagerException;
019: import com.uwyn.rife.scheduler.exceptions.TaskoptionManagerException;
020: import com.uwyn.rife.scheduler.taskmanagers.MemoryTasks;
021: import com.uwyn.rife.scheduler.taskoptionmanagers.MemoryTaskoptions;
022: import com.uwyn.rife.xml.Xml2Data;
023: import com.uwyn.rife.xml.exceptions.XmlErrorException;
024: import java.text.ParseException;
025: import java.text.SimpleDateFormat;
026: import java.util.Date;
027: import org.xml.sax.Attributes;
028:
029: public class Xml2MemoryScheduler extends Xml2Data {
030: private StringBuilder mCharacterData = null;
031: private Scheduler mScheduler = null;
032: private MemoryTasks mTasks = null;
033: private MemoryTaskoptions mTaskoptions = null;
034: private int mLastTaskId = -1;
035: private Taskoption mLastTaskoption = null;
036:
037: public Scheduler getScheduler() {
038: return mScheduler;
039: }
040:
041: public void startDocument() {
042: mCharacterData = new StringBuilder();
043: mTasks = new MemoryTasks();
044: mTaskoptions = new MemoryTaskoptions();
045: mScheduler = new Scheduler(mTasks, mTaskoptions);
046: mLastTaskId = -1;
047: mLastTaskoption = null;
048: }
049:
050: public void endDocument() {
051: mCharacterData = null;
052: mTasks = null;
053: mTaskoptions = null;
054: mLastTaskId = -1;
055: mLastTaskoption = null;
056: }
057:
058: private String registerExecutor(String classname)
059: throws XmlErrorException {
060: try {
061: Class<Executor> executor_class = (Class<Executor>) Class
062: .forName(classname);
063: Executor executor = executor_class.newInstance();
064: if (!mScheduler.addExecutor(executor)) {
065: throw new XmlErrorException(
066: "Couldn't add the executor with class '"
067: + classname + "' to the scheduler.");
068: }
069:
070: return executor.getHandledTasktype();
071: } catch (ClassNotFoundException e) {
072: throw new XmlErrorException(
073: "Error while retrieving the executor's class '"
074: + classname + "'.", e);
075: } catch (InstantiationException e) {
076: throw new XmlErrorException(
077: "Error while instantiating the executor with class '"
078: + classname + "'.", e);
079: } catch (IllegalAccessException e) {
080: throw new XmlErrorException(
081: "Error while instantiating the executor with class '"
082: + classname + "'.", e);
083: } catch (SchedulerException e) {
084: throw new XmlErrorException(
085: "Error while adding the executor with class '"
086: + classname + "' to the scheduler.", e);
087: }
088: }
089:
090: public void startElement(String namespaceURI, String localName,
091: String qName, Attributes atts) {
092: if (qName.equals("scheduler")) {
093: // do nothing
094: } else if (qName.equals("task")) {
095: String classname = atts.getValue("classname");
096: String planned = atts.getValue("planned");
097: String frequency = atts.getValue("frequency");
098: String type = atts.getValue("type");
099:
100: if ((null == classname || 0 == classname.length())) {
101: if (null == type || 0 == type.length()) {
102: throw new XmlErrorException(
103: "Either the executor's classname or the task type have to be specified.");
104: }
105: } else {
106: if (type != null && type.length() > 0) {
107: throw new XmlErrorException(
108: "A task type can't be specified if the executor's class has been specified.");
109: }
110: }
111:
112: // if an executor's classname has been specified, try to instantiate the executor and
113: // register it with the scheduler
114: if (classname != null && classname.length() > 0) {
115: type = registerExecutor(classname);
116: }
117:
118: // if no planned date has been specified, set it to the current time
119: SimpleDateFormat dateformat = new SimpleDateFormat(
120: "yyyy/MM/dd HH:mm");
121: dateformat.setTimeZone(RifeConfig.Tools
122: .getDefaultTimeZone());
123: Date planned_date = null;
124: if (null == planned) {
125: // no explicit planned date was provided
126: // set it to the current time
127: planned_date = new Date();
128: } else {
129: try {
130: planned_date = dateformat.parse(planned);
131: } catch (ParseException e) {
132: throw new XmlErrorException("Invalid planned '"
133: + planned + "'.", e);
134: }
135: }
136:
137: // create the new task and add it to the scheduler
138: Task task = new Task();
139: task.setType(type);
140: task.setPlanned(planned_date);
141: try {
142: task.setFrequency(frequency);
143: } catch (FrequencyException e) {
144: throw new XmlErrorException("Invalid frequency '"
145: + frequency + "'.", e);
146: }
147: try {
148: mLastTaskId = mTasks.addTask(task);
149: } catch (TaskManagerException e) {
150: throw new XmlErrorException(
151: "Error while adding the task to the scheduler.",
152: e);
153: }
154:
155: // if no explicit planned date has been given, and a frequency has
156: // been provided, rearrange the planned date to ensure that the
157: // first execution happens on a valid frequency moment
158: if (null == planned && frequency != null) {
159: try {
160: long one_minute_earlier = task.getPlanned() - 60000;
161: long first_valid_planned = task
162: .getNextDate(one_minute_earlier);
163: task.setPlanned(first_valid_planned);
164: } catch (FrequencyException e) {
165: // do nothing, the planned date will remain at the curren time
166: }
167: }
168: } else if (qName.equals("option")) {
169: mCharacterData = new StringBuilder();
170: mLastTaskoption = new Taskoption();
171: mLastTaskoption.setTaskId(mLastTaskId);
172: mLastTaskoption.setName(atts.getValue("name"));
173: } else if (qName.equals("config")) {
174: if (mCharacterData != null && Config.hasRepInstance()) {
175: mCharacterData.append(Config.getRepInstance()
176: .getString(atts.getValue("param"), ""));
177: }
178: } else if (qName.equals("executor")) {
179: String classname = atts.getValue("classname");
180: registerExecutor(classname);
181: } else {
182: throw new XmlErrorException("Unsupport element name '"
183: + qName + "'.");
184: }
185: }
186:
187: public void endElement(String namespaceURI, String localName,
188: String qName) {
189: if (qName.equals("option")) {
190: mLastTaskoption.setValue(mCharacterData.toString());
191: try {
192: mTaskoptions.addTaskoption(mLastTaskoption);
193: } catch (TaskoptionManagerException e) {
194: throw new XmlErrorException(
195: "Error while adding the taskoption with name '"
196: + mLastTaskoption.getName()
197: + "', value '"
198: + mLastTaskoption.getValue()
199: + "' and task id '"
200: + mLastTaskoption.getTaskId() + "'.", e);
201: }
202: mCharacterData = new StringBuilder();
203: mLastTaskoption = null;
204: }
205: }
206:
207: public void characters(char[] ch, int start, int length) {
208: if (length > 0) {
209: mCharacterData
210: .append(String.copyValueOf(ch, start, length));
211: }
212: }
213: }
|