mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 10:49:34 +02:00
Candidate release of source code.
This commit is contained in:
parent
db81e6b3b0
commit
79d8f164f8
12449 changed files with 2800756 additions and 16 deletions
|
@ -0,0 +1,693 @@
|
|||
/* ###
|
||||
* 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 resources;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import generic.Images;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.SystemUtilities;
|
||||
import resources.icons.*;
|
||||
import utility.module.ModuleUtilities;
|
||||
|
||||
/**
|
||||
* General resource management class that provides a convenient
|
||||
* way of accessing external resources used in Ghidra.
|
||||
* <p>
|
||||
* <a name="safe"></a>
|
||||
* There is a known problem with Java's {@link MediaTracker} that can cause deadlocks. The various
|
||||
* methods of this class that create {@link ImageIcon}s will do so by loading image bytes directly,
|
||||
* as opposed to using the flawed constructor {@link ImageIcon#ImageIcon(Image)}.
|
||||
*/
|
||||
public class ResourceManager {
|
||||
|
||||
private final static String DEFAULT_ICON_FILENAME = Images.BOMB;
|
||||
private static ImageIcon DEFAULT_ICON;
|
||||
private static Map<String, ImageIcon> iconMap = new HashMap<>();
|
||||
|
||||
private static List<String> defaultSearchPaths;
|
||||
private static List<String> testSearchPaths;
|
||||
|
||||
private static ClassLoader classLoader = ResourceManager.class.getClassLoader();
|
||||
|
||||
/**
|
||||
* Finds a resource with a given name. This method returns null if no
|
||||
* resource with this name is found. The rules for searching resources
|
||||
* associated with a given class are implemented by the defining class
|
||||
* loader of the class.
|
||||
*
|
||||
* @param filename "partially" qualified resource filename to get, e.g.,
|
||||
* "images/go-home.png" would look for the file named 'home.gif' in
|
||||
* the 'images' subdirectory of the 'resources' package,
|
||||
* following the search rules defined by your CLASSPATH and
|
||||
* return an InputStream if found; null if it cannot load the resource.
|
||||
* @return the URL
|
||||
*/
|
||||
public static URL getResource(String filename) {
|
||||
URL url = classLoader.getResource(filename);
|
||||
if (url != null) {
|
||||
return url;
|
||||
}
|
||||
|
||||
url = getResource(getTestSearchPaths(), filename);
|
||||
return url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a resource with a given name. This method returns null if no resource
|
||||
* with this name is found. The rules for searching resources associated with a
|
||||
* given class are implemented by the defining class loader of the class.
|
||||
*
|
||||
* @param filename "partially" qualified resource filename to get, e.g., "images/home.gif"
|
||||
* would look for the file named 'home.gif' in the 'images' subdirectory of
|
||||
* the 'resources' package, following the search rules defined by your
|
||||
* CLASSPATH and return an InputStream if found; null if it cannot load the resource.
|
||||
* @return the input stream
|
||||
*/
|
||||
public static InputStream getResourceAsStream(String filename) {
|
||||
InputStream is = classLoader.getResourceAsStream(filename);
|
||||
if (is != null) {
|
||||
return is;
|
||||
}
|
||||
|
||||
URL url = getResource(testSearchPaths, filename);
|
||||
if (url == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return url.openStream();
|
||||
}
|
||||
catch (IOException e) {
|
||||
Msg.debug(RepaintManager.class, "Unable to open input stream for " + url, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Locates a File resource by the given name
|
||||
*
|
||||
* @param filename the filename
|
||||
* @return the File for the given resource; null if there is no such file
|
||||
*/
|
||||
public static File getResourceFile(String filename) {
|
||||
URL url = getResource(filename);
|
||||
if (url == null || !"file".equals(url.getProtocol())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
URI uri = new URI(url.toExternalForm());
|
||||
return new File(uri);
|
||||
}
|
||||
catch (URISyntaxException e) {
|
||||
throw new RuntimeException("Can not find resource " + filename);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches the given set of directory paths for the given filename
|
||||
*
|
||||
* @param searchPaths the paths
|
||||
* @param filename the filename
|
||||
* @return the URL of the first matching file
|
||||
*/
|
||||
private static URL getResource(List<String> searchPaths, String filename) {
|
||||
|
||||
for (String path : searchPaths) {
|
||||
File f = new File(path, filename);
|
||||
if (!f.exists()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
return f.toURI().toURL();
|
||||
}
|
||||
catch (MalformedURLException e) {
|
||||
Msg.debug(ResourceManager.class, "Unable to create URL for file", e);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search the classpath for files in the <classpath entry>/<tt>dirName</tt>
|
||||
* location that have the given extension. In <tt>null</tt> is passed for the
|
||||
* extension, then all files found in the given dir names will be returned. In this
|
||||
* way, <tt>null</tt> is a wildcard.
|
||||
*
|
||||
* <P>This method differs from {@link #getResource(String)} in that this method finds
|
||||
* multiple matches.
|
||||
*
|
||||
* @param dirName the name of the sub-directory under which to search
|
||||
* @param extension the extension that matching files must possess
|
||||
* @return set of URLs in the given directory that end with the given extension
|
||||
*/
|
||||
public static Set<URL> getResources(String dirName, String extension) {
|
||||
|
||||
Set<String> names = doGetResourceNames(getDefaultSearchPaths(), dirName, extension);
|
||||
Set<String> testNames = doGetResourceNames(getTestSearchPaths(), dirName, extension);
|
||||
names.addAll(testNames);
|
||||
|
||||
Set<URL> urls = names.stream().map(name -> getResource(name)).collect(Collectors.toSet());
|
||||
return urls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search the classpath for files in the <classpath entry>/<tt>dirName</tt>
|
||||
* location that have the given extension. In <tt>null</tt> is passed for the
|
||||
* extension, then all files found in the given dir names will be returned. In this
|
||||
* way, <tt>null</tt> is a wildcard.
|
||||
*
|
||||
* <P>The names returned from this method are relative and are meant to be used in a
|
||||
* later callback to this class for methods such as {@link #loadImage(String)} or
|
||||
* {@link #getResource(String)}.
|
||||
*
|
||||
*
|
||||
* @param dirName the name of the directory under which to search
|
||||
* @param extension the extension that matching files must possess
|
||||
* @return set of filenames in the given directory that end with the given extension
|
||||
*/
|
||||
public static Set<String> getResourceNames(String dirName, String extension) {
|
||||
|
||||
Set<String> resourceNames = doGetResourceNames(getDefaultSearchPaths(), dirName, extension);
|
||||
Set<String> testResourceNames =
|
||||
doGetResourceNames(getTestSearchPaths(), dirName, extension);
|
||||
|
||||
resourceNames.addAll(testResourceNames);
|
||||
return resourceNames;
|
||||
}
|
||||
|
||||
private static Set<String> doGetResourceNames(List<String> paths, String resourceDirName,
|
||||
String extension) {
|
||||
|
||||
// check the system resource paths first
|
||||
Set<String> set = new HashSet<>();
|
||||
|
||||
// now search the path entries
|
||||
for (String path : paths) {
|
||||
|
||||
if (!StringUtils.endsWithAny(path.toLowerCase(), ".jar", ".zip")) {
|
||||
|
||||
// maybe a directory
|
||||
String classpathDirectoryEntry = path + File.separator + resourceDirName;
|
||||
File f = new File(classpathDirectoryEntry);
|
||||
findResources(set, f, resourceDirName, extension);
|
||||
continue;
|
||||
}
|
||||
|
||||
// jar/zip
|
||||
File file = new File(path);
|
||||
try {
|
||||
if (file.exists()) {
|
||||
searchJarFile(set, file, resourceDirName, extension);
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
Msg.error(ResourceManager.class, "Unable to search compressed file", e);
|
||||
}
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search the directory for files ending in the given extension and add them to the list
|
||||
* that is returned
|
||||
*
|
||||
* @param set the set to which resource names will be added
|
||||
* @param file directory, e.g., "resources/defaultTools"
|
||||
* @param dirName name of sub-directory, e.g. "defaultTools"
|
||||
* @param extension file extension to look for
|
||||
*/
|
||||
private static void findResources(Set<String> set, File file, String dirName,
|
||||
String extension) {
|
||||
|
||||
if (!file.exists()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String[] names = file.list();
|
||||
if (names == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (String element : names) {
|
||||
if (extension == null || element.endsWith(extension)) {
|
||||
set.add(dirName + "/" + element);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Search the given jar filename for files in
|
||||
* resources with the given file extension.
|
||||
* @param set the set to which resource names will be added
|
||||
* @param file jar or zip filename
|
||||
* @param resourceDirName name of resource directory, e.g. "defaultTools"
|
||||
* @param extension file extension to look for
|
||||
*/
|
||||
private static void searchJarFile(Set<String> set, File file, String resourceDirName,
|
||||
String extension) throws IOException {
|
||||
|
||||
try (JarFile jarFile = new JarFile(file)) {
|
||||
Enumeration<JarEntry> entries = jarFile.entries();
|
||||
while (entries.hasMoreElements()) {
|
||||
JarEntry entry = entries.nextElement();
|
||||
if (entry.getSize() == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String name = entry.getName();
|
||||
|
||||
// the entry must match the pattern "resources/<resourceDirName>/xxx<extension>
|
||||
// where extension may be null and 'xxx' is a filename and not another sub directory
|
||||
if (extension != null && !name.endsWith(extension)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String startPath = resourceDirName;
|
||||
if (!name.startsWith(startPath)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// is it a subdir?
|
||||
name = name.substring(startPath.length() + 1); // strip off valid path info
|
||||
File entryAsFile = new File(name);
|
||||
if (entryAsFile.getParent() != null) {
|
||||
continue; // the name was a subdir and not simply a file
|
||||
}
|
||||
|
||||
// add the entry; chop off "resources/"
|
||||
set.add(entry.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
// Image Related Methods
|
||||
//==================================================================================================
|
||||
|
||||
/**
|
||||
* Creates a scaled ImageIcon from the given icon.
|
||||
*
|
||||
* @param icon the icon to scale
|
||||
* @param width the width of the new icon
|
||||
* @param height the height of the new icon
|
||||
* @param hints scaling hints (see {@link BufferedImage#getScaledInstance(int, int, int)}
|
||||
* @return A new, scaled ImageIcon
|
||||
*/
|
||||
public static ImageIcon getScaledIcon(Icon icon, int width, int height, int hints) {
|
||||
return new ScaledImageIconWrapper(icon, width, height, hints);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a scaled ImageIcon from the given icon with scaling of
|
||||
* {@link Image#SCALE_AREA_AVERAGING}
|
||||
*
|
||||
* @param icon the icon to scale
|
||||
* @param width the width of the new icon
|
||||
* @param height the height of the new icon
|
||||
* @return A new, scaled ImageIcon
|
||||
*/
|
||||
public static ImageIcon getScaledIcon(Icon icon, int width, int height) {
|
||||
return new ScaledImageIconWrapper(icon, width, height);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is really a package-level method. From outside of this package you should instead
|
||||
* be calling {@link ResourceManager#getScaledIcon(Icon, int, int, int)}.
|
||||
*
|
||||
* @param icon the icon to scale
|
||||
* @param width the new width
|
||||
* @param height the new height
|
||||
* @param hints any hints to apply to the scaling operation
|
||||
* @return the new icon
|
||||
* @deprecated use {@link #getScaledIcon(Icon, int, int, int)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public static ImageIcon createScaledIcon(Icon icon, int width, int height, int hints) {
|
||||
return getScaledIcon(icon, width, height, hints);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is really a package-level method. From outside of this package you should instead
|
||||
* be calling {@link ResourceManager#getScaledIcon(Icon, int, int)}.
|
||||
*
|
||||
* @param icon the icon to scale
|
||||
* @param width the new width
|
||||
* @param height the new height
|
||||
* @return the new icon
|
||||
* @deprecated use {@link #getScaledIcon(Icon, int, int, int)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public static ImageIcon createScaledIcon(Icon icon, int width, int height) {
|
||||
return getScaledIcon(icon, width, height, Image.SCALE_AREA_AVERAGING);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a scaled image based upon the given image.
|
||||
* NOTE: Avoid invocation by a static initializer.
|
||||
* @param image the image to scale
|
||||
* @param width the new width
|
||||
* @param height the new height
|
||||
* @param hints {@link RenderingHints} used by {@link Graphics2D}
|
||||
* @return a scaled version of the given image
|
||||
*/
|
||||
public static Image createScaledImage(Image image, int width, int height, int hints) {
|
||||
BufferedImage scaledImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
|
||||
Graphics graphics = scaledImage.getGraphics();
|
||||
Graphics2D g2 = (Graphics2D) graphics;
|
||||
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
|
||||
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
|
||||
graphics.drawImage(image, 0, 0, width, height, null);
|
||||
graphics.dispose();
|
||||
return scaledImage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the disabled rendering of the given icon.
|
||||
* @param icon The icon to disable.
|
||||
* @return disabled icon
|
||||
*/
|
||||
public static ImageIcon getDisabledIcon(Icon icon) {
|
||||
return new DisabledImageIconWrapper(getImageIcon(icon));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the disabled rendering of the given imageIcon.
|
||||
* @param icon The icon to disable.
|
||||
* @return disabled icon
|
||||
*/
|
||||
public static ImageIcon getDisabledIcon(ImageIcon icon) {
|
||||
return new DisabledImageIconWrapper(icon);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a disabled icon while allowing the caller to control the brightness of the icon
|
||||
* returned
|
||||
*
|
||||
* @param icon The icon to disable.
|
||||
* @param brightnessPercent The level of brightness (0-100, where 100 is the brightest).
|
||||
* @return a disabled version of the original icon.
|
||||
*/
|
||||
public static ImageIcon getDisabledIcon(Icon icon, int brightnessPercent) {
|
||||
return new DisabledImageIconWrapper(icon, brightnessPercent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Algorithm for filtering an image to make it appear disabled
|
||||
*
|
||||
* <P>Note: you should use one of the {@link #getDisabledIcon(Icon)} methods, as this is
|
||||
* an internal API method.
|
||||
*
|
||||
* @param icon the icon
|
||||
* @param brightnessPercent the percentage of brightness, 0-100, with 100 being the
|
||||
* brightest possible value
|
||||
* @return the new icon
|
||||
* @see #getDisabledIcon(Icon)
|
||||
* @deprecated use {@link #getDisabledIcon(Icon)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public static ImageIcon createDisabledIcon(Icon icon, final int brightnessPercent) {
|
||||
return getDisabledIcon(icon, brightnessPercent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an image icon from the given image. This method will create an <tt>ImageIcon</tt>
|
||||
* the <a href="safe">"safe"</a> way by avoiding the constructor
|
||||
* {@link ImageIcon#ImageIcon(Image)}, which can
|
||||
* trigger problems with Java's {@link MediaTracker}.
|
||||
*
|
||||
* @param imageName A textual description of the image; may be null
|
||||
* @param image The image to use for creating an ImageIcon.
|
||||
* @return the new icon
|
||||
*/
|
||||
public static ImageIcon getImageIconFromImage(String imageName, Image image) {
|
||||
return new ImageIconWrapper(image, imageName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an {@link ImageIcon} for the given icon. If the value is already an ImageIcon, then
|
||||
* that object is returned; otherwise, an ImageIcon will be created the <a href="#safe">safe</a>
|
||||
* way.
|
||||
|
||||
* @param icon The icon to convert
|
||||
* @return the new icon
|
||||
*/
|
||||
public static ImageIcon getImageIcon(Icon icon) {
|
||||
if (icon instanceof ImageIcon) {
|
||||
return (ImageIcon) icon;
|
||||
}
|
||||
return new ImageIconWrapper(icon);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of this icon. If icon is an ImageIcon, its getDescription() is called to
|
||||
* get the name
|
||||
*
|
||||
* @param icon the icon for which the name is desired
|
||||
* @return the name
|
||||
*/
|
||||
public static String getIconName(Icon icon) {
|
||||
String iconName = icon.toString();
|
||||
if (icon instanceof ImageIcon) {
|
||||
iconName = ((ImageIcon) icon).getDescription();
|
||||
}
|
||||
|
||||
/*
|
||||
TODO - not sure why we wanted just the name and not the entire URL? Delete this
|
||||
after a bit
|
||||
|
||||
if (iconName == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int pos = iconName.lastIndexOf(File.separator);
|
||||
if (pos >= 0) {
|
||||
iconName = iconName.substring(pos + 1);
|
||||
}
|
||||
else {
|
||||
pos = iconName.lastIndexOf("/");
|
||||
if (pos >= 0) {
|
||||
iconName = iconName.substring(pos + 1);
|
||||
}
|
||||
}
|
||||
*/
|
||||
return iconName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the image using the specified bytes. The image icon will
|
||||
* be cached using the image name. The bytes must have been
|
||||
* read from an image file containing a supported image format,
|
||||
* such as GIF, JPEG, or (as of 1.3) PNG.
|
||||
* @param imageName the name of the image
|
||||
* @param imageBytes the bytes of the image
|
||||
* @return the image icon stored in the bytes
|
||||
*/
|
||||
public static ImageIcon loadImage(String imageName, byte[] imageBytes) {
|
||||
ImageIcon icon = iconMap.get(imageName);
|
||||
if (icon != null) {
|
||||
return icon;
|
||||
}
|
||||
icon = new ImageIconWrapper(imageBytes, imageName);
|
||||
iconMap.put(imageName, icon);
|
||||
return icon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load and scale the image specified by filename; returns null if problems occur trying to load
|
||||
* the file.
|
||||
* @param filename name of file to load, e.g., "images/home.gif"
|
||||
* @param width - the width to scale the image to
|
||||
* @param height - the height to scale the image to
|
||||
* @return the scaled image.
|
||||
*/
|
||||
public static ImageIcon loadImage(String filename, int width, int height) {
|
||||
ImageIcon loadImage = loadImage(filename);
|
||||
if (loadImage == null) {
|
||||
return null;
|
||||
}
|
||||
return getScaledIcon(loadImage, width, height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the image specified by filename; returns null if problems occur trying to load the file
|
||||
*
|
||||
* @param filename name of file to load, e.g., "images/home.gif"
|
||||
* @return the image icon stored in the bytes
|
||||
*/
|
||||
public static ImageIcon loadImage(String filename) {
|
||||
|
||||
// use the wrapper so that images are not loaded until they are needed
|
||||
ImageIcon icon = iconMap.get(filename);
|
||||
if (icon != null) {
|
||||
return icon;
|
||||
}
|
||||
|
||||
File imageFile = new File(filename);
|
||||
if (imageFile.exists()) {
|
||||
try {
|
||||
icon = new ImageIconWrapper(imageFile.toURI().toURL());
|
||||
iconMap.put(filename, icon);
|
||||
return icon;
|
||||
}
|
||||
catch (MalformedURLException e) {
|
||||
// handled below
|
||||
}
|
||||
}
|
||||
|
||||
URL url = getResource(filename);
|
||||
if (url != null) {
|
||||
icon = new ImageIconWrapper(url);
|
||||
iconMap.put(filename, icon);
|
||||
return icon;
|
||||
}
|
||||
|
||||
return getDefaultIcon();
|
||||
}
|
||||
|
||||
/**
|
||||
* A convenience method to force the image denoted by <code>filename</code> to be read
|
||||
* from disk and to not use the cached version
|
||||
*
|
||||
* @param filename name of file to load, e.g., "images/home.gif"
|
||||
* @return the image icon stored in the bytes
|
||||
* @see #loadImage(String)
|
||||
*/
|
||||
public static ImageIcon reloadImage(String filename) {
|
||||
iconMap.remove(filename);
|
||||
return loadImage(filename);
|
||||
}
|
||||
|
||||
public static ImageIcon getDefaultIcon() {
|
||||
if (DEFAULT_ICON == null) {
|
||||
URL url = getResource(DEFAULT_ICON_FILENAME);
|
||||
if (url == null) {
|
||||
Msg.error(ResourceManager.class,
|
||||
"Could not find default icon: " + DEFAULT_ICON_FILENAME);
|
||||
}
|
||||
DEFAULT_ICON = new ImageIconWrapper(url);
|
||||
}
|
||||
return DEFAULT_ICON;
|
||||
}
|
||||
|
||||
public static Set<String> getToolImages() {
|
||||
Set<String> list = getResourceNames("defaultTools/images", null);
|
||||
filterImages(list);
|
||||
return list;
|
||||
}
|
||||
|
||||
private static void filterImages(Set<String> set) {
|
||||
Iterator<String> it = set.iterator();
|
||||
while (it.hasNext()) {
|
||||
String filename = it.next().toLowerCase();
|
||||
if (!StringUtils.endsWithAny(filename, ".gif", ".jpg", ".png")) {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static synchronized List<String> getDefaultSearchPaths() {
|
||||
|
||||
if (defaultSearchPaths != null) {
|
||||
return defaultSearchPaths;
|
||||
}
|
||||
|
||||
List<String> results = new ArrayList<>();
|
||||
|
||||
String classPath = System.getProperty("java.class.path");
|
||||
String java = System.getProperty("java.home");
|
||||
|
||||
StringTokenizer st = new StringTokenizer(classPath, File.pathSeparator);
|
||||
while (st.hasMoreElements()) {
|
||||
String path = st.nextToken();
|
||||
if (path.startsWith(java)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
results.add(path);
|
||||
}
|
||||
|
||||
defaultSearchPaths = results;
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns paths to search in test mode when finding resources.
|
||||
*
|
||||
* <P>This allows us to have our Eclipse development environment match the gradle test
|
||||
* environment with respect to how resources are found. Specifically, in Eclipse, resources
|
||||
* are found on the classpath. Further, in Eclipse, the 'test' and 'test.slow' folders are
|
||||
* on the classpath. Even more, Eclipse will include these test folders as transitive
|
||||
* dependencies for submodules. Contrastingly, gradle will not include transitive <b>test</b>
|
||||
* dependencies. So, we add this code here so that we do not have to update each gradle
|
||||
* build file that needs resources defined in a parent modules test resources.
|
||||
*
|
||||
* @return the paths
|
||||
*/
|
||||
private static List<String> getTestSearchPaths() {
|
||||
|
||||
if (testSearchPaths != null) {
|
||||
return testSearchPaths;
|
||||
}
|
||||
|
||||
if (!SystemUtilities.isInTestingMode()) {
|
||||
testSearchPaths = Collections.emptyList();
|
||||
return testSearchPaths;
|
||||
}
|
||||
|
||||
List<String> results = new ArrayList<>();
|
||||
List<String> searchPaths = getDefaultSearchPaths();
|
||||
|
||||
// format: <repo>/Ghidra/Features/Base/build/classes/java/integrationTest
|
||||
for (String path : searchPaths) {
|
||||
|
||||
Path modulePath = ModuleUtilities.getModule(path);
|
||||
if (modulePath == null) {
|
||||
continue; // not in a module
|
||||
}
|
||||
|
||||
File moduleFile = modulePath.toFile();
|
||||
File file = new File(moduleFile, "src/test/resources");
|
||||
if (file.exists()) {
|
||||
results.add(file.getAbsolutePath());
|
||||
}
|
||||
|
||||
file = new File(moduleFile, "src/test.slow/resources");
|
||||
if (file.exists()) {
|
||||
results.add(file.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
testSearchPaths = results;
|
||||
return testSearchPaths;
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue