From 38d18751a30fca4b89131678b0a80edd3eea257d Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Mon, 8 Aug 2022 17:56:10 -0400 Subject: [PATCH] GP-1981 - Support Tool - initial support tool fixes; updates to module discovery to use the classpath in dev mode for filtering --- .../data/docking.palette.theme.properties | 4 +- .../Docking/data/docking.theme.properties | 2 +- .../framework/DockingApplicationLayout.java | 64 ++++++++++++++++++- .../theme/gui/ThemeIconTableModel.java | 4 +- .../widgets/tree/support/GTreeRenderer.java | 2 + .../java/generic/theme/GThemeDefaults.java | 2 + .../src/main/java/generic/theme/Gui.java | 4 +- .../main/java/ghidra/framework/GModule.java | 11 +++- 8 files changed, 84 insertions(+), 9 deletions(-) diff --git a/Ghidra/Framework/Docking/data/docking.palette.theme.properties b/Ghidra/Framework/Docking/data/docking.palette.theme.properties index 3cf0c1ee21..6bf87a025d 100644 --- a/Ghidra/Framework/Docking/data/docking.palette.theme.properties +++ b/Ghidra/Framework/Docking/data/docking.palette.theme.properties @@ -37,4 +37,6 @@ color.palette.white = white // TODO replace values above with dark values #color.palette.black = lightgray -#color.palette.yellow = rgb(191, 191, 64) // olive \ No newline at end of file +#color.palette.yellow = rgb(191, 191, 64) // olive + +color.palette.cyan = #00CCCC // less harsh \ No newline at end of file diff --git a/Ghidra/Framework/Docking/data/docking.theme.properties b/Ghidra/Framework/Docking/data/docking.theme.properties index 11ca64cd94..957f84b895 100644 --- a/Ghidra/Framework/Docking/data/docking.theme.properties +++ b/Ghidra/Framework/Docking/data/docking.theme.properties @@ -51,7 +51,7 @@ color.bg.fieldpanel.selection = color.bg.selection color.bg.fieldpanel.highlight = color.bg.highlight color.bg.fieldpanel.selection-highlight = green -// Icons file +// Icons files icon.empty = images/EmptyIcon16.gif icon.help = images/help-browser.png icon.add = images/Plus2.png diff --git a/Ghidra/Framework/Docking/src/main/java/docking/framework/DockingApplicationLayout.java b/Ghidra/Framework/Docking/src/main/java/docking/framework/DockingApplicationLayout.java index d169142e32..7cab83e2bd 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/framework/DockingApplicationLayout.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/framework/DockingApplicationLayout.java @@ -15,12 +15,16 @@ */ package docking.framework; +import java.io.File; import java.io.FileNotFoundException; -import java.util.Collection; -import java.util.Objects; +import java.util.*; +import java.util.Map.Entry; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import generic.jar.ResourceFile; import ghidra.framework.ApplicationProperties; +import ghidra.framework.GModule; import ghidra.util.SystemUtilities; import util.CollectionUtils; import utility.application.ApplicationLayout; @@ -36,6 +40,10 @@ public class DockingApplicationLayout extends ApplicationLayout { private static final String NO_RELEASE_NAME = "NO_RELEASE"; + /** Dev mode main source bin dir pattern */ + private static final Pattern CLASS_PATH_MODULE_NAME_PATTERN = + Pattern.compile(".*/(\\w+)/bin/main"); + /** * Constructs a new docking application layout object with the given name and version. * @@ -64,7 +72,11 @@ public class DockingApplicationLayout extends ApplicationLayout { * properties. * * @param applicationRootDirs list of application root directories which should be + <<<<<<< Upstream, based on origin/master * used to identify modules and resources. The first entry will be treated as the + ======= + * used to identify modules and resources. The first entry will be treated as the + >>>>>>> 4485b75 GP-1981 - Support Tool - initial support tool fixes; updates to module discovery to use the classpath in dev mode for filtering * installation root. * @param applicationProperties The properties object that will be read system properties. * @throws FileNotFoundException if there was a problem getting a user directory. @@ -74,6 +86,7 @@ public class DockingApplicationLayout extends ApplicationLayout { this.applicationProperties = Objects.requireNonNull(applicationProperties); this.applicationRootDirs = applicationRootDirs; + applicationRootDirs.addAll(getAdditionalApplicationRootDirs(applicationRootDirs)); // Application installation directory applicationInstallationDir = applicationRootDirs.iterator().next().getParentFile(); @@ -102,6 +115,53 @@ public class DockingApplicationLayout extends ApplicationLayout { applicationInstallationDir); } + protected Collection getAdditionalApplicationRootDirs( + Collection roots) { + return Collections.emptyList(); + } + + protected Map findModules() { + if (!SystemUtilities.isInDevelopmentMode()) { + // in release mode we only have one application root, so no need to find all others + return ModuleUtilities.findModules(applicationRootDirs, applicationRootDirs); + } + + // In development mode we may have multiple module root directories under which modules may + // be found. Search all roots for modules. + Collection roots = + ModuleUtilities.findModuleRootDirectories(applicationRootDirs, new ArrayList<>()); + Map allModules = ModuleUtilities.findModules(applicationRootDirs, roots); + + // Filter any modules found to ensure that we only include those that are listed on the + // classpath. (Due to the nature of how the development classpath is created, not all + // found modules may match the classpath entries.) + Set cpNames = getClassPathModuleNames(); + Map filteredModules = new HashMap<>(); + Set> entrySet = allModules.entrySet(); + for (Entry entry : entrySet) { + GModule module = entry.getValue(); + if (cpNames.contains(module.getName())) { + filteredModules.put(entry.getKey(), module); + } + } + + return filteredModules; + } + + private Set getClassPathModuleNames() { + String cp = System.getProperty("java.class.path"); + String[] pathParts = cp.split(File.pathSeparator); + Set paths = new HashSet<>(Arrays.asList(pathParts)); + Set cpNames = new HashSet<>(); + for (String cpEntry : paths) { + Matcher matcher = CLASS_PATH_MODULE_NAME_PATTERN.matcher(cpEntry); + if (matcher.matches()) { + cpNames.add(matcher.group(1)); + } + } + return cpNames; + } + /** * Get the default list of Application directories. In repo-based * development mode this includes the root Ghidra directory within each repo. diff --git a/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeIconTableModel.java b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeIconTableModel.java index 31cfc47f76..f6852962e1 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeIconTableModel.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/theme/gui/ThemeIconTableModel.java @@ -128,6 +128,7 @@ public class ThemeIconTableModel extends GDynamicColumnTableModel getComparator() { return (v1, v2) -> { if (v1 == null && v2 == null) { @@ -210,7 +211,8 @@ public class ThemeIconTableModel extends GDynamicColumnTableModel EXCLUDED_DIRECTORY_NAMES = new HashSet<>(); @@ -99,7 +106,7 @@ public class GModule { String moduleRootPath = moduleRoot.getAbsolutePath(); for (ResourceFile appRoot : appRoots) { - String appRootPath = appRoot.getAbsolutePath(); + String appRootPath = appRoot.getAbsolutePath() + File.separator; if (moduleRootPath.equals(appRootPath)) { // The module root is an appRoot; it doesn't support nested modules @@ -107,7 +114,7 @@ public class GModule { } if (moduleRootPath.startsWith(appRootPath)) { - return moduleRootPath.substring(appRootPath.length() + 1); + return moduleRootPath.substring(appRootPath.length()); } } return null;