From 76a22777d27aa841c61bf73e419f018a506781ee Mon Sep 17 00:00:00 2001 From: Nils Christian Ehmke <nie@informatik.uni-kiel.de> Date: Fri, 24 May 2013 14:13:16 +0200 Subject: [PATCH] Refactoring --- .../webgui/persistence/IProjectDAO.java | 4 +- .../persistence/impl/FSProjectDAOImpl.java | 158 +++--------- .../webgui/service/IProjectService.java | 14 +- .../service/impl/ProjectServiceImpl.java | 225 +++++------------- .../webgui/service/impl/util/ACManager.java | 57 ++--- .../webgui/service/impl/util/Analysis.java | 7 +- .../beans/view/CurrentAnalysisEditorBean.java | 6 +- .../web/beans/view/CurrentCockpitBean.java | 11 +- .../impl/GraphLayoutServiceImplTest.java | 3 +- 9 files changed, 151 insertions(+), 334 deletions(-) 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 34a9e927..f989f310 100644 --- a/Kieker.WebGUI/src/main/java/kieker/webgui/persistence/IProjectDAO.java +++ b/Kieker.WebGUI/src/main/java/kieker/webgui/persistence/IProjectDAO.java @@ -271,9 +271,11 @@ public interface IProjectDAO { * * @throws IOException * If something went wrong during the reloading of the components. + * @throws ProjectNotExistingException + * If a project with the given name does not exist. */ @PreAuthorize("hasAnyRole('User', 'Administrator')") - public abstract boolean deleteLibrary(String projectName, String libName) throws IOException; + public abstract boolean deleteLibrary(String projectName, String libName) throws IOException, ProjectNotExistingException; /** * Delivers the available components (readers, filters and repositories) for the given project. 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 3663716f..5fa99105 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 @@ -86,11 +86,14 @@ public class FSProjectDAOImpl implements IProjectDAO, ReleaseListener { private static final Log LOG = LogFactory.getLog(FSProjectDAOImpl.class); - private static final MIAnalysisMetaModelFactory FACTORY = MIAnalysisMetaModelFactory.eINSTANCE; + private static final MIProject EMPTY_PROJECT = MIAnalysisMetaModelFactory.eINSTANCE.createProject(); + private static final String KIEKER_LIB = "kieker.jar"; private static final String META_FILE = "meta.dat"; + private static final String KAX_EXTENSION = "kax"; private static final String LIB_EXTENSION = "jar"; + private static final String LIB_DIRECTORY = "lib"; private static final String ROOT_DIRECTORY = "data"; @@ -124,7 +127,7 @@ public class FSProjectDAOImpl implements IProjectDAO, ReleaseListener { @PostConstruct public void initialize() throws IOException { // Make sure that the necessary directories exist and that the available component lists (containing plugins and repositories) are initialized. - FSProjectDAOImpl.createDirectoryIfNecessary(FSProjectDAOImpl.ROOT_DIRECTORY); + FSProjectDAOImpl.createDirectoryIfNecessary(ROOT_DIRECTORY); this.initializeAvailableComponentsListContainersForAllProjects(); } @@ -135,27 +138,27 @@ public class FSProjectDAOImpl implements IProjectDAO, ReleaseListener { @Override public String getAnalysisLayout(final String projectName) { - return FSProjectDAOImpl.getProperty(projectName, FSProjectDAOImpl.PROPERTY_KEY_ANALYSIS_LAYOUT, null); + return FSProjectDAOImpl.getProperty(projectName, PROPERTY_KEY_ANALYSIS_LAYOUT, null); } @Override public String getCockpitLayout(final String projectName) { - return FSProjectDAOImpl.getProperty(projectName, FSProjectDAOImpl.PROPERTY_KEY_COCKPIT_LAYOUT, null); + return FSProjectDAOImpl.getProperty(projectName, PROPERTY_KEY_COCKPIT_LAYOUT, null); } @Override public String getOwner(final String projectName) { - return FSProjectDAOImpl.getProperty(projectName, FSProjectDAOImpl.PROPERTY_KEY_OWNER, "N/A"); + return FSProjectDAOImpl.getProperty(projectName, PROPERTY_KEY_OWNER, "N/A"); } @Override public String getLastUser(final String projectName) { - return FSProjectDAOImpl.getProperty(projectName, FSProjectDAOImpl.PROPERTY_KEY_LAST_USER, "N/A"); + return FSProjectDAOImpl.getProperty(projectName, PROPERTY_KEY_LAST_USER, "N/A"); } @Override public void removeProject(final String projectName) throws IOException, ProjectNotExistingException { - this.checkProjectExistence(projectName); + this.assertProjectExistence(projectName); // Simply try to remove the project directory final File projectDir = FSProjectDAOImpl.assembleProjectDir(projectName); @@ -168,46 +171,35 @@ public class FSProjectDAOImpl implements IProjectDAO, ReleaseListener { @Override public void addProject(final String projectName, final String username) throws ProjectAlreadyExistingException, IOException { + this.assertProjectAbsence(projectName); + // Assemble all necessary paths and files for the given project final File projectDir = FSProjectDAOImpl.assembleProjectDir(projectName); final File projectFile = FSProjectDAOImpl.assembleKaxFile(projectName); final File metaFile = FSProjectDAOImpl.assembleMetaFile(projectName); final File libDir = this.assembleLibDir(projectName); - // We need an "empty" project in order to save it. - final MIProject emptyProject = FACTORY.createProject(); - - // Make sure that the project doesn't exist already - if (projectDir.exists()) { - throw new ProjectAlreadyExistingException("The project with the name '" + projectName + "' exists already."); - } - try { // Try to create the directories and files if (projectDir.mkdir() && libDir.mkdir() && metaFile.createNewFile()) { // Try to save the file - AnalysisController.saveToFile(projectFile, emptyProject); + AnalysisController.saveToFile(projectFile, EMPTY_PROJECT); this.initializeAvailableComponentsListContainers(projectName); // Store the initial meta data final Properties properties = new Properties(); - properties.put(FSProjectDAOImpl.PROPERTY_KEY_OWNER, username); - properties.put(FSProjectDAOImpl.PROPERTY_KEY_LAST_USER, username); + properties.put(PROPERTY_KEY_OWNER, username); + properties.put(PROPERTY_KEY_LAST_USER, username); FSProjectDAOImpl.savePropertiesFile(properties, projectName); } else { - // The directories could not be created throw new IOException("Project-Directories could not be created."); } } catch (final IOException ex) { // Something went wrong. Remove the directories and files! - final boolean libDirDeleted = libDir.delete(); + libDir.delete(); // Keep in mind that the potential remains of the file have to be deleted before the directory. - final boolean projectFileDeleted = projectFile.delete(); - final boolean projectDeleted = projectDir.delete(); - - // The following part is only necessary to calm FindBugs... - @SuppressWarnings("unused") - final boolean deleteResults = libDirDeleted && projectFileDeleted && projectDeleted; + projectFile.delete(); + projectDir.delete(); // Rethrow the exception in order to inform the caller of this method throw new IOException("An IO Exception occured while saving the project.", ex); @@ -236,7 +228,7 @@ public class FSProjectDAOImpl implements IProjectDAO, ReleaseListener { // This should not happen! LOG.error("Could not save project.", ex); } catch (final NewerProjectException ex) { - // This should not happen! + // This should not happen! The projects should be locked at this point. LOG.error("Could not save project.", ex); } } @@ -244,16 +236,11 @@ public class FSProjectDAOImpl implements IProjectDAO, ReleaseListener { @Override public void copyProject(final String originalProjectName, final String newProjectName) throws ProjectNotExistingException, ProjectAlreadyExistingException, IOException { + this.assertProjectAbsence(newProjectName); + this.assertProjectExistence(originalProjectName); + final File dstProjDir = FSProjectDAOImpl.assembleProjectDir(newProjectName); try { - // Check whether the project exists already! - if (this.projectExists(newProjectName)) { - throw new ProjectAlreadyExistingException("A project with the name '" + newProjectName + "' exists already."); - } - if (!this.projectExists(originalProjectName)) { - throw new ProjectNotExistingException("A project with the name '" + originalProjectName + "' does not exist."); - } - final File srcProjDir = FSProjectDAOImpl.assembleProjectDir(originalProjectName); // Copy all files and rename the kax file @@ -280,7 +267,7 @@ public class FSProjectDAOImpl implements IProjectDAO, ReleaseListener { @Override public MIProject openProject(final String projectName) throws ProjectNotExistingException, IOException { if (projectName == null) { - throw new IOException("Project is null"); + throw new ProjectNotExistingException("Project is null"); } try { @@ -294,7 +281,7 @@ public class FSProjectDAOImpl implements IProjectDAO, ReleaseListener { @Override public Object openProject(final String projectName, final ClassAndMethodContainer classAndMethodContainer) throws ProjectNotExistingException, IOException { if (projectName == null) { - throw new IOException("Project is null"); + throw new ProjectNotExistingException("Project is null"); } try { @@ -310,10 +297,7 @@ public class FSProjectDAOImpl implements IProjectDAO, ReleaseListener { @Override public void saveProject(final String projectName, final MIProject project, final long timeStamp, final boolean overwriteNewerProject, final String username, final String analysisLayout, final String cockpitLayout) throws ProjectNotExistingException, IOException, NewerProjectException { - // Check whether the project exists - if (!this.projectExists(projectName)) { - throw new ProjectNotExistingException("A project with the name '" + projectName + "' does not exist."); - } + this.assertProjectExistence(projectName); // Check for a newer version first final long currTimeStamp = this.getCurrTimeStamp(projectName); @@ -338,19 +322,13 @@ public class FSProjectDAOImpl implements IProjectDAO, ReleaseListener { @Override public long getCurrTimeStamp(final String projectName) throws ProjectNotExistingException { - // Check whether the project exists - if (!this.projectExists(projectName)) { - throw new ProjectNotExistingException("A project with the name '" + projectName + "' does not exist."); - } + this.assertProjectExistence(projectName); return FSProjectDAOImpl.assembleKaxFile(projectName).lastModified(); } @Override public void uploadLibrary(final UploadedFile file, final String projectName) throws ProjectNotExistingException, IOException { - // Check whether the project exists - if (!this.projectExists(projectName)) { - throw new ProjectNotExistingException("A project with the name '" + projectName + "' does not exist."); - } + this.assertProjectExistence(projectName); // Prepare the files final File libDir = this.assembleLibDir(projectName); @@ -369,10 +347,7 @@ public class FSProjectDAOImpl implements IProjectDAO, ReleaseListener { @Override public ClassLoader getClassLoader(final String projectName, final Object requester) throws ProjectNotExistingException, IOException { - // Check whether the project exists - if (!this.projectExists(projectName)) { - throw new ProjectNotExistingException("A project with the name '" + projectName + "' does not exist."); - } + this.assertProjectExistence(projectName); // Create a new temporary directory final File tempDir = this.createTemporaryDirectory(); @@ -413,10 +388,7 @@ public class FSProjectDAOImpl implements IProjectDAO, ReleaseListener { @Override public List<String> listAllLibraries(final String projectName) throws ProjectNotExistingException { - // Check whether the project exists - if (!this.projectExists(projectName)) { - throw new ProjectNotExistingException("A project with the name '" + projectName + "' does not exist."); - } + this.assertProjectExistence(projectName); final List<String> result = new ArrayList<String>(); @@ -454,7 +426,9 @@ public class FSProjectDAOImpl implements IProjectDAO, ReleaseListener { } @Override - public boolean deleteLibrary(final String projectName, final String libName) throws IOException { + public boolean deleteLibrary(final String projectName, final String libName) throws IOException, ProjectNotExistingException { + this.assertProjectExistence(projectName); + final File libDir = this.assembleLibDir(projectName); final File libFile = new File(libDir, libName); final boolean result = libFile.delete(); @@ -608,100 +582,44 @@ public class FSProjectDAOImpl implements IProjectDAO, ReleaseListener { } } - /** - * This method tries to create a new temporary directory within our temp directory. - * - * @return A file object pointing to the new temporary directory. - */ private File createTemporaryDirectory() { return Files.createTempDir(); } - /** - * Checks whether a project with the name exists on the file system. - * - * @param projectName - * The name of the project. - * - * @throws ProjectNotExistingException - * If a project with the given name does not exist - */ - private void checkProjectExistence(final String projectName) throws ProjectNotExistingException { - if (FSProjectDAOImpl.assembleKaxFile(projectName).exists()) { + private void assertProjectExistence(final String projectName) throws ProjectNotExistingException { + if (!FSProjectDAOImpl.assembleKaxFile(projectName).exists()) { throw new ProjectNotExistingException("A project with the name '" + projectName + "' does not exist."); } } - private boolean projectExists(final String projectName) throws ProjectNotExistingException { - return FSProjectDAOImpl.assembleKaxFile(projectName).exists(); + private void assertProjectAbsence(final String projectName) throws ProjectAlreadyExistingException { + if (FSProjectDAOImpl.assembleKaxFile(projectName).exists()) { + throw new ProjectAlreadyExistingException("A project with the name '" + projectName + "' does already exist."); + } } - /** - * Delivers the url of the given library to the given project. - * - * @param lib - * The library of the project. - * @param project - * The project itself. - * @return An URL pointing to the URL. - * @throws MalformedURLException - * If something went wrong. - */ private URL getURL(final String lib, final String project) throws MalformedURLException { final File file = new File(FSProjectDAOImpl.ROOT_DIRECTORY + File.separator + project + File.separator + FSProjectDAOImpl.LIB_DIRECTORY + File.separator + lib); return file.toURI().toURL(); } - /** - * Assembles the {@link File}-element pointing to the directory of the given project. - * - * @param projectName - * The name of the project. - * @return The directory of the project. - */ private static File assembleProjectDir(final String projectName) { return new File(FSProjectDAOImpl.ROOT_DIRECTORY + File.separator + projectName); } - /** - * Assembles the {@link File}-element pointing to the kax-file of the given project. - * - * @param projectName - * The name of the project. - * @return The kax-file of the project. - */ private static File assembleKaxFile(final String projectName) { return new File(FSProjectDAOImpl.ROOT_DIRECTORY + File.separator + projectName + File.separator + projectName + "." + FSProjectDAOImpl.KAX_EXTENSION); } - /** - * Assembles the {@link File}-element pointing to the meta file of the given project. - * - * @param projectName - * The name of the project. - * @return The meta file of the project. - */ private static File assembleMetaFile(final String projectName) { return new File(FSProjectDAOImpl.ROOT_DIRECTORY + File.separator + projectName + File.separator + FSProjectDAOImpl.META_FILE); } - /** - * Assembles the {@link File}-element pointing to the library directory of the given project. - * - * @param projectName - * The name of the project. - * @return The library directory of the project. - */ private File assembleLibDir(final String projectName) { return new File(FSProjectDAOImpl.ROOT_DIRECTORY + File.separator + projectName + File.separator + FSProjectDAOImpl.LIB_DIRECTORY); } - /** - * Delivers an URL pointing to the kieker library within this application. - * - * @return The kieker url. - */ private URL getKiekerURL() { return Thread.currentThread().getContextClassLoader().getResource(FSProjectDAOImpl.KIEKER_LIB); } diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/service/IProjectService.java b/Kieker.WebGUI/src/main/java/kieker/webgui/service/IProjectService.java index 638ee087..ca724154 100644 --- a/Kieker.WebGUI/src/main/java/kieker/webgui/service/IProjectService.java +++ b/Kieker.WebGUI/src/main/java/kieker/webgui/service/IProjectService.java @@ -331,6 +331,7 @@ public interface IProjectService { * * @param projectName * The name of the project whose analysis should be stopped. + * * @throws ProjectNotExistingException * If a project with the given name does not exist. * @throws InvalidAnalysisStateException @@ -350,19 +351,22 @@ public interface IProjectService { * @param displayName * The name of the display. * @return A display object for the given parameters. - * @throws ProjectNotExistingException - * If a project with the given name does not exist. + * * @throws DisplayNotFoundException * If a view or a display within the given view does not exist. + * @throws InvalidAnalysisStateException + * If the analysis of the given project is in the wrong state to deliver the display. */ @PreAuthorize("isAuthenticated()") - public Object getDisplay(final String projectName, final String viewName, final String displayName) throws ProjectNotExistingException, DisplayNotFoundException; + public Object getDisplay(final String projectName, final String viewName, final String displayName) throws DisplayNotFoundException, + InvalidAnalysisStateException; /** * This method delivers the current state of the given project. * * @param projectName * The name of the project whose state have to be returned. + * * @return The state of the given project, if available. {@code null} otherwise. */ @PreAuthorize("isAuthenticated()") @@ -390,9 +394,11 @@ public interface IProjectService { * @return true if and only if the given library has been removed. * @throws IOException * If something went wrong during the reloading of the components. + * @throws ProjectNotExistingException + * If a project with the given name does not exist. */ @PreAuthorize("hasAnyRole('User', 'Administrator')") - public boolean deleteLibrary(String projectName, String libName) throws IOException; + public boolean deleteLibrary(String projectName, String libName) throws IOException, ProjectNotExistingException; /** * Delivers the stored analysis layout for the given project. 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 36d71100..9c14cf1e 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 @@ -46,12 +46,12 @@ import org.springframework.stereotype.Service; * * @author Nils Christian Ehmke */ -// TODO Remove the lock objects for removed projects as well (take a look at #591). @Service public class ProjectServiceImpl implements IProjectService { private final ConcurrentHashMap<String, Object> fileSystemLocks = new ConcurrentHashMap<String, Object>(); private final ConcurrentHashMap<String, Object> analysesLocks = new ConcurrentHashMap<String, Object>(); + @Autowired private ACManager acManager; @Autowired @@ -64,20 +64,6 @@ public class ProjectServiceImpl implements IProjectService { // No code necessary. } - @Override - public void updateAllAnalyses() { - for (final Entry<String, Object> locks : this.analysesLocks.entrySet()) { - synchronized (locks.getValue()) { - this.acManager.updateDisplays(locks.getKey()); - } - } - } - - /* - * (non-Javadoc) - * - * @see kieker.webgui.service.IProjectService#addProject(java.lang.String, java.lang.String) - */ @Override public void addProject(final String projectName, final String username) throws ProjectAlreadyExistingException, IOException { final Object projectLock = this.getLock(projectName, this.fileSystemLocks); @@ -96,30 +82,14 @@ public class ProjectServiceImpl implements IProjectService { } } - /* - * (non-Javadoc) - * - * @see kieker.webgui.service.IProjectService#copyProject(java.lang.String, java.lang.String) - */ @Override public void copyProject(final String originalProjectName, final String newProjectName) throws ProjectNotExistingException, ProjectAlreadyExistingException, IOException { - // Get the file system locks for both projects - final Object srcProjectLock = this.getLock(originalProjectName, this.fileSystemLocks); - final Object dstProjectLock = this.getLock(newProjectName, this.fileSystemLocks); - // We cannot risk just using two synchronized-blocks as such a thing could block the application. We therefore have to sort the locks by name in order to - // make sure that two methods would use the same order to access (if project A has to be renamed to B and B has to be renamed to A, we would always - // synchronize on A before synchronizing on B). - final Object lockFst; - final Object lockSnd; - if (originalProjectName.compareTo(newProjectName) < 0) { - lockFst = srcProjectLock; - lockSnd = dstProjectLock; - } else { - lockFst = dstProjectLock; - lockSnd = srcProjectLock; - } + // make sure that two methods would use the same order to access. + + final Object lockFst = this.getFirstLock(originalProjectName, newProjectName, this.fileSystemLocks); + final Object lockSnd = this.getSecondLock(originalProjectName, newProjectName, this.fileSystemLocks); synchronized (lockFst) { synchronized (lockSnd) { @@ -128,11 +98,6 @@ public class ProjectServiceImpl implements IProjectService { } } - /* - * (non-Javadoc) - * - * @see kieker.webgui.service.IProjectService#openProject(java.lang.String) - */ @Override public MIProject openProject(final String projectName) throws ProjectNotExistingException, IOException { final Object projectLock = this.getLock(projectName, this.fileSystemLocks); @@ -142,11 +107,6 @@ public class ProjectServiceImpl implements IProjectService { } } - /* - * (non-Javadoc) - * - * @see kieker.webgui.service.IProjectService#openProject(java.lang.String, kieker.webgui.common.ClassAndMethodContainer) - */ @Override public Object openProject(final String projectName, final ClassAndMethodContainer classAndMethodContainer) throws ProjectNotExistingException, IOException { final Object projectLock = this.getLock(projectName, this.fileSystemLocks); @@ -156,11 +116,6 @@ public class ProjectServiceImpl implements IProjectService { } } - /* - * (non-Javadoc) - * - * @see kieker.webgui.service.IProjectService#saveProject(java.lang.String, kieker.analysis.model.analysisMetaModel.MIProject, long, boolean, String, String) - */ @Override public void saveProject(final String projectName, final MIProject project, final long timeStamp, final boolean overwriteNewerProject, final String username, final String analysisLayout, final String cockpitLayout) throws ProjectNotExistingException, IOException, NewerProjectException { @@ -171,11 +126,6 @@ public class ProjectServiceImpl implements IProjectService { } } - /* - * (non-Javadoc) - * - * @see kieker.webgui.service.IProjectService#getCurrTimeStamp(java.lang.String) - */ @Override public long getCurrTimeStamp(final String projectName) throws ProjectNotExistingException { final Object projectLock = this.getLock(projectName, this.fileSystemLocks); @@ -185,11 +135,6 @@ public class ProjectServiceImpl implements IProjectService { } } - /* - * (non-Javadoc) - * - * @see kieker.webgui.service.IProjectService#uploadLibrary(org.primefaces.model.UploadedFile, java.lang.String) - */ @Override public void uploadLibrary(final UploadedFile file, final String projectName) throws ProjectNotExistingException, IOException { final Object projectLock = this.getLock(projectName, this.fileSystemLocks); @@ -199,11 +144,6 @@ public class ProjectServiceImpl implements IProjectService { } } - /* - * (non-Javadoc) - * - * @see kieker.webgui.service.IProjectService#getClassLoader(java.lang.String, java.lang.Object) - */ @Override public ClassLoader getClassLoader(final String projectName, final Object requester) throws ProjectNotExistingException, IOException { final Object projectLock = this.getLock(projectName, this.fileSystemLocks); @@ -213,11 +153,6 @@ public class ProjectServiceImpl implements IProjectService { } } - /* - * (non-Javadoc) - * - * @see kieker.webgui.service.IProjectService#getAvailableComponents(java.lang.String) - */ @Override public ComponentListContainer getAvailableComponents(final String projectName) { final Object projectLock = this.getLock(projectName, this.fileSystemLocks); @@ -227,11 +162,6 @@ public class ProjectServiceImpl implements IProjectService { } } - /* - * (non-Javadoc) - * - * @see kieker.webgui.service.IProjectService#listAllLibraries(java.lang.String) - */ @Override public List<String> listAllLibraries(final String projectName) throws ProjectNotExistingException { final Object projectLock = this.getLock(projectName, this.fileSystemLocks); @@ -241,21 +171,11 @@ public class ProjectServiceImpl implements IProjectService { } } - /* - * (non-Javadoc) - * - * @see kieker.webgui.service.IProjectService#listAllProjects() - */ @Override public Collection<String> listAllProjects() { return this.projectDAO.listAllProjects(); } - /* - * (non-Javadoc) - * - * @see kieker.webgui.service.IProjectService#initializeAnalysis(java.lang.String, java.lang.ClassLoader) - */ @Override public void initializeAnalysis(final String projectName, final ClassLoader classLoader) throws ProjectNotExistingException, InvalidAnalysisStateException, AnalysisInitializationException { @@ -270,11 +190,6 @@ public class ProjectServiceImpl implements IProjectService { } } - /* - * (non-Javadoc) - * - * @see kieker.webgui.service.IProjectService#cleanAnalysis(java.lang.String) - */ @Override public void cleanAnalysis(final String projectName) throws ProjectNotExistingException, InvalidAnalysisStateException { final Object analysisLock = this.getLock(projectName, this.analysesLocks); @@ -284,11 +199,6 @@ public class ProjectServiceImpl implements IProjectService { } } - /* - * (non-Javadoc) - * - * @see kieker.webgui.service.IProjectService#startAnalysis(java.lang.String) - */ @Override public void startAnalysis(final String projectName) throws ProjectNotExistingException, InvalidAnalysisStateException { final Object analysisLock = this.getLock(projectName, this.analysesLocks); @@ -298,11 +208,6 @@ public class ProjectServiceImpl implements IProjectService { } } - /* - * (non-Javadoc) - * - * @see kieker.webgui.service.IProjectService#stopAnalysis(java.lang.String) - */ @Override public void stopAnalysis(final String projectName) throws ProjectNotExistingException, InvalidAnalysisStateException { final Object analysisLock = this.getLock(projectName, this.analysesLocks); @@ -312,13 +217,8 @@ public class ProjectServiceImpl implements IProjectService { } } - /* - * (non-Javadoc) - * - * @see kieker.webgui.service.IProjectService#getDisplay(java.lang.String, java.lang.String, java.lang.String) - */ @Override - public Object getDisplay(final String projectName, final String viewName, final String displayName) throws ProjectNotExistingException, + public Object getDisplay(final String projectName, final String viewName, final String displayName) throws InvalidAnalysisStateException, DisplayNotFoundException { final Object analysisLock = this.getLock(projectName, this.analysesLocks); @@ -327,11 +227,6 @@ public class ProjectServiceImpl implements IProjectService { } } - /* - * (non-Javadoc) - * - * @see kieker.webgui.service.IProjectService#getCurrentState(java.lang.String) - */ @Override public STATE getCurrentState(final String projectName) { final Object analysisLock = this.getLock(projectName, this.analysesLocks); @@ -341,36 +236,6 @@ public class ProjectServiceImpl implements IProjectService { } } - /** - * This method can be used to get the lock for a given project. If the lock doesn't exist already, a new one will be created. - * - * @param projectName - * The project whose lock should be delivered. - * @param lockMap - * The map containing the locks. - * @return A lock object for the project. - */ - private Object getLock(final String projectName, final ConcurrentHashMap<String, Object> lockMap) { - // Create a new lock and put it into the map - if it doesn't already contain the key - final Object newLock = new Object(); - final Object existLock = lockMap.putIfAbsent(projectName, newLock); - - // Find out which of the both locks is the correct one - final Object lock; - if (existLock != null) { - lock = existLock; - } else { - lock = newLock; - } - - return lock; - } - - /* - * (non-Javadoc) - * - * @see kieker.webgui.service.IProjectService#getLogEntries(java.lang.String) - */ @Override public Object[] getLogEntries(final String projectName) throws InvalidAnalysisStateException { final Object analysisLock = this.getLock(projectName, this.analysesLocks); @@ -380,13 +245,8 @@ public class ProjectServiceImpl implements IProjectService { } } - /* - * (non-Javadoc) - * - * @see kieker.webgui.service.IProjectService#deleteLibrary(java.lang.String) - */ @Override - public boolean deleteLibrary(final String projectName, final String libName) throws IOException { + public boolean deleteLibrary(final String projectName, final String libName) throws IOException, ProjectNotExistingException { final Object projectLock = this.getLock(projectName, this.fileSystemLocks); synchronized (projectLock) { @@ -394,11 +254,6 @@ public class ProjectServiceImpl implements IProjectService { } } - /* - * (non-Javadoc) - * - * @see kieker.webgui.service.IProjectService#getOwner(java.lang.String) - */ @Override public String getOwner(final String projectName) throws ProjectNotExistingException { final Object projectLock = this.getLock(projectName, this.fileSystemLocks); @@ -408,11 +263,6 @@ public class ProjectServiceImpl implements IProjectService { } } - /* - * (non-Javadoc) - * - * @see kieker.webgui.service.IProjectService#getLastUser(java.lang.String) - */ @Override public String getLastUser(final String projectName) throws ProjectNotExistingException { final Object projectLock = this.getLock(projectName, this.fileSystemLocks); @@ -431,11 +281,6 @@ public class ProjectServiceImpl implements IProjectService { } } - /* - * (non-Javadoc) - * - * @see kieker.webgui.service.IProjectService#getAnalysisLayout(java.lang.String) - */ @Override public String getAnalysisLayout(final String projectName) { final Object projectLock = this.getLock(projectName, this.fileSystemLocks); @@ -445,11 +290,6 @@ public class ProjectServiceImpl implements IProjectService { } } - /* - * (non-Javadoc) - * - * @see kieker.webgui.service.IProjectService#getCockpitLayout(java.lang.String) - */ @Override public String getCockpitLayout(final String projectName) { final Object projectLock = this.getLock(projectName, this.fileSystemLocks); @@ -458,4 +298,55 @@ public class ProjectServiceImpl implements IProjectService { return this.projectDAO.getCockpitLayout(projectName); } } + + @Override + public void updateAllAnalyses() { + for (final Entry<String, Object> locks : this.analysesLocks.entrySet()) { + synchronized (locks.getValue()) { + this.acManager.updateDisplays(locks.getKey()); + } + } + } + + private Object getFirstLock(final String projectA, final String projectB, final ConcurrentHashMap<String, Object> lockMap) { + if (projectA.compareTo(projectB) < 0) { + return this.getLock(projectA, lockMap); + } else { + return this.getLock(projectB, lockMap); + } + } + + private Object getSecondLock(final String projectA, final String projectB, final ConcurrentHashMap<String, Object> lockMap) { + if (projectA.compareTo(projectB) < 0) { + return this.getLock(projectB, lockMap); + } else { + return this.getLock(projectA, lockMap); + } + } + + /** + * This method can be used to get the lock for a given project. If the lock doesn't exist already, a new one will be created. + * + * @param projectName + * The project whose lock should be delivered. + * @param lockMap + * The map containing the locks. + * + * @return A lock object for the project. + */ + private Object getLock(final String projectName, final ConcurrentHashMap<String, Object> lockMap) { + // Create a new lock and put it into the map - if it doesn't already contain the key + final Object newLock = new Object(); + final Object existLock = lockMap.putIfAbsent(projectName, newLock); + + // Find out which of the both locks is the correct one + final Object lock; + if (existLock != null) { + lock = existLock; + } else { + lock = newLock; + } + + return lock; + } } diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/service/impl/util/ACManager.java b/Kieker.WebGUI/src/main/java/kieker/webgui/service/impl/util/ACManager.java index d17975e6..364bbfe5 100644 --- a/Kieker.WebGUI/src/main/java/kieker/webgui/service/impl/util/ACManager.java +++ b/Kieker.WebGUI/src/main/java/kieker/webgui/service/impl/util/ACManager.java @@ -16,13 +16,13 @@ package kieker.webgui.service.impl.util; +import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import kieker.analysis.AnalysisController.STATE; import kieker.webgui.common.exception.AnalysisInitializationException; import kieker.webgui.common.exception.DisplayNotFoundException; import kieker.webgui.common.exception.InvalidAnalysisStateException; -import kieker.webgui.common.exception.ProjectNotExistingException; import kieker.webgui.persistence.IProjectDAO; import org.springframework.beans.factory.annotation.Autowired; @@ -30,14 +30,15 @@ import org.springframework.stereotype.Service; /** * 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. + * instantiate, start, and to stop them. This is also a singleton instance. * * @author Nils Christian Ehmke */ @Service public class ACManager { - private final ConcurrentHashMap<String, Analysis> analyses = new ConcurrentHashMap<String, Analysis>(); + private final Map<String, Analysis> analyses = new ConcurrentHashMap<String, Analysis>(); + @Autowired private IProjectDAO projectDAO; @@ -55,15 +56,13 @@ public class ACManager { * The name of the project to be initialized. * @param classLoader * The class loader to be used during the loading. - * @throws ProjectNotExistingException - * If a project with the given name does not exist. + * * @throws AnalysisInitializationException * If an error occurred during the initialization of the analysis. * @throws InvalidAnalysisStateException * If the analysis is in an invalid state to be initialized. */ - public void initializeAnalysis(final String projectName, final ClassLoader classLoader) throws ProjectNotExistingException, InvalidAnalysisStateException, - AnalysisInitializationException { + public void initializeAnalysis(final String projectName, final ClassLoader classLoader) throws InvalidAnalysisStateException, AnalysisInitializationException { // The analysis for the given project must not exist! if (this.analyses.containsKey(projectName)) { throw new InvalidAnalysisStateException("The analysis has not been cleaned yet."); @@ -78,23 +77,22 @@ public class ACManager { * * @param projectName * The name of the project to be cleaned. + * * @throws InvalidAnalysisStateException * If the analysis is in an invalid state to be cleaned. */ public void cleanAnalysis(final String projectName) throws InvalidAnalysisStateException { // The analysis for the given project must exist! - if (!this.analyses.containsKey(projectName)) { - // Nothing to do - return; - } - final Analysis analysis = this.analyses.get(projectName); + if (this.analyses.containsKey(projectName)) { + final Analysis analysis = this.analyses.get(projectName); - // The analysis for the given project must not run - if (STATE.RUNNING.toString().equals(analysis.getCurrentState().toString())) { - throw new InvalidAnalysisStateException("The analysis is still running."); - } + // The analysis for the given project must not run + if (STATE.RUNNING.toString().equals(analysis.getCurrentState().toString())) { + throw new InvalidAnalysisStateException("The analysis is still running."); + } - this.analyses.remove(projectName); + this.analyses.remove(projectName); + } } /** @@ -102,16 +100,16 @@ public class ACManager { * * @param projectName * The name of the project to be started. - * @throws ProjectNotExistingException - * If a project with the given name does not exist. + * * @throws InvalidAnalysisStateException * If the analysis is in an invalid state to be started. */ - public void startAnalysis(final String projectName) throws ProjectNotExistingException, InvalidAnalysisStateException { + public void startAnalysis(final String projectName) throws InvalidAnalysisStateException { // The analysis for the given project must exist! if (!this.analyses.containsKey(projectName)) { throw new InvalidAnalysisStateException("The analysis has not been initialized yet."); } + final Analysis analysis = this.analyses.get(projectName); // The analysis for the given project must be ready @@ -127,16 +125,16 @@ public class ACManager { * * @param projectName * The name of the project to be stopped. - * @throws ProjectNotExistingException - * If a project with the given name does not exist. + * * @throws InvalidAnalysisStateException * If the analysis is in an invalid state to be stopped. */ - public void stopAnalysis(final String projectName) throws ProjectNotExistingException, InvalidAnalysisStateException { + public void stopAnalysis(final String projectName) throws InvalidAnalysisStateException { // The analysis for the given project must exist! if (!this.analyses.containsKey(projectName)) { throw new InvalidAnalysisStateException("The analysis has not been initialized yet."); } + final Analysis analysis = this.analyses.get(projectName); // The analysis for the given project must be running @@ -152,7 +150,9 @@ public class ACManager { * * @param projectName * The name of the project. + * * @return An array containing the entries of the log. + * * @throws InvalidAnalysisStateException * If the analysis is in an invalid state to deliver the entries. */ @@ -175,16 +175,17 @@ public class ACManager { * @param displayName * The name of the display. * @return A display object for the given parameters. - * @throws ProjectNotExistingException - * If a project with the given name does not exist. + * * @throws DisplayNotFoundException * If a view or a display within the given view does not exist. + * @throws InvalidAnalysisStateException + * If the analysis is in an invalid state to deliver the displays. */ - public Object getDisplay(final String projectName, final String viewName, final String displayName) throws ProjectNotExistingException, - DisplayNotFoundException { + public Object getDisplay(final String projectName, final String viewName, final String displayName) throws DisplayNotFoundException, + InvalidAnalysisStateException { // The analysis for the given project must exist! if (!this.analyses.containsKey(projectName)) { - throw new ProjectNotExistingException("The analysis has not been initialized yet."); + throw new InvalidAnalysisStateException("The analysis has not been initialized yet."); } return this.analyses.get(projectName).getDisplay(viewName, displayName); diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/service/impl/util/Analysis.java b/Kieker.WebGUI/src/main/java/kieker/webgui/service/impl/util/Analysis.java index f145c5dc..5b688e10 100644 --- a/Kieker.WebGUI/src/main/java/kieker/webgui/service/impl/util/Analysis.java +++ b/Kieker.WebGUI/src/main/java/kieker/webgui/service/impl/util/Analysis.java @@ -48,8 +48,6 @@ public class Analysis { private final Object analysisController; private final Object analysisControllerThread; - private Map<Object, Object> pluginMap; - private final Map<String, Map<String, Object>> displayPlugins = new HashMap<String, Map<String, Object>>(); private final Map<String, Map<String, Object>> displayObjects = new HashMap<String, Map<String, Object>>(); private final Map<String, Map<String, Method>> displayMethods = new HashMap<String, Map<String, Method>>(); @@ -66,6 +64,7 @@ public class Analysis { * @throws AnalysisInitializationException * If an error occurred during the instantiation of the analysis. */ + @SuppressWarnings("unchecked") public Analysis(final ClassLoader classLoader, final File projectFile) throws InvalidAnalysisStateException, AnalysisInitializationException { try { this.classAndMethodContainer = new ClassAndMethodContainer(classLoader); @@ -79,7 +78,7 @@ public class Analysis { this.analysisController = new Mirror().on(controllerAndMapping).invoke().method("getController").withoutArgs(); this.analysisControllerThread = new Mirror().on(analsisControllerThreadClass).invoke().constructor().withArgs(this.analysisController); - this.pluginMap = (Map<Object, Object>) new Mirror().on(controllerAndMapping).invoke().method("getPluginMap").withoutArgs(); + final Map<Object, Object> pluginMap = (Map<Object, Object>) new Mirror().on(controllerAndMapping).invoke().method("getPluginMap").withoutArgs(); final List<Object> views = (List<Object>) new Mirror().on(modelProject).invoke().method("getViews").withoutArgs(); @@ -104,7 +103,7 @@ public class Analysis { final Object display = new Mirror().on(displayConnector).invoke().method("getDisplay").withoutArgs(); final String displayName = (String) new Mirror().on(display).invoke().method("getName").withoutArgs(); final Object displayParent = new Mirror().on(display).invoke().method("getParent").withoutArgs(); - final Object plugin = this.pluginMap.get(displayParent); + final Object plugin = pluginMap.get(displayParent); final Method[] methods = plugin.getClass().getMethods(); for (final Method method : methods) { diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/web/beans/view/CurrentAnalysisEditorBean.java b/Kieker.WebGUI/src/main/java/kieker/webgui/web/beans/view/CurrentAnalysisEditorBean.java index 991801f3..f67bd183 100644 --- a/Kieker.WebGUI/src/main/java/kieker/webgui/web/beans/view/CurrentAnalysisEditorBean.java +++ b/Kieker.WebGUI/src/main/java/kieker/webgui/web/beans/view/CurrentAnalysisEditorBean.java @@ -54,7 +54,6 @@ import kieker.webgui.domain.pluginDecorators.AbstractAnalysisComponentDecorator; import kieker.webgui.domain.pluginDecorators.FilterDecorator; import kieker.webgui.domain.pluginDecorators.ReaderDecorator; import kieker.webgui.domain.pluginDecorators.RepositoryDecorator; -import kieker.webgui.persistence.IUserDAO; import kieker.webgui.service.IProjectService; import kieker.webgui.web.beans.application.GlobalPropertiesBean; import kieker.webgui.web.beans.application.ProjectsBean; @@ -110,8 +109,6 @@ public class CurrentAnalysisEditorBean { private ProjectsBean projectsBean; @Autowired private UserBean userBean; - @Autowired - private IUserDAO userDAO; /** * Creates a new instance of this class. <b>Do not call this constructor manually. It will only be accessed by Spring.</b> @@ -264,6 +261,9 @@ public class CurrentAnalysisEditorBean { } catch (final IOException ex) { CurrentAnalysisEditorBean.LOG.error("An error occured while removing the library.", ex); GlobalPropertiesBean.showMessage(FacesMessage.SEVERITY_ERROR, "An error occured while removing the library."); + } catch (final ProjectNotExistingException ex) { + CurrentAnalysisEditorBean.LOG.error("An error occured while removing the library.", ex); + GlobalPropertiesBean.showMessage(FacesMessage.SEVERITY_ERROR, "An error occured while removing the library."); } } diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/web/beans/view/CurrentCockpitBean.java b/Kieker.WebGUI/src/main/java/kieker/webgui/web/beans/view/CurrentCockpitBean.java index 8e570c91..ade0ef84 100644 --- a/Kieker.WebGUI/src/main/java/kieker/webgui/web/beans/view/CurrentCockpitBean.java +++ b/Kieker.WebGUI/src/main/java/kieker/webgui/web/beans/view/CurrentCockpitBean.java @@ -29,8 +29,8 @@ import kieker.analysis.model.analysisMetaModel.MIView; import kieker.common.logging.Log; import kieker.common.logging.LogFactory; import kieker.webgui.common.exception.DisplayNotFoundException; +import kieker.webgui.common.exception.InvalidAnalysisStateException; import kieker.webgui.common.exception.ProjectLoadException; -import kieker.webgui.common.exception.ProjectNotExistingException; import kieker.webgui.service.IProjectService; import kieker.webgui.web.beans.application.GlobalPropertiesBean; import kieker.webgui.web.beans.application.ProjectsBean; @@ -202,14 +202,13 @@ public class CurrentCockpitBean { if ((this.activeView != null) && (this.projectName != null)) { try { final Object displayObj = this.projectService.getDisplay(this.projectName, this.activeView.getName(), displayName); - final String result = (String) new Mirror().on(displayObj).invoke().method("getText").withoutArgs(); - return result; + return (String) new Mirror().on(displayObj).invoke().method("getText").withoutArgs(); } catch (final DisplayNotFoundException ex) { CurrentCockpitBean.LOG.warn("Display not found.", ex); } catch (final MirrorException ex) { - return "N/A"; - } catch (final ProjectNotExistingException ex) { - return "N/A"; + CurrentCockpitBean.LOG.warn("Reflection exception.", ex); + } catch (final InvalidAnalysisStateException ex) { + CurrentCockpitBean.LOG.warn("Project is in invalid state.", ex); } } return "N/A"; diff --git a/Kieker.WebGUI/src/test/java/kieker/webgui/service/impl/GraphLayoutServiceImplTest.java b/Kieker.WebGUI/src/test/java/kieker/webgui/service/impl/GraphLayoutServiceImplTest.java index 38ff0047..c77e60bb 100644 --- a/Kieker.WebGUI/src/test/java/kieker/webgui/service/impl/GraphLayoutServiceImplTest.java +++ b/Kieker.WebGUI/src/test/java/kieker/webgui/service/impl/GraphLayoutServiceImplTest.java @@ -46,7 +46,8 @@ public class GraphLayoutServiceImplTest { try { layouter.layoutGraph("", ""); Assert.fail(); - } catch (final GraphLayoutException ex) { + } catch (final GraphLayoutException ex) { // NOPMD (Empty catch block) + } } -- GitLab