GT-3547 - Patch dir fix - review fixes

This commit is contained in:
dragonmacher 2020-02-19 18:50:52 -05:00
parent 3dced733df
commit 87bda2b34d
14 changed files with 149 additions and 531 deletions

View file

@ -64,6 +64,9 @@ public class GhidraApplicationLayout extends ApplicationLayout {
// Extensions
extensionInstallationDir = findExtensionInstallationDirectory();
extensionArchiveDir = findExtensionArchiveDirectory();
// Patch directory
patchDir = findPatchDirectory();
}
/**
@ -142,7 +145,7 @@ public class GhidraApplicationLayout extends ApplicationLayout {
// Find standard module root directories from within the application root directories
Collection<ResourceFile> moduleRootDirectories =
ModuleUtilities.findModuleRootDirectories(applicationRootDirs, new ArrayList<>());
// Examine the classpath to look for modules outside of the application root directories.
// These might exist if Ghidra was launched from an Eclipse project that resides
// external to the Ghidra installation.
@ -156,8 +159,9 @@ public class GhidraApplicationLayout extends ApplicationLayout {
// Skip classpath entries that live in an application root directory...we've already
// found those.
if (applicationRootDirs.stream().anyMatch(dir -> FileUtilities.isPathContainedWithin(
dir.getFile(false), classpathEntry.getFile(false)))) {
if (applicationRootDirs.stream()
.anyMatch(dir -> FileUtilities.isPathContainedWithin(
dir.getFile(false), classpathEntry.getFile(false)))) {
continue;
}
@ -173,6 +177,24 @@ public class GhidraApplicationLayout extends ApplicationLayout {
return ModuleUtilities.findModules(applicationRootDirs, moduleRootDirectories);
}
/**
* Returns the directory that allows users to add jar and class files to override existing
* distribution files
* @return the patch dir; null if not in a distribution
*/
protected ResourceFile findPatchDirectory() {
if (SystemUtilities.isInDevelopmentMode()) {
return null;
}
if (applicationInstallationDir == null) {
return null;
}
return new ResourceFile(applicationInstallationDir, "Ghidra/patch");
}
/**
* Returns the directory where all Ghidra extension archives are stored.
* This should be at the following location:<br>

View file

@ -31,7 +31,7 @@ import ghidra.util.Msg;
*
*/
public class GhidraClassLoader extends URLClassLoader {
private static final String CP = "java.class.path";
/**
@ -45,7 +45,7 @@ public class GhidraClassLoader extends URLClassLoader {
}
@Override
public void addURL(URL url) {
public void addURL(URL url) {
super.addURL(url);
try {
System.setProperty(CP,
@ -56,23 +56,6 @@ public class GhidraClassLoader extends URLClassLoader {
}
}
/**
* Places the given path first in the classpath
* @param path the path
*/
void prependPath(String path) {
try {
URL url = new File(path).toURI().toURL();
super.addURL(url);
File file = new File(url.toURI());
System.setProperty(CP, file + File.pathSeparator + System.getProperty(CP));
}
catch (MalformedURLException | URISyntaxException e) {
Msg.debug(this, "Invalid path: " + path, e);
}
}
/**
* Converts the specified path to a {@link URL} and adds it to the classpath.
*

View file

@ -53,7 +53,7 @@ public class GhidraLauncher {
GhidraClassLoader loader = (GhidraClassLoader) ClassLoader.getSystemClassLoader();
// Build the classpath
List<String> classpathList = new ArrayList<String>();
List<String> classpathList = new ArrayList<>();
Map<String, GModule> modules = getOrderedModules(layout);
if (SystemUtilities.isInDevelopmentMode()) {
@ -61,7 +61,7 @@ public class GhidraLauncher {
addExternalJarPaths(classpathList, layout.getApplicationRootDirs());
}
else {
addPatchJarPaths(loader, layout.getApplicationInstallationDir());
addPatchPaths(classpathList, layout.getPatchDir());
addModuleJarPaths(classpathList, modules);
}
classpathList = orderClasspath(classpathList, modules);
@ -83,28 +83,24 @@ public class GhidraLauncher {
}
/**
* Add patch dir and jars to the given path list. This should be done first so they take
* precedence in the classpath.
* Add patch jars to the given path list. This should be done first so they take precedence in
* the classpath.
*
* @param loader The loader to which paths will be added.
* @param installDir The application installation directory.
* @param pathList The list of paths to add to
* @param patchDir The application installation directory
*/
private static void addPatchJarPaths(GhidraClassLoader loader, ResourceFile installDir) {
ResourceFile patchDir = new ResourceFile(installDir, "Ghidra/patch");
private static void addPatchPaths(List<String> pathList, ResourceFile patchDir) {
if (!patchDir.exists()) {
return;
}
List<String> patchJars = findJarsInDir(patchDir);
Collections.sort(patchJars);
// this will allow for unbundled class files
pathList.add(patchDir.getAbsolutePath());
// add in reverse order, since we are prepending
for (int i = patchJars.size() - 1; i >= 0; i--) {
loader.prependPath(patchJars.get(i));
}
// put last; paths are prepended in list order
loader.prependPath(patchDir.getAbsolutePath());
// this is each jar file, sorted for loading consistency
List<String> jars = findJarsInDir(patchDir);
Collections.sort(jars);
pathList.addAll(jars);
}
/**
@ -276,7 +272,7 @@ public class GhidraLauncher {
.flatMap(m -> m.getFatJars().stream())
.collect(Collectors.toSet());
List<String> orderedList = new ArrayList<String>(pathList);
List<String> orderedList = new ArrayList<>(pathList);
for (String path : pathList) {
if (fatJars.contains(new File(path).getName())) {

View file

@ -55,4 +55,10 @@ public class GhidraTestApplicationLayout extends GhidraApplicationLayout {
File installDir = new File(getUserTempDir(), "ExtensionInstallDir");
return new ResourceFile(installDir);
}
@Override
protected ResourceFile findPatchDirectory() {
File dir = new File(getUserTempDir(), "patch");
return new ResourceFile(dir);
}
}

View file

@ -42,6 +42,7 @@ public abstract class ApplicationLayout {
protected File userTempDir;
protected File userCacheDir;
protected File userSettingsDir;
protected ResourceFile patchDir;
protected ResourceFile extensionArchiveDir;
protected ResourceFile extensionInstallationDir;
@ -109,10 +110,10 @@ public abstract class ApplicationLayout {
}
/**
* Returns the directory where archived Ghidra Extensions are stored.
* Returns the directory where archived application Extensions are stored.
*
* @return The Ghidra Extensions archive directory. Could be null if the
* {@link ApplicationLayout} does not support Ghidra Extensions.
* @return the application Extensions archive directory. Could be null if the
* {@link ApplicationLayout} does not support application Extensions.
*
*/
public final ResourceFile getExtensionArchiveDir() {
@ -120,15 +121,24 @@ public abstract class ApplicationLayout {
}
/**
* Returns the Ghidra Extensions installation folder.
* Returns the application Extensions installation folder.
*
* @return The Ghidra Extensions installation directory. Could be null if the
* {@link ApplicationLayout} does not support Ghidra Extensions.
* @return the application Extensions installation directory. Could be null if the
* {@link ApplicationLayout} does not support application Extensions.
*/
public final ResourceFile getExtensionInstallationDir() {
return extensionInstallationDir;
}
/**
* Returns the location of the application patch directory. The patch directory can be
* used to modify existing code within a distribution.
* @return the patch directory; may be null
*/
public final ResourceFile getPatchDir() {
return patchDir;
}
/**
* Creates the application's user directories (or ensures they already exist).
*