Tests - fixed exception seen sporadically in tests due to improper Data

type Manager disposal
This commit is contained in:
dragonmacher 2019-12-05 17:36:20 -05:00
parent 3a6c3312fe
commit adedcde30f
2 changed files with 36 additions and 27 deletions

View file

@ -125,9 +125,8 @@ public class DataTypeManagerPlugin extends ProgramPlugin
@Override @Override
public void archiveClosed(Archive archive) { public void archiveClosed(Archive archive) {
if (archive instanceof ProjectArchive) { if (archive instanceof ProjectArchive) {
// Program is handled by deactivation event ProjectArchive projectArchive = (ProjectArchive) archive;
((ProjectArchive) archive).getDomainObject().removeListener( projectArchive.getDomainObject().removeListener(DataTypeManagerPlugin.this);
DataTypeManagerPlugin.this);
} }
} }
@ -137,11 +136,10 @@ public class DataTypeManagerPlugin extends ProgramPlugin
addRecentlyOpenedArchiveFile(((FileArchive) archive).getFile()); addRecentlyOpenedArchiveFile(((FileArchive) archive).getFile());
} }
else if (archive instanceof ProjectArchive) { else if (archive instanceof ProjectArchive) {
((ProjectArchive) archive).getDomainObject().addListener( ProjectArchive projectArchive = (ProjectArchive) archive;
DataTypeManagerPlugin.this); projectArchive.getDomainObject().addListener(DataTypeManagerPlugin.this);
addRecentlyOpenedProjectArchive((ProjectArchive) archive); addRecentlyOpenedProjectArchive((ProjectArchive) archive);
} }
// Program is handled by activation.
} }
@Override @Override
@ -267,8 +265,7 @@ public class DataTypeManagerPlugin extends ProgramPlugin
@Override @Override
public void dispose() { public void dispose() {
tool.removePopupActionProvider(this); tool.removePopupActionProvider(this);
provider.dispose(); dataTypeManagerHandler.closeAllArchives();
close();
dataTypeManagerHandler.dispose(); dataTypeManagerHandler.dispose();
} }
@ -347,7 +344,7 @@ public class DataTypeManagerPlugin extends ProgramPlugin
@Override @Override
protected void close() { protected void close() {
dataTypeManagerHandler.closeAllArchives(); provider.dispose();
} }
public DataTypeManagerHandler getDataTypeManagerHandler() { public DataTypeManagerHandler getDataTypeManagerHandler() {

View file

@ -17,6 +17,7 @@ package ghidra.framework.plugintool;
import java.util.*; import java.util.*;
import docking.ComponentProvider;
import docking.action.DockingAction; import docking.action.DockingAction;
import ghidra.framework.main.*; import ghidra.framework.main.*;
import ghidra.framework.model.DomainFile; import ghidra.framework.model.DomainFile;
@ -112,10 +113,11 @@ import ghidra.util.classfinder.ExtensionPoint;
* calls the {@link PluginTool#getService(Class)} method. * calls the {@link PluginTool#getService(Class)} method.
* <p> * <p>
* Conversely, any services your Plugin advertises in &#64;PluginInfo must be published via calls to * Conversely, any services your Plugin advertises in &#64;PluginInfo must be published via calls to
* {@link #registerServiceProvided(Class, Object) registerServiceProvided()} in your Plugin's constructor. * {@link #registerServiceProvided(Class, Object) registerServiceProvided()} in your Plugin's
* constructor.
* <p> * <p>
* <b>Cyclic dependencies</b> are not allowed and will cause the Plugin management code to fail to load * <b>Cyclic dependencies</b> are not allowed and will cause the Plugin management code to fail to
* your Plugin. (ie. PluginA requires a service that PluginB provides, which requires a service * load your Plugin. (ie. PluginA requires a service that PluginB provides, which requires a service
* that PluginA provides) * that PluginA provides)
* *
* <h2>Plugin Service implementation</h2> * <h2>Plugin Service implementation</h2>
@ -132,7 +134,8 @@ import ghidra.util.classfinder.ExtensionPoint;
* &nbsp;&nbsp;<code>public MyPlugin(PluginTool tool) {</code><br> * &nbsp;&nbsp;<code>public MyPlugin(PluginTool tool) {</code><br>
* &nbsp;&nbsp;&nbsp;&nbsp;<code>...</code><br> * &nbsp;&nbsp;&nbsp;&nbsp;<code>...</code><br>
* &nbsp;&nbsp;&nbsp;&nbsp;<code>MyService serviceObj = new MyService() { ... };</code><br> * &nbsp;&nbsp;&nbsp;&nbsp;<code>MyService serviceObj = new MyService() { ... };</code><br>
* &nbsp;&nbsp;&nbsp;&nbsp;<code><b>registerServiceProvided(MyService.class, serviceObj);</b></code><br> * &nbsp;&nbsp;&nbsp;&nbsp;<code><b>registerServiceProvided(MyService.class, serviceObj);</b>
* </code><br>
* &nbsp;&nbsp;<code>}</code><br> * &nbsp;&nbsp;<code>}</code><br>
* <p> * <p>
* When your Plugin directly implements the advertised service interface, you should <b>not</b> * When your Plugin directly implements the advertised service interface, you should <b>not</b>
@ -159,26 +162,27 @@ import ghidra.util.classfinder.ExtensionPoint;
* <h2>Plugin Events</h2> * <h2>Plugin Events</h2>
* <UL> * <UL>
* <LI>Every type of plugin event should be represented by some class extending {@link PluginEvent}. * <LI>Every type of plugin event should be represented by some class extending {@link PluginEvent}.
* <LI>One PluginEvent subclass may be used for more than one event type as long as there's some natural grouping. * <LI>One PluginEvent subclass may be used for more than one event type as long as there's some
* natural grouping.
* </UL> * </UL>
* *
* <h2>Component Providers</h2> * <h2>Component Providers</h2>
* <UL> * <UL>
* <LI>A plugin may supply a ComponentProvider that provides a visual component when the plugin is added to the tool. * <LI>A plugin may supply a {@link ComponentProvider} that provides a visual component when
* <LI>TODO - needs more * the plugin is added to the tool.
* </UL> * </UL>
* *
* <h2>Important interfaces Plugins often need to implement</h2> * <h2>Important interfaces Plugins often need to implement</h2>
* <UL> * <UL>
* <LI>{@link OptionsChangeListener} - to receive notification when a configuration option * <LI>{@link OptionsChangeListener} - to receive notification when a configuration option
* is changed by the user. * is changed by the user.
* <LI>{@link FrontEndable} - marks this Plugin as being suitable for inclusion in the FrontEnd tool. * <LI>{@link FrontEndable} - marks this Plugin as being suitable for inclusion in the FrontEnd
* <LI>{@link FrontEndOnly} - marks this Plugin as FrontEnd only, not usable in CodeBrowser or other tools. * tool.
* <LI>{@link FrontEndOnly} - marks this Plugin as FrontEnd only, not usable in CodeBrowser or
* other tools.
* <LI>{@link ProgramaticUseOnly} - marks this Plugin as special and not for user configuration. * <LI>{@link ProgramaticUseOnly} - marks this Plugin as special and not for user configuration.
* <LI>TODO
* </UL> * </UL>
* *
*
*/ */
public abstract class Plugin implements ExtensionPoint, PluginEventListener, ServiceListener { public abstract class Plugin implements ExtensionPoint, PluginEventListener, ServiceListener {
@ -273,11 +277,12 @@ public abstract class Plugin implements ExtensionPoint, PluginEventListener, Ser
} }
/** /**
* Returns plugin name or null if pluginClass does not extend Plugin. * Returns plugin name or null if given class does not extend {@link Plugin}
* <p> * <p>
* Deprecated, use {@link PluginUtils#getPluginNameFromClass(Class)} * Deprecated, use {@link PluginUtils#getPluginNameFromClass(Class)}
* <p> * <p>
* @param pluginClass * @param pluginClass the plugin class
* @return the plugin name
*/ */
@Deprecated @Deprecated
public static String getPluginName(Class<?> pluginClass) { public static String getPluginName(Class<?> pluginClass) {
@ -514,8 +519,10 @@ public abstract class Plugin implements ExtensionPoint, PluginEventListener, Ser
} }
/** /**
* Check if this plugin depends on the given plugin. * Check if this plugin depends on the given plugin
* <p> *
* @param plugin the plugin
* @return true if this plugin depends on the given plugin
*/ */
public boolean dependsUpon(Plugin plugin) { public boolean dependsUpon(Plugin plugin) {
for (Class<?> c : getList(pluginDescription.getServicesRequired(), for (Class<?> c : getList(pluginDescription.getServicesRequired(),
@ -791,8 +798,8 @@ public abstract class Plugin implements ExtensionPoint, PluginEventListener, Ser
} }
/** /**
* Override this method if the plugin needs to cancel the closing of * Override this method if the plugin needs to cancel the closing of the domain object
* the domain object. * @param dObj the domain object
* @return false if the domain object should NOT be closed * @return false if the domain object should NOT be closed
*/ */
protected boolean canCloseDomainObject(DomainObject dObj) { protected boolean canCloseDomainObject(DomainObject dObj) {
@ -826,7 +833,11 @@ public abstract class Plugin implements ExtensionPoint, PluginEventListener, Ser
} }
/** /**
* Close the plugin. * Close the plugin. This is when the plugin should release resources, such as those from
* other services. This method should not close resources being used by others (that should
* happen in dispose()).
*
* <p>This method will be called before {@link #dispose()}.
*/ */
protected void close() { protected void close() {
// do nothing by default; subclasses should override as needed // do nothing by default; subclasses should override as needed
@ -886,6 +897,7 @@ public abstract class Plugin implements ExtensionPoint, PluginEventListener, Ser
* Returns an object containing the plugin's state as needed to restore itself after an undo * Returns an object containing the plugin's state as needed to restore itself after an undo
* or redo operation. Plugins should override this method if they have special undo/redo handling. * or redo operation. Plugins should override this method if they have special undo/redo handling.
* @param domainObject the object that is about to or has had undoable changes made to it. * @param domainObject the object that is about to or has had undoable changes made to it.
* @return the state object
*/ */
public Object getUndoRedoState(DomainObject domainObject) { public Object getUndoRedoState(DomainObject domainObject) {
// do nothing by default; subclasses should override as needed // do nothing by default; subclasses should override as needed