/*
* Copyright (C) 2004 Anthony Smith
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* ----------------------------------------------------------------------------
* TITLE $Id$
* ---------------------------------------------------------------------------
*
* --------------------------------------------------------------------------*/
package opendbcopy.plugin;
import opendbcopy.controller.MainController;
import opendbcopy.plugin.model.*;
import opendbcopy.plugin.model.exception.MissingAttributeException;
import org.apache.log4j.Level;
import org.jdom.Element;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.LinkedList;
import java.util.Observable;
import java.util.Observer;
/**
* class description
*
* @author Anthony Smith
* @version $Revision$
*/
public class PluginScheduler implements Observer {
private static PluginScheduler instance = null;
private static DynamicPluginThread currentPluginThread;
private static Model currentModel;
private MainController controller;
private PluginManager pluginManager;
private LinkedList pluginsToExecute;
private boolean executeSinglePlugin;
/**
* Creates a new PluginExecutor object.
*
* @param pluginManager DOCUMENT ME!
* @param controller DOCUMENT ME!
*/
private PluginScheduler(PluginManager pluginManager,
MainController controller) {
this.pluginManager = pluginManager;
this.controller = controller;
}
/**
* Return singleton instance
*
* @param pluginManager DOCUMENT ME!
* @param controller DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public static PluginScheduler getInstance(PluginManager pluginManager,
MainController controller) {
if (instance == null) {
instance = new PluginScheduler(pluginManager, controller);
}
return instance;
}
/**
* DOCUMENT ME!
*
* @param o DOCUMENT ME!
* @param obj DOCUMENT ME!
*/
public final void update(Observable o,
Object obj) {
// check if current plugin had errors, then do not continue
if (!currentModel.isExceptionOccured()) {
if (!currentModel.isInterrupted() && !currentModel.isSuspended()) {
// only execute the next plugin if the previous isDone() and in the meantime pluginManager has not been interrupted
if (currentModel.isDone() && !pluginManager.isInterrupted()) {
// plugin chain
if (!executeSinglePlugin) {
Model plugin = getNextPlugin();
if (plugin != null) {
// check if next plugin requires input and if so, get it from previous plugin
if (plugin.isInputRequired()) {
if (currentModel.getOutput() != null) {
plugin.setInput((Element) currentModel.getOutput().clone());
} else {
plugin.setProgressMessage("Missing input from previous plugin!");
pluginManager.setExceptionOccured(true);
}
} else {
// if output of previous plugin is not null, pass it to next plugin
if (currentModel.getOutput() != null) {
plugin.setInput((Element) currentModel.getOutput().clone());
}
}
currentModel = plugin;
pluginManager.incrementCurrentExecuteIndex();
try {
executePlugin(currentModel);
} catch (Exception e) {
controller.postException(e, Level.ERROR);
}
} else {
// means all plugins have been executed "successfully"
pluginManager.setDone(true);
}
}
// single plugin
else {
if (currentModel.isDone()) {
pluginManager.setDone(true);
}
}
}
} else {
if (currentModel.isInterrupted()) {
pluginManager.setInterrupted(true);
}
if (currentModel.isSuspended()) {
pluginManager.setSuspended(true);
}
}
} else {
pluginManager.setExceptionOccured(true);
}
}
/**
* DOCUMENT ME!
*
* @param pluginsToExecute DOCUMENT ME!
*
* @throws MissingAttributeException DOCUMENT ME!
* @throws ClassNotFoundException DOCUMENT ME!
* @throws InvocationTargetException DOCUMENT ME!
* @throws IllegalAccessException DOCUMENT ME!
* @throws InstantiationException DOCUMENT ME!
*/
public final void executePlugins(LinkedList pluginsToExecute) throws MissingAttributeException, ClassNotFoundException, InvocationTargetException, IllegalAccessException, InstantiationException {
this.pluginsToExecute = pluginsToExecute;
executeSinglePlugin = false;
// set the first plugin to execute
currentModel = getNextPlugin();
// requires that first first plugin has been set
executePlugin(currentModel);
}
/**
* DOCUMENT ME!
*/
public final void interruptCurrentPlugin() {
if (currentPluginThread != null) {
currentPluginThread.setInterrupted(true);
}
pluginManager.setInterrupted(true);
}
/**
* Returns the next PluginListModel that wants to be executed. Removes returned PluginListModel from list of plugins to execute Registers
* observer and sets it as default in PluginManager 2!
*
* @return DOCUMENT ME!
*/
private Model getNextPlugin() {
if ((pluginsToExecute != null) && (pluginsToExecute.size() > 0)) {
Model plugin = (Model) pluginsToExecute.getFirst();
pluginsToExecute.removeFirst();
plugin.registerObserver(this);
pluginManager.setCurrentModel(plugin);
return plugin;
} else {
return null;
}
}
/**
* DOCUMENT ME!
*
* @param model DOCUMENT ME!
*
* @throws MissingAttributeException DOCUMENT ME!
* @throws ClassNotFoundException DOCUMENT ME!
* @throws InvocationTargetException DOCUMENT ME!
* @throws IllegalAccessException DOCUMENT ME!
* @throws InstantiationException DOCUMENT ME!
*/
protected void executeSinglePlugin(Model model) throws MissingAttributeException, ClassNotFoundException, InvocationTargetException, IllegalAccessException, InstantiationException {
executeSinglePlugin = true;
currentModel = model;
currentModel.registerObserver(this);
currentPluginThread = (DynamicPluginThread) dynamicallyLoadPlugin();
currentPluginThread.start();
}
/**
* DOCUMENT ME!
*
* @param model DOCUMENT ME!
*
* @throws MissingAttributeException DOCUMENT ME!
* @throws ClassNotFoundException DOCUMENT ME!
* @throws InvocationTargetException DOCUMENT ME!
* @throws IllegalAccessException DOCUMENT ME!
* @throws InstantiationException DOCUMENT ME!
*/
private void executePlugin(Model model) throws MissingAttributeException, ClassNotFoundException, InvocationTargetException, IllegalAccessException, InstantiationException {
currentModel = model;
currentPluginThread = (DynamicPluginThread) dynamicallyLoadPlugin();
currentPluginThread.start();
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*
* @throws MissingAttributeException DOCUMENT ME!
* @throws ClassNotFoundException DOCUMENT ME!
* @throws InvocationTargetException DOCUMENT ME!
* @throws IllegalAccessException DOCUMENT ME!
* @throws InstantiationException DOCUMENT ME!
*/
private Object dynamicallyLoadPlugin() throws MissingAttributeException, ClassNotFoundException, InvocationTargetException, IllegalAccessException, InstantiationException {
Class dynClass = Class.forName(currentModel.getThreadClassName());
Constructor[] constructors = dynClass.getConstructors();
Object[] params = new Object[2];
params[0] = controller;
params[1] = currentModel;
// works as long there is only one constructor
return constructors[0].newInstance(params);
}
}