PluginManager.java
001 /* This file is part of the project "Hilbert II" - http://www.qedeq.org
002  *
003  * Copyright 2000-2011,  Michael Meyling <mime@qedeq.org>.
004  *
005  * "Hilbert II" is free software; you can redistribute
006  * it and/or modify it under the terms of the GNU General Public
007  * License as published by the Free Software Foundation; either
008  * version 2 of the License, or (at your option) any later version.
009  *
010  * This program is distributed in the hope that it will be useful,
011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
013  * GNU General Public License for more details.
014  */
015 
016 package org.qedeq.kernel.bo.service;
017 
018 import java.util.ArrayList;
019 import java.util.HashMap;
020 import java.util.List;
021 import java.util.Map;
022 
023 import org.qedeq.base.trace.Trace;
024 import org.qedeq.kernel.bo.common.PluginExecutor;
025 import org.qedeq.kernel.bo.common.ServiceProcess;
026 import org.qedeq.kernel.bo.module.KernelQedeqBo;
027 import org.qedeq.kernel.bo.module.PluginBo;
028 
029 /**
030  * Manage all known plugins.
031  */
032 public class PluginManager {
033 
034     /** This class. */
035     private static final Class CLASS = PluginManager.class;
036 
037     /** Maps plugin ids to plugins. */
038     private final Map id2plugin = new HashMap();
039 
040     /** Stores all plugins. */
041     private final List plugins = new ArrayList();
042 
043     /** Collects process infos. */
044     private ServiceProcessManager processManager;
045 
046 
047     /**
048      * Constructor.
049      *
050      @param   processManager  Collects process information.
051      */
052     public PluginManager(final ServiceProcessManager processManager) {
053         this.processManager = processManager;
054     }
055 
056     /**
057      * Get all registered plugins.
058      *
059      @return  Registered plugins.
060      */
061     synchronized PluginBo[] getPlugins() {
062         return (PluginBo[]) plugins.toArray(new PluginBo[] {});
063     }
064 
065     /**
066      * Add a plugin..
067      *
068      @param   pluginClass Class that extends {@link PluginBo} to add.
069      *                      A plugin with same name can not be added twice.
070      *                      Must not be <code>null</code>.
071      @throws  RuntimeException    Plugin addition failed.
072      */
073     synchronized void addPlugin(final String pluginClass) {
074         final String method = "addPlugin";
075         PluginBo plugin = null;
076         try {
077             Class cl = Class.forName(pluginClass);
078             plugin = (PluginBocl.newInstance();
079         catch (ClassNotFoundException e) {
080             Trace.fatal(CLASS, this, method, "Plugin class not in class path: " + pluginClass, e);
081             throw new RuntimeException(e);
082         catch (InstantiationException e) {
083             Trace.fatal(CLASS, this, method, "Plugin class could not be istanciated: "
084                 + pluginClass, e);
085             throw new RuntimeException(e);
086         catch (IllegalAccessException e) {
087             Trace.fatal(CLASS, this, method,
088                 "Programming error, access for instantiation failed for plugin: " + pluginClass,
089                 e);
090             throw new RuntimeException(e);
091         catch (RuntimeException e) {
092             Trace.fatal(CLASS, this, method,
093                 "Programming error, instantiation failed for plugin: " + pluginClass, e);
094             throw new RuntimeException(e);
095         }
096         addPlugin(plugin);
097     }
098 
099     /**
100      * Add a plugin.
101      *
102      @param   plugin  Plugin to add. A plugin with same name can not be added twice.
103      *                  Must not be <code>null</code>.
104      @throws  RuntimeException    Plugin addition failed.
105      */
106     synchronized void addPlugin(final PluginBo plugin) {
107         if (id2plugin.get(plugin.getPluginId()) != null) {
108             final PluginBo oldPlugin = (PluginBoid2plugin.get(plugin.getPluginId());
109             final RuntimeException e = new IllegalArgumentException("plugin with that name already added: "
110                     + oldPlugin.getPluginId() ": " + plugin.getPluginDescription());
111             Trace.fatal(CLASS, this, "addPlugin""Programing error", e);
112             throw e;
113         }
114         id2plugin.put(plugin.getPluginId(), plugin);
115         plugins.add(plugin);
116     }
117 
118     /**
119      * Execute a plugin on an QEDEQ module.
120      *
121      @param   id          Plugin to use.
122      @param   qedeq       QEDEQ module to work on.
123      @param   parameters  Plugin specific parameters. Might be <code>null</code>.
124      @return  Plugin specific resulting object. Might be <code>null</code>.
125      @throws  RuntimeException    Plugin unknown, or execution had a major problem.
126      */
127     Object executePlugin(final String id, final KernelQedeqBo qedeq,
128             final Map parameters) {
129         final PluginBo plugin = (PluginBoid2plugin.get(id);
130         if (plugin == null) {
131             final String message = "Kernel does not know about plugin: ";
132             final RuntimeException e = new RuntimeException(message + id);
133             Trace.fatal(CLASS, this, "executePlugin", message + id,
134                 e);
135             throw e;
136         }
137         Map para = parameters;
138         if (parameters == null) {
139             para = new HashMap();
140         }
141         final ServiceProcess process = processManager.createProcess(plugin,
142             qedeq, para);
143         process.setBlocked(true);
144         synchronized (qedeq) {
145             process.setBlocked(false);
146             try {
147                 final PluginExecutor exe = plugin.createExecutor(qedeq, para);
148                 process.setExecutor(exe);
149                 final Object result = exe.executePlugin();
150                 process.setSuccessState();
151                 return result;
152             finally {
153                 if (process.isRunning()) {
154                     process.setFailureState();
155                 }
156                 // remove old executor
157                 process.setExecutor(null);
158             }
159         }
160     }
161 
162     /**
163      * Clear all plugin errors and warnings on an QEDEQ module.
164      *
165      @param   qedeq   Clear reults for this module.
166      */
167     public void clearAllPluginResults(final KernelQedeqBo qedeq) {
168         qedeq.clearAllPluginErrorsAndWarnings();
169     }
170 
171 }