PluginManager.java
001 /* This file is part of the project "Hilbert II" - http://www.qedeq.org
002  *
003  * Copyright 2000-2013,  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.io.Parameters;
024 import org.qedeq.base.trace.Trace;
025 import org.qedeq.kernel.bo.KernelContext;
026 import org.qedeq.kernel.bo.common.KernelServices;
027 import org.qedeq.kernel.bo.common.PluginExecutor;
028 import org.qedeq.kernel.bo.common.ServiceProcess;
029 import org.qedeq.kernel.bo.module.KernelQedeqBo;
030 import org.qedeq.kernel.bo.module.PluginBo;
031 
032 /**
033  * Manage all known plugins.
034  */
035 public class PluginManager {
036 
037     /** This class. */
038     private static final Class CLASS = PluginManager.class;
039 
040     /** Maps plugin ids to plugins. */
041     private final Map id2plugin = new HashMap();
042 
043     /** Stores all plugins. */
044     private final List plugins = new ArrayList();
045 
046     /** Collects process infos. */
047     private final ServiceProcessManager processManager;
048 
049     /** Basic kernel properties.  */
050     private final KernelServices kernel;
051 
052     /**
053      * Constructor.
054      *
055      @param   kernel          Kernel access.
056      @param   processManager  Collects process information.
057      */
058     public PluginManager(final KernelServices kernel, final ServiceProcessManager processManager) {
059         this.kernel = kernel;
060         this.processManager = processManager;
061     }
062 
063     /**
064      * Get all registered plugins.
065      *
066      @return  Registered plugins.
067      */
068     synchronized PluginBo[] getPlugins() {
069         return (PluginBo[]) plugins.toArray(new PluginBo[] {});
070     }
071 
072     /**
073      * Add a plugin..
074      *
075      @param   pluginClass Class that extends {@link PluginBo} to add.
076      *                      A plugin with same name can not be added twice.
077      *                      Must not be <code>null</code>.
078      @throws  RuntimeException    Plugin addition failed.
079      */
080     synchronized void addPlugin(final String pluginClass) {
081         final String method = "addPlugin";
082         PluginBo plugin = null;
083         try {
084             Class cl = Class.forName(pluginClass);
085             plugin = (PluginBocl.newInstance();
086         catch (ClassNotFoundException e) {
087             Trace.fatal(CLASS, this, method, "Plugin class not in class path: " + pluginClass, e);
088             throw new RuntimeException(e);
089         catch (InstantiationException e) {
090             Trace.fatal(CLASS, this, method, "Plugin class could not be istanciated: "
091                 + pluginClass, e);
092             throw new RuntimeException(e);
093         catch (IllegalAccessException e) {
094             Trace.fatal(CLASS, this, method,
095                 "Programming error, access for instantiation failed for plugin: " + pluginClass,
096                 e);
097             throw new RuntimeException(e);
098         catch (RuntimeException e) {
099             Trace.fatal(CLASS, this, method,
100                 "Programming error, instantiation failed for plugin: " + pluginClass, e);
101             throw new RuntimeException(e);
102         }
103         addPlugin(plugin);
104         // set default plugin values for not yet set parameters
105         final Parameters parameters = kernel.getConfig().getPluginEntries(plugin);
106         plugin.setDefaultValuesForEmptyPluginParameters(parameters);
107         kernel.getConfig().setPluginKeyValues(plugin, parameters);
108     }
109 
110     /**
111      * Add a plugin.
112      *
113      @param   plugin  Plugin to add. A plugin with same name can not be added twice.
114      *                  Must not be <code>null</code>.
115      @throws  RuntimeException    Plugin addition failed.
116      */
117     synchronized void addPlugin(final PluginBo plugin) {
118         if (id2plugin.get(plugin.getPluginId()) != null) {
119             final PluginBo oldPlugin = (PluginBoid2plugin.get(plugin.getPluginId());
120             final RuntimeException e = new IllegalArgumentException("plugin with that name already added: "
121                     + oldPlugin.getPluginId() ": " + plugin.getPluginDescription());
122             Trace.fatal(CLASS, this, "addPlugin""Programing error", e);
123             throw e;
124         }
125         id2plugin.put(plugin.getPluginId(), plugin);
126         plugins.add(plugin);
127     }
128 
129     /**
130      * Execute a plugin on an QEDEQ module.
131      *
132      @param   id          Plugin to use.
133      @param   qedeq       QEDEQ module to work on.
134      @return  Plugin specific resulting object. Might be <code>null</code>.
135      @throws  RuntimeException    Plugin unknown, or execution had a major problem.
136      */
137     Object executePlugin(final String id, final KernelQedeqBo qedeq) {
138         final PluginBo plugin = (PluginBoid2plugin.get(id);
139         if (plugin == null) {
140             final String message = "Kernel does not know about plugin: ";
141             final RuntimeException e = new RuntimeException(message + id);
142             Trace.fatal(CLASS, this, "executePlugin", message + id,
143                 e);
144             throw e;
145         }
146         final Parameters parameters = KernelContext.getInstance().getConfig().getPluginEntries(plugin);
147         final ServiceProcess process = processManager.createProcess(plugin,
148             qedeq, parameters);
149         process.setBlocked(true);
150         synchronized (qedeq) {
151             process.setBlocked(false);
152             try {
153                 final PluginExecutor exe = plugin.createExecutor(qedeq, parameters);
154                 process.setExecutor(exe);
155                 final Object result = exe.executePlugin();
156                 process.setSuccessState();
157                 return result;
158             finally {
159                 if (process.isRunning()) {
160                     process.setFailureState();
161                 }
162                 // remove old executor
163                 process.setExecutor(null);
164             }
165         }
166     }
167 
168     /**
169      * Clear all plugin errors and warnings on an QEDEQ module.
170      *
171      @param   qedeq   Clear reults for this module.
172      */
173     public void clearAllPluginResults(final KernelQedeqBo qedeq) {
174         qedeq.clearAllPluginErrorsAndWarnings();
175     }
176 
177 }