diff --git a/Kieker.WebGUI/lib/kieker-1.5-SNAPSHOT.jar b/Kieker.WebGUI/lib/kieker-1.5-SNAPSHOT.jar index 412f7a338a64ffa40b1fc7ea874f292c46b70d83..1b2727001ca160a5f659068464424b1a57ca041d 100644 Binary files a/Kieker.WebGUI/lib/kieker-1.5-SNAPSHOT.jar and b/Kieker.WebGUI/lib/kieker-1.5-SNAPSHOT.jar differ diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/beans/session/AnalysisControllerBean.java b/Kieker.WebGUI/src/main/java/kieker/webgui/beans/session/AnalysisControllerBean.java new file mode 100644 index 0000000000000000000000000000000000000000..1b207171d55b25eb816b8761092d7ebb47684d04 --- /dev/null +++ b/Kieker.WebGUI/src/main/java/kieker/webgui/beans/session/AnalysisControllerBean.java @@ -0,0 +1,78 @@ +/*************************************************************************** + * Copyright 2012 by + * + Christian-Albrechts-University of Kiel + * + Department of Computer Science + * + Software Engineering Group + * and others. + * + * 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.beans.session; + +import java.io.File; +import java.io.IOException; + +import javax.faces.bean.ManagedBean; +import javax.faces.bean.SessionScoped; + +import kieker.analysis.AnalysisController; +import kieker.analysis.model.analysisMetaModel.MIProject; +import kieker.common.logging.Log; +import kieker.common.logging.LogFactory; + +/** + * + * @author Nils Christian Ehmke + * @version 1.0 + */ +@ManagedBean +@SessionScoped +public class AnalysisControllerBean { + /** + * The logger within this class. + */ + private static final Log LOG = LogFactory.getLog(AnalysisControllerBean.class); + private AnalysisController controller; + + /** + * Creates a new instance of this class. + */ + public AnalysisControllerBean() { + /* + * No code necessary. + */ + } + + public AnalysisController getController() { + return this.controller; + } + + public void setController(final AnalysisController controller) { + this.controller = controller; + } + + public void instantiate(final MIProject mProject) { + if (mProject != null) { + try { + final File tempFile = File.createTempFile("java", ".tmp"); + AnalysisController.saveToFile(tempFile, mProject); + this.controller = new AnalysisController(tempFile); + tempFile.delete(); + } catch (final IOException ex) { + AnalysisControllerBean.LOG.error("Could not create analysis controller.", ex); + } catch (final NullPointerException ex) { + AnalysisControllerBean.LOG.error("Could not create analysis controller.", ex); + } + } + } +} diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/beans/session/SelectedMainProjectBean.java b/Kieker.WebGUI/src/main/java/kieker/webgui/beans/session/SelectedMainProjectBean.java index 21ac75fe2ec01c4a5b9e48dc4edcecb99f5c266a..0955b33c1002dbffcb1c99810b4963404ab0dae4 100644 --- a/Kieker.WebGUI/src/main/java/kieker/webgui/beans/session/SelectedMainProjectBean.java +++ b/Kieker.WebGUI/src/main/java/kieker/webgui/beans/session/SelectedMainProjectBean.java @@ -20,6 +20,7 @@ package kieker.webgui.beans.session; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Modifier; import java.net.MalformedURLException; import java.net.URL; @@ -42,16 +43,17 @@ import kieker.analysis.model.analysisMetaModel.MIProject; import kieker.analysis.model.analysisMetaModel.MIProperty; import kieker.analysis.model.analysisMetaModel.MIReader; import kieker.analysis.model.analysisMetaModel.impl.MAnalysisMetaModelFactory; -import kieker.analysis.plugin.AbstractAnalysisPlugin; +import kieker.analysis.plugin.AbstractFilterPlugin; import kieker.analysis.plugin.AbstractPlugin; import kieker.analysis.plugin.AbstractReaderPlugin; import kieker.analysis.repository.AbstractRepository; import kieker.common.configuration.Configuration; +import kieker.common.logging.Log; +import kieker.common.logging.LogFactory; import kieker.webgui.common.Connection; import kieker.webgui.common.FileManager; import kieker.webgui.common.PluginClassLoader; import kieker.webgui.common.PluginFinder; -import kieker.webgui.converter.MIPluginToStringConverter; import org.eclipse.emf.common.util.EList; @@ -64,6 +66,14 @@ import org.eclipse.emf.common.util.EList; @ManagedBean @SessionScoped public class SelectedMainProjectBean { + /** + * The logger within this class. + */ + private static final Log LOG = LogFactory.getLog(SelectedMainProjectBean.class); + /** + * The error message used if a plugin could not be instantiated for various reasons. + */ + private static final String ERR_MSG_LOAD_PLUGIN = "Could not instantiate plugin."; /** * This constant is used as the host for the dependencies. */ @@ -117,7 +127,6 @@ public class SelectedMainProjectBean { * @return "bold" if the given project is the current main project, "normal" otherwise. */ public final String getFontWeight(final MIProject project) { - // TODO: This should be done via c:if or something if (project == this.mainProject) { return "bold"; } else { @@ -139,7 +148,7 @@ public class SelectedMainProjectBean { PluginClassLoader.getInstance().addURL( new URL(SelectedMainProjectBean.URL_PROTOCOL_FILE, SelectedMainProjectBean.URL_LOCALHOST, FileManager.getInstance().getFullPath(lib))); } catch (final MalformedURLException ex) { - // TODO Log exception + LOG.warn("Invalid URL for dependency.", ex); } try { final List<Class<AbstractPlugin>> plugins = PluginFinder.getAllPluginsWithinJar(new URL(SelectedMainProjectBean.URL_PROTOCOL_FILE, @@ -150,8 +159,7 @@ public class SelectedMainProjectBean { } } } catch (final MalformedURLException ex) { - ex.printStackTrace(); - // TODO Log exception + LOG.warn("Invalid URL for dependency.", ex); } } } @@ -164,8 +172,8 @@ public class SelectedMainProjectBean { * * @return A list with all filter. */ - public final List<Class<AbstractAnalysisPlugin>> getAvailableFilters() { - final List<Class<AbstractAnalysisPlugin>> list = new ArrayList<Class<AbstractAnalysisPlugin>>(); + public final List<Class<AbstractFilterPlugin>> getAvailableFilters() { + final List<Class<AbstractFilterPlugin>> list = new ArrayList<Class<AbstractFilterPlugin>>(); if (this.mainProject != null) { for (final MIDependency lib : this.mainProject.getDependencies()) { @@ -173,19 +181,18 @@ public class SelectedMainProjectBean { PluginClassLoader.getInstance().addURL( new URL(SelectedMainProjectBean.URL_PROTOCOL_FILE, SelectedMainProjectBean.URL_LOCALHOST, FileManager.getInstance().getFullPath(lib))); } catch (final MalformedURLException ex) { - // TODO Log exception + LOG.warn("Invalid URL for dependency.", ex); } try { final List<Class<AbstractPlugin>> plugins = PluginFinder.getAllPluginsWithinJar(new URL(SelectedMainProjectBean.URL_PROTOCOL_FILE, SelectedMainProjectBean.URL_LOCALHOST, FileManager.getInstance().getFullPath(lib))); for (final Class<?> plugin : plugins) { - if (!Modifier.isAbstract(plugin.getModifiers()) && AbstractAnalysisPlugin.class.isAssignableFrom(plugin)) { - list.add((Class<AbstractAnalysisPlugin>) plugin); + if (!Modifier.isAbstract(plugin.getModifiers()) && AbstractFilterPlugin.class.isAssignableFrom(plugin)) { + list.add((Class<AbstractFilterPlugin>) plugin); } } } catch (final MalformedURLException ex) { - ex.printStackTrace(); - // TODO Log exception + LOG.warn("Invalid URL for dependency.", ex); } } } @@ -208,7 +215,7 @@ public class SelectedMainProjectBean { PluginClassLoader.getInstance().addURL( new URL(SelectedMainProjectBean.URL_PROTOCOL_FILE, SelectedMainProjectBean.URL_LOCALHOST, FileManager.getInstance().getFullPath(lib))); } catch (final MalformedURLException ex) { - // TODO Log exception + LOG.warn("Invalid URL for dependency.", ex); } try { final List<Class<AbstractRepository>> repositories = PluginFinder.getAllRepositoriesWithinJar(new URL(SelectedMainProjectBean.URL_PROTOCOL_FILE, @@ -219,8 +226,7 @@ public class SelectedMainProjectBean { } } } catch (final MalformedURLException ex) { - ex.printStackTrace(); - // TODO Log exception + LOG.warn("Invalid URL for dependency.", ex); } } } @@ -255,6 +261,36 @@ public class SelectedMainProjectBean { } } + /** + * This method uses the actual plugin to create the model port instances and add them to the model plugin instance. + * + * @param plugin + * The plugin whose ports will be used. + * @param mPlugin + * The model plugin which will be modified. + */ + private static void addPorts(final AbstractPlugin plugin, final MIPlugin mPlugin) { + /* Get the port and use them to initialize the model plugin. */ + final String[] inputPortNames = plugin.getAllInputPortNames(); + final String[] outputPortNames = plugin.getAllOutputPortNames(); + + final MAnalysisMetaModelFactory factory = new MAnalysisMetaModelFactory(); + + if (mPlugin instanceof MIAnalysisPlugin) { + for (String inputPortName : inputPortNames) { + final MIInputPort mInputPort = factory.createInputPort(); + mInputPort.setName(inputPortName); + mInputPort.setParent((MIAnalysisPlugin) mPlugin); + } + } + + for (String outputPortName : outputPortNames) { + final MIOutputPort mOutputPort = factory.createOutputPort(); + mOutputPort.setName(outputPortName); + mOutputPort.setParent(mPlugin); + } + } + /** * This method can be used to add a model plugin instance to the current main project using the given class. * @@ -262,29 +298,39 @@ public class SelectedMainProjectBean { * The class which will be instantiated. */ public final void addPlugin(final Class<AbstractPlugin> pluginClass) { - // TODO It seems like it is necessary to completly load all properties, including the available ports in order to work final MAnalysisMetaModelFactory factory = new MAnalysisMetaModelFactory(); + try { final AbstractPlugin plugin = pluginClass.getConstructor(Configuration.class).newInstance(new Configuration()); + MIPlugin mPlugin; if (AbstractReaderPlugin.class.isAssignableFrom(pluginClass)) { - final MIReader reader = factory.createReader(); - reader.setClassname(pluginClass.getCanonicalName()); - reader.setName(pluginClass.getSimpleName()); - SelectedMainProjectBean.addConfiguration(plugin, reader); - - this.mainProject.getPlugins().add(reader); + mPlugin = factory.createReader(); } else { - final MIAnalysisPlugin filter = factory.createAnalysisPlugin(); - filter.setClassname(pluginClass.getCanonicalName()); - filter.setName(pluginClass.getSimpleName()); - SelectedMainProjectBean.addConfiguration(plugin, filter); - - this.mainProject.getPlugins().add(filter); + mPlugin = factory.createAnalysisPlugin(); } - } catch (final Exception ex) { - // TODO Log exception + + mPlugin.setClassname(pluginClass.getCanonicalName()); + mPlugin.setName(pluginClass.getSimpleName()); + SelectedMainProjectBean.addConfiguration(plugin, mPlugin); + SelectedMainProjectBean.addPorts(plugin, mPlugin); + + this.mainProject.getPlugins().add(mPlugin); + + } catch (final InstantiationException ex) { + SelectedMainProjectBean.LOG.warn(SelectedMainProjectBean.ERR_MSG_LOAD_PLUGIN, ex); + } catch (final NoSuchMethodException ex) { + SelectedMainProjectBean.LOG.warn(SelectedMainProjectBean.ERR_MSG_LOAD_PLUGIN, ex); + } catch (final SecurityException ex) { + SelectedMainProjectBean.LOG.warn(SelectedMainProjectBean.ERR_MSG_LOAD_PLUGIN, ex); + } catch (final IllegalAccessException ex) { + SelectedMainProjectBean.LOG.warn(SelectedMainProjectBean.ERR_MSG_LOAD_PLUGIN, ex); + } catch (final IllegalArgumentException ex) { + SelectedMainProjectBean.LOG.warn(SelectedMainProjectBean.ERR_MSG_LOAD_PLUGIN, ex); + } catch (final InvocationTargetException ex) { + SelectedMainProjectBean.LOG.warn(SelectedMainProjectBean.ERR_MSG_LOAD_PLUGIN, ex); } + } /** @@ -341,7 +387,7 @@ public class SelectedMainProjectBean { * This method "submits" the current connections to the main project (In other words: The connections will be stored within the main project). */ public void submitConnections() { - for (final Connection connection : connections) { + for (final Connection connection : this.connections) { if (connection.isValid()) { connection.getOutputPort().getSubscribers().add(connection.getInputPort()); } diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/common/Connection.java b/Kieker.WebGUI/src/main/java/kieker/webgui/common/Connection.java index e317cef73b2fefba229349ea8306e622b3f64e5e..5a272ef5cb7901359a1f2b7406ce5c5d22f031c8 100644 --- a/Kieker.WebGUI/src/main/java/kieker/webgui/common/Connection.java +++ b/Kieker.WebGUI/src/main/java/kieker/webgui/common/Connection.java @@ -149,7 +149,7 @@ public class Connection { * Checks whether the current configuration is valid. The configuration is valid if and only if: All four components are not null, the ports exist and are * compatible. * - * @return + * @return true if and only if all four components are not null, the ports exist and are compatible. */ public boolean isValid() { if (this.source == null || this.destination == null || this.inputPort == null || this.outputPort == null) { diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/converter/MIPortToStringConverter.java b/Kieker.WebGUI/src/main/java/kieker/webgui/converter/MIPortToStringConverter.java index e54843940335e1de2697b5e60432e1331182402e..2d311bf234c55f33e23eb79a565785e5f7912f7a 100644 --- a/Kieker.WebGUI/src/main/java/kieker/webgui/converter/MIPortToStringConverter.java +++ b/Kieker.WebGUI/src/main/java/kieker/webgui/converter/MIPortToStringConverter.java @@ -1,3 +1,22 @@ +/*************************************************************************** + * Copyright 2012 by + * + Christian-Albrechts-University of Kiel + * + Department of Computer Science + * + Software Engineering Group + * and others. + * + * 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.converter; import java.util.concurrent.ConcurrentHashMap; @@ -11,6 +30,7 @@ import kieker.analysis.model.analysisMetaModel.MIPort; /** * * @author Nils Christian Ehmke + * @version 1.0 */ @FacesConverter(value = MIPortToStringConverter.NAME) public class MIPortToStringConverter implements Converter { diff --git a/Kieker.WebGUI/src/main/webapp/WEB-INF/pretty-config.xml b/Kieker.WebGUI/src/main/webapp/WEB-INF/pretty-config.xml index 7cc7ba4aa99c4e21f5953a50e16bb6708547e91b..5d32888c9260b3866224eeace23bdcba3f171b3a 100644 --- a/Kieker.WebGUI/src/main/webapp/WEB-INF/pretty-config.xml +++ b/Kieker.WebGUI/src/main/webapp/WEB-INF/pretty-config.xml @@ -18,5 +18,10 @@ <pattern value="/Kieker.WebGUI/manageDependencies" /> <view-id value="/faces/manageDependencies.xhtml" /> </url-mapping> + + <url-mapping id="handleAnalysis"> + <pattern value="/Kieker.WebGUI/handleAnalysis" /> + <view-id value="/faces/handleAnalysis.xhtml" /> + </url-mapping> </pretty-config> \ No newline at end of file diff --git a/Kieker.WebGUI/src/main/webapp/handleAnalysis.css b/Kieker.WebGUI/src/main/webapp/handleAnalysis.css new file mode 100644 index 0000000000000000000000000000000000000000..4f9b12fd3116141d257c9ede86522175e40f977f --- /dev/null +++ b/Kieker.WebGUI/src/main/webapp/handleAnalysis.css @@ -0,0 +1,30 @@ +@charset "UTF-8"; + +.ui-button { + font-size: 15px; +} + +.fileinput-button { + font-size: 5px; +} + +.ui-layout-center { + font-size: 15px; +} + +.ui-layout-north { + font-size: 15px; +} + +.ui-layout-south { + font-size: 15px; +} + + +.ui-datatable { + font-size: 15px; +} + +.ui-panel { + font-size: 15px; +} \ No newline at end of file diff --git a/Kieker.WebGUI/src/main/webapp/handleAnalysis.xhtml b/Kieker.WebGUI/src/main/webapp/handleAnalysis.xhtml new file mode 100644 index 0000000000000000000000000000000000000000..0c2dad274941c6396e522607dffc7ac3783bc57e --- /dev/null +++ b/Kieker.WebGUI/src/main/webapp/handleAnalysis.xhtml @@ -0,0 +1,61 @@ +<?xml version='1.0' encoding='UTF-8' ?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" + xmlns:h="http://java.sun.com/jsf/html" + xmlns:f="http://java.sun.com/jsf/core" + xmlns:p="http://primefaces.org/ui" + xmlns:ui="http://java.sun.com/jsf/facelets" + xmlns:c="http://java.sun.com/jsp/jstl/core"> + + <f:view contentType="text/html"> + <h:head> + <title>Kieker.WebGUI - Analysis</title> + <link rel="stylesheet" type="text/css" href="../handleAnalysis.css" /> + </h:head> + + <h:body> + + <p:layout fullPage="true"> + <p:layoutUnit header="Navigation" position="north" collapsible="true" resizable="true"> + <!-- The control panel to get back. --> + <h:form> + Click + <h:link outcome="/main">here</h:link> + to get back to the main menu. + </h:form> + </p:layoutUnit> + + <p:layoutUnit position="center" > + <h:form id="centerForm"> + <ui:repeat id="centerRepeat" value="#{selectedProjectBean.selectedProject.plugins}" var="plugin"> + <p:panel header="#{plugin.name}" toggleSpeed="200" toggleable="true" id="plugin" style="width: 20%"> + <p:commandLink ajax="true" value="Show Data"/> + </p:panel> + <p:draggable for="plugin"> + </p:draggable> + </ui:repeat> + </h:form> + </p:layoutUnit> + + + <p:layoutUnit position="south" header="Analysis" resizable="true" collapsible="true"> + <h:form id="analysisForm"> + <p:commandButton value="Instantiate Analysis" action="#{analysisControllerBean.instantiate(selectedProjectBean.selectedProject)}" update=":analysisForm"/> + <p:commandButton value="Start Analysis" action="#{analysisControllerBean.controller.run()}" disabled="#{empty analysisControllerBean.controller}" update=":analysisForm"/> + <p:commandButton value="Stop Analysis" action="#{analysisControllerBean.controller.terminate()}" disabled="#{empty analysisControllerBean.controller}" update=":analysisForm"/> + <p:spacer height="0px" width="150px"/> + <c:choose> + <c:when test="#{empty analysisControllerBean.controller}"> + <h:outputText value="Analysis State: N/A"/> + </c:when> + <c:otherwise> + <h:outputText value="Analysis State: #{analysisControllerBean.controller.state}"/> + </c:otherwise> + </c:choose> + </h:form> + </p:layoutUnit> + </p:layout> + </h:body> + </f:view> + +</html> \ No newline at end of file diff --git a/Kieker.WebGUI/src/main/webapp/main.xhtml b/Kieker.WebGUI/src/main/webapp/main.xhtml index 27f6885b359101d0b22c161be96f43f70a7b8c06..b70c17e0c32670637de85ee70d34d6c0aa5ad72a 100644 --- a/Kieker.WebGUI/src/main/webapp/main.xhtml +++ b/Kieker.WebGUI/src/main/webapp/main.xhtml @@ -38,13 +38,13 @@ <p:menuitem value="Reset Project" ajax="true" onclick="resetProjectDialog.show()" /> <p:separator /> <p:menuitem value="Configure Dependencies" ajax="false" url="/Kieker.WebGUI/projectDependencies" /> + <p:separator /> + <p:menuitem value="Analysis" ajax="false" url="/Kieker.WebGUI/handleAnalysis" /> </p:submenu> <p:submenu label="Help"> <p:menuitem value="About..." ajax="true" onclick="aboutDialog.show()" /> </p:submenu> - - <p:menuitem value="Start/Stop Analysis"></p:menuitem> </p:menubar> </h:form> @@ -60,7 +60,7 @@ <p:ajax event="select" listener="#{selectedProjectBean.onNodeSelect}"/> <p:treeNode type="project"> - <h:outputText style="font-weight: #{selectedMainProjectBean.getFontWeight(node)}" value="#{node}"> + <h:outputText style="font-weight: #{selectedMainProjectBean.getFontWeight(node)}" value="#{node}"> <f:converter converterId="kieker.webgui.converter.MIProjectToStringConverter" /> </h:outputText> @@ -88,6 +88,8 @@ <p:menuitem value="Reset Project" ajax="true" onclick="resetProjectDialog.show()" /> <p:separator /> <p:menuitem value="Configure Dependencies" ajax="false" url="/Kieker.WebGUI/projectDependencies" /> + <p:separator /> + <p:menuitem value="Analysis" ajax="false" url="/Kieker.WebGUI/handleAnalysis" /> </p:contextMenu> <p:contextMenu for="projectsTree" nodeType="dependencies"> @@ -109,6 +111,8 @@ <p:commandLink ajax="true" value="Configure" action="#{selectedPluginBean.setPlugin(plugin)}" update=":propertiesForm"/> <br/> <p:commandLink ajax="true" value="Connect" update=":connectionDialogForm" onclick="connectionDialog.show();"/> + <br/> + <p:commandLink ajax="true" value="Rename"/> <p:ajax event="close" listener="#{selectedMainProjectBean.removePlugin(plugin)}" update=":centerForm"/> </p:panel> <p:draggable for="plugin"> @@ -189,7 +193,6 @@ <!-- Include the dialog to handle the connections. --> <ui:include src="main/connectionDialog.xhtml" /> - </h:body> </f:view> </html> \ No newline at end of file diff --git a/Kieker.WebGUI/src/main/webapp/main/connectionDialog.xhtml b/Kieker.WebGUI/src/main/webapp/main/connectionDialog.xhtml index 00356efc8fea1ad1038d93d012d5dd129fdbccb7..fcd75441db3c0ae55c6b6c30c6801272bfc44412 100644 --- a/Kieker.WebGUI/src/main/webapp/main/connectionDialog.xhtml +++ b/Kieker.WebGUI/src/main/webapp/main/connectionDialog.xhtml @@ -7,7 +7,6 @@ xmlns:c="http://java.sun.com/jsp/jstl/core"> <!-- ******************************************************************************** --> - <!-- This is the dialog for settings and properties. --> <p:dialog id="connectionDialog" header="Manage Connections" resizable="false" modal="true" widgetVar="connectionDialog"> <h:form id="connectionDialogForm">