diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/persistence/IProjectDAO.java b/Kieker.WebGUI/src/main/java/kieker/webgui/persistence/IProjectDAO.java index 6c6adc29924cf3b6686a4c197226cd322501358c..527e34e2802a12ca3748a5f4336091c6119aee3c 100644 --- a/Kieker.WebGUI/src/main/java/kieker/webgui/persistence/IProjectDAO.java +++ b/Kieker.WebGUI/src/main/java/kieker/webgui/persistence/IProjectDAO.java @@ -56,7 +56,7 @@ public interface IProjectDAO { public abstract void addProject(String projectName, final String username) throws ProjectAlreadyExistingException, IOException; @PreAuthorize("hasAnyRole('User', 'Administrator')") - public abstract void delProject(String projectName) throws IOException; + public abstract void removeProject(String projectName) throws IOException; /** * This method imports an existing kax-file into the application. If the given project name does already exist, the application will not try to upload it in the 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 e83909cb2c6ac48ed9e651b4006fb5716fee8269..19e0bab24743f2a36185944dbef4ef182ca30a7a 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 @@ -23,20 +23,15 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; -import java.lang.annotation.Annotation; import java.lang.ref.WeakReference; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.net.MalformedURLException; import java.net.URL; import java.security.AccessController; import java.security.PrivilegedAction; 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 java.util.Map.Entry; @@ -56,24 +51,13 @@ import org.springframework.util.WeakReferenceMonitor.ReleaseListener; import com.google.common.io.Files; import kieker.analysis.AnalysisController; -import kieker.analysis.model.analysisMetaModel.MIAnalysisComponent; import kieker.analysis.model.analysisMetaModel.MIAnalysisMetaModelFactory; -import kieker.analysis.model.analysisMetaModel.MIDisplay; -import kieker.analysis.model.analysisMetaModel.MIFilter; -import kieker.analysis.model.analysisMetaModel.MIInputPort; -import kieker.analysis.model.analysisMetaModel.MIOutputPort; -import kieker.analysis.model.analysisMetaModel.MIPlugin; import kieker.analysis.model.analysisMetaModel.MIProject; -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.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.common.exception.NewerProjectException; import kieker.webgui.common.exception.ProjectAlreadyExistingException; import kieker.webgui.common.exception.ProjectNotExistingException; @@ -81,6 +65,7 @@ import kieker.webgui.domain.ComponentListContainer; import kieker.webgui.domain.PluginContainer; import kieker.webgui.domain.RepositoryContainer; import kieker.webgui.persistence.IProjectDAO; +import kieker.webgui.persistence.impl.util.Class2ModelInstanceConverter; import kieker.webgui.persistence.impl.util.CloseableURLClassLoader; import kieker.webgui.persistence.impl.util.PluginFinder; @@ -110,6 +95,8 @@ public class FSProjectDAOImpl implements IProjectDAO, ReleaseListener { @Autowired private PluginFinder pluginFinder; + @Autowired + private Class2ModelInstanceConverter class2ModelInstanceConverter; private final Map<CloseableURLClassLoader, WeakReference<Object>> classLoaders = new ConcurrentHashMap<CloseableURLClassLoader, WeakReference<Object>>(); private final Map<File, WeakReference<Object>> tempDirs = new ConcurrentHashMap<File, WeakReference<Object>>(); @@ -130,37 +117,18 @@ public class FSProjectDAOImpl implements IProjectDAO, ReleaseListener { */ @PostConstruct public void initialize() throws IOException { - // Check for the necessary directories and create them if necessary - this.checkDir(FSProjectDAOImpl.ROOT_DIRECTORY); - // This method call will initialize the available components for all projects which currently exist. - this.initializeAvailableComponents(); + // Make sure that the necessary directories exist and that the available component lists (containing plugins and repositories) are initialized. + FSProjectDAOImpl.createDirectoryIfNecessary(FSProjectDAOImpl.ROOT_DIRECTORY); + this.initializeAvailableComponentsListContainersForAllProjects(); } - /** - * This method initializes the available components for all projects. This means that this method will run through all projects and load all available plugins, - * filters and repositories from the existing libraries - including Kieker. - * - * @throws IOException - * If something went really wrong during the initialization of one of the projects. - */ - private void initializeAvailableComponents() throws IOException { - final Collection<String> projects = this.listAllProjects(); - // Initialize all available components within all projects - for (final String project : projects) { - this.initializeAvailableComponents(project); + private void initializeAvailableComponentsListContainersForAllProjects() throws IOException { + for (final String project : this.listAllProjects()) { + this.initializeAvailableComponentsListContainers(project); } } - /** - * This method initializes the available components for the given project. This means that this method will load all available plugins, filters and repositories - * from the existing libraries - including Kieker. - * - * @param project - * The name of the project to be initialized. - * @throws IOException - * If something went really wrong during the initialization of the project. - */ - private void initializeAvailableComponents(final String project) throws IOException { + private void initializeAvailableComponentsListContainers(final String project) throws IOException { try { final Object dummyObject = new Object(); // Deliver a dummy object as a requester to make sure that the classloader can be disposed. Once the program exits this scope, it can be released. @@ -174,10 +142,10 @@ public class FSProjectDAOImpl implements IProjectDAO, ReleaseListener { // Update the components using all available dependencies final Collection<String> libs = this.listAllLibraries(project); for (final String lib : libs) { - this.initializeAvailableComponents(readers, filters, repositories, this.getURL(lib, project), classLoader, classAndMethodContainer); + this.initializeAvailableComponentsLists(readers, filters, repositories, this.getURL(lib, project), classLoader, classAndMethodContainer); } // Update the components using the Kieker library. - this.initializeAvailableComponents(readers, filters, repositories, this.getKiekerURL(), classLoader, classAndMethodContainer); + this.initializeAvailableComponentsLists(readers, filters, repositories, this.getKiekerURL(), classLoader, classAndMethodContainer); // Assemble the final object containing the available components - but make sure that the lists cannot be modified. final ComponentListContainer componentList = new ComponentListContainer(Collections.unmodifiableList(readers), Collections.unmodifiableList(filters), @@ -191,43 +159,24 @@ public class FSProjectDAOImpl implements IProjectDAO, ReleaseListener { } } - /** - * This method initializes the available components for the given library and the given project. It runs through the library and extracts all available readers, - * filters and repositories. - * - * @param readers - * The list of readers which will be filled during the extraction process. - * @param filters - * The list of filters which will be filled during the extraction process. - * @param repositories - * The list of repositories which will be filled during the extraction process. - * @param lib - * The url to the library which will be used for the extraction. - * @param classLoader - * The classloader which will be used to load the classes. - * @param classAndMethodContainer - * The object containing classes and methods for the extraction process. - * @throws IOException - * If something went really wrong during the process. - */ - private void initializeAvailableComponents(final List<PluginContainer> readers, final List<PluginContainer> filters, - final List<RepositoryContainer> repositories, final URL lib, final ClassLoader classLoader, final ClassAndMethodContainer classAndMethodContainer) throws - IOException { + private void initializeAvailableComponentsLists(final List<PluginContainer> readers, final List<PluginContainer> filters, + final List<RepositoryContainer> repositories, final URL lib, final ClassLoader classLoader, final ClassAndMethodContainer classAndMethodContainer) + 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); // Convert the repositories into model instances for (final Class<AbstractRepository> repository : repositoryClasses) { - if (!(Modifier.isAbstract(repository.getModifiers()) || FSProjectDAOImpl.isProgrammaticOnly(repository, classAndMethodContainer))) { - repositories.add(FSProjectDAOImpl.convertRepository(repository, classAndMethodContainer)); + if (!(Modifier.isAbstract(repository.getModifiers()) || this.class2ModelInstanceConverter.isProgrammaticOnly(repository, classAndMethodContainer))) { + repositories.add(this.class2ModelInstanceConverter.convertRepository2ModelInstance(repository, classAndMethodContainer)); } } // Convert the plugins into model instances for (final Class<AbstractPlugin> plugin : pluginClasses) { - if (!(Modifier.isAbstract(plugin.getModifiers()) || FSProjectDAOImpl.isProgrammaticOnly(plugin, classAndMethodContainer))) { - final PluginContainer pluginContainer = FSProjectDAOImpl.convertPlugin(plugin, classAndMethodContainer); + 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 { @@ -237,545 +186,7 @@ public class FSProjectDAOImpl implements IProjectDAO, ReleaseListener { } } - /** - * 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. - */ - private static PluginContainer convertPlugin(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 = FSProjectDAOImpl.FACTORY.createReader(); - } else { - plugin = FSProjectDAOImpl.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 = FSProjectDAOImpl.getDescription(clazz, classAndMethodContainer); - dependency = FSProjectDAOImpl.getDependencies(clazz, classAndMethodContainer); - - FSProjectDAOImpl.fillProperties(clazz, plugin, classAndMethodContainer, propertyDescriptions); - FSProjectDAOImpl.fillPorts(clazz, plugin, classAndMethodContainer); - FSProjectDAOImpl.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(); - } - // description = ""; - // dependency = ""; - - fullyInitialized = false; - - FSProjectDAOImpl.LOG.warn("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)); - } - - /** - * 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. - */ - private static 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; - } - - /** - * 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. - */ - private static RepositoryContainer convertRepository(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 = FSProjectDAOImpl.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 = FSProjectDAOImpl.getDescription(clazz, classAndMethodContainer); - dependency = FSProjectDAOImpl.getDependencies(clazz, classAndMethodContainer); - FSProjectDAOImpl.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(); - - fullyInitialized = false; - - FSProjectDAOImpl.LOG.warn("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 RepositoryContainer(repository, description, dependency, fullyInitialized, Collections.unmodifiableMap(propertyDescriptions)); - } - - /** - * This method can be used to get the description of an {@link AbstractPlugin}- or an {@link AbstractRepository}-class. The description is read via the - * annotation using the java reflection API. - * - * @param clazz - * The class whose description should be extracted. - * @param classAndMethodContainer - * The container which will be used for the reflection invocation. - * @return The description for the class. - * @throws ComponentInitializationException - * If the description could not be loaded. - */ - 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); - } - - 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); - } - } - - /** - * Delivers the content of the dependencies-field of the given component (plugin or repository). - * - * @param clazz - * The class whose dependencies should be extracted. - * @param classAndMethodContainer - * The container which will be used for the reflection invocation. - * @return The dependencies for the class. - * @throws ComponentInitializationException - * If the dependencies could not be loaded. - */ - 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); - } - } - - /** - * This method fills the properties of the given repository or plugin. In other words: It tries to extract the list of properties from the given class (using the - * annotations) and to convert them into model instances. - * - * @param clazz - * The class to be used as a base. - * @param component - * The component to be filled. - * @param classAndMethodContainer - * The container which will be used for the reflection invocation. - * @param propertyDescriptions - * The map which will later contain the properties description. - * @throws ComponentInitializationException - * If the properties could not be loaded. - */ - 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 = FSProjectDAOImpl.getProperties(clazz, classAndMethodContainer); - - for (final Annotation property : properties) { - final MIProperty mProperty = FSProjectDAOImpl.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); - } - } - - /** - * Delivers the properties of the given class, using the annotations and the java reflection API. - * - * @param clazz - * The class whose properties will be delivered. - * @param classAndMethodContainer - * The container which will be used for the reflection invocation. - * @return A list of properties. It contains instances of {@link Property} - but those from the project class loader. - * @throws InvocationTargetException - * If something went wrong during the reflection invocation. - * @throws IllegalAccessException - * If something went wrong during the reflection invocation. - * @throws IllegalArgumentException - * If something went wrong during the reflection invocation. - */ - 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()); - - 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); - } - } else { - properties = (Annotation[]) classAndMethodContainer.getPluginConfigurationMethod().invoke(annotationPlugin); - } - - return Arrays.asList(properties); - } - - /** - * This method fills the displays of the given plugin. In other words: It tries to extract the list of displays from the given class (using the annotations) and - * to convert them into model instances. - * - * @param clazz - * The class to be used as a base. - * @param plugin - * The plugin to be filled. - * @param classAndMethodContainer - * The container which will be used for the reflection invocation. - * @param displayDescriptions - * The map which will later contain the display description. - * @throws ComponentInitializationException - * If the properties could not be loaded. - */ - 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 = FSProjectDAOImpl.getDisplays(clazz, classAndMethodContainer); - - for (final Annotation display : displays) { - final MIDisplay mDisplay = FSProjectDAOImpl.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); - } - } - - /** - * This method fills the ports of the given plugin. In other words: It tries to extract the list of ports from the given class (using the annotations) and - * to convert them into model instances. - * - * @param clazz - * The class to be used as a base. - * @param plugin - * The plugin to be filled. - * @param classAndMethodContainer - * The container which will be used for the reflection invocation. - * @throws ComponentInitializationException - * If the properties could not be loaded. - */ - private static void fillPorts(final Class<AbstractPlugin> clazz, final MIPlugin plugin, final ClassAndMethodContainer classAndMethodContainer) throws - ComponentInitializationException { - try { - // Get the ports - final List<Annotation> inputPorts = FSProjectDAOImpl.getInputPorts(clazz, classAndMethodContainer); - final List<Annotation> outputPorts = FSProjectDAOImpl.getOutputPorts(clazz, classAndMethodContainer); - final List<Annotation> repositoryPorts = FSProjectDAOImpl.getRepositoryPorts(clazz, classAndMethodContainer); - - // Add input ports - if (plugin instanceof MIFilter) { - for (final Annotation inputPort : inputPorts) { - final MIInputPort mInputPort = FSProjectDAOImpl.FACTORY.createInputPort(); - mInputPort.setName((String) classAndMethodContainer.getInputPortNameMethod().invoke(inputPort)); - mInputPort.setParent((MIFilter) plugin); - } - } - - // Add output ports. - for (final Annotation outputPort : outputPorts) { - final MIOutputPort mOutputPort = FSProjectDAOImpl.FACTORY.createOutputPort(); - mOutputPort.setName((String) classAndMethodContainer.getOutputPortNameMethod().invoke(outputPort)); - mOutputPort.setParent(plugin); - } - - // Add repository ports. - for (final Annotation repositoryPort : repositoryPorts) { - final MIRepositoryConnector mConnector = FSProjectDAOImpl.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); - } - } - - /** - * Searches for input ports within the given class and returns them. - * - * @param clazz - * The class to be analyzed. - * @param classAndMethodContainer - * The container which will be used for the reflection invocation. - * @return A list containing the available input ports. - */ - 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); - } - } - - return result; - } - - /** - * Searches for output ports within the given class and returns them. - * - * @param clazz - * The class to be analyzed. - * @param classAndMethodContainer - * The container which will be used for the reflection invocation. - * @return A list containing the available output ports. - * @throws InvocationTargetException - * If something went wrong during the reflection invocation. - * @throws IllegalAccessException - * If something went wrong during the reflection invocation. - * @throws IllegalArgumentException - * If something went wrong during the reflection invocation. - */ - private static List<Annotation> getOutputPorts(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 oPort : (Annotation[]) classAndMethodContainer.getPluginOutputPortsMethod().invoke(annotationPlugin)) { - result.add(oPort); - } - } - - return result; - } - - /** - * Searches for repository ports within the given class and returns them. - * - * @param clazz - * The class to be analyzed. - * @param classAndMethodContainer - * The container which will be used for the reflection invocation. - * @return A list containing the available repository ports. - * @throws InvocationTargetException - * If something went wrong during the reflection invocation. - * @throws IllegalAccessException - * If something went wrong during the reflection invocation. - * @throws IllegalArgumentException - * If something went wrong during the reflection invocation. - */ - 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); - } - } - - return result; - } - - /** - * Searches for displays within the given class and returns them. - * - * @param clazz - * The class to be analyzed. - * @param classAndMethodContainer - * The container which will be used for the reflection invocation. - * @return A list containing the available displays. - */ - 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); - } - } - - return result; - } - - /** - * Checks whether the given directory exists and creates it if necessary. - * - * @param dirName - * The name of the directory. - * @throws IOException - * If the directory could not be created. - */ - private void checkDir(final String dirName) throws IOException { + private static void createDirectoryIfNecessary(final String dirName) throws IOException { final File dir = new File(dirName); if (!dir.exists() && !dir.mkdir()) { // Try to create the directory @@ -783,19 +194,22 @@ public class FSProjectDAOImpl implements IProjectDAO, ReleaseListener { } } + /* + * (non-Javadoc) + * + * @see kieker.webgui.persistence.IProjectDAO#removeProject(java.lang.String) + */ @Override @PreAuthorize("hasAnyRole('User', 'Administrator')") - public void delProject(final String projectName) throws IOException { - if (!this.projectExists(projectName)) { - throw new ProjectNotExistingException("A project with the name '" + projectName + "' does not exist."); - } + public void removeProject(final String projectName) throws IOException { + this.checkProjectExistence(projectName); - // Try to remove the whole project + // Simply try to remove the project directory final File projectDir = FSProjectDAOImpl.assembleProjectDir(projectName); final boolean result = FileSystemUtils.deleteRecursively(projectDir); if (!result) { - throw new IOException("Could not remove the project directory."); + throw new IOException("Unable to remove project '" + projectName + "'.)"); } } @@ -826,7 +240,7 @@ public class FSProjectDAOImpl implements IProjectDAO, ReleaseListener { if (projectDir.mkdir() && libDir.mkdir() && metaFile.createNewFile()) { // Try to save the file AnalysisController.saveToFile(projectFile, emptyProject); - this.initializeAvailableComponents(projectName); + this.initializeAvailableComponentsListContainers(projectName); // Store the initial meta data final Properties properties = new Properties(); @@ -907,6 +321,8 @@ public class FSProjectDAOImpl implements IProjectDAO, ReleaseListener { final File realDstKaxFile = FSProjectDAOImpl.assembleKaxFile(newProjectName); dstKaxFile.renameTo(realDstKaxFile); + + this.initializeAvailableComponentsListContainers(newProjectName); } catch (final IOException ex) { // Something went wrong. Remove everything FileSystemUtils.deleteRecursively(dstProjDir); @@ -1061,7 +477,7 @@ public class FSProjectDAOImpl implements IProjectDAO, ReleaseListener { FileCopyUtils.copy(in, out); // Reload the available components - this.initializeAvailableComponents(projectName); + this.initializeAvailableComponentsListContainers(projectName); } /* @@ -1188,10 +604,14 @@ public class FSProjectDAOImpl implements IProjectDAO, ReleaseListener { * * @param projectName * The name of the project. - * @return true if and only if a directory with the name of the project exists in the root dir. + * + * @throws ProjectNotExistingException + * If a project with the given name does not exist */ - private boolean projectExists(final String projectName) { - return FSProjectDAOImpl.assembleKaxFile(projectName).exists(); + private void checkProjectExistence(final String projectName) throws ProjectNotExistingException { + if (FSProjectDAOImpl.assembleKaxFile(projectName).exists()) { + throw new ProjectNotExistingException("A project with the name '" + projectName + "' does not exist."); + } } /** @@ -1267,7 +687,7 @@ public class FSProjectDAOImpl implements IProjectDAO, ReleaseListener { final File libFile = new File(libDir, libName); final boolean result = libFile.delete(); // Reload the available components - this.initializeAvailableComponents(projectName); + this.initializeAvailableComponentsListContainers(projectName); return result; } 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 new file mode 100644 index 0000000000000000000000000000000000000000..05ff96777de2004451ebb841bb378c96f5f7a4b6 --- /dev/null +++ b/Kieker.WebGUI/src/main/java/kieker/webgui/persistence/impl/util/Class2ModelInstanceConverter.java @@ -0,0 +1,471 @@ +/*************************************************************************** + * Copyright 2013 Kieker Project (http://kieker-monitoring.net) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ***************************************************************************/ +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.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.springframework.stereotype.Service; + +import kieker.analysis.model.analysisMetaModel.MIAnalysisComponent; +import kieker.analysis.model.analysisMetaModel.MIAnalysisMetaModelFactory; +import kieker.analysis.model.analysisMetaModel.MIDisplay; +import kieker.analysis.model.analysisMetaModel.MIFilter; +import kieker.analysis.model.analysisMetaModel.MIInputPort; +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.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.PluginContainer; +import kieker.webgui.domain.RepositoryContainer; + +/** + * 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. + * + * @author Nils Christian Ehmke + */ +@Service +public final class Class2ModelInstanceConverter { + + private static final Log LOG = LogFactory.getLog(Class2ModelInstanceConverter.class); + + private static final MIAnalysisMetaModelFactory FACTORY = MIAnalysisMetaModelFactory.eINSTANCE; + + /** + * Default constructor. <b>Do not use this constructor. This bean is Spring managed.</b> + */ + public 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.warn("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)); + } + + /** + * 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; + } + + /** + * 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(); + + fullyInitialized = false; + + Class2ModelInstanceConverter.LOG.warn("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 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); + } + + 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); + } + } + + 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 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 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()); + + 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); + } + } else { + properties = (Annotation[]) classAndMethodContainer.getPluginConfigurationMethod().invoke(annotationPlugin); + } + + return Arrays.asList(properties); + } + + 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 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); + } + + // 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); + } + } + + 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); + } + } + + return result; + } + + private static List<Annotation> getOutputPorts(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 oPort : (Annotation[]) classAndMethodContainer.getPluginOutputPortsMethod().invoke(annotationPlugin)) { + result.add(oPort); + } + } + + 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); + } + } + + 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); + } + } + + return result; + } +} diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/service/impl/ProjectServiceImpl.java b/Kieker.WebGUI/src/main/java/kieker/webgui/service/impl/ProjectServiceImpl.java index 92a6e5402b490728803355f73525d9ba606bcd4e..e8d03685ba033d88e2a5920b243a1bd352733ab1 100644 --- a/Kieker.WebGUI/src/main/java/kieker/webgui/service/impl/ProjectServiceImpl.java +++ b/Kieker.WebGUI/src/main/java/kieker/webgui/service/impl/ProjectServiceImpl.java @@ -81,7 +81,7 @@ public final class ProjectServiceImpl implements IProjectService { final Object projectLock = this.getLock(projectName, this.fileSystemLocks); synchronized (projectLock) { - this.projectDAO.delProject(projectName); + this.projectDAO.removeProject(projectName); } }