Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEd Merks2020-09-17 14:06:42 +0000
committerEd Merks2020-09-17 14:06:42 +0000
commit684fca6acf66f6e7810cee53299fadf0d9fae827 (patch)
tree15c153b5660b534a28884b5fac89a1cb06420f20
parent2d4fa9f4703efdd5b3aa7feea16947892ed1aeca (diff)
downloadorg.eclipse.emf-684fca6acf66f6e7810cee53299fadf0d9fae827.tar.gz
org.eclipse.emf-684fca6acf66f6e7810cee53299fadf0d9fae827.tar.xz
org.eclipse.emf-684fca6acf66f6e7810cee53299fadf0d9fae827.zip
[566747] FindAndReplaceTarget prevents garbage collection of EcoreEditor
leading to memory exhaustion
-rw-r--r--features/org.eclipse.emf-feature/feature.xml2
-rw-r--r--features/org.eclipse.emf-feature/pom.xml2
-rw-r--r--features/org.eclipse.emf.edit.ui-feature/feature.xml2
-rw-r--r--features/org.eclipse.emf.edit.ui-feature/pom.xml2
-rw-r--r--plugins/org.eclipse.emf.edit.ui/META-INF/MANIFEST.MF2
-rw-r--r--plugins/org.eclipse.emf.edit.ui/pom.xml2
-rw-r--r--plugins/org.eclipse.emf.edit.ui/src/org/eclipse/emf/edit/ui/util/FindAndReplaceTarget.java102
7 files changed, 104 insertions, 10 deletions
diff --git a/features/org.eclipse.emf-feature/feature.xml b/features/org.eclipse.emf-feature/feature.xml
index 8a1938346..04aa184d7 100644
--- a/features/org.eclipse.emf-feature/feature.xml
+++ b/features/org.eclipse.emf-feature/feature.xml
@@ -2,7 +2,7 @@
<feature
id="org.eclipse.emf"
label="%featureName"
- version="2.23.0.qualifier"
+ version="2.24.0.qualifier"
provider-name="%providerName"
license-feature="org.eclipse.emf.license"
license-feature-version="2.11.0">
diff --git a/features/org.eclipse.emf-feature/pom.xml b/features/org.eclipse.emf-feature/pom.xml
index 4f3d8b9cf..6b2bddb79 100644
--- a/features/org.eclipse.emf-feature/pom.xml
+++ b/features/org.eclipse.emf-feature/pom.xml
@@ -12,7 +12,7 @@
<groupId>org.eclipse.emf.features</groupId>
<artifactId>org.eclipse.emf</artifactId>
- <version>2.23.0-SNAPSHOT</version>
+ <version>2.24.0-SNAPSHOT</version>
<packaging>eclipse-feature</packaging>
</project>
diff --git a/features/org.eclipse.emf.edit.ui-feature/feature.xml b/features/org.eclipse.emf.edit.ui-feature/feature.xml
index 68acb5ab2..5aed7826c 100644
--- a/features/org.eclipse.emf.edit.ui-feature/feature.xml
+++ b/features/org.eclipse.emf.edit.ui-feature/feature.xml
@@ -2,7 +2,7 @@
<feature
id="org.eclipse.emf.edit.ui"
label="%featureName"
- version="2.19.0.qualifier"
+ version="2.20.0.qualifier"
provider-name="%providerName"
license-feature="org.eclipse.emf.license"
license-feature-version="2.11.0">
diff --git a/features/org.eclipse.emf.edit.ui-feature/pom.xml b/features/org.eclipse.emf.edit.ui-feature/pom.xml
index 033492e51..2a62327d8 100644
--- a/features/org.eclipse.emf.edit.ui-feature/pom.xml
+++ b/features/org.eclipse.emf.edit.ui-feature/pom.xml
@@ -12,7 +12,7 @@
<groupId>org.eclipse.emf.features</groupId>
<artifactId>org.eclipse.emf.edit.ui</artifactId>
- <version>2.19.0-SNAPSHOT</version>
+ <version>2.20.0-SNAPSHOT</version>
<packaging>eclipse-feature</packaging>
</project>
diff --git a/plugins/org.eclipse.emf.edit.ui/META-INF/MANIFEST.MF b/plugins/org.eclipse.emf.edit.ui/META-INF/MANIFEST.MF
index d3d62b98c..d20c8fe1a 100644
--- a/plugins/org.eclipse.emf.edit.ui/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.emf.edit.ui/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.emf.edit.ui;singleton:=true
-Bundle-Version: 2.18.0.qualifier
+Bundle-Version: 2.19.0.qualifier
Bundle-ClassPath: .
Bundle-Activator: org.eclipse.emf.edit.ui.EMFEditUIPlugin$Implementation
Bundle-Vendor: %providerName
diff --git a/plugins/org.eclipse.emf.edit.ui/pom.xml b/plugins/org.eclipse.emf.edit.ui/pom.xml
index 9ea2c9548..88acd3202 100644
--- a/plugins/org.eclipse.emf.edit.ui/pom.xml
+++ b/plugins/org.eclipse.emf.edit.ui/pom.xml
@@ -12,7 +12,7 @@
<groupId>org.eclipse.emf</groupId>
<artifactId>org.eclipse.emf.edit.ui</artifactId>
- <version>2.18.0-SNAPSHOT</version>
+ <version>2.19.0-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>
</project>
diff --git a/plugins/org.eclipse.emf.edit.ui/src/org/eclipse/emf/edit/ui/util/FindAndReplaceTarget.java b/plugins/org.eclipse.emf.edit.ui/src/org/eclipse/emf/edit/ui/util/FindAndReplaceTarget.java
index f9e2eb08b..269d721fd 100644
--- a/plugins/org.eclipse.emf.edit.ui/src/org/eclipse/emf/edit/ui/util/FindAndReplaceTarget.java
+++ b/plugins/org.eclipse.emf.edit.ui/src/org/eclipse/emf/edit/ui/util/FindAndReplaceTarget.java
@@ -9,6 +9,7 @@ package org.eclipse.emf.edit.ui.util;
import java.lang.reflect.Field;
+import java.lang.reflect.Method;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Collection;
@@ -21,7 +22,6 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
-import java.util.WeakHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -96,6 +96,7 @@ import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
+import org.eclipse.ui.IPartListener;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
@@ -141,7 +142,7 @@ public final class FindAndReplaceTarget implements IFindReplaceTarget, IFindRepl
/**
* A map for managing the association between a workbench part and it associated find and replace target.
*/
- private static final Map<IWorkbenchPart, FindAndReplaceTarget> FIND_AND_REPLACE_TARGETS = new WeakHashMap<IWorkbenchPart, FindAndReplaceTarget>();
+ private static final Map<IWorkbenchPart, FindAndReplaceTarget> FIND_AND_REPLACE_TARGETS = new HashMap<IWorkbenchPart, FindAndReplaceTarget>();
/**
* A styler for drawing a box around matching text.
@@ -165,16 +166,25 @@ public final class FindAndReplaceTarget implements IFindReplaceTarget, IFindRepl
*/
private static final Field F_SELECTED_RANGE_RADIO_BUTTON_FIELD;
+ /**
+ * Provides access to the {@code fTarget} of a {@code org.eclipse.ui.texteditor.FindReplaceDialog}.
+ */
+ private static final Field F_TARGET_FIELD;
+
static
{
Field fIsRegExCheckBoxField = null;
Field fSelectedRangeRadioButtonField = null;
+ Field fTarget = null;
try
{
Class<?> findReplaceDialogClass = CommonPlugin.loadClass("org.eclipse.ui.workbench.texteditor", "org.eclipse.ui.texteditor.FindReplaceDialog");
fIsRegExCheckBoxField = findReplaceDialogClass.getDeclaredField("fIsRegExCheckBox");
fIsRegExCheckBoxField.setAccessible(true);
fSelectedRangeRadioButtonField = findReplaceDialogClass.getDeclaredField("fSelectedRangeRadioButton");
+ fSelectedRangeRadioButtonField.setAccessible(true);
+ fTarget = findReplaceDialogClass.getDeclaredField("fTarget");
+ fTarget.setAccessible(true);
}
catch (Throwable throwable)
{
@@ -182,6 +192,7 @@ public final class FindAndReplaceTarget implements IFindReplaceTarget, IFindRepl
}
F_IS_REGEX_CHECK_BOX_FIELD = fIsRegExCheckBoxField;
F_SELECTED_RANGE_RADIO_BUTTON_FIELD = fSelectedRangeRadioButtonField;
+ F_TARGET_FIELD = fTarget;
}
/**
@@ -191,6 +202,41 @@ public final class FindAndReplaceTarget implements IFindReplaceTarget, IFindRepl
private static final Map<Font, Font> TINY_FONT = new HashMap<Font, Font>();
/**
+ * A listener for when parts are closed to clean up the {@link #FIND_AND_REPLACE_TARGETS}.
+ * @see #getAdapter(Class, IWorkbenchPart, AbstractUIPlugin)
+ */
+ private static final IPartListener PART_LISTENER = new IPartListener()
+ {
+ public void partOpened(IWorkbenchPart part)
+ {
+ }
+
+ public void partDeactivated(IWorkbenchPart part)
+ {
+ }
+
+ public void partClosed(IWorkbenchPart part)
+ {
+ synchronized (FIND_AND_REPLACE_TARGETS)
+ {
+ FindAndReplaceTarget findAndReplaceTarget = FIND_AND_REPLACE_TARGETS.remove(part);
+ if (findAndReplaceTarget != null)
+ {
+ findAndReplaceTarget.dispose();
+ }
+ }
+ }
+
+ public void partBroughtToTop(IWorkbenchPart part)
+ {
+ }
+
+ public void partActivated(IWorkbenchPart part)
+ {
+ }
+ };
+
+ /**
* The workbench part of this find and replace target.
*/
private final IWorkbenchPart workbenchPart;
@@ -222,6 +268,14 @@ public final class FindAndReplaceTarget implements IFindReplaceTarget, IFindRepl
private Runnable sessionCleanup;
/**
+ * A cleanup action for when the workbench part is disposed.
+ *
+ * @see #addSearchTypeControl()
+ * @see #dispose()
+ */
+ private Runnable disposeCleanup;
+
+ /**
* If an advanced property needs to be displayed for search results and that action is currently not checked,
* it will be checked and this cleanup action will be set to restore the state when the session ends.
*
@@ -323,6 +377,7 @@ public final class FindAndReplaceTarget implements IFindReplaceTarget, IFindRepl
FindAndReplaceTarget findAndReplaceTarget = FindAndReplaceTarget.FIND_AND_REPLACE_TARGETS.get(workbenchPart);
if (findAndReplaceTarget == null)
{
+ workbenchPart.getSite().getPage().addPartListener(PART_LISTENER);
findAndReplaceTarget = new FindAndReplaceTarget(workbenchPart, plugin);
FindAndReplaceTarget.FIND_AND_REPLACE_TARGETS.put(workbenchPart, findAndReplaceTarget);
}
@@ -549,7 +604,7 @@ public final class FindAndReplaceTarget implements IFindReplaceTarget, IFindRepl
if (data instanceof Dialog && "org.eclipse.ui.texteditor.FindReplaceDialog".equals(data.getClass().getName()))
{
// Find the last checkbox in the dialog.
- Dialog dialog = (Dialog)data;
+ final Dialog dialog = (Dialog)data;
Object checkBox = getFieldValue(dialog, F_IS_REGEX_CHECK_BOX_FIELD);
if (checkBox instanceof Button)
{
@@ -689,6 +744,34 @@ public final class FindAndReplaceTarget implements IFindReplaceTarget, IFindRepl
{
categoriesChangeCleanup.run();
}
+
+ sessionCleanup = null;
+ }
+ };
+
+ disposeCleanup = new Runnable()
+ {
+ public void run()
+ {
+ // It may be the case that the properties view has focus and the editor being closed is the last one.
+ // The find-and-replace target is not updated in this case.
+ // So set it to null to ensure that the
+ //
+ Object fieldValue = getFieldValue(dialog, F_TARGET_FIELD);
+ if (fieldValue == FindAndReplaceTarget.this)
+ {
+ try
+ {
+ Method method = dialog.getClass().getMethod("updateTarget", IFindReplaceTarget.class, boolean.class, boolean.class);
+ method.setAccessible(true);
+ method.invoke(dialog, null, false, false);
+ }
+ catch (Exception exception)
+ {
+ // Ignore.
+ }
+ }
+ disposeCleanup = null;
}
};
}
@@ -697,6 +780,14 @@ public final class FindAndReplaceTarget implements IFindReplaceTarget, IFindRepl
}
}
+ private void dispose()
+ {
+ if (disposeCleanup != null)
+ {
+ disposeCleanup.run();
+ }
+ }
+
public void endSession()
{
// When the session ends, we clean up or search-type control.
@@ -811,7 +902,6 @@ public final class FindAndReplaceTarget implements IFindReplaceTarget, IFindRepl
if (propertiesCleanup != null)
{
propertiesCleanup.run();
- propertiesCleanup = null;
}
}
@@ -1227,6 +1317,7 @@ public final class FindAndReplaceTarget implements IFindReplaceTarget, IFindRepl
{
action.setChecked(false);
action.run();
+ filterChangeCleanup = null;
}
};
}
@@ -1246,6 +1337,7 @@ public final class FindAndReplaceTarget implements IFindReplaceTarget, IFindRepl
{
categoriesAction.setChecked(false);
categoriesAction.run();
+ categoriesChangeCleanup = null;
}
};
}
@@ -1363,6 +1455,8 @@ public final class FindAndReplaceTarget implements IFindReplaceTarget, IFindRepl
// Refresh the view.
propertySheetPage.refreshLabels();
+
+ propertiesCleanup = null;
}
};

Back to the top