Plugins
What is a plugin?
A plugin is a JAR file that contains one or more classes with exactly one of them implementing software.coley.recaf.plugin.Plugin
. When Recaf launches it looks in the plugins directory for JAR files that contain these plugin classes. It will then attempt to load and initialize them. Because a plugin is distributed as a JAR file a plugin developer can create complex logic and organize it easily across multiple classes in the JAR.
Using services
Plugins can use services by annotating the class with @Dependent
and annotating the constructor with @Inject
. For services that are application scoped, see this example:
import jakarta.enterprise.context.Dependent;
import jakarta.inject.Inject;
import software.coley.recaf.plugin.*;
import software.coley.recaf.services.workspace.WorkspaceManager;
// Dependent is a CDI annotation which loosely translates to being un-scoped.
// Plugin instances are managed by Recaf so the scope is bound to when plugins are loaded in practice.
@Dependent
class MyPlugin implements Plugin {
private final WorkspaceManager workspaceManager;
// Example, injecting the 'WorkspaceManager' service which is '@ApplicationScoped'
@Inject
public MyPlugin(WorkspaceManager workspaceManager) {
this.workspaceManager = workspaceManager;
}
@Override
public void onEnable() { ... }
@Override
public void onDisable() { ... }
}
For services that are @WorkspaceScoped
they will not be available on plugin initialization since no Workspace
will be set/opened when this occurs. You can use CDI constructs like Instance<T>
and use them as getters to work around this. Calling get()
on the instance after a Workspace
is opened will grab the workspace-scoped instance of the desired service. As an example here is a basic plugin that injects the InheritanceGraph
service:
import jakarta.enterprise.context.Dependent;
import jakarta.enterprise.inject.Instance;
import jakarta.inject.Inject;
import software.coley.recaf.plugin.*;
import software.coley.recaf.services.inheritance.InheritanceGraph;
import software.coley.recaf.services.workspace.WorkspaceManager;
@Dependent
class MyPlugin implements Plugin {
// We will use the workspace manager to listen to when new workspaces are opened.
// When this occurs we can access instances of workspace scoped services.
@Inject
public MyPlugin(WorkspaceManager workspaceManager,
Instance<InheritanceGraph> graphProvider) {
// No workspace open, wait until one is opened by the user.
if (workspaceManager.getCurrent() == null) {
workspaceManager.addWorkspaceOpenListener(newWorkspace -> {
// This will be called AFTER the 'newWorkspace' value has been assigned
// as the 'current' workspace in the workspace manager.
// At this point, all workspace scoped services are re-allocated by CDI
// to target the newly opened workspace.
//
// Thus, we can get our inheritance graph of the workspace here.
InheritanceGraph graph = graphProvider.get();
});
} else {
// There is a workspace, so we can immediately get the graph for the current workspace.
InheritanceGraph graph = graphProvider.get();
}
}
@Override
public void onEnable() { ... }
@Override
public void onDisable() { ... }
}
For the list of available services, see the service lists.