diff options
| author | Hannes Wellmann | 2022-02-26 22:56:46 +0000 |
|---|---|---|
| committer | Hannes Wellmann | 2022-03-23 08:18:51 +0000 |
| commit | 15d4491246a0bc3eb19f874a4cd2774a1bdc2269 (patch) | |
| tree | fe679c6a5be57bd58caaa45f33cb03751a529705 | |
| parent | fb5ad5bf72c88c5f7bf6076abadbc5e488e897be (diff) | |
| download | eclipse.pde.ui-15d4491246a0bc3eb19f874a4cd2774a1bdc2269.tar.gz eclipse.pde.ui-15d4491246a0bc3eb19f874a4cd2774a1bdc2269.tar.xz eclipse.pde.ui-15d4491246a0bc3eb19f874a4cd2774a1bdc2269.zip | |
Bug 578990 - react to Bundle-Root setting changesI20220323-0740
Change-Id: I2cfa7841c7a64ac59fbd24dfc874de040057ca6a
Signed-off-by: Hannes Wellmann <wellmann.hannes1@gmx.net>
Reviewed-on: https://git.eclipse.org/r/c/pde/eclipse.pde.ui/+/191246
Tested-by: PDE Bot <pde-bot@eclipse.org>
6 files changed, 123 insertions, 21 deletions
diff --git a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/PluginModelManager.java b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/PluginModelManager.java index bf810b51ef..8cd46e9052 100644 --- a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/PluginModelManager.java +++ b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/PluginModelManager.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2018 IBM Corporation and others. + * Copyright (c) 2000, 2022 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -1239,21 +1239,4 @@ public class PluginModelManager implements IModelProviderListener { public void removeExtensionDeltaListener(IExtensionDeltaListener listener) { fWorkspaceManager.removeExtensionDeltaListener(listener); } - - /** - * Called when the bundle root for a project is changed. - * - * @param project - */ - public void bundleRootChanged(IProject project) { - fWorkspaceManager.initialize(); - fWorkspaceManager.removeModel(project); - if (fWorkspaceManager.isInterestingProject(project)) { - fWorkspaceManager.createModel(project, false); - IPluginModelBase model = fWorkspaceManager.getModel(project); - fWorkspaceManager.addChange(model, IModelProviderEvent.MODELS_CHANGED); - } - fWorkspaceManager.processModelChanges(); - } - } diff --git a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/WorkspaceModelManager.java b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/WorkspaceModelManager.java index f313971a60..3e0740cca2 100644 --- a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/WorkspaceModelManager.java +++ b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/WorkspaceModelManager.java @@ -10,6 +10,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Hannes Wellmann - react to changes of Bundle-Root setting and in derived folders *******************************************************************************/ package org.eclipse.pde.internal.core; @@ -17,11 +18,14 @@ import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.LinkedHashMap; import java.util.ListIterator; import java.util.Map; +import java.util.Objects; +import java.util.stream.Stream; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; @@ -31,11 +35,18 @@ import org.eclipse.core.resources.IResourceChangeListener; import org.eclipse.core.resources.IResourceDelta; import org.eclipse.core.resources.IResourceDeltaVisitor; import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.ProjectScope; +import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.preferences.IEclipsePreferences; +import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener; import org.eclipse.pde.core.IModel; import org.eclipse.pde.core.IModelProviderEvent; import org.eclipse.pde.internal.core.project.PDEProject; import org.eclipse.team.core.RepositoryProvider; +import org.osgi.service.prefs.BackingStoreException; +import org.osgi.service.prefs.Preferences; public abstract class WorkspaceModelManager<T> extends AbstractModelManager implements IResourceChangeListener, IResourceDeltaVisitor { @@ -96,6 +107,7 @@ public abstract class WorkspaceModelManager<T> extends AbstractModelManager private Map<IProject, T> fModels = null; private ArrayList<ModelChange> fChangedModels; + private final IPreferenceChangeListener bundleRootChangedListener = createBundleRootChangeListener(); protected Map<IProject, T> getModelsMap() { ensureModelsMapCreated(); @@ -133,6 +145,9 @@ public abstract class WorkspaceModelManager<T> extends AbstractModelManager protected void addListeners() { IWorkspace workspace = PDECore.getWorkspace(); workspace.addResourceChangeListener(this, IResourceChangeEvent.PRE_CLOSE | IResourceChangeEvent.POST_CHANGE); + if (bundleRootChangedListener != null) { + Arrays.stream(workspace.getRoot().getProjects()).forEach(this::addBundleRootChangedListener); + } } @Override @@ -180,6 +195,9 @@ public abstract class WorkspaceModelManager<T> extends AbstractModelManager IProject project = (IProject) resource; boolean addedOrOpened = delta.getKind() == IResourceDelta.ADDED || (delta.getFlags() & IResourceDelta.OPEN) != 0; + if (addedOrOpened && bundleRootChangedListener != null) { + addBundleRootChangedListener(project); + } if (isInterestingProject(project) && addedOrOpened) { createModel(project, true); return false; @@ -202,6 +220,39 @@ public abstract class WorkspaceModelManager<T> extends AbstractModelManager return false; } + private void addBundleRootChangedListener(IProject project) { + IEclipsePreferences pdeNode = new ProjectScope(project).getNode(PDECore.PLUGIN_ID); + // Always add the same listener instance to not add multiple listeners + // in case of repetitive project opening/closing + pdeNode.addPreferenceChangeListener(bundleRootChangedListener); + } + + protected IPreferenceChangeListener createBundleRootChangeListener() { + return e -> { + if (PDEProject.BUNDLE_ROOT_PATH.equals(e.getKey()) && !isInRemovedBranch(e.getNode())) { + String projectName = Path.forPosix(e.getNode().absolutePath()).segment(1); + IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName); + + // bundle-root changed (null value means default): try to + // (re-)load model from new bundle-root path (may delete it) + if (getModel(project) != null) { + removeModel(project); + } + createModel(project, true); + } + }; + } + + private static boolean isInRemovedBranch(Preferences node) { + return !Stream.iterate(node, Objects::nonNull, Preferences::parent).allMatch(n -> { + try { // Returns true if existing node is about to be removed + return n.nodeExists(""); //$NON-NLS-1$ + } catch (BackingStoreException e1) { + return false; + } + }); + } + private boolean isContentChange(IResourceDelta delta) { int kind = delta.getKind(); return (kind == IResourceDelta.ADDED || kind == IResourceDelta.REMOVED || (kind == IResourceDelta.CHANGED && (delta.getFlags() & IResourceDelta.CONTENT) != 0)); diff --git a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/WorkspacePluginModelManager.java b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/WorkspacePluginModelManager.java index e60e790b07..a726211f24 100644 --- a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/WorkspacePluginModelManager.java +++ b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/WorkspacePluginModelManager.java @@ -449,6 +449,8 @@ public class WorkspacePluginModelManager extends WorkspaceModelManager<IPluginMo */ @Override protected void addListeners() { + super.addListeners(); + // Overwrite resource-change event-mask set in the super implementation: PDECore.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.PRE_CLOSE); // PDE must process the POST_CHANGE events before the Java model // for the PDE container classpath update to proceed smoothly diff --git a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/project/PDEProject.java b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/project/PDEProject.java index 7173de273f..53f6feb94f 100644 --- a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/project/PDEProject.java +++ b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/project/PDEProject.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010, 2013 IBM Corporation and others. + * Copyright (c) 2010, 2022 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -135,8 +135,7 @@ public class PDEProject { } try { node.flush(); - // update model manager - PDECore.getDefault().getModelManager().bundleRootChanged(project); + // WorkspacePluginModelManager reacts to setting changes } catch (BackingStoreException e) { throw new CoreException(Status.error(e.getMessage(), e)); } diff --git a/ui/org.eclipse.pde.ui.tests/src/org/eclipse/pde/core/tests/internal/WorkspaceModelManagerTest.java b/ui/org.eclipse.pde.ui.tests/src/org/eclipse/pde/core/tests/internal/WorkspaceModelManagerTest.java index b3ba65a2f6..b6b34c4346 100644 --- a/ui/org.eclipse.pde.ui.tests/src/org/eclipse/pde/core/tests/internal/WorkspaceModelManagerTest.java +++ b/ui/org.eclipse.pde.ui.tests/src/org/eclipse/pde/core/tests/internal/WorkspaceModelManagerTest.java @@ -170,6 +170,67 @@ public class WorkspaceModelManagerTest { assertNull(mm.getModel(project)); } + @Test + public void testBundleRootHandling_bundleRootChangedFromDefaultToOthersAndReverse() throws Exception { + TestWorkspaceModelManager mm = createWorkspaceModelManager(); + IProject project = createModelProject("plugin.a", "1.0.0"); + copyFile(manifest(project), manifestIn(project, "otherRoot"), replaceVersionTo("2.0.0")); + copyFile(manifest(project), manifestIn(project, "root2"), replaceVersionTo("3.0.0")); + + setBundleRoot(project, "otherRoot"); + + IPluginModelBase model1 = mm.getModel(project); + assertExistingModel("plugin.a", "2.0.0", model1); + assertEquals(manifestIn(project, "otherRoot"), model1.getUnderlyingResource()); + + setBundleRoot(project, "root2"); + + IPluginModelBase model2 = mm.getModel(project); + assertExistingModel("plugin.a", "3.0.0", model2); + assertEquals(manifestIn(project, "root2"), model2.getUnderlyingResource()); + + setBundleRoot(project, null); + + IPluginModelBase model0 = mm.getModel(project); + assertExistingModel("plugin.a", "1.0.0", model0); + assertEquals(manifest(project), model0.getUnderlyingResource()); + } + + @Test + public void testBundleRootHandling_bundleRootChangedFromNoneToOther() throws Exception { + TestWorkspaceModelManager mm = createWorkspaceModelManager(); + IProject project = createModelProject("plugin.a", "1.0.0"); + + copyFile(manifest(project), manifestIn(project, "otherRoot"), replaceVersionTo("2.0.0")); + + manifest(project).delete(true, null); + assertNull(mm.getModel(project)); + + setBundleRoot(project, "otherRoot"); + + IPluginModelBase model = mm.getModel(project); + assertExistingModel("plugin.a", "2.0.0", model); + assertEquals(manifestIn(project, "otherRoot"), model.getUnderlyingResource()); + } + + @Test + public void testBundleRootHandling_bundleRootChangedFromNoneToDefault() throws Exception { + TestWorkspaceModelManager mm = createWorkspaceModelManager(); + IProject project = createModelProject("plugin.a", "1.0.0"); + + copyFile(manifest(project), manifestIn(project, "otherRoot"), replaceVersionTo("2.0.0")); + setBundleRoot(project, "otherRoot"); + + manifestIn(project, "otherRoot").delete(true, null); + assertNull(mm.getModel(project)); + + setBundleRoot(project, null); + + IPluginModelBase model = mm.getModel(project); + assertExistingModel("plugin.a", "1.0.0", model); + assertEquals(manifest(project), model.getUnderlyingResource()); + } + // --- utilities --- // This class tests tests the abstract WorkspaceModelManager using the diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/views/features/model/WorkspaceProductModelManager.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/views/features/model/WorkspaceProductModelManager.java index d6bb85671b..4b127ad43f 100644 --- a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/views/features/model/WorkspaceProductModelManager.java +++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/views/features/model/WorkspaceProductModelManager.java @@ -17,6 +17,7 @@ import java.util.ArrayList; import java.util.Collection; import org.eclipse.core.resources.*; import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener; import org.eclipse.jdt.core.JavaCore; import org.eclipse.pde.core.IModelProviderEvent; import org.eclipse.pde.internal.core.WorkspaceModelManager; @@ -28,6 +29,11 @@ public class WorkspaceProductModelManager extends WorkspaceModelManager<Collecti public final static String PRODUCT_FILENAME_SUFFIX = ".product"; //$NON-NLS-1$ @Override + protected IPreferenceChangeListener createBundleRootChangeListener() { + return null; // ignore bundle-root changes + } + + @Override protected boolean isInterestingProject(IProject project) { return (project.isOpen() && !findProductFiles(project, false).isEmpty()); } |
