From e29c593432dcf64760cd259264604dc290695c99 Mon Sep 17 00:00:00 2001
From: Nils Christian Ehmke <nie@informatik.uni-kiel.de>
Date: Sat, 13 Oct 2012 12:17:21 +0200
Subject: [PATCH] The AnalysisController Log will now be intercepted.

---
 .../beans/view/CurrentControllerBean.java     | 11 +++++-
 .../common/ClassAndMethodContainer.java       | 16 +++++++++
 .../common/EnvironmentLoaderListener.java     | 35 +++++++++++++++++++
 .../webgui/common/IProjectManagerFacade.java  |  1 +
 .../webgui/common/ProjectManagerFacade.java   |  9 +++++
 .../kieker/webgui/common/util/ACManager.java  |  8 +++++
 .../kieker/webgui/common/util/Analysis.java   |  8 ++++-
 .../lang/ControllerPage_de.properties         |  7 +++-
 .../lang/ControllerPage_en.properties         |  7 +++-
 .../src/main/webapp/ControllerPage.xhtml      | 33 +++++++++++------
 Kieker.WebGUI/src/main/webapp/WEB-INF/web.xml |  3 ++
 11 files changed, 123 insertions(+), 15 deletions(-)
 create mode 100644 Kieker.WebGUI/src/main/java/kieker/webgui/common/EnvironmentLoaderListener.java

diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/beans/view/CurrentControllerBean.java b/Kieker.WebGUI/src/main/java/kieker/webgui/beans/view/CurrentControllerBean.java
index a49b12e0..c115ae78 100644
--- a/Kieker.WebGUI/src/main/java/kieker/webgui/beans/view/CurrentControllerBean.java
+++ b/Kieker.WebGUI/src/main/java/kieker/webgui/beans/view/CurrentControllerBean.java
@@ -292,7 +292,16 @@ public final class CurrentControllerBean {
 	 * 
 	 * @return The current log entries.
 	 */
-	public Collection<String> getLog() {
+	public Object[] getAnalysisLog() {
+		try {
+			return this.projectManagerFacade.getLogEntries(this.projectName);
+		} catch (final AnalysisStateException ex) {
+			// Ignore
+			return new Object[0];
+		}
+	}
+
+	public Collection<String> getViewLog() {
 		return this.logEntries;
 	}
 
diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/common/ClassAndMethodContainer.java b/Kieker.WebGUI/src/main/java/kieker/webgui/common/ClassAndMethodContainer.java
index 2097e237..267dd7f7 100644
--- a/Kieker.WebGUI/src/main/java/kieker/webgui/common/ClassAndMethodContainer.java
+++ b/Kieker.WebGUI/src/main/java/kieker/webgui/common/ClassAndMethodContainer.java
@@ -41,6 +41,7 @@ import kieker.analysis.repository.AbstractRepository;
 import kieker.analysis.repository.annotation.Repository;
 import kieker.common.logging.Log;
 import kieker.common.logging.LogFactory;
+import kieker.common.logging.LogImplWebguiLogging;
 import kieker.webgui.common.exception.ProjectLoadException;
 
 /**
@@ -63,6 +64,7 @@ public final class ClassAndMethodContainer {
 	 */
 	private static final String MSG_LOAD_EXCEPTION = "An error occured while loading the classes and methods.";
 
+	private final Class<?> logImplWebguiLoggingClass;
 	/**
 	 * This is the class equivalence of {@link AnalysisControllerWithMapping}.
 	 */
@@ -224,6 +226,8 @@ public final class ClassAndMethodContainer {
 	private final Method repositoryDependenciesMethod;
 	private final Method pluginProgrammaticOnlyMethod;
 	private final Method repositoryProgrammaticOnlyMethod;
+	private final Method logImplWebguiLoggingClassGetEntriesMethod;
+
 	/**
 	 * This is the constructor for {@link AnalysisControllerThread}, which gets an instance of {@link AnalysisController}.
 	 */
@@ -240,6 +244,8 @@ public final class ClassAndMethodContainer {
 	@SuppressWarnings("unchecked")
 	public ClassAndMethodContainer(final ClassLoader classLoader) throws ProjectLoadException {
 		try {
+			this.logImplWebguiLoggingClass = classLoader.loadClass(LogImplWebguiLogging.class.getName());
+
 			this.analysisControllerWithMappingClass = classLoader.loadClass(AnalysisControllerWithMapping.class.getName());
 
 			this.analysisControllerClass = classLoader.loadClass(AnalysisController.class.getName());
@@ -284,6 +290,8 @@ public final class ClassAndMethodContainer {
 			this.repositoryDependenciesMethod = this.repositoryAnnotationClass.getMethod("dependencies", new Class<?>[0]);
 			this.pluginProgrammaticOnlyMethod = this.pluginAnnotationClass.getMethod("programmaticOnly", new Class<?>[0]);
 			this.repositoryProgrammaticOnlyMethod = this.repositoryAnnotationClass.getMethod("programmaticOnly", new Class<?>[0]);
+			this.logImplWebguiLoggingClassGetEntriesMethod = this.logImplWebguiLoggingClass.getMethod("getEntries", String.class);
+
 			// This is a special case as we need to load some additional classes to search for the correct method
 			final Class<?> miProjectClass = classLoader.loadClass(MIProject.class.getName());
 			this.analysisControllerLoadFromFile = this.analysisControllerClass.getMethod("loadFromFile", File.class);
@@ -711,6 +719,14 @@ public final class ClassAndMethodContainer {
 		return this.repositoryProgrammaticOnlyMethod;
 	}
 
+	public Class<?> getLogImplWebguiLoggingClass() {
+		return this.logImplWebguiLoggingClass;
+	}
+
+	public Method getLogImplWebguiLoggingClassGetEntriesMethod() {
+		return this.logImplWebguiLoggingClassGetEntriesMethod;
+	}
+
 	/**
 	 * This method can be used to invoke a given method with given parameters, without having to mind about the exceptions. If an exception occurs, the given default
 	 * value will be returned.
diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/common/EnvironmentLoaderListener.java b/Kieker.WebGUI/src/main/java/kieker/webgui/common/EnvironmentLoaderListener.java
new file mode 100644
index 00000000..e80a1126
--- /dev/null
+++ b/Kieker.WebGUI/src/main/java/kieker/webgui/common/EnvironmentLoaderListener.java
@@ -0,0 +1,35 @@
+/***************************************************************************
+ * Copyright 2012 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.common;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+
+public class EnvironmentLoaderListener implements ServletContextListener {
+
+	@Override
+	public void contextDestroyed(final ServletContextEvent event) {
+		// No code necessary
+	}
+
+	@Override
+	public void contextInitialized(final ServletContextEvent event) {
+		// Set the system property to make sure that the webgui logger will be used
+		System.setProperty("kieker.common.logging.Log", "WEBGUI");
+	}
+
+}
diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/common/IProjectManagerFacade.java b/Kieker.WebGUI/src/main/java/kieker/webgui/common/IProjectManagerFacade.java
index 99b7d621..ea8c5fac 100644
--- a/Kieker.WebGUI/src/main/java/kieker/webgui/common/IProjectManagerFacade.java
+++ b/Kieker.WebGUI/src/main/java/kieker/webgui/common/IProjectManagerFacade.java
@@ -336,4 +336,5 @@ public interface IProjectManagerFacade {
 	 */
 	public STATE getCurrentState(final String projectName) throws ProjectNotExistingException;
 
+	public Object[] getLogEntries(final String projectName) throws AnalysisStateException;
 }
diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/common/ProjectManagerFacade.java b/Kieker.WebGUI/src/main/java/kieker/webgui/common/ProjectManagerFacade.java
index 13d3bb9a..c9e22cf7 100644
--- a/Kieker.WebGUI/src/main/java/kieker/webgui/common/ProjectManagerFacade.java
+++ b/Kieker.WebGUI/src/main/java/kieker/webgui/common/ProjectManagerFacade.java
@@ -309,4 +309,13 @@ public final class ProjectManagerFacade implements IProjectManagerFacade {
 
 		return lock;
 	}
+
+	@Override
+	public Object[] getLogEntries(final String projectName) throws AnalysisStateException {
+		final Object analysisLock = this.getLock(projectName, this.analysesLocks);
+
+		synchronized (analysisLock) {
+			return ACManager.getInstance().getLogEntries(projectName);
+		}
+	}
 }
diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/common/util/ACManager.java b/Kieker.WebGUI/src/main/java/kieker/webgui/common/util/ACManager.java
index adca14b7..469c7ade 100644
--- a/Kieker.WebGUI/src/main/java/kieker/webgui/common/util/ACManager.java
+++ b/Kieker.WebGUI/src/main/java/kieker/webgui/common/util/ACManager.java
@@ -148,6 +148,14 @@ public final class ACManager {
 		analysis.stop();
 	}
 
+	public Object[] getLogEntries(final String projectName) throws AnalysisStateException {
+		// The analysis for the given project must exist!
+		if (!this.analyses.containsKey(projectName)) {
+			throw new AnalysisStateException("The analysis has not been initialized yet.");
+		}
+		return this.analyses.get(projectName).getLogEntries();
+	}
+
 	/**
 	 * This method delivers the display object of the (currently running) analysis for the given project and the given parameters. Technically it is an instance of
 	 * {@code AbstractDisplay}, but in fact the project specific class loader has been used.
diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/common/util/Analysis.java b/Kieker.WebGUI/src/main/java/kieker/webgui/common/util/Analysis.java
index 37a97b1d..91302501 100644
--- a/Kieker.WebGUI/src/main/java/kieker/webgui/common/util/Analysis.java
+++ b/Kieker.WebGUI/src/main/java/kieker/webgui/common/util/Analysis.java
@@ -24,6 +24,7 @@ import java.util.concurrent.ConcurrentHashMap;
 
 import javax.annotation.PostConstruct;
 
+import kieker.analysis.AnalysisController;
 import kieker.common.logging.Log;
 import kieker.common.logging.LogFactory;
 import kieker.webgui.common.ClassAndMethodContainer;
@@ -154,6 +155,11 @@ public final class Analysis {
 		return this.updateDisplaysThread.getDisplay(viewName, displayName);
 	}
 
+	public Object[] getLogEntries() {
+		return (Object[]) ClassAndMethodContainer.invokeClassMethod(Analysis.this.classAndMethodContainer.getLogImplWebguiLoggingClassGetEntriesMethod(), null,
+				AnalysisController.class.getName());
+	}
+
 	/**
 	 * This manager is responsible for the currently used and running instances of {@code AnalysisController}. It supplies methods to check the states of analysis,
 	 * instantiate, start and to stop them.
@@ -161,7 +167,7 @@ public final class Analysis {
 	 * @author Nils Christian Ehmke
 	 * @version 1.0
 	 */
-	private static class UpdateDisplaysThread extends Thread {
+	private class UpdateDisplaysThread extends Thread {
 
 		private static final long SLEEP_TIME_MS = 2 * 1000;
 		// private final Object pluginMap;
diff --git a/Kieker.WebGUI/src/main/resources/lang/ControllerPage_de.properties b/Kieker.WebGUI/src/main/resources/lang/ControllerPage_de.properties
index 1fbc8559..cec041b9 100644
--- a/Kieker.WebGUI/src/main/resources/lang/ControllerPage_de.properties
+++ b/Kieker.WebGUI/src/main/resources/lang/ControllerPage_de.properties
@@ -13,4 +13,9 @@ analysisControllerStopAnalysis = Analyse Stoppen
 analysisControllerMsgNotInstantiated = Zeigt an, dass der AnalysisController noch nicht instanziiert wurde.
 analysisControllerMsgReady = Zeigt an, dass der AnalysisController zwar instanziiert, jedoch noch nicht gestartet wurde.
 analysisControllerMsgRunning = Zeigt an, dass der AnalysisController gestartet wurde und zur Zeit läuft.
-analysisControllerMsgFailed = Zeigt an, dass der AnalysisController terminiert oder abgestürzt ist.
\ No newline at end of file
+analysisControllerMsgFailed = Zeigt an, dass der AnalysisController terminiert oder abgestürzt ist.
+
+control = Steuerung
+
+analysisControllerLog = AnalysisController Log
+personalLog = Persönlicher Log
\ No newline at end of file
diff --git a/Kieker.WebGUI/src/main/resources/lang/ControllerPage_en.properties b/Kieker.WebGUI/src/main/resources/lang/ControllerPage_en.properties
index 589350fa..30bb7489 100644
--- a/Kieker.WebGUI/src/main/resources/lang/ControllerPage_en.properties
+++ b/Kieker.WebGUI/src/main/resources/lang/ControllerPage_en.properties
@@ -13,4 +13,9 @@ analysisControllerStopAnalysis = Stop Analysis
 analysisControllerMsgNotInstantiated = Indicates that the AnalysisController has not been instantiated yet.
 analysisControllerMsgReady = Indicates that the AnalysisController has been instantiated, but not yet started.
 analysisControllerMsgRunning = Indicates that the AnalysisController has been started and is running.
-analysisControllerMsgFailed = Indicates that the AnalysisController has been terminated or has failed.
\ No newline at end of file
+analysisControllerMsgFailed = Indicates that the AnalysisController has been terminated or has failed.
+
+control = Control
+
+analysisControllerLog = AnalysisController Log
+personalLog = Personal Log
\ No newline at end of file
diff --git a/Kieker.WebGUI/src/main/webapp/ControllerPage.xhtml b/Kieker.WebGUI/src/main/webapp/ControllerPage.xhtml
index ac4df2f6..80bb8248 100644
--- a/Kieker.WebGUI/src/main/webapp/ControllerPage.xhtml
+++ b/Kieker.WebGUI/src/main/webapp/ControllerPage.xhtml
@@ -68,20 +68,31 @@
 
 
             <p:layoutUnit position="center" id="centerLayout">
-                <h:form id="logList"> 
-                    <ui:repeat  value="#{currentControllerBean.log}" var="entry">
-                        <h:outputText value="#{entry}"/><br/><br/>
-                    </ui:repeat> 
-                </h:form>
+                <p:tabView id="tabView" style="height: 99%"> 
+                    <p:tab title="#{localizedControllerPageMessages.personalLog}">
+                        <h:form id="currentViewLog">
+                            <ui:repeat value="#{currentControllerBean.viewLog}" var="entry" varStatus="stat">
+                                <h:outputText value="#{entry}"/><ui:fragment rendered="#{not stat.last}"><br/><br/></ui:fragment>
+                            </ui:repeat> 
+                        </h:form>
+                    </p:tab>
+                    <p:tab title="#{localizedControllerPageMessages.analysisControllerLog}">
+                        <h:form  id="analysisControllerLog">
+                            <ui:repeat value="#{currentControllerBean.analysisLog}" var="entry" varStatus="stat">
+                                <h:outputText value="#{entry}"/><ui:fragment rendered="#{not stat.last}"><br/><br/></ui:fragment>
+                            </ui:repeat> 
+                        </h:form>
+                    </p:tab>
+                </p:tabView>
             </p:layoutUnit>
 
-            <p:layoutUnit position="south" header="Control" resizable="true" collapsible="true">
+            <p:layoutUnit position="south" header="#{localizedControllerPageMessages.control}" resizable="true" collapsible="true">
                 <h:form id="controllerForm">
-                    <p:commandButton value="#{localizedControllerPageMessages.analysisControllerInstantiateAnalysisController}" action="#{currentControllerBean.instantiateAnalysis()}" update=":messages :logList" disabled="#{empty currentControllerBean.projectName}"/>
-                    <p:commandButton value="#{localizedControllerPageMessages.analysisControllerCleaAnalysisController}" action="#{currentControllerBean.cleanAnalysis()}"  update=":messages :logList" disabled="#{empty currentControllerBean.projectName}"/>
-                    <p:commandButton value="#{localizedControllerPageMessages.analysisControllerStartAnalysis}" action="#{currentControllerBean.startAnalysis()}"  update=":messages :logList" disabled="#{empty currentControllerBean.projectName}"/>
-                    <p:commandButton value="#{localizedControllerPageMessages.analysisControllerStopAnalysis}" action="#{currentControllerBean.stopAnalysis()}"  update=":messages :logList" disabled="#{empty currentControllerBean.projectName}"/>
-                    <p:poll interval="1" update=":ledsForm"/>
+                    <p:commandButton value="#{localizedControllerPageMessages.analysisControllerInstantiateAnalysisController}" action="#{currentControllerBean.instantiateAnalysis()}" update=":messages :tabView:currentViewLog" disabled="#{empty currentControllerBean.projectName}"/>
+                    <p:commandButton value="#{localizedControllerPageMessages.analysisControllerCleaAnalysisController}" action="#{currentControllerBean.cleanAnalysis()}"  update=":messages :tabView:currentViewLog" disabled="#{empty currentControllerBean.projectName}"/>
+                    <p:commandButton value="#{localizedControllerPageMessages.analysisControllerStartAnalysis}" action="#{currentControllerBean.startAnalysis()}"  update=":messages :tabView:currentViewLog" disabled="#{empty currentControllerBean.projectName}"/>
+                    <p:commandButton value="#{localizedControllerPageMessages.analysisControllerStopAnalysis}" action="#{currentControllerBean.stopAnalysis()}"  update=":messages :tabView:currentViewLog" disabled="#{empty currentControllerBean.projectName}"/>
+                    <p:poll interval="1" update=":ledsForm :tabView:analysisControllerLog"/>
                 </h:form>  
                 <hr/>
                 <h:form id="ledsForm">
diff --git a/Kieker.WebGUI/src/main/webapp/WEB-INF/web.xml b/Kieker.WebGUI/src/main/webapp/WEB-INF/web.xml
index 57f2cbab..f296c05d 100644
--- a/Kieker.WebGUI/src/main/webapp/WEB-INF/web.xml
+++ b/Kieker.WebGUI/src/main/webapp/WEB-INF/web.xml
@@ -92,4 +92,7 @@
         <dispatcher>ERROR</dispatcher>
     </filter-mapping>
     
+    <listener>
+        <listener-class>kieker.webgui.common.EnvironmentLoaderListener</listener-class>
+    </listener>
 </web-app>
-- 
GitLab