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