/*
* Copyright (C) 2000 - 2011 TagServlet Ltd
*
* This file is part of Open BlueDragon (OpenBD) CFML Server Engine.
*
* OpenBD is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* Free Software Foundation,version 3.
*
* OpenBD is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenBD. If not, see http://www.gnu.org/licenses/
*
* Additional permission under GNU GPL version 3 section 7
*
* If you modify this Program, or any covered work, by linking or combining
* it with any of the JARS listed in the README.txt (or a modified version of
* (that library), containing parts covered by the terms of that JAR, the
* licensors of this Program grant you additional permission to convey the
* resulting work.
* README.txt @ http://www.openbluedragon.org/license/README.txt
*
* http://www.openbluedragon.org/
* $Id: $
*/
package com.naryx.tagfusion.cfm.schedule;
import java.io.File;
import java.io.FilenameFilter;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import com.nary.io.FileUtils;
import com.nary.util.LogFile;
import com.naryx.tagfusion.cfm.engine.cfEngine;
import com.naryx.tagfusion.xmlConfig.xmlCFML;
public class scheduleEngine extends Thread {
private static scheduleEngine engine = null;
private File taskDirectory;
private Hashtable<String, scheduleTask> taskList;
private File outFile;
private boolean bPauseSchedule = false;
// -------------------------
private scheduleEngine(xmlCFML configFile) {
super("scheduleEngine");
try {
taskDirectory = FileUtils.checkAndCreateDirectory( cfEngine.thisPlatform.getFileIO().getWorkingDirectory(), "cfschedule", false );
} catch (Exception e) {
cfEngine.log("Failed to create the ScheduleEngine: " + e.getMessage() );
return;
}
taskList = new Hashtable<String, scheduleTask>(10);
outFile = new File(taskDirectory, "schedule.log");
setDaemon(false);
setPriority(MIN_PRIORITY);
}
public static void pause( boolean bPause ){
engine.bPauseSchedule = bPause;
}
public void run(){
cfEngine.log("ScheduleEngine: Started. Initial Tasks=" + taskList.size() );
while (cfEngine.bEngineActive){
try {
sleep(30000);
} catch (InterruptedException e) {continue;}
if ( bPauseSchedule )
continue;
// Run around the tasks to see who is waiting for running
try{
Enumeration<scheduleTask> e = taskList.elements();
while ( e.hasMoreElements() ){
scheduleTask sT = e.nextElement();
long cT = System.currentTimeMillis();
long nT = sT.getNextRunTime();
if ( !sT.isPause() && nT > 0 && nT <= cT ){
sT.runAndSchedule();
}
}
}catch(Exception e){
LogFile.println(engine.outFile, "scheduleEngine.run(): " + e.getMessage() );
}
}
cfEngine.log("ScheduleEngine: Shutdown");
}
public static Enumeration<String> getTasks() {
return engine.taskList.keys();
}
public static synchronized void init(xmlCFML configFile) {
if ( engine == null ){
engine = new scheduleEngine(configFile);
// The loadTasks() method relies on the engine member being initialized so it cannot
// be called from within the scheduleEngine constructor.
LogFile.println(engine.outFile, "scheduleEngine started");
engine.loadTasks(configFile);
engine.start();
LogFile.println(engine.outFile, "Active Tasks=" + engine.taskList.size() + "; Directory=" + engine.taskDirectory);
cfEngine.log("scheduleEngine started; logfile=" + engine.outFile.toString() );
}
}
public static void updateTask(String taskName, scheduleTask task) {
engine._updateTask(taskName.toLowerCase(), task);
}
public static void deleteTask(String taskName) {
engine._deleteTask(taskName.toLowerCase());
}
public static void runTask(String taskName) {
engine._runTask(taskName.toLowerCase());
}
public static void log(String _line) {
LogFile.println(engine.outFile, _line);
}
public static scheduleTask getTask(String taskName) {
return engine._getTask(taskName.toLowerCase());
}
// -------------------------
private void _updateTask(String taskName, scheduleTask task) {
if (taskList.containsKey(taskName))
taskList.remove(taskName);
task.setName(taskName.toLowerCase());
taskList.put(taskName, task);
saveTask(task);
LogFile.println(outFile, "scheduleEngine: UpdateTask: " + taskName );
LogFile.println(outFile, task.toString());
task.schedule();
}
private void _deleteTask(String taskName) {
if (taskList.containsKey(taskName)) {
// Remove task from task list
taskList.remove(taskName);
// Remove task from XML config data
String taskKey = "server.cfschedule.task[" + taskName.toLowerCase() + "]";
cfEngine.getConfig().removeData(taskKey);
try {
cfEngine.writeXmlFile(cfEngine.getConfig(), false);
} catch (Exception e) {
cfEngine.log("Delete task error: " + e.getMessage());
}
LogFile.println(outFile, "scheduleEngine: TaskRemoved: " + taskName );
}
}
private scheduleTask _getTask(String taskName) {
return taskList.get(taskName);
}
private void _runTask(String taskName) {
if (taskList.containsKey(taskName))
(taskList.get(taskName)).run();
else
LogFile.println(outFile, "scheduleEngine: RunTask: " + taskName );
}
private void loadTasks(xmlCFML configFile) {
scheduleTask task;
// Read in the tasks from bluedragon.xml
Vector elements = configFile.getKeys("server.cfschedule.task[]");
if (elements != null) {
Enumeration E = elements.elements();
while (E.hasMoreElements()) {
String taskKey = (String) E.nextElement();
task = scheduleTask.getTaskConfig(configFile, taskKey);
_updateTask(task.getName(), task);
}
}
// Now read in the old tasks from disk and copy them to the XML config object
String listOfFile[] = taskDirectory.list(new fileFilter());
boolean writeToFile = false;
for (int x = 0; x < listOfFile.length; x++) {
File thisFile = new File(taskDirectory, listOfFile[x]);
task = (scheduleTask) com.nary.Debug.loadClass(thisFile.toString());
if (task != null) {
_updateTask(task.getName(), task);
// write the task to the XML config object and delete the file
task.writeToConfig(configFile);
thisFile.delete();
writeToFile = true;
}
}
// If we converted some old tasks then save them to bluedragon.xml
if (writeToFile) {
try {
cfEngine.writeXmlFile(configFile, false);
} catch (Exception e) {
cfEngine.log("Save tasks to new format error: " + e.getMessage());
}
}
}
private void saveTask(scheduleTask task) {
// Save the task to the XML config data
task.writeToConfig(cfEngine.getConfig());
try {
cfEngine.writeXmlFile(cfEngine.getConfig(), false);
} catch (Exception e) {
cfEngine.log("Save task error: " + e.getMessage());
}
}
// -------------------------
class fileFilter implements FilenameFilter {
public fileFilter() {
}
public boolean accept(File dir, String name) {
if (name.indexOf(".task") != -1)
return true;
else
return false;
}
}
public static void pauseTask(String taskname ) {
taskname = taskname.toLowerCase();
scheduleTask task = engine._getTask(taskname);
if ( task != null ){
task.pause();
engine.saveTask( task );
}
}
public static void resumeTask(String taskname) {
taskname = taskname.toLowerCase();
scheduleTask task = engine._getTask(taskname);
if ( task != null ){
task.resume();
engine.saveTask( task );
}
}
}