/********************************************************* begin of preamble
**
** Copyright (C) 2003-2010 Software- und Organisations-Service GmbH.
** All rights reserved.
**
** This file may be used under the terms of either the
**
** GNU General Public License version 2.0 (GPL)
**
** as published by the Free Software Foundation
** http://www.gnu.org/licenses/gpl-2.0.txt and appearing in the file
** LICENSE.GPL included in the packaging of this file.
**
** or the
**
** Agreement for Purchase and Licensing
**
** as offered by Software- und Organisations-Service GmbH
** in the respective terms of supply that ship with this file.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
** IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
** THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
** BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
** POSSIBILITY OF SUCH DAMAGE.
********************************************************** end of preamble*/
package sos.scheduler.job;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StringReader;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Collection;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Vector;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.apache.xalan.xslt.EnvironmentCheck;
import org.apache.xml.serialize.OutputFormat;
import org.apache.xml.serialize.XMLSerializer;
import org.apache.xpath.XPathAPI;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import sos.connection.SOSConnection;
import sos.connection.SOSPgSQLConnection;
import sos.scheduler.command.SOSSchedulerCommand;
import sos.scheduler.consoleviews.events.SOSActions;
import sos.scheduler.consoleviews.events.SOSEvaluateEvents;
import sos.spooler.Spooler;
import sos.spooler.Variable_set;
import sos.util.SOSDate;
import sos.util.SOSFile;
import sos.util.SOSLogger;
import sos.xml.SOSXMLTransformer;
import sos.xml.SOSXMLXPath;
/**
*
* @author andreas.pueschel@sos-berlin.com
*
* This job is used to process events by a Supervisor instance
*
*/
public class JobSchedulerEventJob extends JobSchedulerJob {
public static final String EVENT_CLASS_ALL_EVENTS = "*all_events*";
/** event action */
private String eventAction = "";
/** event job scheduler id */
private String eventSchedulerId = "";
/** event remote Job Scheduler host */
private String eventRemoteSchedulerHost = "";
/** event remote Job Scheduler port */
private String eventRemoteSchedulerPort = "";
/** job chain that caused the event */
private String eventJobChainName = "";
/** order identification that caused the event */
private String eventOrderId = "";
/** job that caused the event */
private String eventJobName = "";
/** event class name */
private String eventClass = "";
/** event identification */
private String eventId = "";
/** event exit code */
private String eventExitCode = "";
/** event expiration date */
private String eventExpires = "";
/** event creation date */
private String eventCreated = "";
/** event parameters */
private Element eventParameters = null;
/** expiration period */
private String expirationPeriod = "";
/** expiration cycle */
private String expirationCycle = "";
/** calculated expiration date */
private Calendar expirationDate = null;
/** event handler file path */
private String eventHandlerFilepath = "";
/** event handler file specification */
private String eventHandlerFilespec = "";
/** job and order parameters */
private Variable_set parameters = null;
/** table name */
private static String tableEvents = "SCHEDULER_EVENTS";
/** local DOM objects of events */
private Document events = null;
/** local list of event handlers */
private Collection eventHandlerFileList = new LinkedHashSet();
/** iterator for local list of event handlers */
private Iterator eventHandlerFileListIterator = null;
/** local list of transformed files */
private Collection eventHandlerResultFileList = new Vector();
/** iterator for local list of transformed files */
private Iterator eventHandlerResultFileListIterator = null;
/** Timeout for Socket communication default=5 **/
private int socket_timeout = 5;
public boolean spooler_init() {
boolean rc = super.spooler_init();
EnvironmentCheck ec = new EnvironmentCheck();
StringWriter sWri = new StringWriter();
PrintWriter pWri = new PrintWriter(sWri);
ec.checkEnvironment(pWri);
pWri.close();
try {
getLogger().debug3("Checking Xalan environment...");
getLogger().debug3(sWri.toString());
}
catch (Exception ex) {
}
return rc;
}
public boolean spooler_process() {
boolean rc = true;
try {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document eventDocument = docBuilder.newDocument();
eventDocument.appendChild(eventDocument.createElement("events"));
this.setEvents(eventDocument);
// fetch events from global Job Scheduler variable
this.getSchedulerEvents();
this.setParameters(spooler.create_variable_set());
HashSet jobParameterNames = new HashSet();
try {
if (spooler_task.params() != null)
this.getParameters().merge(spooler_task.params());
if (spooler_job.order_queue() != null)
this.getParameters().merge(spooler_task.order().params());
/* event processing parameters */
if (this.getParameters().value("socket_timeout") != null && this.getParameters().value("socket_timeout").length() > 0) {
this.setSocket_timeout(this.getParameters().value("socket_timeout"));
spooler_log.debug1(".. parameter [socket_timeout]: " + socket_timeout);
}
else {
this.setSocket_timeout("5");
}
if (this.getParameters().value("action") != null && this.getParameters().value("action").length() > 0) {
this.setEventAction(this.getParameters().value("action"));
spooler_log.debug1(".. parameter [action]: " + this.getEventAction());
}
else {
this.setEventAction("add");
}
jobParameterNames.add("action");
if (this.getParameters().value("scheduler_id") != null && this.getParameters().value("scheduler_id").length() > 0) {
this.setEventSchedulerId(this.getParameters().value("scheduler_id"));
spooler_log.debug1(".. parameter [scheduler_id]: " + this.getEventSchedulerId());
}
else {
this.setEventSchedulerId(spooler.id());
}
jobParameterNames.add("scheduler_id");
if (this.getParameters().value("spooler_id") != null && this.getParameters().value("spooler_id").length() > 0) {
this.setEventSchedulerId(this.getParameters().value("spooler_id"));
spooler_log.debug1(".. parameter [spooler_id]: " + this.getEventSchedulerId());
}
jobParameterNames.add("spooler_id");
/* standard parameters */
if (this.getParameters().value("remote_scheduler_host") != null && this.getParameters().value("remote_scheduler_host").length() > 0) {
this.setEventRemoteSchedulerHost(this.getParameters().value("remote_scheduler_host"));
spooler_log.debug1(".. parameter [remote_scheduler_host]: " + this.getEventRemoteSchedulerHost());
}
else {
this.setEventRemoteSchedulerHost("");
}
jobParameterNames.add("remote_scheduler_host");
if (this.getParameters().value("remote_scheduler_port") != null && this.getParameters().value("remote_scheduler_port").length() > 0) {
this.setEventRemoteSchedulerPort(this.getParameters().value("remote_scheduler_port"));
spooler_log.debug1(".. parameter [remote_scheduler_port]: " + this.getEventRemoteSchedulerPort());
}
else {
this.setEventRemoteSchedulerPort("0");
}
jobParameterNames.add("remote_scheduler_port");
if (this.getParameters().value("job_chain") != null && this.getParameters().value("job_chain").length() > 0) {
this.setEventJobChainName(this.getParameters().value("job_chain"));
spooler_log.debug1(".. parameter [job_chain]: " + this.getEventJobChainName());
}
else {
this.setEventJobChainName("");
}
jobParameterNames.add("job_chain");
if (this.getParameters().value("order_id") != null && this.getParameters().value("order_id").length() > 0) {
this.setEventOrderId(this.getParameters().value("order_id"));
spooler_log.debug1(".. parameter [order_id]: " + this.getEventOrderId());
}
else {
this.setEventOrderId("");
}
jobParameterNames.add("order_id");
if (this.getParameters().value("job_name") != null && this.getParameters().value("job_name").length() > 0) {
this.setEventJobName(this.getParameters().value("job_name"));
spooler_log.debug1(".. parameter [job_name]: " + this.getEventJobName());
}
else {
this.setEventJobName("");
}
jobParameterNames.add("job_name");
if (this.getParameters().value("event_class") != null && this.getParameters().value("event_class").length() > 0) {
this.setEventClass(this.getParameters().value("event_class"));
spooler_log.debug1(".. parameter [event_class]: " + this.getEventClass());
}
else {
this.setEventClass("");
}
jobParameterNames.add("event_class");
if (this.getParameters().value("event_id") != null && this.getParameters().value("event_id").length() > 0) {
this.setEventId(this.getParameters().value("event_id"));
spooler_log.debug1(".. parameter [event_id]: " + this.getEventId());
}
else {
this.setEventId("");
}
jobParameterNames.add("event_id");
if (this.getParameters().value("exit_code") != null && this.getParameters().value("exit_code").length() > 0) {
this.setEventExitCode(this.getParameters().value("exit_code"));
spooler_log.debug1(".. parameter [exit_code]: " + this.getEventExitCode());
}
else {
this.setEventExitCode("");
}
jobParameterNames.add("exit_code");
if (this.getParameters().value("expires") != null && this.getParameters().value("expires").length() > 0) {
this.setEventExpires(this.getParameters().value("expires"));
spooler_log.debug1(".. parameter [expires]: " + this.getEventExpires());
}
else {
this.setEventExpires("");
}
jobParameterNames.add("expires");
if (this.getParameters().value("created") != null && this.getParameters().value("created").length() > 0) {
this.setEventCreated(this.getParameters().value("created"));
spooler_log.debug1(".. parameter [created]: " + this.getEventCreated());
}
else {
this.setEventCreated(SOSDate.getCurrentTimeAsString());
}
jobParameterNames.add("created");
/* recommended job parameters */
if (this.getParameters().value("expiration_period") != null && this.getParameters().value("expiration_period").length() > 0) {
this.setExpirationPeriod(this.getParameters().value("expiration_period"));
spooler_log.debug1(".. parameter [expiration_period]: " + this.getExpirationPeriod());
}
else {
// by default events are removed after 24 hours
this.setExpirationPeriod("24:00:00");
}
jobParameterNames.add("expiration_period");
if (this.getParameters().value("expiration_cycle") != null && this.getParameters().value("expiration_cycle").length() > 0) {
this.setExpirationCycle(this.getParameters().value("expiration_cycle"));
spooler_log.debug1(".. parameter [expiration_cycle]: " + this.getExpirationCycle());
}
else {
this.setExpirationCycle("");
}
jobParameterNames.add("expiration_cycle");
if (this.getParameters().value("event_handler_filepath") != null && this.getParameters().value("event_handler_filepath").length() > 0) {
this.setEventHandlerFilepath(this.getParameters().value("event_handler_filepath"));
spooler_log.debug1(".. parameter [event_handler_filepath]: " + this.getEventHandlerFilepath());
}
else {
this.setEventHandlerFilepath("./config/events");
}
jobParameterNames.add("event_handler_filepath");
if (this.getParameters().value("event_handler_filespec") != null && this.getParameters().value("event_handler_filespec").length() > 0) {
this.setEventHandlerFilespec(this.getParameters().value("event_handler_filespec"));
spooler_log.debug1(".. parameter [event_handler_filespec]: " + this.getEventHandlerFilespec());
}
else {
this.setEventHandlerFilespec("\\.xsl$");
}
jobParameterNames.add("event_handler_filespec");
/* any additional parameters */
this.setEventParameters(getEvents().createElement("params"));
String[] parameterNames = this.getParameters().names().split(";");
for (int i = 0; i < parameterNames.length; i++) {
if (!jobParameterNames.contains(parameterNames[i])) {
Element param = getEvents().createElement("param");
param.setAttribute("name", parameterNames[i]);
param.setAttribute("value", this.getParameters().value(parameterNames[i]));
getLogger().debug3("Event parameter [" + parameterNames[i] + "]: " + this.getParameters().value(parameterNames[i]));
this.getEventParameters().appendChild(param);
}
}
}
catch (Exception e) {
throw new Exception("error occurred processing parameters: " + e.getMessage());
}
this.setExpirationDate(calculateExpirationDate(expirationCycle, expirationPeriod));
try { // to process events
// moved to the beginning of spooler_process()
// fetch events from global Job Scheduler variable
// this.getSchedulerEvents();
// perform event action
if (this.getEventAction().equalsIgnoreCase("add")) {
this.getLogger().info("adding event: " + this.getEventClass() + " " + this.getEventId());
this.addEvent();
}
else
if (this.getEventAction().equalsIgnoreCase("remove")) {
this.getLogger().info("removing event: " + this.getEventClass() + " " + this.getEventId());
this.removeEvent();
}
else {
this.getLogger().info("processing events");
}
// process events, launch dependent jobs and orders
this.processSchedulerEvents();
// update events in global Job Scheduler variable
this.putSchedulerEvents();
}
catch (Exception e) {
throw new Exception("error occurred processing event: " + e.getMessage());
}
return ((spooler_job.order_queue() != null) ? rc : false);
}
catch (Exception e) {
spooler_log.warn("error occurred processing event [" + this.getEventClass() + " " + this.getEventId() + "]: " + e.getMessage());
return false;
}
}
public static Calendar calculateExpirationDate(String expirationCycle, String expirationPeriod) throws Exception {
Calendar cal = Calendar.getInstance();
try {
cal.setTime(SOSDate.getCurrentTime());
if (expirationCycle.indexOf(":") > -1) {
String[] timeArray = expirationCycle.split(":");
int hours = Integer.parseInt(timeArray[0]);
int minutes = Integer.parseInt(timeArray[1]);
int seconds = 0;
if (timeArray.length > 2) {
seconds = Integer.parseInt(timeArray[2]);
}
cal.set(Calendar.HOUR_OF_DAY, hours);
cal.set(Calendar.MINUTE, minutes);
cal.set(Calendar.SECOND, seconds);
// add one day if the current timestamp is after the calculated cycle
// TODO: Was ist im Dezember?
if (cal.after(SOSDate.getCurrentTime()))
cal.add(Calendar.DAY_OF_MONTH, 1);
}
else
if (expirationPeriod.indexOf(":") > -1) {
String[] timeArray = expirationPeriod.split(":");
int hours = Integer.parseInt(timeArray[0]);
int minutes = Integer.parseInt(timeArray[1]);
int seconds = 0;
if (timeArray.length > 2) {
seconds = Integer.parseInt(timeArray[2]);
}
// add the interval from the given period to the expiration date
if (hours > 0)
cal.add(Calendar.HOUR_OF_DAY, hours);
if (minutes > 0)
cal.add(Calendar.MINUTE, minutes);
if (seconds > 0)
cal.add(Calendar.SECOND, seconds);
}
else
if (expirationPeriod.length() > 0) {
cal.add(Calendar.SECOND, Integer.parseInt(expirationPeriod));
}
}
catch (Exception e) {
throw new Exception("Error calculating expiration date: " + e, e);
}
return cal;
}
/**
* get events from Job Scheduler global variables
*/
public void getSchedulerEvents() throws Exception {
try {
String eventSet = spooler.var(this.spooler_job.name() + ".events");
if (this.getConnection() != null && (eventSet == null || eventSet.length() == 0)) {
// ??
/*if (this.getExpirationPeriod().length() > 0) {
this.getConnection().executeUpdate("DELETE FROM " + this.getTableEvents() + " WHERE \"EXPIRES\"<=%timestamp_iso('" + SOSDate.getTimeAsString(this.getExpirationDate().getTime()) + "') AND (\"SPOOLER_ID\" IS NULL OR \"SPOOLER_ID\"='' OR \"SPOOLER_ID\"='" + spooler.id() + "')");
this.getConnection().commit();
}*/
readEventsFromDB(getConnection(), spooler, getEvents(), getLogger());
}
else {
eventSet = eventSet.replaceAll(String.valueOf((char) 254), "<").replaceAll(String.valueOf((char) 255), ">");
this.getLogger().debug6("current event set: " + eventSet);
if (eventSet.length() == 0)
return;
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document eventDocument = docBuilder.parse(new InputSource(new StringReader(eventSet)));
this.setEvents(eventDocument);
// check for expired events
// Sun JRE 1.5
// XPath xpath = XPathFactory.newInstance().newXPath();
// NodeList nodes = (NodeList) xpath.evaluate("//events/*", eventDocument, XPathConstants.NODESET);
this.getLogger().debug9("looking for //events/event");
NodeList nodes = (NodeList) org.apache.xpath.XPathAPI.selectNodeList(this.getEvents(), "//events/event");
this.getLogger().debug9("nodes.getLength(): " + nodes.getLength());
int activeNodeCount = 0;
int expiredNodeCount = 0;
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
if (node == null || node.getNodeType() != Node.ELEMENT_NODE)
continue;
Node curEventExpires = node.getAttributes().getNamedItem("expires");
if (curEventExpires == null || curEventExpires.getNodeValue() == null || curEventExpires.getNodeValue().length() == 0) {
activeNodeCount++;
continue;
}
// remove this event should the expiration date be overdue
Calendar expiresDate = GregorianCalendar.getInstance();
Calendar now = GregorianCalendar.getInstance();
expiresDate.setTime(SOSDate.getTime(curEventExpires.getNodeValue()));
if (expiresDate.before(now)) {
this.getLogger().debug9("Found expired event");
this.getEvents().getFirstChild().removeChild(node);
this.getLogger().debug9("event removed");
expiredNodeCount++;
}
else {
activeNodeCount++;
}
}
this.getLogger().info(activeNodeCount + " events are active, " + expiredNodeCount + " events have expired");
}
}
catch (Exception e) { // ignore subsequent transactional errors
if (this.getConnection() != null) {
try {
this.getConnection().rollback();
}
catch (Exception ex) {
} // gracefully ignore this error
}
throw new Exception("events fetched with errors: " + e.getMessage());
}
}
public static void readEventsFromDB(SOSConnection conn, Spooler spooler, Document eventsDoc, SOSLogger log) throws Exception {
try {
conn.executeUpdate("DELETE FROM " + getTableEvents()
+ " WHERE \"EXPIRES\"<=%now AND (\"SPOOLER_ID\" IS NULL OR \"SPOOLER_ID\"='' OR \"SPOOLER_ID\"='" + spooler.id() + "')");
conn.commit();
Vector vEvents = conn.getArrayAsVector("SELECT \"SPOOLER_ID\", \"REMOTE_SCHEDULER_HOST\", \"REMOTE_SCHEDULER_PORT\", \"JOB_CHAIN\", \"ORDER_ID\", \"JOB_NAME\", \"EVENT_CLASS\", \"EVENT_ID\", \"EXIT_CODE\", \"CREATED\", \"EXPIRES\", \"PARAMETERS\" FROM "
+ getTableEvents() + " WHERE (\"SPOOLER_ID\" IS NULL OR \"SPOOLER_ID\"='' OR \"SPOOLER_ID\"='" + spooler.id() + "') ORDER BY \"ID\" ASC");
Iterator vIterator = vEvents.iterator();
int vCount = 0;
while (vIterator.hasNext()) {
HashMap record = (HashMap) vIterator.next();
Element event = eventsDoc.createElement("event");
event.setAttribute("scheduler_id", record.get("spooler_id").toString());
event.setAttribute("remote_scheduler_host", record.get("remote_scheduler_host").toString());
event.setAttribute("remote_scheduler_port", record.get("remote_scheduler_port").toString());
event.setAttribute("job_chain", record.get("job_chain").toString());
event.setAttribute("order_id", record.get("order_id").toString());
event.setAttribute("job_name", record.get("job_name").toString());
event.setAttribute("event_class", record.get("event_class").toString());
event.setAttribute("event_id", record.get("event_id").toString());
event.setAttribute("exit_code", record.get("exit_code").toString());
event.setAttribute("expires", record.get("expires").toString());
event.setAttribute("created", record.get("created").toString());
if (record.get("parameters").toString().length() > 0) {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document eventParameters = docBuilder.parse(new InputSource(new StringReader(record.get("parameters").toString())));
log.debug9("Importing params node...");
Node impParameters = eventsDoc.importNode(eventParameters.getDocumentElement(), true);
log.debug9("appending params child...");
event.appendChild(impParameters);
}
eventsDoc.getLastChild().appendChild(event);
vCount++;
}
log.info(vCount + " events restored from database");
}
catch (Exception e) {
throw new Exception("Failed to read events from database: " + e, e);
}
}
/**
* update events in Job Scheduler global variables
*/
public void putSchedulerEvents() throws Exception {
try {
String eventsString = this.xmlDocumentToString(this.getEvents());
this.getLogger().debug9("Updating events: " + eventsString);
spooler.set_var(spooler_job.name() + ".events", eventsString.replaceAll("<", String.valueOf((char) 254))
.replaceAll(">", String.valueOf((char) 255)));
}
catch (Exception e) {
throw new Exception("events updated with errors: " + e.getMessage());
}
}
private boolean analyseMonitorEventHandler(String fileSpec, String fileSpecLog) throws Exception {
boolean erg = false;
this.getLogger().debug6(".. looking for special event handler for: " + fileSpecLog + " " + fileSpec);
Vector specialFiles = SOSFile.getFilelist(this.getEventHandlerFilepath(), fileSpec, 0);
Iterator iter = specialFiles.iterator();
while (iter.hasNext()) {
File actionEventHandler = (File) iter.next();
if (actionEventHandler.exists() && actionEventHandler.canRead()) {
erg = true;
this.getLogger().debug1(".. analysing action event handler: " + actionEventHandler.getCanonicalPath());
SOSEvaluateEvents eval = new SOSEvaluateEvents(spooler.hostname(), spooler.tcp_port());
try {
eval.setActiveEvents(this.getEvents());
eval.readConfigurationFile(actionEventHandler);
}
catch (Exception e) {
e.printStackTrace();
}
// Logging
Iterator iActions = eval.getListOfActions().iterator();
while (iActions.hasNext()) {
SOSActions a = (SOSActions) iActions.next();
this.getLogger().debug1(".... checking action " + a.getName());
if (a.isActive(eval.getListOfActiveEvents())) {
this.getLogger().debug1(".... added action:" + a.getName());
this.getEventHandlerResultFileList().add(a.getCommands());
NodeList commands = (NodeList) XPathAPI.selectNodeList(a.getCommands(), "command | remove_event | add_event");
for (int i = 0; i < commands.getLength(); i++) {
Node n = commands.item(i);
if (n.getNodeName().equals("command") || n.getNodeName().equals("remove_event") || n.getNodeName().equals("add_event")) {
this.getLogger().debug1(".. " + n.getNodeName() + " was added");
NamedNodeMap attr = n.getAttributes();
if (attr != null) {
for (int ii = 0; ii < attr.getLength(); ii++) {
this.getLogger().debug1("...." + attr.item(ii).getNodeName() + "=" + attr.item(ii).getNodeValue());
}
}
}
}
}
}
// Logging Ende
}
}
return erg;
}
private void getMonitorEventHandler() throws IOException, Exception {
boolean fileFound = false;
File eventHandlerFile = new File(this.getEventHandlerFilepath());
if (eventHandlerFile.isDirectory()) {
if (!eventHandlerFile.canRead())
throw new Exception("event handler directory is not accessible: " + eventHandlerFile.getCanonicalPath());
this.getLogger().debug6("retrieving event handlers from directory: " + this.getEventHandlerFilepath() + " for file specification: Action");
String fileSpec = "";
String fileSpecLog = "";
if (this.getEventJobChainName().length() > 0) {
fileSpec = this.getEventJobChainName() + "(\\..*)?\\.job_chain\\.actions.xml$";
fileSpecLog = "job_chain";
fileFound = analyseMonitorEventHandler(fileSpec, fileSpecLog);
}
if (!fileFound && this.getEventJobName().length() > 0) {
fileSpec = this.getEventJobName() + "(\\..*)?\\.job\\.actions.xml$";
fileSpecLog = "job";
fileFound = analyseMonitorEventHandler(fileSpec, fileSpecLog);
}
if (!fileFound && this.getEventClass().length() > 0) {
fileSpec = this.getEventClass() + "(\\..*)?\\.event_class\\.actions.xml$";
fileSpecLog = "event_class";
fileFound = analyseMonitorEventHandler(fileSpec, fileSpecLog);
}
if (!fileFound) {
fileSpec = "(\\..*)?\\.actions\\.xml$";
fileSpecLog = "";
fileFound = analyseMonitorEventHandler(fileSpec, fileSpecLog);
}
}
}
/**
* process events from individual event handlers
*/
public void processSchedulerEvents() throws Exception {
File eventHandler = null;
try {
HashMap eventHandlerResultReference = new HashMap();
try { // to process event handlers for events
this.getLogger().debug3(".. current events for event handler processing:");
this.getLogger().debug3(this.xmlDocumentToString(this.getEvents()));
this.setEventHandlerResultFileList(new LinkedHashSet());
this.setEventHandlerFileList(new LinkedHashSet());
// add Resultfile for scheduler_action.xml
this.getMonitorEventHandler();
File eventHandlerFile = new File(this.getEventHandlerFilepath());
if (eventHandlerFile.isDirectory()) {
if (!eventHandlerFile.canRead())
throw new Exception("event handler directory is not accessible: " + eventHandlerFile.getCanonicalPath());
this.getLogger().debug6(
"retrieving event handlers from directory: " + this.getEventHandlerFilepath() + " for file specification: "
+ this.getEventHandlerFilespec());
if (this.getEventJobChainName().length() > 0) {
String fileSpec = this.getEventJobChainName() + "(\\..*)?\\.job_chain\\.xsl$";
this.getLogger().debug6(".. looking for special event handler for job chain: " + fileSpec);
Vector specialFiles = SOSFile.getFilelist(this.getEventHandlerFilepath(), fileSpec, 0);
Iterator iter = specialFiles.iterator();
while (iter.hasNext()) {
File specialEventHandler = (File) iter.next();
if (specialEventHandler.exists() && specialEventHandler.canRead()) {
this.getEventHandlerFileList().add(specialEventHandler);
this.getLogger().debug1(".. using special event handler for job chain: " + specialEventHandler.getCanonicalPath());
}
}
}
if (this.getEventJobName().length() > 0) {
String fileSpec = this.getEventJobName() + "(\\..*)?\\.job\\.xsl$";
this.getLogger().debug6(".. looking for special event handler for job: " + fileSpec);
Vector specialFiles = SOSFile.getFilelist(this.getEventHandlerFilepath(), fileSpec, 0);
Iterator iter = specialFiles.iterator();
while (iter.hasNext()) {
File specialEventHandler = (File) iter.next();
if (specialEventHandler.exists() && specialEventHandler.canRead()) {
this.getEventHandlerFileList().add(specialEventHandler);
this.getLogger().debug1(".. using special event handler for job: " + specialEventHandler.getCanonicalPath());
}
}
}
if (this.getEventClass().length() > 0) {
String fileSpec = this.getEventClass() + "(\\..*)?\\.event_class\\.xsl$";
this.getLogger().debug6(".. looking for special event handlers for event class: " + fileSpec);
Vector specialFiles = SOSFile.getFilelist(this.getEventHandlerFilepath(), fileSpec, 0);
Iterator iter = specialFiles.iterator();
while (iter.hasNext()) {
File specialEventHandler = (File) iter.next();
if (specialEventHandler.exists() && specialEventHandler.canRead()) {
this.getEventHandlerFileList().add(specialEventHandler);
this.getLogger().debug1(".. using special event handler for event class: " + specialEventHandler.getCanonicalPath());
}
}
}
// add default event handlers
this.getEventHandlerFileList().addAll(SOSFile.getFilelist(this.getEventHandlerFilepath(), this.getEventHandlerFilespec(), 0));
this.getLogger().debug1(
".. adding list of default event handlers: " + this.getEventHandlerFilepath() + "/" + this.getEventHandlerFilespec());
}
else {
if (!eventHandlerFile.canRead())
throw new Exception("event handler file is not accessible: " + eventHandlerFile.getCanonicalPath());
this.getEventHandlerFileList().add(eventHandlerFile);
}
HashMap stylesheetParameters = new HashMap();
stylesheetParameters.put("current_date", SOSDate.getCurrentTimeAsString());
stylesheetParameters.put("expiration_date", SOSDate.getTimeAsString(this.getExpirationDate().getTime()));
// old Xalan doesn't work with parameters
getEvents().getDocumentElement().setAttribute("current_date", SOSDate.getCurrentTimeAsString());
getEvents().getDocumentElement().setAttribute("expiration_date", SOSDate.getTimeAsString(this.getExpirationDate().getTime()));
this.setEventHandlerFileListIterator(this.getEventHandlerFileList().iterator());
while (this.getEventHandlerFileListIterator().hasNext()) {
eventHandler = (File) this.getEventHandlerFileListIterator().next();
if (eventHandler == null)
continue;
File stylesheetResultFile = File.createTempFile("sos", ".xml");
stylesheetResultFile.deleteOnExit();
this.getEventHandlerResultFileList().add(stylesheetResultFile);
eventHandlerResultReference.put(stylesheetResultFile, eventHandler);
this.getLogger().debug1(".. processing events with stylesheet: " + eventHandler.getCanonicalPath());
SOSXMLTransformer.transform(this.xmlDocumentToString(this.getEvents()), eventHandler, stylesheetResultFile, stylesheetParameters);
}
}
catch (Exception e) {
throw new Exception("error occurred processing event handler" + ((eventHandler != null) ? " [" + eventHandler.getCanonicalPath() + "]" : "")
+ ": " + e.getMessage());
}
try { // to execute commands returned by event handlers
this.setEventHandlerResultFileListIterator(this.getEventHandlerResultFileList().iterator());
while (this.getEventHandlerResultFileListIterator().hasNext()) {
NodeList commands = null;
Object result = this.getEventHandlerResultFileListIterator().next();
if (result instanceof File) {
File resultFile = (File) result;
if (resultFile == null)
continue;
File eventHandlerFile = (File) eventHandlerResultReference.get(resultFile);
this.getLogger().debug3(".. content of result file for event handler: " + eventHandlerFile.getCanonicalPath());
this.getLogger().debug3(this.getFileContent(resultFile).toString());
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document eventDocument = docBuilder.parse(new InputSource(new StringReader(this.getFileContent(resultFile).toString())));
Element eCommands = eventDocument.getDocumentElement();
if (eCommands != null) {
String debug = eCommands.getAttribute("debug");
if (debug.equalsIgnoreCase("true"))
logTransformation(resultFile, eventHandlerFile);
}
// XPath xpath = XPathFactory.newInstance().newXPath();
// NodeList commands = (NodeList) xpath.evaluate("//command", eventDocument, XPathConstants.NODESET);
commands = (NodeList) XPathAPI.selectNodeList(eventDocument, "//command");
}
else {
commands = (NodeList) XPathAPI.selectNodeList((Node) result, "command");
}
for (int i = 0; i < commands.getLength(); i++) {
Node command = commands.item(i);
NamedNodeMap commandAttributes = command.getAttributes();
// String commandSchedulerID = spooler.id();
String commandHost = spooler.hostname();
String commandPort = Integer.toString(spooler.tcp_port());
String commandProtocol = "tcp";
for (int j = 0; j < commandAttributes.getLength(); j++) {
// if (commandAttributes.item(j).getNodeName().equals("scheduler_id") &&
// commandAttributes.item(j).getNodeValue().length() > 0) commandSchedulerID =
// commandAttributes.item(j).getNodeValue();
if (commandAttributes.item(j).getNodeName().equals("scheduler_host") && commandAttributes.item(j).getNodeValue().length() > 0) {
this.getLogger().debug7("using host from command: " + commandAttributes.item(j).getNodeValue());
commandHost = commandAttributes.item(j).getNodeValue();
}
if (commandAttributes.item(j).getNodeName().equals("scheduler_port") && commandAttributes.item(j).getNodeValue().length() > 0)
commandPort = commandAttributes.item(j).getNodeValue();
if (commandAttributes.item(j).getNodeName().equals("protocol") && commandAttributes.item(j).getNodeValue().length() > 0)
commandProtocol = commandAttributes.item(j).getNodeValue();
}
SOSSchedulerCommand schedulerCommand = new SOSSchedulerCommand();
schedulerCommand.setTimeout(socket_timeout);
/*if (commandSchedulerID.length() > 0) {
// TODO: fetch remote Job Schedulers via XML response <show_state what="remote_schedulers"/>
// <answer><remote_schedulers><remote_scheduler ip="" tcp_port="" scheduler_id=""/></remote_schedulers></answer>
} else*/
if (commandHost.length() > 0) {
schedulerCommand.setHost(commandHost);
if (commandPort.length() > 0) {
schedulerCommand.setPort(Integer.parseInt(commandPort));
}
else {
throw new Exception("empty port has been specified by event handler response for commands");
}
}
else {
throw new Exception("empty Job Scheduler ID or host and port have been specified by event handler response for commands");
}
if (commandProtocol.length() > 0)
schedulerCommand.setProtocol(commandProtocol);
try {
this.getLogger().debug1(".. connecting to Job Scheduler " + schedulerCommand.getHost() + ":" + schedulerCommand.getPort());
schedulerCommand.connect();
NodeList commandElements = command.getChildNodes();
for (int k = 0; k < commandElements.getLength(); k++) {
if (commandElements.item(k).getNodeType() != Node.ELEMENT_NODE)
continue;
String commandRequest = this.xmlNodeToString(commandElements.item(k));
this.getLogger()
.info(".. sending command to remote Job Scheduler [" + commandHost + ":" + commandPort + "]: " + commandRequest);
schedulerCommand.sendRequest(commandRequest);
SOSXMLXPath answer = new SOSXMLXPath(new StringBuffer(schedulerCommand.getResponse()));
String errorText = answer.selectSingleNodeValue("//ERROR/@text");
if (errorText != null && errorText.length() > 0) {
throw new Exception("could not send command to remote Job Scheduler [" + commandHost + ":" + commandPort + "]: "
+ errorText);
}
}
}
catch (Exception e) {
throw new Exception("Error contacting remote Job Scheduler: " + e, e);
}
finally {
try {
schedulerCommand.disconnect();
}
catch (Exception ex) {
}
}
}
}
}
catch (Exception e) {
throw new Exception("could not execute command: " + e.getMessage());
}
try { // to remove events that have been dismissed by stylsheets
this.setEventHandlerResultFileListIterator(this.getEventHandlerResultFileList().iterator());
while (this.getEventHandlerResultFileListIterator().hasNext()) {
Object result = this.getEventHandlerResultFileListIterator().next();
NodeList commands = null;
if (result instanceof File) {
File resultFile = (File) result;
if (resultFile == null)
continue;
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document eventDocument = docBuilder.parse(new InputSource(new StringReader(this.getFileContent(resultFile).toString())));
// XPath xpath = XPathFactory.newInstance().newXPath();
// NodeList commands = (NodeList) xpath.evaluate("//remove_event", eventDocument, XPathConstants.NODESET);
commands = (NodeList) XPathAPI.selectNodeList(eventDocument, "//remove_event");
}
else {
commands = (NodeList) XPathAPI.selectNodeList((Node) result, "remove_event");
}
this.getLogger().debug3("-->" + commands.getLength() + " events should be deleted");
for (int i = 0; i < commands.getLength(); i++) {
if (commands.item(i) == null)
continue;
if (commands.item(i).getNodeType() == Node.ELEMENT_NODE) {
this.removeEvents(commands.item(i).getChildNodes());
}
}
}
}
catch (Exception e) {
throw new Exception("could not remove event caused by event handler: " + e.getMessage());
}
try { // to add events that have been created by event handlers
this.setEventHandlerResultFileListIterator(this.getEventHandlerResultFileList().iterator());
while (this.getEventHandlerResultFileListIterator().hasNext()) {
Object result = this.getEventHandlerResultFileListIterator().next();
NodeList commands = null;
if (result instanceof File) {
File resultFile = (File) result;
if (resultFile == null)
continue;
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document eventDocument = docBuilder.parse(new InputSource(new StringReader(this.getFileContent(resultFile).toString())));
// XPath xpath = XPathFactory.newInstance().newXPath();
// NodeList commands = (NodeList) xpath.evaluate("//add_event/*", eventDocument, XPathConstants.NODESET);
commands = (NodeList) XPathAPI.selectNodeList(eventDocument, "//add_event/event");
}
else {
commands = (NodeList) XPathAPI.selectNodeList((Node) result, "add_event/event");
}
for (int i = 0; i < commands.getLength(); i++) {
if (commands.item(i) == null)
continue;
if (commands.item(i).getNodeType() == Node.ELEMENT_NODE) {
NamedNodeMap attributes = commands.item(i).getAttributes();
if (attributes == null)
continue;
Element event = this.getEvents().createElement("event");
for (int j = 0; j < attributes.getLength(); j++) {
if (attributes.item(j).getNodeName().equalsIgnoreCase("event_name"))
continue;
event.setAttribute(attributes.item(j).getNodeName(), attributes.item(j).getNodeValue());
}
this.addEvent(event);
}
}
}
}
catch (Exception e) {
throw new Exception("could not add event created by event handler: " + e.getMessage());
}
}
catch (Exception e) {
throw new Exception("events processed with errors: " + e.getMessage());
}
finally {
try { // to remove temporary files
this.setEventHandlerResultFileListIterator(this.getEventHandlerResultFileList().iterator());
while (this.getEventHandlerResultFileListIterator().hasNext()) {
Object result = this.getEventHandlerResultFileListIterator().next();
if (result instanceof File) {
File resultFile = (File) result;
if (resultFile == null)
continue;
if (!resultFile.delete()) {
this.getLogger().info(".. temporary file could not be removed: " + resultFile.getCanonicalPath());
resultFile.deleteOnExit();
}
}
}
}
catch (Exception e) {
this.getLogger().warn("could not delete temporary file: " + e.getMessage());
}
}
}
private void logTransformation(File resultFile, File stylesheetFile) throws Exception {
try {
File logDir = new File(spooler.log_dir());
File eventLogDir = new File(logDir, "events");
if (!eventLogDir.exists()) {
getLogger().info("creating event log dir: " + eventLogDir.getAbsolutePath());
if (!eventLogDir.mkdir()) {
getLogger().warn("directory [" + eventLogDir.getAbsolutePath() + "] could not be created.");
return;
}
}
File stylesheetLogDir = new File(eventLogDir, stylesheetFile.getName());
if (!stylesheetLogDir.exists()) {
getLogger().info("creating stylesheet log dir: " + stylesheetLogDir.getAbsolutePath());
if (!stylesheetLogDir.mkdir()) {
getLogger().warn("directory [" + stylesheetLogDir.getAbsolutePath() + "] could not be created.");
return;
}
}
String timeStamp = SOSDate.getCurrentDateAsString("yyyy-MM-dd_HHmmss_SSS");
File resultLogFile = new File(stylesheetLogDir, "events_" + timeStamp + "_result.xml");
SOSFile.copyFile(resultFile, resultLogFile);
File eventFile = new File(stylesheetLogDir, "events_" + timeStamp + ".xml");
// write current events to eventFile
OutputStream fout = new FileOutputStream(eventFile, false);
OutputStreamWriter out = new OutputStreamWriter(fout, "UTF-8");
OutputFormat format = new OutputFormat(getEvents());
format.setEncoding("UTF-8");
format.setIndenting(true);
format.setIndent(2);
XMLSerializer serializer = new XMLSerializer(out, format);
serializer.serialize(getEvents());
out.close();
getLogger().debug("current events logged to: " + eventFile.getAbsolutePath());
getLogger().debug("transformation result logged to: " + resultLogFile.getAbsolutePath());
}
catch (Exception e) {
throw new Exception("Error logging Transformation result: " + e, e);
}
}
/**
* add an event
*/
public void addEvent() throws Exception {
try {
this.getLogger().debug9(
".. constructing event: schedulerId=" + this.getEventSchedulerId() + ", eventClass=" + this.getEventClass() + ", eventId="
+ this.getEventId());
Element event = this.getEvents().createElement("event");
event.setAttribute("scheduler_id", this.getEventSchedulerId());
event.setAttribute("remote_scheduler_host", this.getEventRemoteSchedulerHost());
event.setAttribute("remote_scheduler_port", this.getEventRemoteSchedulerPort());
event.setAttribute("job_chain", this.getEventJobChainName());
event.setAttribute("order_id", this.getEventOrderId());
event.setAttribute("job_name", this.getEventJobName());
event.setAttribute("event_class", this.getEventClass());
event.setAttribute("event_id", this.getEventId());
event.setAttribute("exit_code", this.getEventExitCode());
event.setAttribute("created", this.getEventCreated());
if (getEventExpires().length() == 0 || getEventExpires().equalsIgnoreCase("default")) {
event.setAttribute("expires", SOSDate.getTimeAsString(this.getExpirationDate().getTime()));
}
else
if (getEventExpires().equalsIgnoreCase("never")) {
getLogger().debug7("event expires: never");
}
else {
event.setAttribute("expires", this.getEventExpires());
}
if (this.getEventParameters() != null && this.getEventParameters().getChildNodes().getLength() > 0) {
event.appendChild(this.getEventParameters());
}
this.addEvent(event);
}
catch (Exception e) {
throw new Exception(e);
}
}
/**
* add an event
*/
public void addEvent(Element event) throws Exception {
addEvent(event, true);
}
/**
* add an event
*/
public void addEvent(Element event, boolean replace) throws Exception {
if (event.getAttribute("scheduler_id").length() == 0) {
event.setAttribute("scheduler_id", spooler.id());
}
if (replace) {
Element dummyParent = getEvents().createElement("events");
Element remEv = (Element) event.cloneNode(true);
dummyParent.appendChild(remEv);
getLogger().debug9("remEv: " + remEv);
getLogger().debug9("remEv.getParentNode(): " + remEv.getParentNode());
remEv.removeAttribute("created");
remEv.removeAttribute("expires");
removeEvents(remEv.getParentNode().getChildNodes());
}
try {
String curEventSchedulerId = this.getAttributeValue(event, "scheduler_id");
String curEventRemoteSchedulerHost = this.getAttributeValue(event, "remote_scheduler_host");
String curEventRemoteSchedulerPort = this.getAttributeValue(event, "remote_scheduler_port");
String curEventClass = this.getAttributeValue(event, "event_class");
String curEventId = this.getAttributeValue(event, "event_id");
String curEventExitCode = this.getAttributeValue(event, "exit_code");
String curEventJobChainName = this.getAttributeValue(event, "job_chain");
String curEventOrderId = this.getAttributeValue(event, "order_id");
String curEventJobName = this.getAttributeValue(event, "job_name");
String curEventCreated = this.getAttributeValue(event, "created");
String curExpiration_period = this.getAttributeValue(event, "expiration_period");
String curExpiration_cycle = this.getAttributeValue(event, "expiration_cycle");
this.getLogger().debug3(".. --> curExpiration_period:" + curExpiration_period);
this.getLogger().debug3(".. --> curExpiration_cycle:" + curExpiration_cycle);
// Im AddEvent ist kein ExpirationPeriod angegeben. Wir nehmen den Wert des Jobs (Default = "24:00:00")
if (curExpiration_period == null || curExpiration_period.length() <= 0) {
curExpiration_period = this.getExpirationPeriod();
}
// Im AddEvent ist kein ExpirationCycle angegeben. Wir nehmen den Wert des Jobs (Default="")
if (curExpiration_cycle == null || curExpiration_cycle.length() <= 0) {
curExpiration_cycle = this.getExpirationCycle();
}
String curEventExpires = this.getAttributeValue(event, "expires");
this.getLogger().debug3(".. --> curEventExpires:" + curEventExpires);
// Wenn kein Expires explizit angegeben ist, wird es aus expirationPeriod (Dauer) bzw. expirationCycle(Zeitpunkt) errechnet.
// Default ist das eine Lebensdauer von 24 Stunden.
if (curEventExpires == null || curEventExpires.length() <= 0) {
Calendar cal = calculateExpirationDate(curExpiration_cycle, curExpiration_period);
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
curEventExpires = format.format(cal.getTime());
this.getLogger().debug3(".. --> curEventExpires:" + curEventExpires);
}
catch (Exception pe) {
this.getLogger().warn(cal.getTime().toString() + " is not a valid Date. Expires will be set to default");
}
}
if (curEventId.length() == 0)
throw new Exception("Empty event_id is not allowed.");
this.getLogger().info(
".. adding event ...: scheduler id=" + curEventSchedulerId + ", event class=" + curEventClass + ", event id=" + curEventId + ", exit code="
+ curEventExitCode + ", job chain=" + curEventJobChainName + ", order id=" + curEventOrderId + ", job=" + curEventJobName);
this.getEvents().getLastChild().appendChild(event);
if (this.getConnection() == null) {
// spooler_log.debug1("no database in use - events are not stored persistently");
}
else {
String stmt = "INSERT INTO "
+ this.getTableEvents()
+ " (\"SPOOLER_ID\", \"REMOTE_SCHEDULER_HOST\", \"REMOTE_SCHEDULER_PORT\", \"JOB_CHAIN\", \"ORDER_ID\", \"JOB_NAME\", \"EVENT_CLASS\", \"EVENT_ID\", \"EXIT_CODE\", \"CREATED\", \"EXPIRES\")"
+ " VALUES ('" + curEventSchedulerId + "', '" + curEventRemoteSchedulerHost + "', "
+ ((curEventRemoteSchedulerPort.length() == 0) ? "0" : curEventRemoteSchedulerPort) + ", '" + curEventJobChainName + "', '"
+ curEventOrderId + "', '" + curEventJobName + "', '" + curEventClass + "', '" + curEventId + "', '" + curEventExitCode + "', "
+ ((curEventCreated.length() > 0) ? "%timestamp_iso('" + curEventCreated + "')" : "%now") + ", "
+ ((curEventExpires.length() > 0) ? "%timestamp_iso('" + curEventExpires + "')" : "NULL") + ")";
this.getConnection().executeUpdate(stmt);
NodeList nodes = (NodeList) XPathAPI.selectNodeList(event, "params");
if (nodes != null && nodes.getLength() > 0) {
getLogger().debug5("Event has parameters. Storing parameters...");
Element params = (Element) nodes.item(0);
String paramsString = xmlElementToString(params);
getLogger().debug5(paramsString);
String sequenceName = "SCHEDULER_EVENTS_ID_SEQ";
if (getConnection() instanceof SOSPgSQLConnection)
sequenceName = "\"scheduler_events_ID_seq\"";
String eventDbID = getConnection().getLastSequenceValue(sequenceName);
getConnection().updateClob(getTableEvents(), "PARAMETERS", paramsString, "\"ID\"=" + eventDbID);
}
this.getConnection().commit();
}
}
catch (Exception e) {
if (this.getConnection() != null) {
try {
this.getConnection().rollback();
}
catch (Exception ex) {
} // gracefully ignore this error
}
throw new Exception(e);
}
}
/**
* remove multiple events with matching attributes
*/
public void removeEvents(NodeList events) throws Exception {
try {
for (int i = 0; i < events.getLength(); i++) {
if (events.item(i) == null || events.item(i).getNodeType() != Node.ELEMENT_NODE)
continue;
String xquery = "//event[";
String and = "";
Element event = (Element) events.item(i);
String curEventClass = event.getAttribute("event_class");
if (curEventClass != null && curEventClass.equalsIgnoreCase(EVENT_CLASS_ALL_EVENTS)) {
removeAllEvents();
return;
}
boolean hasAttributes = false;
NamedNodeMap eventAttributeList = event.getAttributes();
for (int j = 0; j < eventAttributeList.getLength(); j++) {
Node eventAttribute = eventAttributeList.item(j);
if (eventAttribute == null)
continue;
if (eventAttribute.getNodeName().equalsIgnoreCase("event_name"))
continue;
String value = eventAttribute.getNodeValue();
if (!eventAttribute.getNodeName().equals("event_title") && value != null && value.length() > 0) {
hasAttributes = true;
xquery += and + "@" + eventAttribute.getNodeName() + "='" + eventAttribute.getNodeValue() + "'";
and = " and ";
}
}
xquery += "]";
if (!hasAttributes) {
getLogger().warn("current event has no attributes. Removal (of all elements) will not be performed.");
continue;
}
// XPath xpath = XPathFactory.newInstance().newXPath();
// NodeList nodes = (NodeList) xpath.evaluate(xquery, this.getEvents(), XPathConstants.NODESET);
getLogger().debug7("xquery to remove events: " + xquery);
NodeList nodes = (NodeList) XPathAPI.selectNodeList(this.getEvents(), xquery);
for (int j = 0; j < nodes.getLength(); j++) {
if (nodes.item(j) == null)
continue;
if (nodes.item(j).getNodeType() == Node.ELEMENT_NODE)
this.removeEvent(nodes.item(j));
}
}
}
catch (Exception e) {
throw new Exception(e);
}
}
public void removeAllEvents() throws Exception {
try {
getLogger().info("event class is: " + EVENT_CLASS_ALL_EVENTS + ". Removing all events.");
Document eventDocument = getEvents();
eventDocument.removeChild(eventDocument.getFirstChild());
eventDocument.appendChild(eventDocument.createElement("events"));
if (this.getConnection() != null) {
String stmt = "DELETE FROM " + this.getTableEvents() + " WHERE 1>0";
this.getConnection().executeUpdate(stmt);
this.getConnection().commit();
}
this.setEventClass("");
}
catch (Exception e) {
throw new Exception("Error removing all events: " + e, e);
}
}
/**
* remove an event
*/
public void removeEvent() throws Exception {
try {
this.getLogger().debug9(".. constructing event: eventClass=" + this.getEventClass() + ", eventId=" + this.getEventId());
Element event = this.getEvents().createElement("event");
event.setAttribute("event_class", this.getEventClass());
event.setAttribute("event_id", this.getEventId());
event.setAttribute("scheduler_id", this.getEventSchedulerId());
event.setAttribute("remote_scheduler_host", this.getEventRemoteSchedulerHost());
if (!this.getEventRemoteSchedulerPort().equalsIgnoreCase("0"))
event.setAttribute("remote_scheduler_port", this.getEventRemoteSchedulerPort());
event.setAttribute("job_chain", this.getEventJobChainName());
event.setAttribute("order_id", this.getEventOrderId());
event.setAttribute("job_name", this.getEventJobName());
if (this.getEventExitCode().length() > 0) {
event.setAttribute("exit_code", this.getEventExitCode());
}
// event.setAttribute("expires", this.getEventExpires());
// event.setAttribute("created", this.getEventCreated());
// TODO: sollen Parameter beim Remove ausgewertet werden?
// event.setAttribute("parameters", this.getEventParameters());
Element dummyParent = getEvents().createElement("events");
dummyParent.appendChild(event);
this.removeEvents(event.getParentNode().getChildNodes());
}
catch (Exception e) {
throw new Exception(e);
}
}
/**
* remove an event
*/
public void removeEvent(Node event) throws Exception {
try {
String curEventSchedulerId = this.getAttributeValue(event, "scheduler_id");
String curEventClass = this.getAttributeValue(event, "event_class");
String curEventId = this.getAttributeValue(event, "event_id");
String curEventExitCode = this.getAttributeValue(event, "exit_code");
String curEventJobChainName = this.getAttributeValue(event, "job_chain");
String curEventOrderId = this.getAttributeValue(event, "order_id");
String curEventJobName = this.getAttributeValue(event, "job_name");
this.getLogger().info(
".. removing event ...: scheduler id=" + curEventSchedulerId + ", event class=" + curEventClass + ", event id=" + curEventId
+ ", exit code=" + curEventExitCode + ", job chain=" + curEventJobChainName + ", order id=" + curEventOrderId + ", job="
+ curEventJobName);
Node nEvents = this.getEvents().getFirstChild();
this.getLogger().debug7("Events Name: " + nEvents.getLocalName());
this.getLogger().debug7("Events size: " + nEvents.getChildNodes().getLength());
this.getEvents().getFirstChild().removeChild(event);
this.getLogger().debug7("Events size: " + nEvents.getChildNodes().getLength());
if (this.getConnection() == null) {
// this.getLogger().debug1("no database in use - events are not stored persistently");
}
else {
String stmt = "DELETE FROM " + this.getTableEvents() + " WHERE ";
String and = "";
if (curEventSchedulerId.length() > 0) {
stmt += and + "\"SPOOLER_ID\"='" + curEventSchedulerId + "'";
and = " AND ";
}
if (curEventJobChainName.length() > 0) {
stmt += and + "\"JOB_CHAIN\"='" + curEventJobChainName + "'";
and = " AND ";
}
if (curEventOrderId.length() > 0) {
stmt += and + "\"ORDER_ID\"='" + curEventOrderId + "'";
and = " AND ";
}
if (curEventJobName.length() > 0) {
stmt += and + "\"JOB_NAME\"='" + curEventJobName + "'";
and = " AND ";
}
if (curEventClass.length() > 0) {
stmt += and + "\"EVENT_CLASS\"='" + curEventClass + "'";
and = " AND ";
}
if (curEventId.length() > 0) {
stmt += and + "\"EVENT_ID\"='" + curEventId + "'";
and = " AND ";
}
this.getConnection().executeUpdate(stmt);
this.getConnection().commit();
}
}
catch (Exception e) {
if (this.getConnection() != null) {
try {
this.getConnection().rollback();
}
catch (Exception ex) {
} // gracefully ignore this error
}
throw new Exception(e);
}
}
/**
* return XML String
*/
public String getAttributeValue(Node node, String namedItem) throws Exception {
try {
if (node.getAttributes() == null || node.getAttributes().getLength() == 0)
return "";
if (node.getAttributes().getNamedItem(namedItem) == null)
return "";
return node.getAttributes().getNamedItem(namedItem).getNodeValue();
}
catch (Exception e) {
throw new Exception("error occurred reading attribute value: " + e.getMessage());
}
}
/**
* return XML String
*/
public String xmlNodeToString(Node node) throws Exception {
try {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document document = docBuilder.newDocument();
document.appendChild(document.importNode(node, true));
StringWriter out = new StringWriter();
XMLSerializer serializer = new XMLSerializer(out, new OutputFormat(document));
serializer.serialize(document);
return out.toString();
}
catch (Exception e) {
throw new Exception("error occurred transforming node: " + e.getMessage());
}
}
/**
* return XML String
*/
public String xmlDocumentToString(Document document) throws Exception {
try {
StringWriter out = new StringWriter();
XMLSerializer serializer = new XMLSerializer(out, new OutputFormat(document));
serializer.serialize(document);
return out.toString();
}
catch (Exception e) {
throw new Exception("error occurred transforming document: " + e.getMessage());
}
}
/**
* return XML String
*/
public String xmlElementToString(Element element) throws Exception {
try {
StringWriter out = new StringWriter();
XMLSerializer serializer = new XMLSerializer(out, new OutputFormat());
serializer.serialize(element);
return out.toString();
}
catch (Exception e) {
throw new Exception("error occurred transforming document: " + e.getMessage());
}
}
/**
* read content of a file to a string buffer
*/
private StringBuffer getFileContent(File file) throws Exception {
BufferedInputStream in = null;
StringBuffer content = new StringBuffer();
if (file == null)
throw new Exception("no valid file object found");
if (!file.canRead())
throw new Exception("file not accessible: " + file.getCanonicalPath());
try {
FileInputStream fis = new FileInputStream(file);
in = new BufferedInputStream(fis);
byte buffer[] = new byte[1024];
int bytesRead;
while ((bytesRead = in.read(buffer)) != -1) {
content.append(new String(buffer, 0, bytesRead));
}
fis.close();
fis = null;
in.close();
in = null;
return content;
}
catch (Exception e) {
throw new Exception("error occurred reading content of file [" + file.getCanonicalPath() + "]: " + e.getMessage());
}
finally {
if (in != null) {
in.close();
in = null;
}
}
}
/**
* @return the parameters
*/
public Variable_set getParameters() {
return parameters;
}
/**
* @param parameters the parameters to set
*/
public void setParameters(Variable_set parameters) {
this.parameters = parameters;
}
/**
* @return the eventClass
*/
public String getEventClass() {
return eventClass;
}
/**
* @param eventClass the eventClass to set
*/
public void setEventClass(String eventClass) {
this.eventClass = eventClass;
}
/**
* @return the eventExpires
*/
public String getEventExpires() {
return eventExpires;
}
/**
* @param eventExpires the eventExpires to set
*/
public void setEventExpires(String eventExpires) {
this.eventExpires = eventExpires;
}
/**
* @return the eventId
*/
public String getEventId() {
return eventId;
}
/**
* @param eventId the eventId to set
*/
public void setEventId(String eventId) {
this.eventId = eventId;
}
/**
* @return the eventParameters
*/
public Element getEventParameters() {
return eventParameters;
}
/**
* @param eventParameters the eventParameters to set
*/
public void setEventParameters(Element eventParameters) {
this.eventParameters = eventParameters;
}
/**
* @return the eventAction
*/
public String getEventAction() {
return eventAction;
}
/**
* @param eventAction the eventAction to set
*/
public void setEventAction(String eventAction) throws Exception {
if (!eventAction.equalsIgnoreCase("add") && !eventAction.equalsIgnoreCase("remove") && !eventAction.equalsIgnoreCase("process")) {
throw new Exception("invalid action specified [add, remove, process]: " + eventAction);
}
this.eventAction = eventAction;
}
/**
* @return the tableEvents
*/
public static String getTableEvents() {
return JobSchedulerEventJob.tableEvents;
}
/**
* @param tableEvents the tableEvents to set
*/
public static void setTableEvents(String tableEvents) {
JobSchedulerEventJob.tableEvents = tableEvents;
}
/**
* @return the events
*/
public Document getEvents() {
return events;
}
/**
* @param events the events to set
*/
public void setEvents(Document events) {
this.events = events;
}
/**
* @return the eventSchedulerId
*/
public String getEventSchedulerId() {
return eventSchedulerId;
}
/**
* @param eventSchedulerId the eventSchedulerId to set
*/
public void setEventSchedulerId(String eventSchedulerId) {
this.eventSchedulerId = eventSchedulerId;
}
/**
* @return the expirationPeriod
*/
public String getExpirationPeriod() {
return expirationPeriod;
}
/**
* @param expirationPeriod the expirationPeriod to set
*/
public void setExpirationPeriod(String expirationPeriod) {
this.expirationPeriod = expirationPeriod;
}
/**
* @return the eventJobChainName
*/
public String getEventJobChainName() {
return eventJobChainName;
}
/**
* @param eventJobChainName the eventJobChainName to set
*/
public void setEventJobChainName(String eventJobChainName) {
this.eventJobChainName = eventJobChainName;
}
/**
* @return the eventJobName
*/
public String getEventJobName() {
return eventJobName;
}
/**
* @param eventJobName the eventJobName to set
*/
public void setEventJobName(String eventJobName) {
this.eventJobName = eventJobName;
}
/**
* @return the event handler Filepath
*/
public String getEventHandlerFilepath() {
return eventHandlerFilepath;
}
/**
* @param eventHandlerFilepath the event handler Filepath to set
*/
public void setEventHandlerFilepath(String eventHandlerFilepath) {
this.eventHandlerFilepath = eventHandlerFilepath;
}
/**
* @return the stylesheetFilespec
*/
public String getEventHandlerFilespec() {
return eventHandlerFilespec;
}
/**
* @param eventHandlerFilespec the stylesheetFilespec to set
*/
public void setEventHandlerFilespec(String eventHandlerFilespec) {
this.eventHandlerFilespec = eventHandlerFilespec;
}
/**
* @return the stylesheetFileList
*/
public Collection getEventHandlerFileList() {
return eventHandlerFileList;
}
/**
* @param eventHandlerFileList the stylesheetFileList to set
*/
public void setEventHandlerFileList(Collection eventHandlerFileList) {
this.eventHandlerFileList = eventHandlerFileList;
}
/**
* @return the stylesheetFileListIterator
*/
public Iterator getEventHandlerFileListIterator() {
return eventHandlerFileListIterator;
}
/**
* @param eventHandlerFileListIterator the stylesheetFileListIterator to set
*/
public void setEventHandlerFileListIterator(Iterator eventHandlerFileListIterator) {
this.eventHandlerFileListIterator = eventHandlerFileListIterator;
}
/**
* @return the stylesheetResultFileList
*/
public Collection getEventHandlerResultFileList() {
return eventHandlerResultFileList;
}
/**
* @param eventHandlerResultFileList the stylesheetResultFileList to set
*/
public void setEventHandlerResultFileList(Collection eventHandlerResultFileList) {
this.eventHandlerResultFileList = eventHandlerResultFileList;
}
/**
* @return the expirationDate
*/
public Calendar getExpirationDate() {
return expirationDate;
}
/**
* @param expirationDate the expirationDate to set
*/
public void setExpirationDate(Calendar expirationDate) {
this.expirationDate = expirationDate;
}
/**
* @return the stylesheetResultFileListIterator
*/
public Iterator getEventHandlerResultFileListIterator() {
return eventHandlerResultFileListIterator;
}
/**
* @param eventHandlerResultFileListIterator the stylesheetResultFileListIterator to set
*/
public void setEventHandlerResultFileListIterator(Iterator eventHandlerResultFileListIterator) {
this.eventHandlerResultFileListIterator = eventHandlerResultFileListIterator;
}
/**
* @return the eventRemoteSchedulerHost
*/
public String getEventRemoteSchedulerHost() {
return eventRemoteSchedulerHost;
}
/**
* @param eventRemoteSchedulerHost the eventRemoteSchedulerHost to set
*/
public void setEventRemoteSchedulerHost(String eventRemoteSchedulerHost) {
this.eventRemoteSchedulerHost = eventRemoteSchedulerHost;
}
/**
* @return the eventRemoteSchedulerPort
*/
public String getEventRemoteSchedulerPort() {
return eventRemoteSchedulerPort;
}
/**
* @param eventRemoteSchedulerPort the eventRemoteSchedulerPort to set
*/
public void setEventRemoteSchedulerPort(String eventRemoteSchedulerPort) {
this.eventRemoteSchedulerPort = eventRemoteSchedulerPort;
}
/**
* @return the eventExitCode
*/
public String getEventExitCode() {
return eventExitCode;
}
/**
* @param eventExitCode the eventExitCode to set
*/
public void setEventExitCode(String eventExitCode) {
this.eventExitCode = eventExitCode;
}
/**
* @return the eventOrderId
*/
public String getEventOrderId() {
return eventOrderId;
}
/**
* @param eventOrderId the eventOrderId to set
*/
public void setEventOrderId(String eventOrderId) {
this.eventOrderId = eventOrderId;
}
/**
* @return the eventCreated
*/
public String getEventCreated() {
return eventCreated;
}
/**
* @param eventCreated the eventCreated to set
*/
public void setEventCreated(String eventCreated) {
this.eventCreated = eventCreated;
}
/**
* @return the expirationCycle
*/
public String getExpirationCycle() {
return expirationCycle;
}
/**
* @param expirationCycle the expirationCycle to set
*/
public void setExpirationCycle(String expirationCycle) {
this.expirationCycle = expirationCycle;
}
private int getSocket_timeout() {
return socket_timeout;
}
private void setSocket_timeout(String s) {
try {
socket_timeout = Integer.parseInt(s);
}
catch (NumberFormatException e) {
spooler_log.warn("Illegal value for parameter socket_timeout:" + s + ". Integer expected. Using default=5");
socket_timeout = 5;
}
}
}