From 57afab135d591e8505645eda9bf2937394269db1 Mon Sep 17 00:00:00 2001 From: Andrew Gvozdev Date: Thu, 22 Sep 2011 21:37:18 -0400 Subject: [PATCH] Support for global (workspace level) IResourceChangeListener providers --- .../LanguageSettingsExtensionManager.java | 143 -------------- .../LanguageSettingsProvidersSerializer.java | 187 +++++++++++++++++- .../model/CConfigurationSpecSettings.java | 3 +- .../xml/XmlProjectDescriptionStorage.java | 3 +- 4 files changed, 186 insertions(+), 150 deletions(-) diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/language/settings/providers/LanguageSettingsExtensionManager.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/language/settings/providers/LanguageSettingsExtensionManager.java index 9bb935d61cd..53d271faa61 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/language/settings/providers/LanguageSettingsExtensionManager.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/language/settings/providers/LanguageSettingsExtensionManager.java @@ -12,7 +12,6 @@ package org.eclipse.cdt.internal.core.language.settings.providers; import java.util.ArrayList; -import java.util.Collection; import java.util.Comparator; import java.util.HashMap; import java.util.LinkedHashMap; @@ -25,13 +24,11 @@ import org.eclipse.cdt.core.AbstractExecutableExtensionBase; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsProvider; import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsBaseProvider; -import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsManager; import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsSerializable; import org.eclipse.cdt.core.model.ILanguage; import org.eclipse.cdt.core.model.LanguageManager; import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry; -import org.eclipse.cdt.core.settings.model.ICProjectDescription; import org.eclipse.cdt.core.settings.model.ICSettingEntry; import org.eclipse.cdt.core.settings.model.ILanguageSettingsEditableProvider; import org.eclipse.cdt.core.settings.model.util.CDataUtil; @@ -40,10 +37,7 @@ import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; -import org.eclipse.core.resources.IResourceChangeListener; -import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.IWorkspaceRoot; -import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; @@ -618,142 +612,5 @@ public class LanguageSettingsExtensionManager { ILanguageSettingsProvider extensionProvider = fExtensionProviders.get(id); return provider.equals(extensionProvider); } - - /** - * TODO - remove me - * Temporary method to report inconsistency in log. - */ - @Deprecated - public static void assertConsistency(ICProjectDescription prjDescription) { - if (prjDescription != null) { - List prjProviders = new ArrayList(); - for (ICConfigurationDescription cfgDescription : prjDescription.getConfigurations()) { - List providers = cfgDescription.getLanguageSettingProviders(); - for (ILanguageSettingsProvider provider : providers) { - if (!LanguageSettingsManager.isWorkspaceProvider(provider)) { - if (isObjectInTheList(prjProviders, provider)) { - IStatus status = new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, "Inconsistent state, duplicate LSP in project description " - + "[" + System.identityHashCode(provider) + "] " - + provider); - CoreException e = new CoreException(status); - CCorePlugin.log(e); - } - prjProviders.add(provider); - } - } - } - } - } - - /** - * TODO - remove me - * Temporary method to report inconsistency in log. - */ - @Deprecated - public static void assertConsistency(ICConfigurationDescription cfgDescription) { - List listeners = new ArrayList(); - List providers = cfgDescription.getLanguageSettingProviders(); - for (ILanguageSettingsProvider provider : providers) { - if (isObjectInTheList(listeners, provider)) { - IStatus status = new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, "Inconsistent state, duplicate LSP in project description " + provider); - CoreException e = new CoreException(status); - CCorePlugin.log(e); - } - listeners.add(provider); - } - } - - /** - * Get a providers list including only providers of type IResourceChangeListener - * for a given project description - collecting from all configurations. - */ - private static List getResourceChangeListeners(ICProjectDescription prjDescription) { - List listeners = new ArrayList(); - if (prjDescription != null) { - for (ICConfigurationDescription cfgDescription : prjDescription.getConfigurations()) { - List providers = cfgDescription.getLanguageSettingProviders(); - for (ILanguageSettingsProvider provider : providers) { - if (provider instanceof IResourceChangeListener) { - listeners.add((IResourceChangeListener) provider); - } - } - } - } - return listeners; - } - - /** - * Unregister listeners which are not used anymore and register new listeners. - * The method is used when project description is applied to workspace. - * @param oldPrjDescription - old project descriptions being replaced in the workspace. - * @param newPrjDescription - new project description being applied to the workspace. - */ - public static void reRegisterListeners(ICProjectDescription oldPrjDescription, ICProjectDescription newPrjDescription) { - if (oldPrjDescription == newPrjDescription) { - assertConsistency(oldPrjDescription); // TODO - remove me - return; - } - - assertConsistency(oldPrjDescription); // TODO - remove me - assertConsistency(newPrjDescription); // TODO - remove me - - IWorkspace workspace = ResourcesPlugin.getWorkspace(); - - List oldListeners = getResourceChangeListeners(oldPrjDescription); - List newListeners = getResourceChangeListeners(newPrjDescription); - - for (IResourceChangeListener listener : oldListeners) { - if (!isObjectInTheList(newListeners, listener)) { - workspace.removeResourceChangeListener(listener); - // TODO - remove me - CCorePlugin.log(new Status(IStatus.WARNING,CCorePlugin.PLUGIN_ID, oldPrjDescription.getProject() + ": Removed IResourceChangeListener " - + "[" + System.identityHashCode(listener) + "] " - + listener)); - } - } - - for (IResourceChangeListener listener : newListeners) { - if (!isObjectInTheList(oldListeners, listener)) { - workspace.addResourceChangeListener(listener); - // TODO - remove me - CCorePlugin.log(new Status(IStatus.WARNING,CCorePlugin.PLUGIN_ID, newPrjDescription.getProject() + ": Added IResourceChangeListener " - + "[" + System.identityHashCode(listener) + "] " - + listener)); - } - } - - } - - private static boolean isObjectInTheList(Collection list, T element) { - // list.contains(element) won't do it as we are interested in exact object, not in equal object - for (T elem : list) { - if (elem == element) - return true; - } - return false; - } - - /** - * Deep clone of a list of language settings providers. - * - * @param baseProviders - list of providers to clone. - * @return newly cloned list. - */ - public static List cloneProviders(List baseProviders) { - List newProviders = new ArrayList(); - for (ILanguageSettingsProvider provider : baseProviders) { - if (provider instanceof ILanguageSettingsEditableProvider) { - try { - provider = ((ILanguageSettingsEditableProvider) provider).clone(); - } catch (CloneNotSupportedException e) { - IStatus status = new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, "Not able to clone provider " + provider.getClass()); - CCorePlugin.log(new CoreException(status)); - } - } - newProviders.add(provider); - } - return new ArrayList(newProviders); - } - } diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/language/settings/providers/LanguageSettingsProvidersSerializer.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/language/settings/providers/LanguageSettingsProvidersSerializer.java index 954461c3e75..e81dd9ca1ca 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/language/settings/providers/LanguageSettingsProvidersSerializer.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/language/settings/providers/LanguageSettingsProvidersSerializer.java @@ -13,12 +13,14 @@ package org.eclipse.cdt.internal.core.language.settings.providers; import java.net.URI; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsProvider; +import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsManager; import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsSerializable; import org.eclipse.cdt.core.language.settings.providers.ScannerDiscoveryLegacySupport; import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; @@ -31,6 +33,10 @@ import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; 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.IWorkspace; +import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; @@ -58,9 +64,11 @@ public class LanguageSettingsProvidersSerializer { private static ILock serializingLock = Job.getJobManager().newLock(); /** Cache of globally available providers to be consumed by calling clients */ private static Map rawGlobalWorkspaceProviders = new HashMap(); + private static Map globalWorkspaceProviders = new HashMap(); - private static class LanguageSettingsWorkspaceProvider implements ILanguageSettingsProvider { + private static class LanguageSettingsWorkspaceProvider implements ILanguageSettingsProvider, IResourceChangeListener { private String providerId; + private int registrationCount = 0; public LanguageSettingsWorkspaceProvider(String id) { Assert.isNotNull(id); @@ -107,6 +115,25 @@ public class LanguageSettingsProvidersSerializer { public String toString() { return "id="+getId()+", name="+getName(); } + + /** + * {@inheritDoc} + * + * LanguageSettingsWorkspaceProvider delegates event handling to raw provider. + * + */ + public void resourceChanged(IResourceChangeEvent event) { + // keep in mind that type of rawProvider can change + ILanguageSettingsProvider rawProvider = getRawProvider(); + if (rawProvider instanceof IResourceChangeListener) { + ((IResourceChangeListener) rawProvider).resourceChanged(event); + } + } + + synchronized int incrementListenerCount(int inc) { + registrationCount += inc; + return registrationCount; + } } @@ -565,7 +592,12 @@ public class LanguageSettingsProvidersSerializer { * @return the provider or {@code null} if provider is not defined. */ public static ILanguageSettingsProvider getWorkspaceProvider(String id) { - return new LanguageSettingsWorkspaceProvider(id); + ILanguageSettingsProvider provider = globalWorkspaceProviders.get(id); + if (provider == null) { + provider = new LanguageSettingsWorkspaceProvider(id); + globalWorkspaceProviders.put(id, provider); + } + return provider; } public static ILanguageSettingsProvider getRawWorkspaceProvider(String id) { @@ -580,7 +612,7 @@ public class LanguageSettingsProvidersSerializer { public static List getWorkspaceProviders() { ArrayList workspaceProviders = new ArrayList(); for (ILanguageSettingsProvider rawProvider : rawGlobalWorkspaceProviders.values()) { - workspaceProviders.add(new LanguageSettingsWorkspaceProvider(rawProvider.getId())); + workspaceProviders.add(getWorkspaceProvider(rawProvider.getId())); } return workspaceProviders; } @@ -595,4 +627,153 @@ public class LanguageSettingsProvidersSerializer { public static boolean isWorkspaceProvider(ILanguageSettingsProvider provider) { return provider instanceof LanguageSettingsWorkspaceProvider; } + + /** + * TODO - remove me + * Temporary method to report inconsistency in log. + */ + @Deprecated + public static void assertConsistency(ICProjectDescription prjDescription) { + if (prjDescription != null) { + List prjProviders = new ArrayList(); + for (ICConfigurationDescription cfgDescription : prjDescription.getConfigurations()) { + List providers = cfgDescription.getLanguageSettingProviders(); + for (ILanguageSettingsProvider provider : providers) { + if (!LanguageSettingsManager.isWorkspaceProvider(provider)) { + if (isObjectInTheList(prjProviders, provider)) { + IStatus status = new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, "Inconsistent state, duplicate LSP in project description " + + "[" + System.identityHashCode(provider) + "] " + + provider); + CoreException e = new CoreException(status); + CCorePlugin.log(e); + } + prjProviders.add(provider); + } + } + } + } + } + + /** + * TODO - remove me + * Temporary method to report inconsistency in log. + */ + @Deprecated + public static void assertConsistency(ICConfigurationDescription cfgDescription) { + List listeners = new ArrayList(); + List providers = cfgDescription.getLanguageSettingProviders(); + for (ILanguageSettingsProvider provider : providers) { + if (isObjectInTheList(listeners, provider)) { + IStatus status = new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, "Inconsistent state, duplicate LSP in project description " + provider); + CoreException e = new CoreException(status); + CCorePlugin.log(e); + } + listeners.add(provider); + } + } + + /** + * Get a providers list including only providers of type IResourceChangeListener + * for a given project description - collecting from all configurations. + */ + private static List getResourceChangeListeners(ICProjectDescription prjDescription) { + List listeners = new ArrayList(); + if (prjDescription != null) { + for (ICConfigurationDescription cfgDescription : prjDescription.getConfigurations()) { + List providers = cfgDescription.getLanguageSettingProviders(); + for (ILanguageSettingsProvider provider : providers) { + if (provider instanceof IResourceChangeListener) { + listeners.add((IResourceChangeListener) provider); + } + } + } + } + return listeners; + } + + /** + * Unregister listeners which are not used anymore and register new listeners. + * The method is used when project description is applied to workspace. + * @param oldPrjDescription - old project descriptions being replaced in the workspace. + * @param newPrjDescription - new project description being applied to the workspace. + */ + public static void reRegisterListeners(ICProjectDescription oldPrjDescription, ICProjectDescription newPrjDescription) { + if (oldPrjDescription == newPrjDescription) { + assertConsistency(oldPrjDescription); // TODO - remove me + return; + } + + assertConsistency(oldPrjDescription); // TODO - remove me + assertConsistency(newPrjDescription); // TODO - remove me + + IWorkspace workspace = ResourcesPlugin.getWorkspace(); + + List oldListeners = getResourceChangeListeners(oldPrjDescription); + List newListeners = getResourceChangeListeners(newPrjDescription); + + for (IResourceChangeListener listener : oldListeners) { + if (!isObjectInTheList(newListeners, listener)) { + int count = 0; + if (listener instanceof LanguageSettingsWorkspaceProvider) { + count = ((LanguageSettingsWorkspaceProvider) listener).incrementListenerCount(-1); + } + if (count == 0) { + workspace.removeResourceChangeListener(listener); + // TODO - remove me + CCorePlugin.log(new Status(IStatus.WARNING,CCorePlugin.PLUGIN_ID, oldPrjDescription.getProject() + ": Removed IResourceChangeListener " + + "[" + System.identityHashCode(listener) + "] " + + listener)); + } + } + } + + for (IResourceChangeListener listener : newListeners) { + if (!isObjectInTheList(oldListeners, listener)) { + int count = 1; + if (listener instanceof LanguageSettingsWorkspaceProvider) { + count = ((LanguageSettingsWorkspaceProvider) listener).incrementListenerCount(1); + } + if (count == 1) { + workspace.addResourceChangeListener(listener); + // TODO - remove me + CCorePlugin.log(new Status(IStatus.WARNING,CCorePlugin.PLUGIN_ID, newPrjDescription.getProject() + ": Added IResourceChangeListener " + + "[" + System.identityHashCode(listener) + "] " + + listener)); + } + } + } + + } + + private static boolean isObjectInTheList(Collection list, T element) { + // list.contains(element) won't do it as we are interested in exact object, not in equal object + for (T elem : list) { + if (elem == element) + return true; + } + return false; + } + + /** + * Deep clone of a list of language settings providers. + * + * @param baseProviders - list of providers to clone. + * @return newly cloned list. + */ + public static List cloneProviders(List baseProviders) { + List newProviders = new ArrayList(); + for (ILanguageSettingsProvider provider : baseProviders) { + if (provider instanceof ILanguageSettingsEditableProvider) { + try { + provider = ((ILanguageSettingsEditableProvider) provider).clone(); + } catch (CloneNotSupportedException e) { + IStatus status = new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, "Not able to clone provider " + provider.getClass()); + CCorePlugin.log(new CoreException(status)); + } + } + newProviders.add(provider); + } + return new ArrayList(newProviders); + } + } diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/CConfigurationSpecSettings.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/CConfigurationSpecSettings.java index 60418d3431a..d63af54e1a2 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/CConfigurationSpecSettings.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/CConfigurationSpecSettings.java @@ -41,7 +41,6 @@ import org.eclipse.cdt.internal.core.COwner; import org.eclipse.cdt.internal.core.COwnerConfiguration; import org.eclipse.cdt.internal.core.cdtvariables.StorableCdtVariables; import org.eclipse.cdt.internal.core.envvar.EnvironmentVariableManager; -import org.eclipse.cdt.internal.core.language.settings.providers.LanguageSettingsExtensionManager; import org.eclipse.cdt.internal.core.language.settings.providers.LanguageSettingsProvidersSerializer; import org.eclipse.cdt.utils.envvar.StorableEnvironment; import org.eclipse.core.runtime.CoreException; @@ -189,7 +188,7 @@ public class CConfigurationSpecSettings implements ICSettingsStorage{ copyExtensionInfo(base); - fLanguageSettingsProviders = LanguageSettingsExtensionManager.cloneProviders(base.getLanguageSettingProviders()); + fLanguageSettingsProviders = LanguageSettingsProvidersSerializer.cloneProviders(base.getLanguageSettingProviders()); } // private void copyRefInfos(Map infosMap){ diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/xml/XmlProjectDescriptionStorage.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/xml/XmlProjectDescriptionStorage.java index 61649f71125..32a44e2c568 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/xml/XmlProjectDescriptionStorage.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/xml/XmlProjectDescriptionStorage.java @@ -42,7 +42,6 @@ import org.eclipse.cdt.core.settings.model.extension.ICProjectConverter; import org.eclipse.cdt.core.settings.model.util.CDataUtil; import org.eclipse.cdt.internal.core.XmlUtil; import org.eclipse.cdt.internal.core.envvar.ContributedEnvironment; -import org.eclipse.cdt.internal.core.language.settings.providers.LanguageSettingsExtensionManager; import org.eclipse.cdt.internal.core.language.settings.providers.LanguageSettingsProvidersSerializer; import org.eclipse.cdt.internal.core.settings.model.AbstractCProjectDescriptionStorage; import org.eclipse.cdt.internal.core.settings.model.CProjectDescription; @@ -377,7 +376,7 @@ public class XmlProjectDescriptionStorage extends AbstractCProjectDescriptionSto fProjectDescription = new SoftReference(null); } - LanguageSettingsExtensionManager.reRegisterListeners(oldDes, fProjectDescription.get()); + LanguageSettingsProvidersSerializer.reRegisterListeners(oldDes, fProjectDescription.get()); return true; }