package de.gaalop.gui.util; import de.gaalop.ConfigurationProperty; import de.gaalop.Plugin; import de.gaalop.Plugins; import de.gaalop.gui.PanelPluginSelection; import org.apache.commons.beanutils.BeanUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.util.Observable; import java.util.Observer; import java.util.Properties; import java.util.Set; import java.util.HashSet; import java.util.Arrays; /** * This utility class helps with the configuration of plugins. */ public class PluginConfigurator { private final Properties configuration; private Log log = LogFactory.getLog(PluginConfigurator.class); /** * Constructs a new Plugin configurator. * * @param configuration Configuration options will be read from this properties object. * A copy of this object will be stored. */ public PluginConfigurator(Properties configuration) { this.configuration = configuration; } /** * Constructs a Plugin configurator with no configuration options. */ public PluginConfigurator() { configuration = new Properties(); } public void configure(Plugin plugin) { log.debug("Configuring " + plugin.getClass()); Field[] fields = plugin.getClass().getFields(); for (Field field : fields) { if (field.isAnnotationPresent(ConfigurationProperty.class)) { configure(plugin, field); } } } private void configure(Plugin plugin, Field field) { String propertyKey = getPropertyKey(field); String propertyValue = configuration.getProperty(propertyKey); log.debug("Configuration for " + propertyKey + " = " + propertyValue); if (propertyValue != null) { try { BeanUtils.setProperty(plugin, field.getName(), propertyValue); } catch (IllegalAccessException e) { log.error("Unable to configure property " + propertyKey, e); } catch (InvocationTargetException e) { log.error("Unable to configure property " + propertyKey, e); } } } private String getPropertyKey(Field field) { Class<?> declaringClass = field.getDeclaringClass(); String fieldName = field.getName(); return declaringClass.getName() + "." + fieldName; } /** * Configures all registered Plugins using the currently set configuration options. */ public void configureAll(Observer o) { Set<? extends Plugin> plugins; plugins = Plugins.getGlobalSettingsStrategyPlugins(); for (Plugin plugin : plugins) { configure(plugin); register(plugin, o); } plugins = Plugins.getOptimizationStrategyPlugins(); for (Plugin plugin : plugins) { configure(plugin); register(plugin, o); } plugins = Plugins.getAlgebraStrategyPlugins(); for (Plugin plugin : plugins) { configure(plugin); register(plugin, o); } plugins = Plugins.getCodeParserPlugins(); for (Plugin plugin : plugins) { configure(plugin); register(plugin, o); } plugins = Plugins.getCodeGeneratorPlugins(); for (Plugin plugin : plugins) { configure(plugin); register(plugin, o); } PanelPluginSelection.lastUsedAlgebra = (String) configuration.get("lastUsedAlgebra"); PanelPluginSelection.lastUsedAlgebraRessource = Boolean.parseBoolean((String) configuration.get("lastUsedAlgebraRessource")); PanelPluginSelection.lastUsedGenerator = (String) configuration.get("lastUsedGenerator"); PanelPluginSelection.lastUsedVisualCodeInserter = (String) configuration.get("lastUsedVisualCodeInserter"); PanelPluginSelection.lastUsedOptimization = (String) configuration.get("lastUsedOptimization"); } private void register(Plugin plugin, Observer o) { if (plugin.getClass().getSuperclass() == Observable.class) { log.debug("Registering " + o + " as observer of " + plugin.getName() + " plugin"); ((Observable) plugin).addObserver(o); } } /** * Iterates over all plugins and reads their current configuration state into the property map. * The property map can be retrieved using <code>getConfiguration</code>. */ public void readConfiguration() { Set<? extends Plugin> plugins; plugins = Plugins.getGlobalSettingsStrategyPlugins(); for (Plugin plugin : plugins) { readConfiguration(plugin); } plugins = Plugins.getOptimizationStrategyPlugins(); for (Plugin plugin : plugins) { readConfiguration(plugin); } plugins = Plugins.getAlgebraStrategyPlugins(); for (Plugin plugin : plugins) { readConfiguration(plugin); } plugins = Plugins.getCodeParserPlugins(); for (Plugin plugin : plugins) { readConfiguration(plugin); } plugins = Plugins.getCodeGeneratorPlugins(); for (Plugin plugin : plugins) { readConfiguration(plugin); } configuration.put("lastUsedAlgebra", PanelPluginSelection.lastUsedAlgebra); configuration.put("lastUsedAlgebraRessource", Boolean.toString(PanelPluginSelection.lastUsedAlgebraRessource)); configuration.put("lastUsedGenerator", PanelPluginSelection.lastUsedGenerator); configuration.put("lastUsedVisualCodeInserter", PanelPluginSelection.lastUsedVisualCodeInserter); configuration.put("lastUsedOptimization", PanelPluginSelection.lastUsedOptimization); } private void readConfiguration(Plugin plugin) { log.debug("Reading configuration of " + plugin.getClass()); Set<Field> fields = getAllFields(plugin.getClass()); for (Field field : fields) { if (field.isAnnotationPresent(ConfigurationProperty.class)) { readConfiguration(plugin, field); } } } private Set<Field> getAllFields(Class<?> clazz) { // Get the fields of clazz (without inherited fields) Set<Field> fields = new HashSet<Field>(Arrays.asList(clazz.getDeclaredFields())); // If clazz inherits from some class, get their fields as well and merge them with ours Class<?> superclass = clazz.getSuperclass(); if (superclass != null && !superclass.equals(Object.class)) { Set<Field> superFields = getAllFields(superclass); fields.addAll(superFields); } return fields; } private void readConfiguration(Plugin plugin, Field field) { String propertyKey = getPropertyKey(field); try { String configValue = BeanUtils.getProperty(plugin, field.getName()); log.debug("Read value for " + propertyKey + " = " + configValue); configuration.put(propertyKey, configValue); } catch (IllegalAccessException e) { log.error("Unable to read property " + propertyKey, e); } catch (InvocationTargetException e) { log.error("Unable to read property " + propertyKey, e); } catch (NoSuchMethodException e) { log.error("No getter is available for " + propertyKey, e); } } public Properties getConfiguration() { return configuration; } }