/******************************************************************************* * Copyright © 2012, 2013 IBM Corporation and others. * 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: * IBM Corporation - initial API and implementation * *******************************************************************************/ package org.eclipse.edt.ide.deployment.services.internal.testserver; 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.resources.ProjectScope; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.preferences.IEclipsePreferences; import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener; import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent; import org.eclipse.edt.ide.core.EDTCoreIDEPlugin; import org.eclipse.edt.ide.core.utils.ProjectSettingsUtility; import org.eclipse.edt.ide.testserver.TestServerConfiguration; import org.osgi.service.prefs.Preferences; public class DDResourceChangeListener implements IResourceChangeListener { private final ServicesContribution contrib; private final Object syncObj; private Map<IProject, DefaultDDPreferenceListener> listenerMap; public DDResourceChangeListener(ServicesContribution contrib) { this.contrib = contrib; this.syncObj = new Object(); this.listenerMap = new HashMap<IProject, DDResourceChangeListener.DefaultDDPreferenceListener>(); // Populate the initial listeners. IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects(); for (IProject project : projects) { if (project.isAccessible()) { addDDListener(project); } } ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.PRE_CLOSE | IResourceChangeEvent.PRE_DELETE | IResourceChangeEvent.POST_CHANGE); } public void dispose() { ResourcesPlugin.getWorkspace().removeResourceChangeListener(this); synchronized (syncObj) { for (DefaultDDPreferenceListener listener : listenerMap.values()) { removeDDListener(listener); } this.listenerMap = null; } } @Override public void resourceChanged(IResourceChangeEvent event) { switch (event.getType()) { case IResourceChangeEvent.POST_CHANGE: if (event.getDelta() != null) { for (IResourceDelta child : event.getDelta().getAffectedChildren()) { if ((child.getFlags() & IResourceDelta.OPEN) != 0) { IResource resource = child.getResource(); // No need to check if the project is open, if it was being closed we wouldn't have gotten here. if (resource.getType() == IResource.PROJECT) { addDDListener(resource.getProject()); } } else if (child.getKind() == IResourceDelta.CHANGED) { IResource resource = child.getResource(); if (resource.getType() == IResource.PROJECT) { addDDListener(resource.getProject()); } } } } break; case IResourceChangeEvent.PRE_DELETE: case IResourceChangeEvent.PRE_CLOSE: IResource resource = event.getResource(); if (resource != null && resource.getType() == IResource.PROJECT) { removeDDListener(resource.getProject()); } break; } } private void addDDListener(IProject project) { synchronized (syncObj) { if (listenerMap == null || listenerMap.containsKey(project)) { return; } Preferences prefs = new ProjectScope(project).getNode(EDTCoreIDEPlugin.PLUGIN_ID).node(ProjectSettingsUtility.PROJECT_DEFAULT_DEPLOYMENT_DESCRIPTOR); if (prefs instanceof IEclipsePreferences) { DefaultDDPreferenceListener listener = new DefaultDDPreferenceListener(project); ((IEclipsePreferences)prefs).addPreferenceChangeListener(listener); listenerMap.put(project, listener); } } } private void removeDDListener(IProject project) { DefaultDDPreferenceListener listener; synchronized (syncObj) { if (listenerMap == null) { return; } listener = listenerMap.remove(project); } if (listener != null) { removeDDListener(listener); } } private void removeDDListener(DefaultDDPreferenceListener listener) { Preferences prefs = new ProjectScope(listener.project).getNode(EDTCoreIDEPlugin.PLUGIN_ID).node(ProjectSettingsUtility.PROJECT_DEFAULT_DEPLOYMENT_DESCRIPTOR); if (prefs instanceof IEclipsePreferences) { ((IEclipsePreferences)prefs).removePreferenceChangeListener(listener); } } /** * When the default DD for a project changes, then for any project with this project on the EGL path we need * to check if the settings should be updated on the server. */ private class DefaultDDPreferenceListener implements IPreferenceChangeListener { private final IProject project; DefaultDDPreferenceListener(IProject project) { this.project = project; } @Override public void preferenceChange(PreferenceChangeEvent event) { // For each config, have it update its settings if the project is on its EGL path. for (TestServerConfiguration config : contrib.getRunningConfigurationsCopy()) { if (config.isOnEGLPath(this.project)) { contrib.updateDDSettingsOnServer(config); } } } } }