/******************************************************************************* * Copyright (c) 2010, 2011 Obeo. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Obeo - initial API and implementation *******************************************************************************/ package org.eclipse.mylyn.docs.intent.client.ui.ide.builder; import com.google.common.collect.Sets; import java.util.Collection; import java.util.HashMap; import java.util.Map; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceChangeEvent; import org.eclipse.core.resources.IResourceChangeListener; import org.eclipse.core.resources.IResourceDelta; import org.eclipse.core.runtime.CoreException; import org.eclipse.mylyn.docs.intent.client.ui.editor.IntentEditorInput; import org.eclipse.mylyn.docs.intent.client.ui.ide.projectmanager.IntentProjectManager; import org.eclipse.mylyn.docs.intent.client.ui.logger.IntentUiLogger; import org.eclipse.mylyn.docs.intent.collab.common.logger.IIntentLogger.LogType; import org.eclipse.mylyn.docs.intent.collab.common.logger.IntentLogger; import org.eclipse.mylyn.docs.intent.collab.repository.RepositoryConnectionException; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.IEditorReference; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; /** * A {@link IResourceChangeListener} that reacts to the creation or opening of Intent projects by creating * Repository and launching clients. * * @author <a href="mailto:alex.lagarde@obeo.fr">Alex Lagarde</a> * @author <a href="mailto:william.piers@obeo.fr">William Piers</a> */ public class IntentProjectListener implements IResourceChangeListener { /** * A map associating each repository ID with the associated {@link IntentProjectManager}. */ private Map<String, IntentProjectManager> projectManagers = new HashMap<String, IntentProjectManager>(); /** * Default constructor. */ public IntentProjectListener() { } /** * {@inheritDoc} * * @see org.eclipse.core.resources.IResourceChangeListener#resourceChanged(org.eclipse.core.resources.IResourceChangeEvent) */ public void resourceChanged(IResourceChangeEvent event) { if (event.getType() == IResourceChangeEvent.PRE_CLOSE || event.getType() == IResourceChangeEvent.PRE_DELETE) { IResource resource = event.getResource(); try { // TODO check if there is a repository associated to this project, even if not accessible if (resource instanceof IProject && resource.isAccessible() && ((IProject)resource).hasNature(IntentNature.NATURE_ID)) { handleClosedProject((IProject)resource); } } catch (CoreException e) { IntentUiLogger.logError(e); } } else { // We want to be notified AFTER any changed that occurred if (event.getType() == IResourceChangeEvent.POST_CHANGE) { final IResourceDelta rootDelta = event.getDelta(); // If any resource of the repository has changed if (rootDelta != null) { // We launch the analysis of the delta in a new thread analyseWorkspaceDelta(rootDelta); } } } } /** * Analyzes the given {@link IResourceDelta}. * * @param repositoryDelta * the {@link IResourceDelta} to analyze */ protected void analyseWorkspaceDelta(IResourceDelta repositoryDelta) { try { // Step 1 : We visit the given delta using a IntentBuilderDeltaVisitor visitor final IntentBuilderDeltaVisitor visitor = new IntentBuilderDeltaVisitor(); repositoryDelta.accept(visitor); // Step 2 : if any project has been opened, we handle this creation for (IProject project : visitor.getOpenedProjects()) { handleOpenedProject(project); } // Step 3 : if any project has been closed, we handle this creation for (IProject project : visitor.getClosedProjects()) { handleClosedProject(project); } } catch (CoreException e) { IntentUiLogger.logError(e); } } /** * Handles the creation or opening of Intent projects by launching all clients. * * @param project * the created or opened project to handle */ public void handleOpenedProject(IProject project) { // Step 1: determine if the opened project is a valid Intent project synchronized(projectManagers) { try { if (project.isAccessible() && project.hasNature(IntentNature.NATURE_ID)) { // Step 2: determine if it is already handled by this project listener if (projectManagers.get(project.getName()) == null) { // Step 3: if not, create an Intent project manager for this project IntentProjectManager projectManager = getIntentProjectManager(project); try { IntentLogger.getInstance().log(LogType.LIFECYCLE, "[IntentProjectListener] Handling project " + project.getName()); projectManager.connect(); projectManagers.put(project.getName(), projectManager); } catch (RepositoryConnectionException e) { IntentUiLogger.logError(e); } } } } catch (CoreException e) { IntentUiLogger.logError(e); } } } /** * Handles the deletion or closing of Intent projects by stopping all clients and closing repository. * * @param project * the deleted or closed project to handle */ public void handleClosedProject(IProject project) { IntentProjectManager projectManager = getIntentProjectManager(project); // Closing all intent editors opened of this project IWorkbenchWindow activeWorkbenchWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); if (activeWorkbenchWindow == null && PlatformUI.getWorkbench().getWorkbenchWindowCount() == 1) { activeWorkbenchWindow = PlatformUI.getWorkbench().getWorkbenchWindows()[0]; } if (activeWorkbenchWindow != null) { final IWorkbenchPage activePage = activeWorkbenchWindow.getActivePage(); if (activePage != null) { final Collection<IEditorReference> activeEditorsToClose = Sets.newLinkedHashSet(); for (IEditorReference activeEditor : activePage.getEditorReferences()) { try { if (activeEditor.getEditorInput() instanceof IntentEditorInput && ((IntentEditorInput)activeEditor.getEditorInput()).getRepository() != null && project.getName().equals( ((IntentEditorInput)activeEditor.getEditorInput()).getRepository() .getIdentifier())) { activeEditorsToClose.add(activeEditor); } } catch (PartInitException e) { // Silent catch } } Display.getDefault().asyncExec(new Runnable() { public void run() { activePage.closeEditors(activeEditorsToClose .toArray(new IEditorReference[activeEditorsToClose.size()]), false); } }); } } // Closing project manager if (projectManager != null) { // should not happen try { projectManager.disconnect(); projectManagers.remove(project.getName()); } catch (RepositoryConnectionException e) { IntentUiLogger.logError(e); } } } /** * Returns the project manager associated to the given project. * * @param project * the intent project * @return the project manager associated to the given project */ private IntentProjectManager getIntentProjectManager(IProject project) { IntentProjectManager projectManager = projectManagers.get(project.getName()); if (projectManager == null) { projectManager = new IntentProjectManager(project); } return projectManager; } }