Class Plugin
- java.lang.Object
-
- ghidra.framework.plugintool.Plugin
-
- All Implemented Interfaces:
PluginEventListener
,ServiceListener
,ExtensionPoint
- Direct Known Subclasses:
DataTypeDecompilerHoverPlugin
,FileSystemBrowserPlugin
,FrontEndPlugin
,FunctionSignatureDecompilerHoverPlugin
,ImporterPlugin
,ListingMergePanelPlugin
,MergeManagerPlugin
,ghidra.app.plugin.ProgramPlugin
,ReferenceDecompilerHoverPlugin
,ScalarValueDecompilerHoverPlugin
public abstract class Plugin extends java.lang.Object implements ExtensionPoint, PluginEventListener, ServiceListener
Plugins are a basic building block in Ghidra, used to bundle features or capabilities into a unit that can be enabled or disabled by the user in their Tool.Plugins expose their features or capabilities to users via menu items and buttons that the user can click on, and via "service" APIs that other Plugins can programmatically subscribe to, and via
PluginEvent
s that are broadcast.Well formed Plugins:
- Derive from
Plugin
(directly or indirectly). - Class name ends with "Plugin" and does not match any other Plugin, regardless of its location in the package tree.
- Have a
@PluginInfo()
annotation. - Have a constructor with exactly 1 parameter: PluginTool.
public MyPlugin(PluginTool tool) { ... }
- Usually overrides
protected void init()
.
Class naming
All Plugin Classes MUST END IN "Plugin". If not, the ClassSearcher will not find them.Some special Plugins marked with the
ProgramaticUseOnly
interface are manually created and do not follow this naming requirement.Plugin Life cycle
- Your Plugin's constructor is called
- Plugin base class constructor is called.
- Services listed in the @PluginInfo annotation are automatically added to dependency list
- Your Plugin publishes any services listed in PluginInfo using
registerServiceProvided()
. (required) - Create Actions (optional)
- Register
Options
with thePluginTool.getOptions(String)
. (optional)
- Plugin base class constructor is called.
- Other Plugins are constructed, dependencies evaluated, etc.
If your dependencies are not available (ie. not installed, threw an exception during their initialization, etc), your Plugin'sdispose()
will be called and then your Plugin instance will be discarded.
- Your Plugin's
init()
method is called (when its dependencies are met).- Call
PluginTool.getService(Class)
to get service implementations. (the service class being requested should already be listed in the @PluginInfo) - Create Actions (optional)
- Other initialization stuff.
- Call
- Your Plugin's
readConfigState(SaveState)
is called. - ...user uses Ghidra...
- Your Plugin's
processEvent(PluginEvent)
is called for events. - Your Plugin's Action's methods (ie.
actionPerformed
) are called. - Your Plugin's published service methods are called by other Plugins.
- Your Plugin's listener methods are called.
- Your Plugin's
- Plugin is unloaded due to shutdown of the Tool or being disabled by user
- Your Plugin's
writeConfigState(SaveState)
is called - override this method to write configuration info into the Tool definition. - Your Plugin's
dispose()
is called - override this method to free any resources and perform any needed cleanup. - Your Plugin's services and events are de-registered automatically.
- Your Plugin's
Plugin Service dependency
All Plugins must be tagged with a@PluginInfo(...)
annotation.The annotation gives you the ability to declare a dependency on another Plugin via the
servicesRequired
/servicesUsed
Ghidra will ensure that your Plugin will not be
initialized
until all of its required services are loaded successfully and are available for use when your Plugin calls thePluginTool.getService(Class)
method.Conversely, any services your Plugin advertises in @PluginInfo must be published via calls to
registerServiceProvided()
in your Plugin's constructor.Cyclic dependencies are not allowed and will cause the Plugin management code to fail to load your Plugin. (ie. PluginA requires a service that PluginB provides, which requires a service that PluginA provides)
Plugin Service implementation
A Plugin may provide a service to other Plugins by advertising in itsPluginInfo
annotation that itprovides
an interface class.Your Plugin can either directly implement the interface in your Plugin class:
public class MyPlugin extends Plugin implements MyService {....}
or it may delegate the handling of the service interface to another object during its constructor:
public MyPlugin(PluginTool tool) {
...
MyService serviceObj = new MyService() { ... };
registerServiceProvided(MyService.class, serviceObj);
}
When your Plugin directly implements the advertised service interface, you should not call
registerServiceProvided
for that service interface.Service interface classes are just normal java interface declarations and have no preconditions or other requirements to be used as a Plugin's advertised service interface.
Optionally, service interface classes can be marked with meta-data via a
@ServiceInfo
annotation that can have adefaultProvider
property which specifies a Plugin's class (or classname) that should be auto-loaded to provide an implementation of the service interface when that service is required by some other Plugin. Without the defaultProvider information, dependent Plugins will fail to load unless the user manually loads a Plugin that provides the necessary interface service.Multiple Plugins can implement the same service interface. Plugins that use that multi-implemented service will either receive a randomly picked instance if using
PluginTool.getService(Class)
or will receive all implementations if usingPluginTool.getServices(Class)
.Plugin Events
- Every type of plugin event should be represented by some class extending
PluginEvent
. - One PluginEvent subclass may be used for more than one event type as long as there's some natural grouping.
Component Providers
- A plugin may supply a ComponentProvider that provides a visual component when the plugin is added to the tool.
- TODO - needs more
Important interfaces Plugins often need to implement
OptionsChangeListener
- to receive notification when a configuration option is changed by the user.FrontEndable
- marks this Plugin as being suitable for inclusion in the FrontEnd tool.FrontEndOnly
- marks this Plugin as FrontEnd only, not usable in CodeBrowser or other tools.ProgramaticUseOnly
- marks this Plugin as special and not for user configuration.- TODO
-
-
Nested Class Summary
-
Nested classes/interfaces inherited from interface ghidra.util.classfinder.ExtensionPoint
ExtensionPoint.Exclude, ExtensionPoint.Util
-
-
Field Summary
Fields Modifier and Type Field Description protected java.lang.String
name
Name of this plugin, derived from the simple class name.protected PluginDescription
pluginDescription
Static information about this Plugin, derived from itsPluginInfo
annotation.protected PluginTool
tool
ThePluginTool
that hosts/contains this Plugin.
-
Constructor Summary
Constructors Modifier Constructor Description protected
Plugin(PluginTool tool)
Construct a new Plugin.protected
Plugin(java.lang.String pluginName, PluginTool tool)
Deprecated.
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Deprecated Methods Modifier and Type Method Description boolean
acceptData(DomainFile[] data)
Method called if the plugin supports this domain file.protected boolean
canClose()
Called to force this plugin to terminate any tasks it has running and apply any unsaved data to domain objects or files.protected boolean
canCloseDomainObject(DomainObject dObj)
Override this method if the plugin needs to cancel the closing of the domain object.protected void
cleanup()
protected void
close()
Close the plugin.void
dataStateRestoreCompleted()
Notification that all plugins have had their data states restored.boolean
dependsUpon(Plugin plugin)
Check if this plugin depends on the given plugin.protected void
deregisterService(java.lang.Class<?> interfaceClass, java.lang.Object service)
protected void
dispose()
Tells a plugin that it is no longer needed.boolean
equals(java.lang.Object obj)
void
eventSent(PluginEvent event)
Notification that the given plugin event was sent.void
firePluginEvent(PluginEvent event)
Fire the given plugin event; the tool notifies all other plugins who are interested in receiving the given event type.DomainFile[]
getData()
Get the domain files that this plugin has open.java.util.List<java.lang.Class<?>>
getMissingRequiredServices()
java.lang.String
getName()
Returns this plugin's name.PluginDescription
getPluginDescription()
Returns the staticPluginDescription
object that was derived from the@PluginInfo
annotation at the top of your Plugin.static java.lang.String
getPluginName(java.lang.Class<?> pluginClass)
Deprecated.protected java.util.List<java.lang.Class<?>>
getServicesRequired()
Returns the combination of required and non-required used services.java.lang.Class<?>[]
getSupportedDataTypes()
Return classes of data types that this plugin can support.PluginTool
getTool()
Get thePluginTool
that hosts/contains this plugin.java.lang.Object
getTransientState()
Returns an object containing the plugins state.java.lang.Object
getUndoRedoState(DomainObject domainObject)
Returns an object containing the plugin's state as needed to restore itself after an undo or redo operation.int
hashCode()
boolean
hasMissingRequiredService()
Checks if this plugin is missing a required service.protected boolean
hasUnsaveData()
Returns true if this plugin has data that needs saving;protected void
init()
Initialization method; override to add initialization for this plugin.boolean
isDisposed()
protected void
prepareToSave(DomainObject dObj)
Called to allow this plugin to flush any caches to the domain object before it is saved.void
processEvent(PluginEvent event)
Method called to process a plugin event.void
readConfigState(SaveState saveState)
Tells the Plugin to read its data-independent (preferences) properties from the input stream.void
readDataState(SaveState saveState)
Tells the Plugin to read its data-dependent state from the given SaveState object.protected void
registerDynamicEventConsumed(java.lang.Class<? extends PluginEvent> eventClass)
Register event that this plugin consumes.protected <T> void
registerDynamicServiceProvided(java.lang.Class<? super T> interfaceClass, T service)
Used to register a service dynamically, during runtime, instead of during the Plugin's constructor.protected void
registerEventConsumed(java.lang.Class<? extends PluginEvent> eventClass)
Deprecated.protected void
registerEventProduced(java.lang.Class<? extends PluginEvent> eventClass)
Deprecated.protected <T> void
registerServiceProvided(java.lang.Class<? super T> interfaceClass, T service)
Used to register a service (that has already been announced in this Plugin's PluginInfo annotation viaservicesProvided = SomeService.class
) during the Plugin's constructor phase, IFF the service is implemented by an object other than the Plugin instance itself.protected void
registerServiceUsed(java.lang.Class<?> interfaceClass, boolean isDependency)
Deprecated.void
restoreTransientState(java.lang.Object state)
Provides the transient state object that was returned in the corresponding getTransientState() call.void
restoreUndoRedoState(DomainObject domainObject, java.lang.Object state)
Updates the plugin's state based on the data stored in the state object.protected boolean
saveData()
Called to force this plugin to save any domain object data it is controlling.void
serviceAdded(java.lang.Class<?> interfaceClass, java.lang.Object service)
Notifies this plugin that a service has been added to the plugin tool.void
serviceRemoved(java.lang.Class<?> interfaceClass, java.lang.Object service)
Notifies this plugin that service has been removed from the plugin tool.void
writeConfigState(SaveState saveState)
Tells a Plugin to write any data-independent (preferences) properties to the output stream.void
writeDataState(SaveState saveState)
Tells the Plugin to write any data-dependent state to the output stream.
-
-
-
Field Detail
-
tool
protected PluginTool tool
ThePluginTool
that hosts/contains this Plugin.
-
name
protected final java.lang.String name
Name of this plugin, derived from the simple class name.
-
pluginDescription
protected final PluginDescription pluginDescription
Static information about this Plugin, derived from itsPluginInfo
annotation.
-
-
Constructor Detail
-
Plugin
protected Plugin(PluginTool tool)
Construct a new Plugin.- Parameters:
tool
- PluginTool that will host/contain this plugin.
-
Plugin
@Deprecated protected Plugin(java.lang.String pluginName, PluginTool tool)
Deprecated.Construct a new Plugin.Deprecated, use
Plugin(PluginTool)
instead.- Parameters:
pluginName
- name of plugin - not used.tool
- tool that will contain this plugin
-
-
Method Detail
-
getPluginName
@Deprecated public static java.lang.String getPluginName(java.lang.Class<?> pluginClass)
Deprecated.Returns plugin name or null if pluginClass does not extend Plugin.Deprecated, use
PluginUtils.getPluginNameFromClass(Class)
- Parameters:
pluginClass
-
-
cleanup
protected void cleanup()
-
getName
public final java.lang.String getName()
Returns this plugin's name.- Returns:
- String name, derived from simple class name.
-
eventSent
public final void eventSent(PluginEvent event)
Description copied from interface:PluginEventListener
Notification that the given plugin event was sent.- Specified by:
eventSent
in interfacePluginEventListener
- Parameters:
event
- plugin event that was sent
-
processEvent
public void processEvent(PluginEvent event)
Method called to process a plugin event. Plugins should override this method if the plugin processes PluginEvents;- Parameters:
event
- plugin to process
-
getTool
public final PluginTool getTool()
Get thePluginTool
that hosts/contains this plugin.- Returns:
- PluginTool
-
getSupportedDataTypes
public java.lang.Class<?>[] getSupportedDataTypes()
Return classes of data types that this plugin can support.- Returns:
- classes of data types that this plugin can support
-
acceptData
public boolean acceptData(DomainFile[] data)
Method called if the plugin supports this domain file.- Parameters:
data
- array ofDomainFile
s- Returns:
- boolean true if can accept
-
getData
public DomainFile[] getData()
Get the domain files that this plugin has open.- Returns:
- array of
DomainFile
s that are open by this Plugin.
-
init
protected void init()
Initialization method; override to add initialization for this plugin. This is where a plugin should acquire its services. When this method is called, all plugins have been instantiated in the tool.
-
dispose
protected void dispose()
Tells a plugin that it is no longer needed. The plugin should release any resources that it has. All actions, components, services will automatically be cleaned up.
-
readConfigState
public void readConfigState(SaveState saveState)
Tells the Plugin to read its data-independent (preferences) properties from the input stream.- Parameters:
saveState
- object that holds primitives for state information
-
writeConfigState
public void writeConfigState(SaveState saveState)
Tells a Plugin to write any data-independent (preferences) properties to the output stream.- Parameters:
saveState
- object that holds primitives for state information
-
writeDataState
public void writeDataState(SaveState saveState)
Tells the Plugin to write any data-dependent state to the output stream.- Parameters:
saveState
- object that holds primitives for state information
-
readDataState
public void readDataState(SaveState saveState)
Tells the Plugin to read its data-dependent state from the given SaveState object.- Parameters:
saveState
- object that holds primitives for state information
-
firePluginEvent
public void firePluginEvent(PluginEvent event)
Fire the given plugin event; the tool notifies all other plugins who are interested in receiving the given event type.- Parameters:
event
- event to fire
-
serviceAdded
public void serviceAdded(java.lang.Class<?> interfaceClass, java.lang.Object service)
Notifies this plugin that a service has been added to the plugin tool. Plugins should override this method if they update their state when a particular service is added.- Specified by:
serviceAdded
in interfaceServiceListener
- Parameters:
interfaceClass
- The interface of the added serviceservice
- service that is being added
-
serviceRemoved
public void serviceRemoved(java.lang.Class<?> interfaceClass, java.lang.Object service)
Notifies this plugin that service has been removed from the plugin tool. Plugins should override this method if they update their state when a particular service is removed.- Specified by:
serviceRemoved
in interfaceServiceListener
- Parameters:
interfaceClass
- The interface of the added serviceservice
- that is being removed.
-
dependsUpon
public boolean dependsUpon(Plugin plugin)
Check if this plugin depends on the given plugin.
-
getMissingRequiredServices
public java.util.List<java.lang.Class<?>> getMissingRequiredServices()
-
hasMissingRequiredService
public boolean hasMissingRequiredService()
Checks if this plugin is missing a required service.- Returns:
- boolean true if a required service isn't available via the PluginTool.
-
registerEventProduced
@Deprecated protected final void registerEventProduced(java.lang.Class<? extends PluginEvent> eventClass)
Deprecated.Register event that this plugin produces.Deprecated, use
@PluginInfo.eventsProduced
instead.- Parameters:
eventClass
- Class of the produced event; class is required to force it to be loaded
-
registerEventConsumed
@Deprecated protected final void registerEventConsumed(java.lang.Class<? extends PluginEvent> eventClass)
Deprecated.Register event that this plugin consumes.Deprecated, use
@PluginInfo.eventsConsumed
instead.- Parameters:
eventClass
- Class for the event; class is required to force it to be loaded
-
registerDynamicEventConsumed
protected final void registerDynamicEventConsumed(java.lang.Class<? extends PluginEvent> eventClass)
Register event that this plugin consumes.- Parameters:
eventClass
- Class for the event; class is required to force it to be loaded
-
registerServiceProvided
protected final <T> void registerServiceProvided(java.lang.Class<? super T> interfaceClass, T service)
Used to register a service (that has already been announced in this Plugin's PluginInfo annotation viaservicesProvided = SomeService.class
) during the Plugin's constructor phase, IFF the service is implemented by an object other than the Plugin instance itself.Do not use this to register a service if your Plugin class implements that service's interface because your Plugin will have been automatically registered as providing that service.
If you need to register a service after the constructor is finished, use
registerDynamicServiceProvided(Class, Object)
.Using this method outside of your constructor will (someday) throw an IllegalArgumentException.
- Parameters:
interfaceClass
- service interface classservice
- service implementation
-
registerDynamicServiceProvided
protected final <T> void registerDynamicServiceProvided(java.lang.Class<? super T> interfaceClass, T service)
Used to register a service dynamically, during runtime, instead of during the Plugin's constructor.- Parameters:
interfaceClass
- service interface classservice
- service implementation
-
getServicesRequired
protected final java.util.List<java.lang.Class<?>> getServicesRequired()
Returns the combination of required and non-required used services.- Returns:
- union of the lists of required and non-required used services.
-
registerServiceUsed
@Deprecated protected final void registerServiceUsed(java.lang.Class<?> interfaceClass, boolean isDependency)
Deprecated.Registers a dependency on a service interface Class.This method is deprecated. Use
@PluginInfo.servicesRequired
instead.- Parameters:
interfaceClass
- interface class that this plugin depends onisDependency
- boolean flag, if true this plugin will not work without the specified service, if false this service can work without it. If false, this method is a no-op as non-dependency registration information is now discarded.
-
deregisterService
protected final void deregisterService(java.lang.Class<?> interfaceClass, java.lang.Object service)
-
canClose
protected boolean canClose()
Called to force this plugin to terminate any tasks it has running and apply any unsaved data to domain objects or files. If it can't do this or the user cancels then this returns false.- Returns:
- true if this plugin can close.
-
canCloseDomainObject
protected boolean canCloseDomainObject(DomainObject dObj)
Override this method if the plugin needs to cancel the closing of the domain object.- Returns:
- false if the domain object should NOT be closed
-
prepareToSave
protected void prepareToSave(DomainObject dObj)
Called to allow this plugin to flush any caches to the domain object before it is saved.- Parameters:
dObj
- domain object about to be saved
-
saveData
protected boolean saveData()
Called to force this plugin to save any domain object data it is controlling.- Returns:
- false if this plugin controls a domain object, but couldn't save its data or the user canceled the save.
-
hasUnsaveData
protected boolean hasUnsaveData()
Returns true if this plugin has data that needs saving;- Returns:
- true if this plugin has data that needs saving;
-
close
protected void close()
Close the plugin.
-
isDisposed
public boolean isDisposed()
-
equals
public boolean equals(java.lang.Object obj)
- Overrides:
equals
in classjava.lang.Object
-
hashCode
public int hashCode()
- Overrides:
hashCode
in classjava.lang.Object
-
restoreTransientState
public void restoreTransientState(java.lang.Object state)
Provides the transient state object that was returned in the corresponding getTransientState() call. Plugins should override this method if they have state that needs to be saved as domain objects get switched between active and inactive.- Parameters:
state
- the state object that was generated by this plugin's getTransientState() method.
-
getTransientState
public java.lang.Object getTransientState()
Returns an object containing the plugins state. Plugins should override this method if they have state that they want to maintain between domain object state transitions (i.e. when the user tabs to a different domain object and back) Whatever object is returned will be fed back to the plugin after the tool state is switch back to the domain object that was active when the this method was called.- Returns:
- Object to be return in the restoreTransientState() method.
-
dataStateRestoreCompleted
public void dataStateRestoreCompleted()
Notification that all plugins have had their data states restored.
-
getUndoRedoState
public java.lang.Object getUndoRedoState(DomainObject domainObject)
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.- Parameters:
domainObject
- the object that is about to or has had undoable changes made to it.
-
restoreUndoRedoState
public void restoreUndoRedoState(DomainObject domainObject, java.lang.Object state)
Updates the plugin's state based on the data stored in the state object. The state object is the object that was returned by this plugin in thegetUndoRedoState(DomainObject)
- Parameters:
domainObject
- the domain object that has had an undo or redo operation applied to it.state
- the state that was recorded before the undo or redo operation.
-
getPluginDescription
public final PluginDescription getPluginDescription()
Returns the staticPluginDescription
object that was derived from the@PluginInfo
annotation at the top of your Plugin.- Returns:
- the static/shared
PluginDescription
instance that describes this Plugin.
-
-