Skip to content
Snippets Groups Projects
Commit 0c9c78a8 authored by Nils Christian Ehmke's avatar Nils Christian Ehmke
Browse files

Moved some code for the analysis controller into an ACManager; Analysis can now be controlled.

parent c1c95e9e
No related branches found
No related tags found
No related merge requests found
Showing with 535 additions and 36 deletions
......@@ -3,4 +3,5 @@
/build/
/dist/
/nbproject/private
/Kieker.WebGUI/target/
\ No newline at end of file
/Kieker.WebGUI/target/
/Kieker.WebGUI/data
\ No newline at end of file
......@@ -25,7 +25,6 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
......@@ -36,6 +35,7 @@ import javax.faces.context.FacesContext;
import kieker.analysis.AnalysisController;
import kieker.analysis.model.analysisMetaModel.MIProject;
import kieker.webgui.common.ACManager;
import kieker.webgui.common.FSManager;
import kieker.webgui.common.exception.ProjectAlreadyExistingException;
......@@ -54,10 +54,6 @@ public final class ProjectsBean {
* This is the list containing all projects.
*/
private final List<String> projects = Collections.synchronizedList(new ArrayList<String>());
/**
* This list contains the current analysis controllers. Not every project does have a controller, but every project can have maximal one.
*/
private final ConcurrentHashMap<String, AnalysisController> analysisController = new ConcurrentHashMap<String, AnalysisController>();
/**
* Creates a new instance of this class.
......@@ -140,17 +136,6 @@ public final class ProjectsBean {
return this.projects;
}
/**
* This method delivers the corresponding analysis controller of the given project.
*
* @param project
* The project whose analysis controller should be delivered.
* @return The corresponding instance of {@link AnalysisController} if it exists, null otherwise.
*/
public AnalysisController getAnalysisController(final String project) {
return this.analysisController.get(project);
}
/**
* This method can be used to deliver the state of the analysis controller of the given project as a human readable string.
*
......@@ -159,15 +144,7 @@ public final class ProjectsBean {
* @return The current state of the corresponding {@link AnalysisController} if it exists, 'N/A' otherwise.
*/
public String getAnalysisControllerState(final String project) {
final AnalysisController controller = this.analysisController.get(project);
final String controllerState;
if (controller == null) {
controllerState = "N/A";
} else {
controllerState = controller.getState().toString();
}
return controllerState;
return ACManager.getInstance().getAnalysisControllerStateString(project);
}
/**
......
......@@ -20,8 +20,21 @@
package kieker.webgui.beans.session;
import java.io.IOException;
import javax.faces.application.FacesMessage;
import javax.faces.application.FacesMessage.Severity;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import kieker.analysis.AnalysisController;
import kieker.analysis.exception.AnalysisConfigurationException;
import kieker.webgui.common.ACManager;
import kieker.webgui.common.exception.AnalysisNotInstantiatedException;
import kieker.webgui.common.exception.AnalysisNotRunningException;
import kieker.webgui.common.exception.ProjectAlreadyStartedException;
import kieker.webgui.common.exception.ProjectStillRunningException;
/**
* This bean contains the project of the current (session) user for the analysis controller page.
......@@ -85,4 +98,84 @@ public class CurrentAnalysisControllerProjectBean {
return CurrentAnalysisControllerProjectBean.PAGE_PROJECT_OVERVIEW;
}
/**
* This method starts the current analysis and informs the user about a fail.
*/
public void startAnalysis() {
try {
ACManager.getInstance().startAnalysisController(this.projectName);
} catch (final ProjectAlreadyStartedException ex) {
CurrentAnalysisControllerProjectBean.showMessage(FacesMessage.SEVERITY_WARN, "The analysis is already running.");
} catch (final AnalysisNotInstantiatedException ex) {
CurrentAnalysisControllerProjectBean.showMessage(FacesMessage.SEVERITY_WARN, "The analysis has not been instantiated yet.");
}
}
/**
* This method stops the current analysis and informs the user about a fail.
*/
public void stopAnalysis() {
try {
ACManager.getInstance().stopAnalysisController(this.projectName);
} catch (final AnalysisNotRunningException e) {
CurrentAnalysisControllerProjectBean.showMessage(FacesMessage.SEVERITY_WARN, "The analysis has not been started yet.");
} catch (final InterruptedException ex) {
ex.printStackTrace();
}
}
/**
* This method initializes the current analysis and informs the user about a fail.
*/
public void instantiateAnalysis() {
try {
ACManager.getInstance().instantiateAnalysisController(this.projectName);
} catch (final NullPointerException e) {
CurrentAnalysisControllerProjectBean.showMessage(FacesMessage.SEVERITY_ERROR, "An error occurred while instantiating the analysis.");
} catch (final AnalysisConfigurationException e) {
CurrentAnalysisControllerProjectBean.showMessage(FacesMessage.SEVERITY_ERROR, "An error occurred while instantiating the analysis.");
} catch (final IOException e) {
CurrentAnalysisControllerProjectBean.showMessage(FacesMessage.SEVERITY_ERROR, "An error occurred while instantiating the analysis.");
} catch (final ProjectStillRunningException e) {
CurrentAnalysisControllerProjectBean.showMessage(FacesMessage.SEVERITY_ERROR, "The analysis is still running.");
}
}
/**
* Checks whether the analysis is currently running.
*
* @return true if and only if the analysis is running.
*/
public boolean isAnalysisRunning() {
return ACManager.getInstance().getAnalysisControllerState(this.projectName) == AnalysisController.STATE.RUNNING;
}
public boolean isAnalysisReady() {
return ACManager.getInstance().getAnalysisControllerState(this.projectName) == AnalysisController.STATE.READY;
}
public boolean isAnalysisNotAvailable() {
return ACManager.getInstance().getAnalysisControllerState(this.projectName) == null;
}
public boolean isAnalysisTerminated() {
return ACManager.getInstance().getAnalysisControllerState(this.projectName) == AnalysisController.STATE.TERMINATED;
}
public boolean isAnalysisFailed() {
return ACManager.getInstance().getAnalysisControllerState(this.projectName) == AnalysisController.STATE.FAILED;
}
/**
* This method shows the current user a message by using the growl-component of PrimeFaces.
*
* @param severity
* The severity of the message.
* @param msg
* The message itself.
*/
private static void showMessage(final Severity severity, final String msg) {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(severity, "", msg));
}
}
/***************************************************************************
* 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.common;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import kieker.analysis.AnalysisController;
import kieker.analysis.AnalysisController.STATE;
import kieker.analysis.exception.AnalysisConfigurationException;
import kieker.analysis.model.analysisMetaModel.MIProject;
import kieker.webgui.common.exception.AnalysisNotInstantiatedException;
import kieker.webgui.common.exception.AnalysisNotRunningException;
import kieker.webgui.common.exception.ProjectAlreadyStartedException;
import kieker.webgui.common.exception.ProjectStillRunningException;
/**
* 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. This is also a singleton instance.
*
* @author Nils Christian Ehmke
* @version 1.0
*/
public class ACManager {
/**
* This is the maximal time the application will wait for an analysis thread to be terminated.
*/
private static final long MAX_THREAD_WAIT_TIME_MS = 1000;
/**
* This list contains the current analysis controllers and their corresponding threads. Not every project does have a controller, but every project can have
* maximal one.
*/
private final ConcurrentHashMap<String, Pair<AnalysisController, Thread>> analysisController = new ConcurrentHashMap<String, Pair<AnalysisController, Thread>>();
/**
* This is the singleton instance of this class.
*/
private static final ACManager INSTANCE = new ACManager();
/**
* Creates a new instance of this class.
*/
private ACManager() {
// No code necessary.
}
/**
* Delivers the singleton instance of this class.
*
* @return The only instance of {@link FSManager}.
*/
public static ACManager getInstance() {
return ACManager.INSTANCE;
}
/**
* This method tries to stop a running analysis.
*
* @param project
* The project to be stopped.
* @throws AnalysisNotRunningException
* If the analysis is not running or has not yet been initialized.
* @throws InterruptedException
* If the current thread has somehow been interrupted while waiting for the existing analysis thread.
*/
public void stopAnalysisController(final String project) throws AnalysisNotRunningException, InterruptedException {
final Pair<AnalysisController, Thread> currController = this.analysisController.get(project);
synchronized (currController) {
// Is there a thread available?
if ((currController.getFst() == null) || (currController.getSnd() == null)) {
throw new AnalysisNotRunningException();
}
// Try to stop the analysis
currController.getFst().terminate();
currController.getSnd().join(ACManager.MAX_THREAD_WAIT_TIME_MS);
}
}
/**
* This method tries to start the analysis for the given project. It has already to be initialized.
*
* @param project
* The project to be started.
* @throws ProjectAlreadyStartedException
* If the project is already running.
* @throws AnalysisNotInstantiatedException
* If the analysis has not yet been initialized.
*/
public void startAnalysisController(final String project) throws ProjectAlreadyStartedException, AnalysisNotInstantiatedException {
final Pair<AnalysisController, Thread> currController = this.analysisController.get(project);
synchronized (currController) {
// Is there an analysis after all?
if (currController.getFst() == null) {
throw new AnalysisNotInstantiatedException();
}
// Check whether this analysis has already been started.
if (currController.getSnd() != null) {
throw new ProjectAlreadyStartedException();
} else {
// Otherwise start a thread and run the analysis in it.
currController.setSnd(new Thread() {
@Override
public void run() {
try {
currController.getFst().run();
} catch (final IllegalStateException ex) {
ex.printStackTrace();
} catch (final AnalysisConfigurationException ex) {
ex.printStackTrace();
}
}
});
currController.getSnd().start();
}
}
}
/**
* This method tries to instantiate the analysis controller of the given project using the data available on the file system.
*
* @param project
* The project whose analysis controller should be instantiated.
* @throws NullPointerException
* If an error occurred while loading the project.
* @throws AnalysisConfigurationException
* If the given configuration is somehow invalid.
* @throws IOException
* If an error occurred while loading the project.
* @throws ProjectStillRunningException
* If there exists already an analysis controller and is still running.
*/
public void instantiateAnalysisController(final String project) throws NullPointerException, AnalysisConfigurationException, IOException,
ProjectStillRunningException {
// Add the potential new project atomically
final MIProject modelProject = FSManager.getInstance().openProject(project);
final ClassLoader classLoader = FSManager.getInstance().getClassLoader(project);
final Pair<AnalysisController, Thread> newController = new Pair<AnalysisController, Thread>(new AnalysisController(modelProject, classLoader), null);
final Pair<AnalysisController, Thread> currController = this.analysisController.putIfAbsent(project, newController);
if (currController != null) {
// There is currently an analysis controller available. Decide what to do.
synchronized (currController) {
switch (currController.getFst().getState()) {
case FAILED:
case TERMINATED:
case READY:
// No problem in instantiating a new controller
this.analysisController.put(project, newController);
break;
case RUNNING:
throw new ProjectStillRunningException("The project with the name '" + project + "' is still running.");
}
}
}
}
/**
* This method can be used to deliver the state of the analysis controller of the given project as a human readable string.
*
* @param project
* The project whose state should be delivered.
* @return The current state of the corresponding {@link AnalysisController} if it exists, 'N/A' otherwise.
*/
public String getAnalysisControllerStateString(final String project) {
final STATE controllerState = this.getAnalysisControllerState(project);
final String controllerStateString;
if (controllerState == null) {
controllerStateString = "N/A";
} else {
controllerStateString = controllerState.toString();
}
return controllerStateString;
}
/**
* This method can be used to deliver the state of the analysis controller of the given project as a human readable string.
*
* @param project
* The project whose state should be delivered.
* @return The current state of the corresponding {@link AnalysisController} if it exists, 'N/A' otherwise.
*/
public STATE getAnalysisControllerState(final String project) {
final Pair<AnalysisController, Thread> controller = this.analysisController.get(project);
final STATE controllerState;
if (controller == null) {
controllerState = null;
} else {
synchronized (controller) {
if (controller.getFst() == null) {
controllerState = null;
} else {
controllerState = controller.getFst().getState();
}
}
}
return controllerState;
}
}
/***************************************************************************
* 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.common.exception;
/**
* This exception shows that the analysis has not yet been instantiated.
*
* @author Nils Christian Ehmke
* @version 1.0
*/
public class AnalysisNotInstantiatedException extends Exception {
private static final long serialVersionUID = 1L;
/**
* Creates a new instance of this class.
*/
public AnalysisNotInstantiatedException() {
// No code necessary
}
/**
* Creates a new instance of this class using the given parameters.
*
* @param msg
* The message used for the exception.
*/
public AnalysisNotInstantiatedException(final String msg) {
super(msg);
}
}
/***************************************************************************
* 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.common.exception;
/**
* This exception shows that the analysis has not yet been instantiated.
*
* @author Nils Christian Ehmke
* @version 1.0
*/
public class AnalysisNotRunningException extends Exception {
private static final long serialVersionUID = 1L;
/**
* Creates a new instance of this class.
*/
public AnalysisNotRunningException() {
// No code necessary
}
/**
* Creates a new instance of this class using the given parameters.
*
* @param msg
* The message used for the exception.
*/
public AnalysisNotRunningException(final String msg) {
super(msg);
}
}
/***************************************************************************
* 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.common.exception;
/**
* This exception shows that the given project has already been started.
*
* @author Nils Christian Ehmke
* @version 1.0
*/
public class ProjectAlreadyStartedException extends Exception {
private static final long serialVersionUID = 1L;
/**
* Creates a new instance of this class.
*/
public ProjectAlreadyStartedException() {
// No code necessary
}
/**
* Creates a new instance of this class using the given parameters.
*
* @param msg
* The message used for the exception.
*/
public ProjectAlreadyStartedException(final String msg) {
super(msg);
}
}
/***************************************************************************
* 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.common.exception;
/**
* This exception shows that the project is still running.
*
* @author Nils Christian Ehmke
* @version 1.0
*/
public class ProjectStillRunningException extends Exception {
private static final long serialVersionUID = 1L;
/**
* Creates a new instance of this class.
*/
public ProjectStillRunningException() {
// No code necessary
}
/**
* Creates a new instance of this class using the given parameters.
*
* @param msg
* The message used for the exception.
*/
public ProjectStillRunningException(final String msg) {
super(msg);
}
}
......@@ -44,25 +44,36 @@
</p:layoutUnit>
<p:layoutUnit position="south" header="Control" resizable="true" collapsible="true">
<h:form>
<p:commandButton value="Instantiate Analysis Controller" disabled="#{empty currentAnalysisControllerProjectBean.projectName}"/>
<p:commandButton value="Start Analysis" disabled="true"/>
<p:commandButton value="Stop Analysis" disabled="true"/>
<hr/>
<h:form id="controllerForm">
<p:commandButton value="Instantiate Analysis Controller" action="#{currentAnalysisControllerProjectBean.instantiateAnalysis()}" update=":messages" disabled="#{empty currentAnalysisControllerProjectBean.projectName}"/>
<p:commandButton value="Start Analysis" action="#{currentAnalysisControllerProjectBean.startAnalysis()}" update=":messages" disabled="#{empty currentAnalysisControllerProjectBean.projectName}"/>
<p:commandButton value="Stop Analysis" action="#{currentAnalysisControllerProjectBean.stopAnalysis()}" update=":messages" disabled="#{empty currentAnalysisControllerProjectBean.projectName}"/>
</h:form>
<hr/>
<h:form id="ledsForm">
<div align="center">
<h:graphicImage id="iconLEDRed1" url="../img/Icon_LED_Red.png" height="50px"/>
<h:graphicImage id="iconLEDRed1" url="../img/Icon_LED_Red.png" height="50px" rendered="#{currentAnalysisControllerProjectBean.isAnalysisNotAvailable()}"/>
<h:graphicImage id="iconLEDRed1_2" url="../img/Icon_LED_Gray.png" height="50px" rendered="#{not currentAnalysisControllerProjectBean.isAnalysisNotAvailable()}"/>
<p:spacer height="0" width="15px"/>
<h:graphicImage id="iconLEDYellow" url="../img/Icon_LED_Gray.png" height="50px"/>
<h:graphicImage id="iconLEDYellow" url="../img/Icon_LED_Yellow.png" height="50px" rendered="#{currentAnalysisControllerProjectBean.isAnalysisReady()}"/>
<h:graphicImage id="iconLEDYellow_2" url="../img/Icon_LED_Gray.png" height="50px" rendered="#{not currentAnalysisControllerProjectBean.isAnalysisReady()}"/>
<p:spacer height="0" width="15px"/>
<h:graphicImage id="iconLEDGreen" url="../img/Icon_LED_Gray.png" height="50px"/>
<h:graphicImage id="iconLEDGreen" url="../img/Icon_LED_Green.png" height="50px" rendered="#{currentAnalysisControllerProjectBean.isAnalysisRunning()}"/>
<h:graphicImage id="iconLEDGreen_2" url="../img/Icon_LED_Gray.png" height="50px" rendered="#{not currentAnalysisControllerProjectBean.isAnalysisRunning()}"/>
<p:spacer height="0" width="15px"/>
<h:graphicImage id="iconLEDRed2" url="../img/Icon_LED_Gray.png" height="50px"/>
<h:graphicImage id="iconLEDRed2" url="../img/Icon_LED_Red.png" height="50px" rendered="#{currentAnalysisControllerProjectBean.isAnalysisTerminated() or currentAnalysisControllerProjectBean.isAnalysisFailed()}"/>
<h:graphicImage id="iconLEDRed2_2" url="../img/Icon_LED_Gray.png" height="50px" rendered="#{not (currentAnalysisControllerProjectBean.isAnalysisTerminated() or currentAnalysisControllerProjectBean.isAnalysisFailed())}"/>
<p:tooltip for="iconLEDRed1" value="Indicates that the AnalysisController has not been instantiated yet."/>
<p:tooltip for="iconLEDYellow" value="Indicates that the AnalysisController has been instantiated, but not yet started."/>
<p:tooltip for="iconLEDGreen" value="Indicates that the AnalysisController has been started and is running."/>
<p:tooltip for="iconLEDRed2" value="Indicates that the AnalysisController has been terminated."/>
<p:tooltip for="iconLEDRed2" value="Indicates that the AnalysisController has been terminated or has failed."/>
<p:tooltip for="iconLEDRed1_2" value="Indicates that the AnalysisController has not been instantiated yet."/>
<p:tooltip for="iconLEDYellow_2" value="Indicates that the AnalysisController has been instantiated, but not yet started."/>
<p:tooltip for="iconLEDGreen_2" value="Indicates that the AnalysisController has been started and is running."/>
<p:tooltip for="iconLEDRed2_2" value="Indicates that the AnalysisController has been terminated or has failed."/>
</div>
<p:poll interval="1" update="ledsForm"/>
</h:form>
</p:layoutUnit>
</p:layout>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment