mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
Merge remote-tracking branch 'origin/GT-3350_ryanmkurtz_ExtensionPoints'
This commit is contained in:
commit
36a628ae97
52 changed files with 341 additions and 169 deletions
|
@ -17,7 +17,8 @@ package ghidra.app.util.disassemble;
|
|||
|
||||
import java.awt.Color;
|
||||
import java.math.BigInteger;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import docking.widgets.fieldpanel.field.*;
|
||||
import docking.widgets.fieldpanel.support.FieldLocation;
|
||||
|
@ -43,7 +44,7 @@ public class ExternalDisassemblyFieldFactory extends FieldFactory {
|
|||
availableDisassemblers = new ArrayList<>();
|
||||
|
||||
// find the available external disassemblers
|
||||
Set<ExternalDisassembler> extDisassemblers =
|
||||
List<ExternalDisassembler> extDisassemblers =
|
||||
ClassSearcher.getInstances(ExternalDisassembler.class);
|
||||
|
||||
for (ExternalDisassembler disassember : extDisassemblers) {
|
||||
|
|
|
@ -42,7 +42,7 @@ public class DumpGhidraCapabilitiesScript extends GhidraScript {
|
|||
addPlugin(moduleName, pluginDescription);
|
||||
}
|
||||
|
||||
Set<Analyzer> instances = ClassSearcher.getInstances(Analyzer.class);
|
||||
List<Analyzer> instances = ClassSearcher.getInstances(Analyzer.class);
|
||||
for (Analyzer analyzer : instances) {
|
||||
Class<? extends Analyzer> clazz = analyzer.getClass();
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ public class SummarizeAnalyzers extends GhidraScript {
|
|||
|
||||
Options options = currentProgram.getOptions(Program.ANALYSIS_PROPERTIES);
|
||||
|
||||
Set<Class<? extends Analyzer>> classes = ClassSearcher.getClasses(Analyzer.class);
|
||||
List<Class<? extends Analyzer>> classes = ClassSearcher.getClasses(Analyzer.class);
|
||||
for (Class<? extends Analyzer> element : classes) {
|
||||
Analyzer analyzer;
|
||||
try {
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
*/
|
||||
package ghidra.app.cmd.label;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.app.util.demangler.*;
|
||||
import ghidra.framework.cmd.BackgroundCommand;
|
||||
|
@ -33,7 +33,7 @@ public class DemanglerCmd extends BackgroundCommand {
|
|||
private String mangled;
|
||||
private String result;
|
||||
private DemangledObject demangledObject;
|
||||
private static Set<Demangler> demanglers;
|
||||
private static List<Demangler> demanglers;
|
||||
private DemanglerOptions options;
|
||||
|
||||
public DemanglerCmd(Address addr, String mangled) {
|
||||
|
@ -138,7 +138,7 @@ public class DemanglerCmd extends BackgroundCommand {
|
|||
return demangledObject;
|
||||
}
|
||||
|
||||
private static Set<Demangler> getDemanglers() {
|
||||
private static List<Demangler> getDemanglers() {
|
||||
if (demanglers == null) {
|
||||
demanglers = ClassSearcher.getInstances(Demangler.class);
|
||||
}
|
||||
|
|
|
@ -158,7 +158,7 @@ public class AutoAnalysisManager implements DomainObjectListener, DomainObjectCl
|
|||
taskArray = new AnalysisTaskList[] { byteTasks, instructionTasks, functionTasks,
|
||||
functionModifierChangedTasks, functionSignatureChangedTasks, dataTasks };
|
||||
|
||||
Set<Analyzer> analyzers = ClassSearcher.getInstances(Analyzer.class);
|
||||
List<Analyzer> analyzers = ClassSearcher.getInstances(Analyzer.class);
|
||||
for (Analyzer analyzer : analyzers) {
|
||||
if (!analyzer.canAnalyze(program)) {
|
||||
continue;
|
||||
|
|
|
@ -19,15 +19,13 @@ import ghidra.program.model.address.AddressSetView;
|
|||
import ghidra.program.model.mem.Memory;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.program.model.util.MemoryByteIterator;
|
||||
import ghidra.util.classfinder.ExtensionPoint;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
* This class is used for the computation of various basic checksums.
|
||||
*/
|
||||
@ExtensionPoint.Exclude(reason = "Subclasses will get picked up by extension points.")
|
||||
public class BasicChecksumAlgorithm extends ChecksumAlgorithm {
|
||||
public abstract class BasicChecksumAlgorithm extends ChecksumAlgorithm {
|
||||
|
||||
/**
|
||||
* The byte sizes that are supported by the basic checksum algorithm.
|
||||
|
|
|
@ -17,7 +17,8 @@ package ghidra.app.plugin.core.checksums;
|
|||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
|
@ -63,7 +64,7 @@ public class ComputeChecksumsProvider extends ComponentProviderAdapter {
|
|||
super(plugin.getTool(), "Checksum Generator", plugin.getName(), ProgramContextAction.class);
|
||||
|
||||
setHelpLocation(new HelpLocation("ComputeChecksumsPlugin", "Generate_Checksum_Help"));
|
||||
Set<ChecksumAlgorithm> algorithms = ClassSearcher.getInstances(ChecksumAlgorithm.class);
|
||||
List<ChecksumAlgorithm> algorithms = ClassSearcher.getInstances(ChecksumAlgorithm.class);
|
||||
checksums.addAll(algorithms);
|
||||
|
||||
this.plugin = plugin;
|
||||
|
|
|
@ -22,7 +22,6 @@ import ghidra.program.model.address.AddressSetView;
|
|||
import ghidra.program.model.mem.Memory;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.program.model.util.MemoryByteIterator;
|
||||
import ghidra.util.classfinder.ExtensionPoint;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
|
@ -30,8 +29,7 @@ import ghidra.util.task.TaskMonitor;
|
|||
* This class is used for the computation of various digest checksums that are provided
|
||||
* by java. These checksums do not have options associated with them.
|
||||
*/
|
||||
@ExtensionPoint.Exclude(reason = "Subclasses will get picked up by extension points.")
|
||||
public class DigestChecksumAlgorithm extends ChecksumAlgorithm {
|
||||
public abstract class DigestChecksumAlgorithm extends ChecksumAlgorithm {
|
||||
|
||||
MessageDigest digester;
|
||||
|
||||
|
|
|
@ -112,7 +112,7 @@ public class ExportToHeaderAction extends DockingAction {
|
|||
*/
|
||||
private void exportToC(GTree gTree, DataTypeManager programDataTypeMgr) {
|
||||
|
||||
Set<Class<? extends AnnotationHandler>> classes =
|
||||
List<Class<? extends AnnotationHandler>> classes =
|
||||
ClassSearcher.getClasses(AnnotationHandler.class);
|
||||
|
||||
List<AnnotationHandler> list = new ArrayList<>();
|
||||
|
|
|
@ -154,7 +154,7 @@ public class FunctionComparisonPanel extends JPanel implements ChangeListener {
|
|||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
private Set<CodeComparisonPanel<? extends FieldPanelCoordinator>> createAllPossibleCodeComparisonPanels() {
|
||||
Set<CodeComparisonPanel<? extends FieldPanelCoordinator>> instances = new HashSet<>();
|
||||
Set<Class<? extends CodeComparisonPanel>> classes =
|
||||
List<Class<? extends CodeComparisonPanel>> classes =
|
||||
ClassSearcher.getClasses(CodeComparisonPanel.class);
|
||||
for (Class<? extends CodeComparisonPanel> panelClass : classes) {
|
||||
try {
|
||||
|
|
|
@ -284,7 +284,7 @@ public final class ReferenceUtils {
|
|||
Accumulator<LocationReference> accumulator, Program program, DataType dataType,
|
||||
String fieldName, TaskMonitor monitor) throws CancelledException {
|
||||
|
||||
Set<DataTypeReferenceFinder> finders =
|
||||
List<DataTypeReferenceFinder> finders =
|
||||
ClassSearcher.getInstances(DataTypeReferenceFinder.class);
|
||||
|
||||
Consumer<DataTypeReference> callback = ref -> {
|
||||
|
|
|
@ -54,7 +54,7 @@ import resources.ResourceManager;
|
|||
public class OverviewColorPlugin extends ProgramPlugin {
|
||||
public static final String HELP_TOPIC = "OverviewPlugin";
|
||||
private static final String ACTIVE_SERVICES = "ActiveServices";
|
||||
private Set<OverviewColorService> allServices;
|
||||
private List<OverviewColorService> allServices;
|
||||
private Map<OverviewColorService, OverviewColorComponent> activeServices =
|
||||
new LinkedHashMap<>(); // maintain the left to right order of the active overview bars.
|
||||
private CodeViewerService codeViewerService;
|
||||
|
|
|
@ -15,18 +15,6 @@
|
|||
*/
|
||||
package ghidra.app.plugin.core.validator;
|
||||
|
||||
import ghidra.app.CorePluginPackage;
|
||||
import ghidra.app.context.ProgramActionContext;
|
||||
import ghidra.app.context.ProgramContextAction;
|
||||
import ghidra.app.plugin.PluginCategoryNames;
|
||||
import ghidra.app.plugin.core.analysis.validator.PostAnalysisValidator;
|
||||
import ghidra.framework.plugintool.*;
|
||||
import ghidra.framework.plugintool.util.*;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.HelpLocation;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.classfinder.ClassSearcher;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.*;
|
||||
|
||||
|
@ -35,6 +23,17 @@ import docking.action.DockingAction;
|
|||
import docking.action.MenuData;
|
||||
import docking.tool.ToolConstants;
|
||||
import docking.widgets.conditiontestpanel.ConditionTester;
|
||||
import ghidra.app.CorePluginPackage;
|
||||
import ghidra.app.context.ProgramActionContext;
|
||||
import ghidra.app.context.ProgramContextAction;
|
||||
import ghidra.app.plugin.PluginCategoryNames;
|
||||
import ghidra.app.plugin.core.analysis.validator.PostAnalysisValidator;
|
||||
import ghidra.framework.plugintool.*;
|
||||
import ghidra.framework.plugintool.util.PluginStatus;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.HelpLocation;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.classfinder.ClassSearcher;
|
||||
|
||||
/**
|
||||
* Display a pop-up dialog to run PostAnalysisValidator tests on the Program
|
||||
|
@ -117,7 +116,7 @@ public class ValidateProgramPlugin extends Plugin {
|
|||
private List<ConditionTester> getConditionTests(Program program) {
|
||||
List<ConditionTester> list = new ArrayList<ConditionTester>();
|
||||
|
||||
Set<Class<? extends PostAnalysisValidator>> validatorClasses =
|
||||
List<Class<? extends PostAnalysisValidator>> validatorClasses =
|
||||
ClassSearcher.getClasses(PostAnalysisValidator.class);
|
||||
for (Class<? extends PostAnalysisValidator> validatorClass : validatorClasses) {
|
||||
try {
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
package ghidra.app.util.demangler;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
@ -39,7 +38,7 @@ public class DemanglerUtil {
|
|||
* @return the demangled object or null
|
||||
*/
|
||||
public static DemangledObject demangle(String mangled) {
|
||||
Set<Demangler> demanglers = getDemanglers();
|
||||
List<Demangler> demanglers = getDemanglers();
|
||||
for (Demangler demangler : demanglers) {
|
||||
try {
|
||||
// not sure if we should be doing all symbols, but this is what it used to do
|
||||
|
@ -65,7 +64,7 @@ public class DemanglerUtil {
|
|||
* @return the demangled object or null
|
||||
*/
|
||||
public static DemangledObject demangle(Program program, String mangled) {
|
||||
Set<Demangler> demanglers = getDemanglers();
|
||||
List<Demangler> demanglers = getDemanglers();
|
||||
for (Demangler demangler : demanglers) {
|
||||
try {
|
||||
if (!demangler.canDemangle(program)) {
|
||||
|
@ -91,7 +90,7 @@ public class DemanglerUtil {
|
|||
*
|
||||
* @return a list of all demanglers
|
||||
*/
|
||||
private static Set<Demangler> getDemanglers() {
|
||||
private static List<Demangler> getDemanglers() {
|
||||
return ClassSearcher.getInstances(Demangler.class);
|
||||
}
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ public class Annotation {
|
|||
Map<String, AnnotatedStringHandler> map = new HashMap<>();
|
||||
|
||||
// find all instances of AnnotatedString
|
||||
Set<AnnotatedStringHandler> instances =
|
||||
List<AnnotatedStringHandler> instances =
|
||||
ClassSearcher.getInstances(AnnotatedStringHandler.class);
|
||||
|
||||
for (AnnotatedStringHandler instance : instances) {
|
||||
|
|
|
@ -15,7 +15,8 @@
|
|||
*/
|
||||
package ghidra.app.util.viewer.format;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import org.jdom.Element;
|
||||
|
@ -139,7 +140,7 @@ public class FormatManager implements OptionsChangeListener {
|
|||
private void getFactorys() {
|
||||
ClassFilter filter = new ClassExclusionFilter(DummyFieldFactory.class,
|
||||
SpacerFieldFactory.class, SubDataFieldFactory.class);
|
||||
Set<FieldFactory> instances = ClassSearcher.getInstances(FieldFactory.class, filter);
|
||||
List<FieldFactory> instances = ClassSearcher.getInstances(FieldFactory.class, filter);
|
||||
List<FieldFactory> list = new ArrayList<>();
|
||||
for (FieldFactory fieldFactory : instances) {
|
||||
if (fieldFactory instanceof SpacerFieldFactory) {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -16,6 +15,10 @@
|
|||
*/
|
||||
package ghidra.app.util.viewer.util;
|
||||
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.*;
|
||||
|
||||
import docking.widgets.fieldpanel.support.FieldLocation;
|
||||
import ghidra.app.nav.Navigatable;
|
||||
import ghidra.app.services.*;
|
||||
import ghidra.app.util.viewer.field.*;
|
||||
|
@ -23,11 +26,6 @@ import ghidra.framework.plugintool.ServiceProvider;
|
|||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.util.classfinder.ClassSearcher;
|
||||
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.*;
|
||||
|
||||
import docking.widgets.fieldpanel.support.FieldLocation;
|
||||
|
||||
/**
|
||||
* Helper class to navigate to an address when user double clicks in a
|
||||
* Field. This class will find {@link FieldMouseHandlerExtension}s by using the {@link ClassSearcher}.
|
||||
|
@ -84,7 +82,7 @@ public class FieldNavigator implements ButtonPressedListener, FieldMouseHandlerS
|
|||
new HashMap<Class<?>, List<FieldMouseHandler>>();
|
||||
|
||||
// find all instances of AnnotatedString
|
||||
Set<FieldMouseHandlerExtension> instances =
|
||||
List<FieldMouseHandlerExtension> instances =
|
||||
ClassSearcher.getInstances(FieldMouseHandlerExtension.class);
|
||||
for (FieldMouseHandlerExtension fieldMouseHandler : instances) {
|
||||
addHandler(map, fieldMouseHandler);
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
package ghidra.framework;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Set;
|
||||
import java.util.List;
|
||||
|
||||
import generic.jar.ResourceFile;
|
||||
import ghidra.GhidraClassLoader;
|
||||
|
@ -111,7 +111,7 @@ public class HeadlessGhidraApplicationConfiguration extends ApplicationConfigura
|
|||
}
|
||||
|
||||
private void performModuleInitialization() {
|
||||
Set<ModuleInitializer> instances = ClassSearcher.getInstances(ModuleInitializer.class);
|
||||
List<ModuleInitializer> instances = ClassSearcher.getInstances(ModuleInitializer.class);
|
||||
for (ModuleInitializer initializer : instances) {
|
||||
monitor.setMessage("Initializing " + initializer.getName() + "...");
|
||||
initializer.run();
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -16,12 +15,13 @@
|
|||
*/
|
||||
package ghidra.framework.analysis;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.app.services.Analyzer;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.classfinder.ClassSearcher;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class AnalysisRecipeBuilder {
|
||||
|
||||
private static List<Class<? extends Analyzer>> classes;
|
||||
|
@ -39,7 +39,7 @@ public class AnalysisRecipeBuilder {
|
|||
|
||||
private static AnalysisRecipe buildDefaultRecipe(Program program) {
|
||||
List<Analyzer> analyzerList = new ArrayList<Analyzer>();
|
||||
Set<Analyzer> anayzers = ClassSearcher.getInstances(Analyzer.class);
|
||||
List<Analyzer> anayzers = ClassSearcher.getInstances(Analyzer.class);
|
||||
for (Analyzer analyzer : anayzers) {
|
||||
if (analyzer.canAnalyze(program)) {
|
||||
analyzerList.add(analyzer);
|
||||
|
|
|
@ -27,11 +27,11 @@ import ghidra.program.model.listing.Program;
|
|||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.program.util.ProgramSelection;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.classfinder.ExtensionPoint;
|
||||
import ghidra.util.classfinder.ExtensionPointProperties;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
@ExtensionPoint.Exclude(reason = "requires explicit instantiation to wrap a script")
|
||||
@ExtensionPointProperties(exclude = true) // exclude class from extension point discovery because it has to be directly instantiated in order to wrap the supplied script
|
||||
public class GhidraScriptAnalyzerAdapter extends AbstractAnalyzer {
|
||||
|
||||
private ResourceFile scriptFile;
|
||||
|
|
|
@ -18,7 +18,6 @@ package ghidra.framework.plugintool.dialog;
|
|||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.*;
|
||||
|
||||
|
@ -88,7 +87,7 @@ public class ManageFrontEndToolTest extends AbstractGhidraHeadedIntegrationTest
|
|||
count++;
|
||||
}
|
||||
|
||||
Set<Class<? extends FrontEndable>> classes = ClassSearcher.getClasses(FrontEndable.class);
|
||||
List<Class<? extends FrontEndable>> classes = ClassSearcher.getClasses(FrontEndable.class);
|
||||
assertEquals(count, classes.size());
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ package ghidra.app.plugin.core.byteviewer;
|
|||
|
||||
import java.awt.event.*;
|
||||
import java.math.BigInteger;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.swing.*;
|
||||
|
@ -696,7 +697,7 @@ public class ProgramByteViewerComponentProvider extends ByteViewerComponentProvi
|
|||
@Override
|
||||
protected Set<DataFormatModel> getDataFormatModels() {
|
||||
Set<DataFormatModel> dataFormatModels = super.getDataFormatModels();
|
||||
Set<ProgramDataFormatModel> instances =
|
||||
List<ProgramDataFormatModel> instances =
|
||||
ClassSearcher.getInstances(ProgramDataFormatModel.class);
|
||||
dataFormatModels.addAll(instances);
|
||||
return dataFormatModels;
|
||||
|
|
|
@ -15,13 +15,13 @@
|
|||
*/
|
||||
package ghidra.file.analyzers;
|
||||
|
||||
import ghidra.util.classfinder.ClassSearcher;
|
||||
import java.util.List;
|
||||
|
||||
import java.util.Set;
|
||||
import ghidra.util.classfinder.ClassSearcher;
|
||||
|
||||
public final class FileFormatAnalyzerFactory {
|
||||
|
||||
public final static Set<FileFormatAnalyzer> getAnalyzers() {
|
||||
public final static List<FileFormatAnalyzer> getAnalyzers() {
|
||||
return ClassSearcher.getInstances(FileFormatAnalyzer.class);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,15 +15,15 @@
|
|||
*/
|
||||
package ghidra.file.crypto;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.app.util.bin.ByteProvider;
|
||||
import ghidra.util.classfinder.ClassSearcher;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.exception.CryptoException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Not used by any known code, not tested.
|
||||
*/
|
||||
|
@ -34,7 +34,7 @@ public final class DecryptorFactory {
|
|||
ByteProvider provider, TaskMonitor monitor) throws IOException, CryptoException,
|
||||
CancelledException {
|
||||
|
||||
Set<Decryptor> instances = ClassSearcher.getInstances(Decryptor.class);
|
||||
List<Decryptor> instances = ClassSearcher.getInstances(Decryptor.class);
|
||||
for (Decryptor decryptor : instances) {
|
||||
if (monitor.isCancelled()) {
|
||||
throw new CancelledException();
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
*/
|
||||
package ghidra.app.plugin.core.functiongraph;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.app.plugin.core.functiongraph.graph.layout.FGLayout;
|
||||
import ghidra.app.plugin.core.functiongraph.graph.layout.FGLayoutProvider;
|
||||
|
@ -27,8 +27,8 @@ import ghidra.util.classfinder.ClassSearcher;
|
|||
public class DiscoverableFGLayoutFinder implements FGLayoutFinder {
|
||||
|
||||
@Override
|
||||
public Set<FGLayoutProvider> findLayouts() {
|
||||
Set<FGLayoutProvider> instances = ClassSearcher.getInstances(FGLayoutProvider.class);
|
||||
public List<FGLayoutProvider> findLayouts() {
|
||||
List<FGLayoutProvider> instances = ClassSearcher.getInstances(FGLayoutProvider.class);
|
||||
return instances;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
*/
|
||||
package ghidra.app.plugin.core.functiongraph;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.app.plugin.core.functiongraph.graph.layout.FGLayout;
|
||||
import ghidra.app.plugin.core.functiongraph.graph.layout.FGLayoutProvider;
|
||||
|
@ -24,5 +24,5 @@ import ghidra.app.plugin.core.functiongraph.graph.layout.FGLayoutProvider;
|
|||
* An interface that provides {@link FGLayout}s
|
||||
*/
|
||||
public interface FGLayoutFinder {
|
||||
public Set<FGLayoutProvider> findLayouts();
|
||||
public List<FGLayoutProvider> findLayouts();
|
||||
}
|
||||
|
|
|
@ -135,7 +135,7 @@ public class FunctionGraphPlugin extends ProgramPlugin implements OptionsChangeL
|
|||
private List<FGLayoutProvider> loadLayoutProviders() {
|
||||
|
||||
FGLayoutFinder layoutFinder = new DiscoverableFGLayoutFinder();
|
||||
Set<FGLayoutProvider> instances = layoutFinder.findLayouts();
|
||||
List<FGLayoutProvider> instances = layoutFinder.findLayouts();
|
||||
if (instances.isEmpty()) {
|
||||
throw new AssertException("Could not find any layout providers. You project may not " +
|
||||
"be configured properly.");
|
||||
|
|
|
@ -59,7 +59,7 @@ public class FidService {
|
|||
this.digestFactory = new FNV1a64MessageDigestFactory();
|
||||
this.skippers = new HashMap<>();
|
||||
|
||||
Set<Class<? extends InstructionSkipper>> classes =
|
||||
List<Class<? extends InstructionSkipper>> classes =
|
||||
ClassSearcher.getClasses(InstructionSkipper.class);
|
||||
for (Class<? extends InstructionSkipper> clazz : classes) {
|
||||
try {
|
||||
|
|
|
@ -15,6 +15,9 @@
|
|||
*/
|
||||
package ghidra.feature.vt;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
import ghidra.app.script.GhidraScript;
|
||||
import ghidra.feature.vt.api.db.VTSessionDB;
|
||||
import ghidra.feature.vt.api.main.*;
|
||||
|
@ -26,9 +29,6 @@ import ghidra.util.classfinder.ClassSearcher;
|
|||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.exception.VersionException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
public abstract class GhidraVersionTrackingScript extends GhidraScript {
|
||||
protected VTSession vtSession;
|
||||
protected Program sourceProgram;
|
||||
|
@ -162,7 +162,7 @@ public abstract class GhidraVersionTrackingScript extends GhidraScript {
|
|||
|
||||
public List<String> getProgramCorrelators() {
|
||||
List<String> correlators = new ArrayList<String>();
|
||||
Set<VTProgramCorrelatorFactory> generateList = getVTProgramCorrelatorFactory();
|
||||
List<VTProgramCorrelatorFactory> generateList = getVTProgramCorrelatorFactory();
|
||||
for (VTProgramCorrelatorFactory vtProgramCorrelatorFactory : generateList) {
|
||||
correlators.add(vtProgramCorrelatorFactory.getName());
|
||||
}
|
||||
|
@ -221,7 +221,7 @@ public abstract class GhidraVersionTrackingScript extends GhidraScript {
|
|||
//==================================================================================================
|
||||
|
||||
private VTProgramCorrelatorFactory getCorrelatorFactory(String name) {
|
||||
Set<VTProgramCorrelatorFactory> generateList = getVTProgramCorrelatorFactory();
|
||||
List<VTProgramCorrelatorFactory> generateList = getVTProgramCorrelatorFactory();
|
||||
for (VTProgramCorrelatorFactory vtProgramCorrelatorFactory : generateList) {
|
||||
if (vtProgramCorrelatorFactory.getName().equals(name)) {
|
||||
return vtProgramCorrelatorFactory;
|
||||
|
@ -230,7 +230,7 @@ public abstract class GhidraVersionTrackingScript extends GhidraScript {
|
|||
return null;
|
||||
}
|
||||
|
||||
private static Set<VTProgramCorrelatorFactory> getVTProgramCorrelatorFactory() {
|
||||
private static List<VTProgramCorrelatorFactory> getVTProgramCorrelatorFactory() {
|
||||
return ClassSearcher.getInstances(VTProgramCorrelatorFactory.class);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ public abstract class Stringable implements ExtensionPoint, DisplayStringProvide
|
|||
|
||||
private static void initializeNameMap() {
|
||||
shortNameToClassnameMap = new HashMap<String, Class<? extends Stringable>>();
|
||||
Set<Class<? extends Stringable>> classes = ClassSearcher.getClasses(Stringable.class);
|
||||
List<Class<? extends Stringable>> classes = ClassSearcher.getClasses(Stringable.class);
|
||||
for (Class<? extends Stringable> clazz : classes) {
|
||||
String name = getShortNameFieldValue(clazz);
|
||||
shortNameToClassnameMap.put(name, clazz);
|
||||
|
|
|
@ -62,7 +62,7 @@ public class AddressCorrelatorManager {
|
|||
|
||||
private List<AddressCorrelator> initializeAddressCorrelators() {
|
||||
|
||||
Set<DiscoverableAddressCorrelator> instances =
|
||||
List<DiscoverableAddressCorrelator> instances =
|
||||
ClassSearcher.getInstances(DiscoverableAddressCorrelator.class);
|
||||
List<AddressCorrelator> addressCorrelatorList = new ArrayList<AddressCorrelator>(instances);
|
||||
|
||||
|
|
|
@ -17,7 +17,8 @@ package ghidra.feature.vt.gui.provider.matchtable;
|
|||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.event.*;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
|
@ -98,7 +99,7 @@ public class AlgorithmFilter extends CheckBoxBasedAncillaryFilter<VTMatch> {
|
|||
list.add(ManualMatchProgramCorrelator.NAME);
|
||||
list.add(ImpliedMatchProgramCorrelator.NAME);
|
||||
|
||||
Set<VTAbstractProgramCorrelatorFactory> instances =
|
||||
List<VTAbstractProgramCorrelatorFactory> instances =
|
||||
ClassSearcher.getInstances(VTAbstractProgramCorrelatorFactory.class);
|
||||
for (VTAbstractProgramCorrelatorFactory factory : instances) {
|
||||
list.add(factory.getName());
|
||||
|
|
|
@ -15,13 +15,6 @@
|
|||
*/
|
||||
package ghidra.feature.vt.gui.wizard;
|
||||
|
||||
import ghidra.feature.vt.api.main.VTSession;
|
||||
import ghidra.feature.vt.gui.validator.VTPreconditionValidator;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.HelpLocation;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.classfinder.ClassSearcher;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
@ -33,6 +26,12 @@ import javax.swing.*;
|
|||
|
||||
import docking.widgets.conditiontestpanel.*;
|
||||
import docking.wizard.*;
|
||||
import ghidra.feature.vt.api.main.VTSession;
|
||||
import ghidra.feature.vt.gui.validator.VTPreconditionValidator;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.HelpLocation;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.classfinder.ClassSearcher;
|
||||
|
||||
public class PreconditionsPanel extends AbstractMageJPanel<VTWizardStateKey> implements Scrollable {
|
||||
private static final Dimension DEFAULT_SIZE = new Dimension(650, 480);
|
||||
|
@ -148,7 +147,7 @@ public class PreconditionsPanel extends AbstractMageJPanel<VTWizardStateKey> imp
|
|||
Program destinationProgram, VTSession existingResults) throws SecurityException {
|
||||
List<ConditionTester> list = new ArrayList<ConditionTester>();
|
||||
|
||||
Set<Class<? extends VTPreconditionValidator>> vtValidatorClasses =
|
||||
List<Class<? extends VTPreconditionValidator>> vtValidatorClasses =
|
||||
ClassSearcher.getClasses(VTPreconditionValidator.class);
|
||||
for (Class<? extends VTPreconditionValidator> validatorClass : vtValidatorClasses) {
|
||||
try {
|
||||
|
|
|
@ -60,13 +60,12 @@ public class VTProgramTableCorrelatorModel extends AbstractGTableModel<VTProgram
|
|||
}
|
||||
|
||||
private static List<VTProgramCorrelatorFactory> generateList() {
|
||||
Set<VTAbstractProgramCorrelatorFactory> instances =
|
||||
List<VTAbstractProgramCorrelatorFactory> instances =
|
||||
ClassSearcher.getInstances(VTAbstractProgramCorrelatorFactory.class);
|
||||
|
||||
List<VTProgramCorrelatorFactory> list =
|
||||
new ArrayList<>(instances);
|
||||
List<VTProgramCorrelatorFactory> list = new ArrayList<>(instances);
|
||||
|
||||
Collections.sort(list, comparator);
|
||||
Collections.sort(instances, comparator);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
|
|
@ -208,7 +208,7 @@ public class DiscoverableTableUtils {
|
|||
Set<TableRowMapper<ROW_TYPE, EXPECTED_TYPE, DATA_SOURCE>> set = new HashSet<>();
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
Set<TableRowMapper> instances = ClassSearcher.getInstances(TableRowMapper.class);
|
||||
List<TableRowMapper> instances = ClassSearcher.getInstances(TableRowMapper.class);
|
||||
for (TableRowMapper<ROW_TYPE, EXPECTED_TYPE, DATA_SOURCE> mapper : instances) {
|
||||
if (mapper.getSourceType() == fromType && mapper.getDestinationType() == toType) {
|
||||
set.add(mapper);
|
||||
|
@ -293,7 +293,7 @@ public class DiscoverableTableUtils {
|
|||
List<ColumnConstraint<?>> mappedConstraints = new ArrayList<>();
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
Set<ColumnTypeMapper> mappers = ClassSearcher.getInstances(ColumnTypeMapper.class);
|
||||
List<ColumnTypeMapper> mappers = ClassSearcher.getInstances(ColumnTypeMapper.class);
|
||||
|
||||
for (ColumnTypeMapper<?, ?> mapper : mappers) {
|
||||
mappedConstraints.addAll(generateMappedConstraints(mapper, foundConstraints));
|
||||
|
@ -371,7 +371,7 @@ public class DiscoverableTableUtils {
|
|||
private static List<ColumnConstraint<?>> findColumnConstraints() {
|
||||
List<ColumnConstraint<?>> constraints = new ArrayList<>();
|
||||
|
||||
Set<ColumnConstraintProvider> constraintProviders =
|
||||
List<ColumnConstraintProvider> constraintProviders =
|
||||
ClassSearcher.getInstances(ColumnConstraintProvider.class);
|
||||
|
||||
for (ColumnConstraintProvider provider : constraintProviders) {
|
||||
|
|
|
@ -72,21 +72,43 @@ public class ClassFinder {
|
|||
}
|
||||
}
|
||||
|
||||
Set<Class<?>> getClasses(TaskMonitor monitor) throws CancelledException {
|
||||
List<Class<?>> getClasses(TaskMonitor monitor) throws CancelledException {
|
||||
|
||||
Set<Class<?>> classes = new HashSet<>();
|
||||
Set<Class<?>> classSet = new HashSet<>();
|
||||
|
||||
for (ClassDir dir : classDirs) {
|
||||
monitor.checkCanceled();
|
||||
dir.getClasses(classes, monitor);
|
||||
dir.getClasses(classSet, monitor);
|
||||
}
|
||||
|
||||
for (ClassJar jar : classJars) {
|
||||
monitor.checkCanceled();
|
||||
jar.getClasses(classes, monitor);
|
||||
jar.getClasses(classSet, monitor);
|
||||
}
|
||||
|
||||
return classes;
|
||||
List<Class<?>> classList = new ArrayList<>(classSet);
|
||||
|
||||
Collections.sort(classList, (c1, c2) -> {
|
||||
// Sort classes primarily by priority and secondarily by name
|
||||
int p1 = ExtensionPointProperties.Util.getPriority(c1);
|
||||
int p2 = ExtensionPointProperties.Util.getPriority(c2);
|
||||
if (p1 > p2) {
|
||||
return -1;
|
||||
}
|
||||
if (p1 < p2) {
|
||||
return 1;
|
||||
}
|
||||
String n1 = c1.getName();
|
||||
String n2 = c2.getName();
|
||||
if (n1.equals(n2)) {
|
||||
// Same priority and same package/class name....just arbitrarily choose one
|
||||
return Integer.compare(c1.hashCode(), c2.hashCode());
|
||||
}
|
||||
return n1.compareTo(n2);
|
||||
});
|
||||
|
||||
|
||||
return classList;
|
||||
}
|
||||
|
||||
/*package*/ static Class<?> loadExtensionPoint(String path, String fullName) {
|
||||
|
@ -178,7 +200,7 @@ public class ClassFinder {
|
|||
if (!Modifier.isPublic(c.getModifiers())) {
|
||||
return false;
|
||||
}
|
||||
if (ExtensionPoint.Util.isExcluded(c)) {
|
||||
if (ExtensionPointProperties.Util.isExcluded(c)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ public class ClassSearcher {
|
|||
static final Logger log = LogManager.getLogger(ClassSearcher.class);
|
||||
|
||||
private static ClassFinder searcher;
|
||||
private static Set<Class<?>> extensionPoints;
|
||||
private static List<Class<?>> extensionPoints;
|
||||
|
||||
private static WeakSet<ChangeListener> listenerList =
|
||||
WeakDataStructureFactory.createCopyOnReadWeakSet();
|
||||
|
@ -82,53 +82,67 @@ public class ClassSearcher {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get classes that implement or derive from the given class
|
||||
* Get {@link ExtensionPointProperties#priority() priority-sorted} classes that implement or
|
||||
* derive from the given class
|
||||
*
|
||||
* @param c class filter class
|
||||
* @param c the filter class
|
||||
* @return set of classes that implement or extend T
|
||||
*/
|
||||
public static <T> Set<Class<? extends T>> getClasses(Class<T> c) {
|
||||
public static <T> List<Class<? extends T>> getClasses(Class<T> c) {
|
||||
return getClasses(c, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get classes that implement or derive from the given class
|
||||
* Get {@link ExtensionPointProperties#priority() priority-sorted} classes that
|
||||
* implement or derive from the given class
|
||||
*
|
||||
* @param c class filter class
|
||||
* @param c the filter class
|
||||
* @param classFilter A Predicate that tests class objects (that are already of type T)
|
||||
* for further filtering, <code>null</code> is equivalent to "return true"
|
||||
* @return set of classes that implement or extend T and pass the filtering test performed
|
||||
* by the predicate.
|
||||
* @return {@link ExtensionPointProperties#priority() priority-sorted} list of
|
||||
* classes that implement or extend T and pass the filtering test performed by the
|
||||
* predicate
|
||||
*/
|
||||
@SuppressWarnings("unchecked") // we checked the type of each use so we know the casts are safe
|
||||
public static <T> Set<Class<? extends T>> getClasses(Class<T> c,
|
||||
public static <T> List<Class<? extends T>> getClasses(Class<T> c,
|
||||
Predicate<Class<? extends T>> classFilter) {
|
||||
if (isSearching) {
|
||||
throw new IllegalStateException(
|
||||
"Cannot call the getClasses() while the ClassSearcher is searching!");
|
||||
}
|
||||
|
||||
Set<Class<? extends T>> set = new HashSet<>();
|
||||
List<Class<? extends T>> list = new ArrayList<>();
|
||||
if (extensionPoints == null) {
|
||||
return set;
|
||||
return list;
|
||||
}
|
||||
|
||||
for (Class<?> extensionPoint : extensionPoints) {
|
||||
if (c.isAssignableFrom(extensionPoint) &&
|
||||
(classFilter == null || classFilter.test((Class<T>) extensionPoint))) {
|
||||
set.add((Class<? extends T>) extensionPoint);
|
||||
list.add((Class<? extends T>) extensionPoint);
|
||||
}
|
||||
}
|
||||
return set;
|
||||
return list;
|
||||
}
|
||||
|
||||
public static <T> Set<T> getInstances(Class<T> c) {
|
||||
public static <T> List<T> getInstances(Class<T> c) {
|
||||
return getInstances(c, DO_NOTHING_FILTER);
|
||||
}
|
||||
|
||||
public static <T> Set<T> getInstances(Class<T> c, ClassFilter filter) {
|
||||
Set<Class<? extends T>> classes = getClasses(c);
|
||||
Set<T> instances = new HashSet<>();
|
||||
/**
|
||||
* Get {@link ExtensionPointProperties#priority() priority-sorted} classes
|
||||
* instances that implement or derive from the given class
|
||||
*
|
||||
* @param c the filter class
|
||||
* @param filter A Predicate that tests class objects (that are already of type T)
|
||||
* for further filtering, <code>null</code> is equivalent to "return true"
|
||||
* @return {@link ExtensionPointProperties#priority() priority-sorted} list of
|
||||
* classes instances that implement or extend T and pass the filtering test performed by
|
||||
* the predicate
|
||||
*/
|
||||
public static <T> List<T> getInstances(Class<T> c, ClassFilter filter) {
|
||||
List<Class<? extends T>> classes = getClasses(c);
|
||||
List<T> instances = new ArrayList<>();
|
||||
|
||||
for (Class<? extends T> clazz : classes) {
|
||||
if (!filter.accepts(clazz)) {
|
||||
|
@ -298,7 +312,7 @@ public class ClassSearcher {
|
|||
ResourceFile extensionClassesFile = new ResourceFile(appRoot, "EXTENSION_POINT_CLASSES");
|
||||
try {
|
||||
List<String> classNames = FileUtilities.getLines(extensionClassesFile);
|
||||
Set<Class<?>> extensionClasses = new HashSet<>();
|
||||
List<Class<?>> extensionClasses = new ArrayList<>();
|
||||
for (String className : classNames) {
|
||||
try {
|
||||
Class<?> clazz = Class.forName(className);
|
||||
|
@ -308,7 +322,7 @@ public class ClassSearcher {
|
|||
Msg.warn(ClassSearcher.class, "Can't load extension point: " + className);
|
||||
}
|
||||
}
|
||||
extensionPoints = Collections.unmodifiableSet(extensionClasses);
|
||||
extensionPoints = Collections.unmodifiableList(extensionClasses);
|
||||
|
||||
}
|
||||
catch (IOException e) {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -16,11 +15,6 @@
|
|||
*/
|
||||
package ghidra.util.classfinder;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* NOTE: ExtensionPoint logistics have changed! It is no longer sufficient to
|
||||
* implement ExtensionPoint in order for the ClassSearcher to dynamically pick
|
||||
|
@ -35,15 +29,5 @@ import java.lang.annotation.Target;
|
|||
* will automatically search for and load.
|
||||
*/
|
||||
public interface ExtensionPoint {
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public static @interface Exclude {
|
||||
String reason();
|
||||
}
|
||||
|
||||
public static class Util {
|
||||
public static boolean isExcluded(Class<?> c) {
|
||||
return c.getAnnotation(Exclude.class) != null;
|
||||
}
|
||||
}
|
||||
// Marker interface
|
||||
}
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.util.classfinder;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* {@link ExtensionPoint} properties
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface ExtensionPointProperties {
|
||||
|
||||
/**
|
||||
* Default {@link ExtensionPoint} priority. Higher values represent higher priorities.
|
||||
*/
|
||||
final static int DEFAULT_PRIORITY = 1;
|
||||
|
||||
/**
|
||||
* Default behavior for an {@link ExtensionPoint} being discoverable
|
||||
*/
|
||||
final static boolean DEFAULT_EXCLUDE = false;
|
||||
|
||||
/**
|
||||
* {@link ExtensionPoint} priority. Higher values represent higher priorities.
|
||||
*
|
||||
* @return the {@link ExtensionPoint} priority.
|
||||
*/
|
||||
int priority() default DEFAULT_PRIORITY;
|
||||
|
||||
/**
|
||||
* Enable to exclude an {@link ExtensionPoint} from being discovered
|
||||
*
|
||||
* @return true to exclude an {@link ExtensionPoint} from being discovered
|
||||
*/
|
||||
boolean exclude() default DEFAULT_EXCLUDE;
|
||||
|
||||
/**
|
||||
* Utility methods for working with {@link ExtensionPointProperties}
|
||||
*/
|
||||
public static class Util {
|
||||
|
||||
/**
|
||||
* Gets whether or not the {@link ExtensionPoint} will be excluded from being discovered
|
||||
*
|
||||
* @param c the class check
|
||||
* @return true if the class is an {@link ExtensionPoint} and should be excluded from being
|
||||
* discovered
|
||||
*/
|
||||
public static boolean isExcluded(Class<?> c) {
|
||||
ExtensionPointProperties properties = c.getAnnotation(ExtensionPointProperties.class);
|
||||
return properties != null ? properties.exclude()
|
||||
: ExtensionPointProperties.DEFAULT_EXCLUDE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link ExtensionPoint} priority.
|
||||
*
|
||||
* @param c the class to get {@link ExtensionPoint} priority of.
|
||||
* @return the class's {@link ExtensionPoint} priority
|
||||
* ({@link ExtensionPointProperties#DEFAULT_PRIORITY} will be used in a
|
||||
* non-{@link ExtensionPoint} is passed in)
|
||||
*/
|
||||
public static int getPriority(Class<?> c) {
|
||||
ExtensionPointProperties properties = c.getAnnotation(ExtensionPointProperties.class);
|
||||
return properties != null ? properties.priority()
|
||||
: ExtensionPointProperties.DEFAULT_PRIORITY;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -16,12 +15,6 @@
|
|||
*/
|
||||
package ghidra.framework.data;
|
||||
|
||||
import ghidra.framework.model.*;
|
||||
import ghidra.framework.store.FileSystem;
|
||||
import ghidra.framework.store.LockException;
|
||||
import ghidra.util.Lock;
|
||||
import ghidra.util.classfinder.ClassSearcher;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
@ -29,6 +22,12 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
|
||||
import ghidra.framework.model.*;
|
||||
import ghidra.framework.store.FileSystem;
|
||||
import ghidra.framework.store.LockException;
|
||||
import ghidra.util.Lock;
|
||||
import ghidra.util.classfinder.ClassSearcher;
|
||||
|
||||
/**
|
||||
* An abstract class that provides default behavior for
|
||||
* DomainObject(s), specifically it handles listeners and
|
||||
|
@ -488,7 +487,7 @@ public abstract class DomainObjectAdapter implements DomainObject {
|
|||
contentHandlerClassMap = new HashMap<Class<?>, ContentHandler>();
|
||||
contentHandlerTypeMap = new HashMap<String, ContentHandler>();
|
||||
|
||||
Set<ContentHandler> handlers = ClassSearcher.getInstances(ContentHandler.class);
|
||||
List<ContentHandler> handlers = ClassSearcher.getInstances(ContentHandler.class);
|
||||
for (ContentHandler ch : handlers) {
|
||||
String type = ch.getContentType();
|
||||
Class<?> DOClass = ch.getDomainObjectClass();
|
||||
|
|
|
@ -96,7 +96,7 @@ public class ProjectDataTableModel extends ThreadedTableModel<DomainFileInfo, Pr
|
|||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private List<ProjectDataColumn<?>> findAppSpecificColumns() {
|
||||
Set<ProjectDataColumn> instances = ClassSearcher.getInstances(ProjectDataColumn.class);
|
||||
List<ProjectDataColumn> instances = ClassSearcher.getInstances(ProjectDataColumn.class);
|
||||
List<ProjectDataColumn<?>> columns = new ArrayList<>();
|
||||
|
||||
for (ProjectDataColumn projectDataColumn : instances) {
|
||||
|
|
|
@ -48,7 +48,7 @@ public class PluginClassManager {
|
|||
(localExclusionClass == null || !localExclusionClass.isAssignableFrom(c)) &&
|
||||
!ProgramaticUseOnly.class.isAssignableFrom(c);
|
||||
|
||||
Set<Class<? extends Plugin>> classes =
|
||||
List<Class<? extends Plugin>> classes =
|
||||
ClassSearcher.getClasses(Plugin.class, myClassFilter);
|
||||
|
||||
for (Class<? extends Plugin> pluginClass : classes) {
|
||||
|
|
|
@ -49,7 +49,8 @@ public abstract class PluginPackage implements ExtensionPoint, Comparable<Plugin
|
|||
|
||||
private static Map<String, PluginPackage> createPackageMap() {
|
||||
Map<String, PluginPackage> map = new HashMap<>();
|
||||
Set<Class<? extends PluginPackage>> classes = ClassSearcher.getClasses(PluginPackage.class);
|
||||
List<Class<? extends PluginPackage>> classes =
|
||||
ClassSearcher.getClasses(PluginPackage.class);
|
||||
for (Class<? extends PluginPackage> class1 : classes) {
|
||||
PluginPackage pluginPackage;
|
||||
try {
|
||||
|
|
|
@ -119,7 +119,7 @@ public class PluginUtils {
|
|||
|
||||
// Now get all Plugin.class files that have been loaded, and see if any of them
|
||||
// were loaded from one of the jars we just found.
|
||||
Set<Class<? extends Plugin>> plugins = ClassSearcher.getClasses(Plugin.class);
|
||||
List<Class<? extends Plugin>> plugins = ClassSearcher.getClasses(Plugin.class);
|
||||
for (Class<? extends Plugin> plugin : plugins) {
|
||||
URL location = plugin.getResource('/' + plugin.getName().replace('.', '/') + ".class");
|
||||
if (location == null) {
|
||||
|
|
|
@ -390,7 +390,7 @@ class ToolServicesImpl implements ToolServices {
|
|||
}
|
||||
|
||||
contentHandlers = new HashSet<>();
|
||||
Set<ContentHandler> instances = ClassSearcher.getInstances(ContentHandler.class);
|
||||
List<ContentHandler> instances = ClassSearcher.getInstances(ContentHandler.class);
|
||||
for (ContentHandler contentHandler : instances) {
|
||||
// a bit of validation
|
||||
String contentType = contentHandler.getContentType();
|
||||
|
|
|
@ -128,7 +128,7 @@ public class Handler extends URLStreamHandler {
|
|||
|
||||
private static void loadGhidraProtocolHandlers() {
|
||||
protocolHandlers = new ArrayList<>();
|
||||
Set<Class<? extends GhidraProtocolHandler>> classes =
|
||||
List<Class<? extends GhidraProtocolHandler>> classes =
|
||||
ClassSearcher.getClasses(GhidraProtocolHandler.class);
|
||||
for (Class<?> c : classes) {
|
||||
try {
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
package ghidra.program.model.data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Set;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.event.ChangeListener;
|
||||
|
||||
|
@ -134,7 +134,7 @@ public class BuiltInDataTypeManager extends StandAloneDataTypeManager {
|
|||
try {
|
||||
ArrayList<DataType> list = new ArrayList<>();
|
||||
ClassFilter filter = new BuiltInDataTypeClassExclusionFilter();
|
||||
Set<BuiltInDataType> datatypes =
|
||||
List<BuiltInDataType> datatypes =
|
||||
ClassSearcher.getInstances(BuiltInDataType.class, filter);
|
||||
for (BuiltInDataType datatype : datatypes) {
|
||||
list.clear();
|
||||
|
|
|
@ -110,7 +110,7 @@ public class SymbolUtilities {
|
|||
private static List<String> getDynamicDataTypePrefixes() {
|
||||
List<String> list = new ArrayList<>();
|
||||
ClassFilter filter = new BuiltInDataTypeClassExclusionFilter();
|
||||
Set<BuiltInDataType> instances = ClassSearcher.getInstances(BuiltInDataType.class, filter);
|
||||
List<BuiltInDataType> instances = ClassSearcher.getInstances(BuiltInDataType.class, filter);
|
||||
for (BuiltInDataType builtIn : instances) {
|
||||
String prefix = builtIn.getDefaultAbbreviatedLabelPrefix();
|
||||
if (prefix != null) {
|
||||
|
|
|
@ -85,7 +85,7 @@ public class DefaultLanguageService implements LanguageService, ChangeListener {
|
|||
}
|
||||
|
||||
private void searchForProviders() {
|
||||
Set<LanguageProvider> languageProviders =
|
||||
List<LanguageProvider> languageProviders =
|
||||
ClassSearcher.getInstances(LanguageProvider.class);
|
||||
|
||||
searchCompleted = true;
|
||||
|
@ -338,7 +338,7 @@ public class DefaultLanguageService implements LanguageService, ChangeListener {
|
|||
throw new LanguageNotFoundException(processor);
|
||||
}
|
||||
|
||||
private void processProviders(Set<LanguageProvider> providers) {
|
||||
private void processProviders(List<LanguageProvider> providers) {
|
||||
for (LanguageProvider provider : providers) {
|
||||
addLanguages(provider);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -16,18 +15,18 @@
|
|||
*/
|
||||
package ghidra.util.constraint;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import generic.constraint.DecisionTree;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.classfinder.ClassSearcher;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class ProgramDecisionTree extends DecisionTree<Program> {
|
||||
public ProgramDecisionTree() {
|
||||
super();
|
||||
|
||||
Set<Class<? extends ProgramConstraint>> classes =
|
||||
List<Class<? extends ProgramConstraint>> classes =
|
||||
ClassSearcher.getClasses(ProgramConstraint.class);
|
||||
for (Class<? extends ProgramConstraint> constraintClass : classes) {
|
||||
try {
|
||||
|
|
|
@ -22,6 +22,7 @@ import java.util.stream.Collectors;
|
|||
import generic.jar.ResourceFile;
|
||||
import ghidra.framework.GModule;
|
||||
import ghidra.util.SystemUtilities;
|
||||
import utility.application.ApplicationLayout;
|
||||
import utility.module.ModuleUtilities;
|
||||
|
||||
/**
|
||||
|
@ -52,15 +53,17 @@ public class GhidraLauncher {
|
|||
|
||||
// Build the classpath
|
||||
List<String> classpathList = new ArrayList<String>();
|
||||
Map<String, GModule> modules = getOrderedModules(layout);
|
||||
|
||||
if (SystemUtilities.isInDevelopmentMode()) {
|
||||
addModuleBinPaths(classpathList, layout.getModules());
|
||||
addModuleBinPaths(classpathList, modules);
|
||||
addExternalJarPaths(classpathList, layout.getApplicationRootDirs());
|
||||
}
|
||||
else {
|
||||
addPatchPaths(classpathList, layout.getApplicationInstallationDir());
|
||||
addModuleJarPaths(classpathList, layout.getModules());
|
||||
addModuleJarPaths(classpathList, modules);
|
||||
}
|
||||
classpathList = orderClasspath(classpathList, layout.getModules());
|
||||
classpathList = orderClasspath(classpathList, modules);
|
||||
|
||||
// Add the classpath to the class loader
|
||||
GhidraClassLoader loader = (GhidraClassLoader) ClassLoader.getSystemClassLoader();
|
||||
|
@ -189,6 +192,63 @@ public class GhidraLauncher {
|
|||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the modules ordered by "class-loader priority". This ensures that core modules (things
|
||||
* in Framework/Features/Processors, etc) come before user modules (Extensions). It also
|
||||
* guarantees a consistent module order from run to run.
|
||||
*
|
||||
* @param layout The layout
|
||||
* @return the modules mapped by name, ordered by priority
|
||||
*/
|
||||
private static Map<String, GModule> getOrderedModules(ApplicationLayout layout) {
|
||||
|
||||
Comparator<GModule> comparator = (module1, module2) -> {
|
||||
int nameComparison = module1.getName().compareTo(module2.getName());
|
||||
|
||||
// First handle modules that are external to the Ghidra installation.
|
||||
// These should be put at the end of the list.
|
||||
boolean external1 = ModuleUtilities.isExternalModule(module1, layout);
|
||||
boolean external2 = ModuleUtilities.isExternalModule(module2, layout);
|
||||
if (external1 && external2) {
|
||||
return nameComparison;
|
||||
}
|
||||
if (external1) {
|
||||
return -1;
|
||||
}
|
||||
if (external2) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Now handle modules that are internal to the Ghidra installation.
|
||||
// We will primarily order them by "type" and secondarily by name.
|
||||
Map<String, Integer> typePriorityMap = Map.of(
|
||||
"Framework", 0,
|
||||
"Configurations", 1,
|
||||
"Features", 2,
|
||||
"Processors", 3,
|
||||
"GPL", 4,
|
||||
"Extensions", 5,
|
||||
"Test", 6
|
||||
);
|
||||
String type1 = module1.getModuleRoot().getParentFile().getName();
|
||||
String type2 = module2.getModuleRoot().getParentFile().getName();
|
||||
int priority1 = typePriorityMap.getOrDefault(type1, typePriorityMap.size());
|
||||
int priority2 = typePriorityMap.getOrDefault(type2, typePriorityMap.size());
|
||||
if (priority1 != priority2) {
|
||||
return Integer.compare(priority1, priority2);
|
||||
}
|
||||
return nameComparison;
|
||||
};
|
||||
|
||||
List<GModule> moduleList = new ArrayList<>(layout.getModules().values());
|
||||
Collections.sort(moduleList, comparator);
|
||||
Map<String, GModule> moduleMap = new LinkedHashMap<>();
|
||||
for (GModule module : moduleList) {
|
||||
moduleMap.put(module.getName(), module);
|
||||
}
|
||||
return moduleMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the list of paths to make sure the order is correct for any class-loading dependencies.
|
||||
*
|
||||
|
@ -199,18 +259,16 @@ public class GhidraLauncher {
|
|||
private static List<String> orderClasspath(List<String> pathList,
|
||||
Map<String, GModule> modules) {
|
||||
|
||||
//@formatter:off
|
||||
Set<String> flatJars = modules
|
||||
Set<String> fatJars = modules
|
||||
.values()
|
||||
.stream()
|
||||
.flatMap(m -> m.getFatJars().stream())
|
||||
.collect(Collectors.toSet());
|
||||
//@formatter:on
|
||||
|
||||
List<String> orderedList = new ArrayList<String>(pathList);
|
||||
|
||||
for (String path : pathList) {
|
||||
if (flatJars.contains(new File(path).getName())) {
|
||||
if (fatJars.contains(new File(path).getName())) {
|
||||
orderedList.remove(path);
|
||||
orderedList.add(path);
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ import ghidra.util.Msg;
|
|||
import ghidra.util.SystemUtilities;
|
||||
import ghidra.util.exception.AssertException;
|
||||
import utilities.util.FileUtilities;
|
||||
import utility.application.ApplicationLayout;
|
||||
|
||||
/**
|
||||
* Utility methods for module related things.
|
||||
|
@ -334,4 +335,21 @@ public class ModuleUtilities {
|
|||
}
|
||||
return findRepo(f.getParentFile());
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if the given {@link GModule module} is external to the Ghidra installation
|
||||
* directory
|
||||
*
|
||||
* @param module the module to check
|
||||
* @param layout Ghidra's layout
|
||||
* @return true if the given {@link GModule module} is external to the Ghidra installation
|
||||
* directory
|
||||
*/
|
||||
public static boolean isExternalModule(GModule module, ApplicationLayout layout) {
|
||||
File moduleRootDir = module.getModuleRoot().getFile(false);
|
||||
return !layout.getApplicationRootDirs()
|
||||
.stream()
|
||||
.map(dir -> dir.getParentFile().getFile(false))
|
||||
.anyMatch(dir -> FileUtilities.isPathContainedWithin(dir, moduleRootDir));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue