From 9544f0cd4a92ed93e711dcd9da536102d85ab270 Mon Sep 17 00:00:00 2001 From: Nils Christian Ehmke <nie@informatik.uni-kiel.de> Date: Wed, 1 May 2013 10:54:06 +0200 Subject: [PATCH] Started with refactoring using Mirror. --- .../.settings/org.eclipse.jdt.ui.prefs | 2 +- .../config/quality-config/cs-conf.xml | 2 +- .../persistence/impl/FSProjectDAOImpl.java | 26 +- .../util/Class2ModelInstanceConverter.java | 509 +++++------------- .../persistence/impl/util/PluginFinder.java | 30 +- .../webgui/service/impl/util/Analysis.java | 6 +- .../impl/util/PluginFinderTest.java | 9 +- 7 files changed, 196 insertions(+), 388 deletions(-) diff --git a/Kieker.WebGUI/.settings/org.eclipse.jdt.ui.prefs b/Kieker.WebGUI/.settings/org.eclipse.jdt.ui.prefs index 85c1f324..e8289876 100644 --- a/Kieker.WebGUI/.settings/org.eclipse.jdt.ui.prefs +++ b/Kieker.WebGUI/.settings/org.eclipse.jdt.ui.prefs @@ -58,7 +58,7 @@ formatter_settings_version=12 org.eclipse.jdt.ui.exception.name=ex org.eclipse.jdt.ui.gettersetter.use.is=true org.eclipse.jdt.ui.ignorelowercasenames=true -org.eclipse.jdt.ui.importorder=java;javax;junit;org;com;kieker;org.primefaces;org.eclipse;de.cau.cs.kieler; +org.eclipse.jdt.ui.importorder=java;javax;junit;org;com;kieker;org.primefaces;org.eclipse;de.cau.cs.kieler;net.vidageek;org.springframework; org.eclipse.jdt.ui.keywordthis=false org.eclipse.jdt.ui.ondemandthreshold=99 org.eclipse.jdt.ui.overrideannotation=true diff --git a/Kieker.WebGUI/config/quality-config/cs-conf.xml b/Kieker.WebGUI/config/quality-config/cs-conf.xml index 3abf3c32..b7d26517 100644 --- a/Kieker.WebGUI/config/quality-config/cs-conf.xml +++ b/Kieker.WebGUI/config/quality-config/cs-conf.xml @@ -668,7 +668,7 @@ <!-- See http://checkstyle.sf.net/config_import.html !--> <module name="ImportOrder"> <property name="option" value="under"/> - <property name="groups" value="java,javax,junit,org,com,kieker,kieker,org.primefaces,org.eclipse"/> + <property name="groups" value="java,javax,junit,org,com,kieker,kieker,org.primefaces,org.eclipse,de.cau.cs.kieler,net.vidageek,org.springframework"/> <property name="ordered" value="true"/> <property name="separated" value="true"/> <property name="caseSensitive" value="true"/> diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/persistence/impl/FSProjectDAOImpl.java b/Kieker.WebGUI/src/main/java/kieker/webgui/persistence/impl/FSProjectDAOImpl.java index f03958ae..0bfe99b5 100644 --- a/Kieker.WebGUI/src/main/java/kieker/webgui/persistence/impl/FSProjectDAOImpl.java +++ b/Kieker.WebGUI/src/main/java/kieker/webgui/persistence/impl/FSProjectDAOImpl.java @@ -53,7 +53,8 @@ import com.google.common.io.Files; import kieker.analysis.AnalysisController; import kieker.analysis.model.analysisMetaModel.MIAnalysisMetaModelFactory; import kieker.analysis.model.analysisMetaModel.MIProject; -import kieker.analysis.plugin.AbstractPlugin; +import kieker.analysis.plugin.filter.AbstractFilterPlugin; +import kieker.analysis.plugin.reader.AbstractReaderPlugin; import kieker.analysis.repository.AbstractRepository; import kieker.common.logging.Log; import kieker.common.logging.LogFactory; @@ -165,24 +166,27 @@ public class FSProjectDAOImpl implements IProjectDAO, ReleaseListener { throws IOException { // FInd the available classes within the library final List<Class<AbstractRepository>> repositoryClasses = this.pluginFinder.getAllRepositoriesWithinJar(lib, classLoader, classAndMethodContainer); - final List<Class<AbstractPlugin>> pluginClasses = this.pluginFinder.getAllPluginsWithinJar(lib, classLoader, classAndMethodContainer); + final List<Class<AbstractFilterPlugin>> filterClasses = this.pluginFinder.getAllFiltersWithinJar(lib, classLoader, classAndMethodContainer); + final List<Class<AbstractReaderPlugin>> readerClasses = this.pluginFinder.getAllReadersWithinJar(lib, classLoader, classAndMethodContainer); // Convert the repositories into model instances for (final Class<AbstractRepository> repository : repositoryClasses) { if (!(Modifier.isAbstract(repository.getModifiers()) || this.class2ModelInstanceConverter.isProgrammaticOnly(repository, classAndMethodContainer))) { - repositories.add(this.class2ModelInstanceConverter.convertRepository2ModelInstance(repository, classAndMethodContainer)); + repositories.add(this.class2ModelInstanceConverter.convertRepositoryClass2ModelInstance(repository, classAndMethodContainer)); } } // Convert the plugins into model instances - for (final Class<AbstractPlugin> plugin : pluginClasses) { - if (!(Modifier.isAbstract(plugin.getModifiers()) || this.class2ModelInstanceConverter.isProgrammaticOnly(plugin, classAndMethodContainer))) { - final PluginContainer pluginContainer = this.class2ModelInstanceConverter.convertPlugin2ModelInstance(plugin, classAndMethodContainer); - if (pluginContainer.isReader()) { - readers.add(pluginContainer); - } else { - filters.add(pluginContainer); - } + for (final Class<AbstractReaderPlugin> reader : readerClasses) { + if (!(Modifier.isAbstract(reader.getModifiers()) || this.class2ModelInstanceConverter.isProgrammaticOnly(reader, classAndMethodContainer))) { + final PluginContainer pluginContainer = this.class2ModelInstanceConverter.convertReaderClass2ModelInstance(reader, classAndMethodContainer); + readers.add(pluginContainer); + } + } + for (final Class<AbstractFilterPlugin> filter : filterClasses) { + if (!(Modifier.isAbstract(filter.getModifiers()) || this.class2ModelInstanceConverter.isProgrammaticOnly(filter, classAndMethodContainer))) { + final PluginContainer pluginContainer = this.class2ModelInstanceConverter.convertFilterClass2ModelInstance(filter, classAndMethodContainer); + readers.add(pluginContainer); } } } diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/persistence/impl/util/Class2ModelInstanceConverter.java b/Kieker.WebGUI/src/main/java/kieker/webgui/persistence/impl/util/Class2ModelInstanceConverter.java index 50e4e0d0..e0d1b9b8 100644 --- a/Kieker.WebGUI/src/main/java/kieker/webgui/persistence/impl/util/Class2ModelInstanceConverter.java +++ b/Kieker.WebGUI/src/main/java/kieker/webgui/persistence/impl/util/Class2ModelInstanceConverter.java @@ -16,17 +16,14 @@ package kieker.webgui.persistence.impl.util; import java.lang.annotation.Annotation; -import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; -import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; -import java.util.List; import java.util.Map; -import org.springframework.stereotype.Service; - +import kieker.analysis.analysisComponent.AbstractAnalysisComponent; import kieker.analysis.model.analysisMetaModel.MIAnalysisComponent; import kieker.analysis.model.analysisMetaModel.MIAnalysisMetaModelFactory; import kieker.analysis.model.analysisMetaModel.MIDisplay; @@ -36,17 +33,21 @@ import kieker.analysis.model.analysisMetaModel.MIOutputPort; import kieker.analysis.model.analysisMetaModel.MIPlugin; import kieker.analysis.model.analysisMetaModel.MIProperty; import kieker.analysis.model.analysisMetaModel.MIRepository; -import kieker.analysis.model.analysisMetaModel.MIRepositoryConnector; import kieker.analysis.plugin.AbstractPlugin; -import kieker.analysis.plugin.annotation.Property; +import kieker.analysis.plugin.filter.AbstractFilterPlugin; +import kieker.analysis.plugin.reader.AbstractReaderPlugin; import kieker.analysis.repository.AbstractRepository; import kieker.common.logging.Log; import kieker.common.logging.LogFactory; import kieker.webgui.common.ClassAndMethodContainer; -import kieker.webgui.common.exception.ComponentInitializationException; +import kieker.webgui.domain.IComponentContainer; import kieker.webgui.domain.PluginContainer; import kieker.webgui.domain.RepositoryContainer; +import net.vidageek.mirror.dsl.Mirror; + +import org.springframework.stereotype.Service; + /** * This service provides methods to convert a given {@link Class} instance (the one from a reflection loaded repository or plugin) to a meta model instance. This is * done by using the annotations and methods which will be accessed via the reflection API. @@ -67,405 +68,187 @@ public class Class2ModelInstanceConverter { // No code necessary } - /** - * This method converts the given class instance into a model instance. - * - * @param clazz - * The class to be converted. - * @param classAndMethodContainer - * The container which will be used for the converting. - * - * @return An object containing the model instance. - */ - public PluginContainer convertPlugin2ModelInstance(final Class<AbstractPlugin> clazz, final ClassAndMethodContainer classAndMethodContainer) { - final Map<String, String> propertyDescriptions = new HashMap<String, String>(); - final Map<String, String> displayDescriptions = new HashMap<String, String>(); - boolean fullyInitialized; - String description = ""; - String dependency = ""; - - // Create a new instance for the model - final MIPlugin plugin; - if (classAndMethodContainer.getAbstractReaderPluginClass().isAssignableFrom(clazz)) { - plugin = Class2ModelInstanceConverter.FACTORY.createReader(); - } else { - plugin = Class2ModelInstanceConverter.FACTORY.createFilter(); - } - plugin.setClassname(clazz.getName()); - plugin.setName(clazz.getSimpleName()); - - // Those are the attributes which can go wrong because of the lazy class loading - try { - description = Class2ModelInstanceConverter.getDescription(clazz, classAndMethodContainer); - dependency = Class2ModelInstanceConverter.getDependencies(clazz, classAndMethodContainer); - - Class2ModelInstanceConverter.fillProperties(clazz, plugin, classAndMethodContainer, propertyDescriptions); - Class2ModelInstanceConverter.fillPorts(clazz, plugin, classAndMethodContainer); - Class2ModelInstanceConverter.fillDisplays(clazz, plugin, classAndMethodContainer, displayDescriptions); - - fullyInitialized = true; - } catch (final ComponentInitializationException ex) { - // This exception can occur if (for example) a class is missing. We clear the component as far as possible - except for the description and the - // dependencies. This is important - plugin.getProperties().clear(); - plugin.getOutputPorts().clear(); - propertyDescriptions.clear(); - displayDescriptions.clear(); - if (plugin instanceof MIFilter) { - ((MIFilter) plugin).getInputPorts().clear(); - } - - fullyInitialized = false; - - Class2ModelInstanceConverter.LOG.info("A component with the classname '" + clazz.getCanonicalName() + "' could not be initialized.", ex); - } - - // Assemble the resulting instance with everything we could extract and return it - return new PluginContainer(plugin, description, dependency, fullyInitialized, Collections.unmodifiableMap(propertyDescriptions), - Collections.unmodifiableMap(displayDescriptions)); + public PluginContainer convertReaderClass2ModelInstance(final Class<AbstractReaderPlugin> clazz, final ClassAndMethodContainer classAndMethodContainer) { + return (PluginContainer) this.convertComponentClass2ModelInstance(clazz, classAndMethodContainer, Type.Reader); } - /** - * Tells whether the given class is "programmaticOnly". If there is no annotation which could tell the state of the flag, true will be returned. - * - * @param clazz - * The class of the plugin or repository. - * @param classAndMethodContainer - * The container which will be used for the reflection access. - * - * @return The state of the programmaticOnly flag of the plugin or repository. - */ - public boolean isProgrammaticOnly(final Class<?> clazz, final ClassAndMethodContainer classAndMethodContainer) { - boolean result; - try { - // Get the two potential annotations - final Annotation annotationPlugin = clazz.getAnnotation(classAndMethodContainer.getPluginAnnotationClass()); - final Annotation annotationRepository = clazz.getAnnotation(classAndMethodContainer.getRepositoryAnnotationClass()); - - final Method pluginProgOnlyMethod = classAndMethodContainer.getPluginProgrammaticOnlyMethod(); - final Method repoProgOnlyMethod = classAndMethodContainer.getRepositoryProgrammaticOnlyMethod(); - - // Now check which one of them is available - if (annotationPlugin == null) { - if (annotationRepository == null) { - // None. Say it is programmatic only. - result = true; - } else { - result = (Boolean) repoProgOnlyMethod.invoke(annotationRepository); - } - } else { - result = (Boolean) pluginProgOnlyMethod.invoke(annotationPlugin); - } - - } catch (final IllegalAccessException ex) { - result = true; - } catch (final IllegalArgumentException ex) { - result = true; - } catch (final InvocationTargetException ex) { - result = true; - } catch (final NoClassDefFoundError ex) { - result = true; - } - - return result; + public PluginContainer convertFilterClass2ModelInstance(final Class<AbstractFilterPlugin> clazz, final ClassAndMethodContainer classAndMethodContainer) { + return (PluginContainer) this.convertComponentClass2ModelInstance(clazz, classAndMethodContainer, Type.Filter); } - /** - * This method converts the given class instance into a model instance. - * - * @param clazz - * The class to be converted. - * @param classAndMethodContainer - * The container which will be used for the converting. - * - * @return An object containing the model instance. - */ - public RepositoryContainer convertRepository2ModelInstance(final Class<AbstractRepository> clazz, final ClassAndMethodContainer classAndMethodContainer) { - final Map<String, String> propertyDescriptions = new HashMap<String, String>(); - boolean fullyInitialized; - String description = ""; - String dependency = ""; - - // Create a new instance for the model - final MIRepository repository = Class2ModelInstanceConverter.FACTORY.createRepository(); - - repository.setClassname(clazz.getName()); - repository.setName(clazz.getSimpleName()); - - // Those are the attributes which can go wrong because of the lazy class loading - try { - description = Class2ModelInstanceConverter.getDescription(clazz, classAndMethodContainer); - dependency = Class2ModelInstanceConverter.getDependencies(clazz, classAndMethodContainer); - Class2ModelInstanceConverter.fillProperties(clazz, repository, classAndMethodContainer, propertyDescriptions); - - fullyInitialized = true; - } catch (final ComponentInitializationException ex) { - // This exception can occur if (for example) a class is missing. We clear the component as far as possible - except for the description and the - // dependencies. This is important - repository.getProperties().clear(); + public RepositoryContainer convertRepositoryClass2ModelInstance(final Class<AbstractRepository> clazz, final ClassAndMethodContainer classAndMethodContainer) { + return (RepositoryContainer) this.convertComponentClass2ModelInstance(clazz, classAndMethodContainer, Type.Repository); + } - fullyInitialized = false; + @SuppressWarnings("unchecked") + private IComponentContainer convertComponentClass2ModelInstance(final Class<? extends AbstractAnalysisComponent> clazz, + final ClassAndMethodContainer classAndMethodContainer, final Type type) { + final MIAnalysisComponent plugin = this.createSuitableModelInstance(clazz, classAndMethodContainer); - Class2ModelInstanceConverter.LOG.warn("A component with the classname '" + clazz.getCanonicalName() + "' could not be initialized.", ex); + final Collection<MIProperty> properties = new ArrayList<MIProperty>(); + final Collection<MIInputPort> inputPorts = new ArrayList<MIInputPort>(); + final Collection<MIOutputPort> outputPorts = new ArrayList<MIOutputPort>(); + final Collection<MIDisplay> displays = new ArrayList<MIDisplay>(); + final Map<String, String> propertyDescriptions = new HashMap<String, String>(); + final Map<String, String> displayDescriptions = new HashMap<String, String>(); + String description; + String dependency; + + this.fillProperties(clazz, classAndMethodContainer, properties, propertyDescriptions); + if ((type == Type.Filter) || (type == Type.Reader)) { + this.fillOutputPorts((Class<AbstractPlugin>) clazz, classAndMethodContainer, outputPorts, (MIPlugin) plugin); + this.fillDisplays((Class<AbstractPlugin>) clazz, classAndMethodContainer, displays, displayDescriptions); + if (type == Type.Filter) { + this.fillInputPorts((Class<AbstractFilterPlugin>) clazz, classAndMethodContainer, inputPorts, (MIFilter) plugin); + } } - - // Assemble the resulting instance with everything we could extract and return it - return new RepositoryContainer(repository, description, dependency, fullyInitialized, Collections.unmodifiableMap(propertyDescriptions)); - } - - private static String getDescription(final Class<?> clazz, final ClassAndMethodContainer classAndMethodContainer) throws ComponentInitializationException { - try { - final String description; - // Get the two potential annotations - final Annotation annotationPlugin = clazz.getAnnotation(classAndMethodContainer.getPluginAnnotationClass()); - final Annotation annotationRepository = clazz.getAnnotation(classAndMethodContainer.getRepositoryAnnotationClass()); - - final Method pluginDescrMethod = classAndMethodContainer.getPluginDescriptionMethod(); - final Method repoDescrMethod = classAndMethodContainer.getRepositoryDescriptionMethod(); - - // Now check which one of them is available - if ((annotationPlugin == null) || ((String) pluginDescrMethod.invoke(annotationPlugin)).isEmpty()) { - if ((annotationRepository == null) || ((String) repoDescrMethod.invoke(annotationRepository)).isEmpty()) { - // None. Deliver a human readable substitute. - description = "No description available"; - } else { - description = (String) repoDescrMethod.invoke(annotationRepository); - } - } else { - description = (String) pluginDescrMethod.invoke(annotationPlugin); + description = this.fillDescription(clazz, classAndMethodContainer); + dependency = this.fillDependency(clazz, classAndMethodContainer); + + plugin.getProperties().addAll(properties); + if ((type == Type.Filter) || (type == Type.Reader)) { + ((MIPlugin) plugin).getOutputPorts().addAll(outputPorts); + ((MIPlugin) plugin).getDisplays().addAll(displays); + if (type == Type.Filter) { + ((MIFilter) plugin).getDisplays().addAll(displays); } + } + plugin.setClassname(clazz.getName()); + plugin.setName(clazz.getSimpleName()); - return description; - } catch (final IllegalAccessException ex) { - throw new ComponentInitializationException("Could not load the description of the class.", ex); - } catch (final IllegalArgumentException ex) { - throw new ComponentInitializationException("Could not load the description of the class.", ex); - } catch (final InvocationTargetException ex) { - throw new ComponentInitializationException("Could not load the description of the class.", ex); - } catch (final NoClassDefFoundError ex) { - throw new ComponentInitializationException("Could not load the description of the class.", ex); + if (type == Type.Repository) { + return new RepositoryContainer((MIRepository) plugin, description, dependency, true, Collections.unmodifiableMap(propertyDescriptions)); + } else { + return new PluginContainer((MIPlugin) plugin, description, dependency, true, Collections.unmodifiableMap(propertyDescriptions), + Collections.unmodifiableMap(displayDescriptions)); } } - private static String getDependencies(final Class<?> clazz, final ClassAndMethodContainer classAndMethodContainer) throws ComponentInitializationException { - try { - final String description; - - // Get the two potential annotations - final Annotation annotationPlugin = clazz.getAnnotation(classAndMethodContainer.getPluginAnnotationClass()); - final Annotation annotationRepository = clazz.getAnnotation(classAndMethodContainer.getRepositoryAnnotationClass()); - - final Method pluginDepMethod = classAndMethodContainer.getPluginDependenciesMethod(); - final Method repoDepMethod = classAndMethodContainer.getRepositoryDependenciesMethod(); - - // Now check which one of them is available - if (annotationPlugin == null) { - if (annotationRepository == null) { - // None. Deliver a human readable substitute. - description = "No dependency information available"; - } else { - description = (String) repoDepMethod.invoke(annotationRepository); - } - } else { - description = (String) pluginDepMethod.invoke(annotationPlugin); - } - - return description; - } catch (final IllegalAccessException ex) { - throw new ComponentInitializationException("Could not load the dependencies of the class.", ex); - } catch (final IllegalArgumentException ex) { - throw new ComponentInitializationException("Could not load the dependencies of the class.", ex); - } catch (final InvocationTargetException ex) { - throw new ComponentInitializationException("Could not load the dependencies of the class.", ex); - } catch (final NoClassDefFoundError ex) { - throw new ComponentInitializationException("Could not load the dependencies of the class.", ex); + private void fillInputPorts(final Class<AbstractFilterPlugin> clazz, final ClassAndMethodContainer classAndMethodContainer, + final Collection<MIInputPort> inputPorts, + final MIFilter parent) { + final Collection<Method> methods = this.getInputPortMethods(clazz, classAndMethodContainer); + for (final Method method : methods) { + final Annotation inputPortAnnotation = method.getAnnotation(classAndMethodContainer.getInputPortAnnotationClass()); + final MIInputPort newPort = Class2ModelInstanceConverter.FACTORY.createInputPort(); + newPort.setName((String) new Mirror().on(inputPortAnnotation).invoke().method("name").withoutArgs()); + newPort.setParent(parent); + inputPorts.add(newPort); } } - private static void fillProperties(final Class<?> clazz, final MIAnalysisComponent component, final ClassAndMethodContainer classAndMethodContainer, - final Map<String, String> propertyDescriptions) throws ComponentInitializationException { - try { - // Get the default configuration and use it to initialize the model repository - final List<Annotation> properties = Class2ModelInstanceConverter.getProperties(clazz, classAndMethodContainer); - - for (final Annotation property : properties) { - final MIProperty mProperty = Class2ModelInstanceConverter.FACTORY.createProperty(); - - mProperty.setName((String) classAndMethodContainer.getPropertyNameMethod().invoke(property)); - mProperty.setValue((String) classAndMethodContainer.getPropertyDefaultValueMethod().invoke(property)); - - if (component instanceof MIPlugin) { - ((MIPlugin) component).getProperties().add(mProperty); - } else { - ((MIRepository) component).getProperties().add(mProperty); - } - - // Get the description as well - final String description = (String) classAndMethodContainer.getPropertyDescriptionMethod().invoke(property); - propertyDescriptions.put(mProperty.getName(), description); - } - } catch (final IllegalAccessException ex) { - throw new ComponentInitializationException("Could not load the properties of the class.", ex); - } catch (final IllegalArgumentException ex) { - throw new ComponentInitializationException("Could not load the properties of the class.", ex); - } catch (final InvocationTargetException ex) { - throw new ComponentInitializationException("Could not load the properties of the class.", ex); - } catch (final NoClassDefFoundError ex) { - throw new ComponentInitializationException("Could not load the properties of the class.", ex); + private void fillDisplays(final Class<? extends AbstractPlugin> clazz, final ClassAndMethodContainer classAndMethodContainer, + final Collection<MIDisplay> displays, + final Map<String, String> displayDescriptions) { + final Collection<Method> methods = this.getDisplayMethods(clazz, classAndMethodContainer); + for (final Method method : methods) { + final Annotation displayAnnotation = method.getAnnotation(classAndMethodContainer.getDisplayAnnotationClass()); + final MIDisplay newDisplay = Class2ModelInstanceConverter.FACTORY.createDisplay(); + newDisplay.setName((String) new Mirror().on(displayAnnotation).invoke().method("name").withoutArgs()); + displays.add(newDisplay); + displayDescriptions.put(newDisplay.getName(), (String) new Mirror().on(displayAnnotation).invoke().method("description").withoutArgs()); } } - private static List<Annotation> getProperties(final Class<?> clazz, final ClassAndMethodContainer classAndMethodContainer) throws IllegalArgumentException, - IllegalAccessException, InvocationTargetException { - // Get the two potential annotations - final Annotation annotationPlugin = clazz.getAnnotation(classAndMethodContainer.getPluginAnnotationClass()); - final Annotation annotationRepository = clazz.getAnnotation(classAndMethodContainer.getRepositoryAnnotationClass()); + private Collection<Method> getAnnotatedMethods(final Class<? extends AbstractPlugin> clazz, final Class<? extends Annotation> annotation) { + final Collection<Method> result = new ArrayList<Method>(); - final Annotation[] properties; - - // Now check which one of them is available - if (annotationPlugin == null) { - if (annotationRepository == null) { - // None. - properties = new Property[0]; - } else { - properties = (Annotation[]) classAndMethodContainer.getRepositoryConfigurationMethod().invoke(annotationRepository); + final Method[] methods = clazz.getMethods(); + for (final Method method : methods) { + if (method.isAnnotationPresent(annotation)) { + result.add(method); } - } else { - properties = (Annotation[]) classAndMethodContainer.getPluginConfigurationMethod().invoke(annotationPlugin); } - return Arrays.asList(properties); + return result; } - private static void fillDisplays(final Class<AbstractPlugin> clazz, final MIPlugin plugin, final ClassAndMethodContainer classAndMethodContainer, - final Map<String, String> displayDescriptions) throws ComponentInitializationException { - try { - // Get the displays and convert them into model instances - final List<Annotation> displays = Class2ModelInstanceConverter.getDisplays(clazz, classAndMethodContainer); - - for (final Annotation display : displays) { - final MIDisplay mDisplay = Class2ModelInstanceConverter.FACTORY.createDisplay(); - mDisplay.setName((String) classAndMethodContainer.getDisplayNameMethod().invoke(display)); - plugin.getDisplays().add(mDisplay); - - // Get the description as well - final String description = (String) classAndMethodContainer.getDisplayDescriptionMethod().invoke(display); - displayDescriptions.put(mDisplay.getName(), description); - } - } catch (final IllegalAccessException ex) { - throw new ComponentInitializationException("Could not load the displays of the class.", ex); - } catch (final IllegalArgumentException ex) { - throw new ComponentInitializationException("Could not load the displays of the class.", ex); - } catch (final InvocationTargetException ex) { - throw new ComponentInitializationException("Could not load the displays of the class.", ex); - } catch (final NoClassDefFoundError ex) { - throw new ComponentInitializationException("Could not load the displays of the class.", ex); - } + private Collection<Method> getInputPortMethods(final Class<AbstractFilterPlugin> clazz, final ClassAndMethodContainer classAndMethodContainer) { + return this.getAnnotatedMethods(clazz, classAndMethodContainer.getInputPortAnnotationClass()); } - private static void fillPorts(final Class<AbstractPlugin> clazz, final MIPlugin plugin, final ClassAndMethodContainer classAndMethodContainer) throws - ComponentInitializationException { - try { - // Get the ports - final List<Annotation> inputPorts = Class2ModelInstanceConverter.getInputPorts(clazz, classAndMethodContainer); - final List<Annotation> outputPorts = Class2ModelInstanceConverter.getOutputPorts(clazz, classAndMethodContainer); - final List<Annotation> repositoryPorts = Class2ModelInstanceConverter.getRepositoryPorts(clazz, classAndMethodContainer); - - // Add input ports - if (plugin instanceof MIFilter) { - for (final Annotation inputPort : inputPorts) { - final MIInputPort mInputPort = Class2ModelInstanceConverter.FACTORY.createInputPort(); - mInputPort.setName((String) classAndMethodContainer.getInputPortNameMethod().invoke(inputPort)); - mInputPort.setParent((MIFilter) plugin); - } - } - - // Add output ports. - for (final Annotation outputPort : outputPorts) { - final MIOutputPort mOutputPort = Class2ModelInstanceConverter.FACTORY.createOutputPort(); - mOutputPort.setName((String) classAndMethodContainer.getOutputPortNameMethod().invoke(outputPort)); - mOutputPort.setParent(plugin); - } + private Collection<Method> getDisplayMethods(final Class<? extends AbstractPlugin> clazz, final ClassAndMethodContainer classAndMethodContainer) { + return this.getAnnotatedMethods(clazz, classAndMethodContainer.getDisplayAnnotationClass()); + } - // Add repository ports. - for (final Annotation repositoryPort : repositoryPorts) { - final MIRepositoryConnector mConnector = Class2ModelInstanceConverter.FACTORY.createRepositoryConnector(); - mConnector.setName((String) classAndMethodContainer.getRepositoryPortNameMethod().invoke(repositoryPort)); - plugin.getRepositories().add(mConnector); - } - } catch (final IllegalAccessException ex) { - throw new ComponentInitializationException("Could not load the ports of the class.", ex); - } catch (final IllegalArgumentException ex) { - throw new ComponentInitializationException("Could not load the ports of the class.", ex); - } catch (final InvocationTargetException ex) { - throw new ComponentInitializationException("Could not load the ports of the class.", ex); - } catch (final NoClassDefFoundError ex) { - throw new ComponentInitializationException("Could not load the ports of the class.", ex); + @SuppressWarnings("unchecked") + private void fillOutputPorts(final Class<? extends AbstractPlugin> clazz, final ClassAndMethodContainer classAndMethodContainer, + final Collection<MIOutputPort> outputPorts, final MIPlugin parent) { + final Annotation annotation = this.getSuitableAnnotation(clazz, classAndMethodContainer); + final Annotation[] outputPortAnnotations = (Annotation[]) new Mirror().on(annotation).invoke().method("outputPorts").withoutArgs(); + for (final Annotation outputPortAnnotation : outputPortAnnotations) { + final MIOutputPort newPort = Class2ModelInstanceConverter.FACTORY.createOutputPort(); + newPort.setName((String) new Mirror().on(outputPortAnnotation).invoke().method("name").withoutArgs()); + newPort.setParent(parent); + outputPorts.add(newPort); } } - private static List<Annotation> getInputPorts(final Class<?> clazz, final ClassAndMethodContainer classAndMethodContainer) { - final List<Annotation> result = new ArrayList<Annotation>(); - - for (final Method method : clazz.getMethods()) { - // Get the potential annotation - final Annotation annotationPort = method.getAnnotation(classAndMethodContainer.getInputPortAnnotationClass()); - // Now check whether it is available - if (annotationPort != null) { - result.add(annotationPort); - } + @SuppressWarnings("unchecked") + private void fillProperties(final Class<? extends AbstractAnalysisComponent> clazz, final ClassAndMethodContainer classAndMethodContainer, + final Collection<MIProperty> properties, final Map<String, String> propertyDescriptions) { + final Annotation annotation = this.getSuitableAnnotation(clazz, classAndMethodContainer); + final Annotation[] propertyAnnotations = (Annotation[]) new Mirror().on(annotation).invoke().method("configuration").withoutArgs(); + for (final Annotation propertyAnnotation : propertyAnnotations) { + final MIProperty newProperty = Class2ModelInstanceConverter.FACTORY.createProperty(); + newProperty.setName((String) new Mirror().on(propertyAnnotation).invoke().method("name").withoutArgs()); + newProperty.setValue((String) new Mirror().on(propertyAnnotation).invoke().method("defaultValue").withoutArgs()); + properties.add(newProperty); + propertyDescriptions.put(newProperty.getName(), (String) new Mirror().on(propertyAnnotation).invoke().method("description").withoutArgs()); } + } - return result; + private String fillDependency(final Class<? extends AbstractAnalysisComponent> clazz, final ClassAndMethodContainer classAndMethodContainer) { + final Annotation annotation = this.getSuitableAnnotation(clazz, classAndMethodContainer); + return (String) new Mirror().on(annotation).invoke().method("dependencies").withoutArgs(); } - private static List<Annotation> getOutputPorts(final Class<?> clazz, final ClassAndMethodContainer classAndMethodContainer) throws IllegalArgumentException, - IllegalAccessException, InvocationTargetException { - final List<Annotation> result = new ArrayList<Annotation>(); + private String fillDescription(final Class<? extends AbstractAnalysisComponent> clazz, final ClassAndMethodContainer classAndMethodContainer) { + final Annotation annotation = this.getSuitableAnnotation(clazz, classAndMethodContainer); + return (String) new Mirror().on(annotation).invoke().method("description").withoutArgs(); + } - // Get the potential annotation + private Annotation getSuitableAnnotation(final Class<? extends AbstractAnalysisComponent> clazz, final ClassAndMethodContainer classAndMethodContainer) { + // Get the two potential annotations final Annotation annotationPlugin = clazz.getAnnotation(classAndMethodContainer.getPluginAnnotationClass()); + final Annotation annotationRepository = clazz.getAnnotation(classAndMethodContainer.getRepositoryAnnotationClass()); - // Now check whether it is available + // Find out which of them exists if (annotationPlugin != null) { - for (final Annotation oPort : (Annotation[]) classAndMethodContainer.getPluginOutputPortsMethod().invoke(annotationPlugin)) { - result.add(oPort); - } + return annotationPlugin; + } else { + return annotationRepository; } - - return result; } - private static List<Annotation> getRepositoryPorts(final Class<?> clazz, final ClassAndMethodContainer classAndMethodContainer) throws IllegalArgumentException, - IllegalAccessException, InvocationTargetException { - final List<Annotation> result = new ArrayList<Annotation>(); - - // Get the potential annotation - final Annotation annotationPlugin = clazz.getAnnotation(classAndMethodContainer.getPluginAnnotationClass()); - - // Now check whether it is available - if (annotationPlugin != null) { - for (final Annotation rPort : (Annotation[]) classAndMethodContainer.getPluginRepositoryPortsMethod().invoke(annotationPlugin)) { - result.add(rPort); - } + private MIAnalysisComponent createSuitableModelInstance(final Class<? extends AbstractAnalysisComponent> clazz, + final ClassAndMethodContainer classAndMethodContainer) { + if (classAndMethodContainer.getAbstractReaderPluginClass().isAssignableFrom(clazz)) { + return Class2ModelInstanceConverter.FACTORY.createReader(); + } else if (classAndMethodContainer.getAbstractFilterPluginClass().isAssignableFrom(clazz)) { + return Class2ModelInstanceConverter.FACTORY.createFilter(); + } else { + return Class2ModelInstanceConverter.FACTORY.createRepository(); } - - return result; } - private static List<Annotation> getDisplays(final Class<?> clazz, final ClassAndMethodContainer classAndMethodContainer) { - final List<Annotation> result = new ArrayList<Annotation>(); - - for (final Method method : clazz.getMethods()) { - // Get the potential annotation - final Annotation display = method.getAnnotation(classAndMethodContainer.getDisplayAnnotationClass()); - // Now check whether it is available - if (display != null) { - result.add(display); - } - } + /** + * Tells whether the given class is "programmaticOnly". If there is no annotation which could tell the state of the flag, true will be returned. + * + * @param clazz + * The class of the plugin or repository. + * @param classAndMethodContainer + * The container which will be used for the reflection access. + * + * @return The state of the programmaticOnly flag of the plugin or repository. + */ + public boolean isProgrammaticOnly(final Class<? extends AbstractAnalysisComponent> clazz, final ClassAndMethodContainer classAndMethodContainer) { + final Annotation annotation = this.getSuitableAnnotation(clazz, classAndMethodContainer); + return (Boolean) new Mirror().on(annotation).invoke().method("programmaticOnly").withoutArgs(); + } - return result; + private static enum Type { + Reader, Filter, Repository } + } diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/persistence/impl/util/PluginFinder.java b/Kieker.WebGUI/src/main/java/kieker/webgui/persistence/impl/util/PluginFinder.java index 66cb2ee8..85f21c83 100644 --- a/Kieker.WebGUI/src/main/java/kieker/webgui/persistence/impl/util/PluginFinder.java +++ b/Kieker.WebGUI/src/main/java/kieker/webgui/persistence/impl/util/PluginFinder.java @@ -24,7 +24,8 @@ import java.util.jar.JarInputStream; import org.springframework.stereotype.Service; -import kieker.analysis.plugin.AbstractPlugin; +import kieker.analysis.plugin.filter.AbstractFilterPlugin; +import kieker.analysis.plugin.reader.AbstractReaderPlugin; import kieker.analysis.repository.AbstractRepository; import kieker.webgui.common.ClassAndMethodContainer; @@ -89,17 +90,34 @@ public class PluginFinder { * @throws IOException * If something went wrong during the opening of the jar file. */ - public List<Class<AbstractPlugin>> getAllPluginsWithinJar(final URL url, final ClassLoader classLoader, + public List<Class<AbstractReaderPlugin>> getAllReadersWithinJar(final URL url, final ClassLoader classLoader, final ClassAndMethodContainer classAndMethodContainer) throws IOException { final List<Class<?>> clazzes = this.getAllClassesWithinJar(url, classLoader); - List<Class<AbstractPlugin>> result = null; + List<Class<AbstractReaderPlugin>> result = null; - result = new ArrayList<Class<AbstractPlugin>>(); + result = new ArrayList<Class<AbstractReaderPlugin>>(); for (final Class<?> clazz : clazzes) { // This is the cast resulting in an unchecked cast warning. if (clazz.isAnnotationPresent(classAndMethodContainer.getPluginAnnotationClass()) - && classAndMethodContainer.getAbstractPluginClass().isAssignableFrom(clazz)) { - result.add((Class<AbstractPlugin>) clazz); + && classAndMethodContainer.getAbstractReaderPluginClass().isAssignableFrom(clazz)) { + result.add((Class<AbstractReaderPlugin>) clazz); + } + } + + return result; + } + + public List<Class<AbstractFilterPlugin>> getAllFiltersWithinJar(final URL url, final ClassLoader classLoader, + final ClassAndMethodContainer classAndMethodContainer) throws IOException { + final List<Class<?>> clazzes = this.getAllClassesWithinJar(url, classLoader); + List<Class<AbstractFilterPlugin>> result = null; + + result = new ArrayList<Class<AbstractFilterPlugin>>(); + for (final Class<?> clazz : clazzes) { + // This is the cast resulting in an unchecked cast warning. + if (clazz.isAnnotationPresent(classAndMethodContainer.getPluginAnnotationClass()) + && classAndMethodContainer.getAbstractFilterPluginClass().isAssignableFrom(clazz)) { + result.add((Class<AbstractFilterPlugin>) clazz); } } diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/service/impl/util/Analysis.java b/Kieker.WebGUI/src/main/java/kieker/webgui/service/impl/util/Analysis.java index 6831593f..02676483 100644 --- a/Kieker.WebGUI/src/main/java/kieker/webgui/service/impl/util/Analysis.java +++ b/Kieker.WebGUI/src/main/java/kieker/webgui/service/impl/util/Analysis.java @@ -21,9 +21,6 @@ import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; -import net.vidageek.mirror.dsl.Mirror; -import net.vidageek.mirror.exception.MirrorException; - import kieker.analysis.AnalysisController; import kieker.common.logging.Log; import kieker.common.logging.LogFactory; @@ -32,6 +29,9 @@ import kieker.webgui.common.exception.AnalysisInitializationException; import kieker.webgui.common.exception.AnalysisStateException; import kieker.webgui.common.exception.ProjectLoadException; +import net.vidageek.mirror.dsl.Mirror; +import net.vidageek.mirror.exception.MirrorException; + /** * An analysis within the web gui. * diff --git a/Kieker.WebGUI/src/test/java/kieker/webgui/persistence/impl/util/PluginFinderTest.java b/Kieker.WebGUI/src/test/java/kieker/webgui/persistence/impl/util/PluginFinderTest.java index 96a54c99..958d1d3c 100644 --- a/Kieker.WebGUI/src/test/java/kieker/webgui/persistence/impl/util/PluginFinderTest.java +++ b/Kieker.WebGUI/src/test/java/kieker/webgui/persistence/impl/util/PluginFinderTest.java @@ -23,7 +23,8 @@ import java.util.List; import org.junit.Assert; import org.junit.Test; -import kieker.analysis.plugin.AbstractPlugin; +import kieker.analysis.plugin.filter.AbstractFilterPlugin; +import kieker.analysis.plugin.reader.AbstractReaderPlugin; import kieker.analysis.repository.AbstractRepository; import kieker.webgui.common.ClassAndMethodContainer; @@ -54,11 +55,13 @@ public class PluginFinderTest { final ClassAndMethodContainer classAndMethodContainer = new ClassAndMethodContainer(classLoader); try { - final List<Class<AbstractPlugin>> plugins = pluginFinder.getAllPluginsWithinJar(kiekerURL, classLoader, classAndMethodContainer); + final List<Class<AbstractFilterPlugin>> filters = pluginFinder.getAllFiltersWithinJar(kiekerURL, classLoader, classAndMethodContainer); + final List<Class<AbstractReaderPlugin>> readers = pluginFinder.getAllReadersWithinJar(kiekerURL, classLoader, classAndMethodContainer); final List<Class<AbstractRepository>> repositories = pluginFinder.getAllRepositoriesWithinJar(kiekerURL, classLoader, classAndMethodContainer); // There should be at least one element of both types - Assert.assertFalse("No plugins found.", plugins.isEmpty()); + Assert.assertFalse("No filters found.", filters.isEmpty()); + Assert.assertFalse("No readers found.", readers.isEmpty()); Assert.assertFalse("No repositories found.", repositories.isEmpty()); classLoader.close(); -- GitLab