mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +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
296
GhidraBuild/LaunchSupport/src/main/java/LaunchSupport.java
Normal file
296
GhidraBuild/LaunchSupport/src/main/java/LaunchSupport.java
Normal file
|
@ -0,0 +1,296 @@
|
|||
/* ###
|
||||
* 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.
|
||||
*/
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.io.*;
|
||||
import java.text.ParseException;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.JFileChooser;
|
||||
|
||||
import ghidra.launch.*;
|
||||
import ghidra.launch.JavaFinder.JavaFilter;
|
||||
|
||||
/**
|
||||
* Tool that helps gather information needed to launch Ghidra/GhidraServer. This is intended
|
||||
* to be a helper for the launch scripts so that most of the "heavy-lifting" can be done in Java
|
||||
* rather than in OS-specific scripts.
|
||||
*/
|
||||
public class LaunchSupport {
|
||||
|
||||
private static final int EXIT_SUCCESS = 0;
|
||||
private static final int EXIT_FAILURE = 1;
|
||||
|
||||
/**
|
||||
* {@link LaunchSupport} entry point. Uses standard exit codes to tell the user if
|
||||
* the desired operation succeeded for failed.
|
||||
*
|
||||
* @param args [INSTALL_DIR] [-java_home | -jdk_home | -vmargs] [-ask | -save]
|
||||
* <ul>
|
||||
* <li><b>-java_home: </b> Get Java home (JDK or JRE)</li>
|
||||
* <li><b>-jdk_home: </b> Get Java home (JDK only)</li>
|
||||
* <li><b>-vmargs: </b> Get JVM arguments</li>
|
||||
* <li><b>-ask: </b> Interactively ask the user to choose a Java home</li>
|
||||
* <li><b>-save: </b> Save Java home to file for future use</li>
|
||||
* </ul>
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
|
||||
int exitCode = EXIT_FAILURE; // failure by default
|
||||
|
||||
// Validate command line arguments
|
||||
if (args.length < 2 || args.length > 4) {
|
||||
System.err.println("LaunchSupport expected 2 to 4 arguments but got " + args.length);
|
||||
System.exit(exitCode);
|
||||
}
|
||||
|
||||
// Parse command line arguments
|
||||
String installDirPath = args[0];
|
||||
String mode = args[1];
|
||||
boolean ask = false;
|
||||
boolean save = false;
|
||||
|
||||
for (int i = 2; i < args.length; i++) {
|
||||
if (args[i].equals("-ask")) {
|
||||
ask = true;
|
||||
}
|
||||
else if (args[i].equals("-save")) {
|
||||
save = true;
|
||||
}
|
||||
else {
|
||||
System.err.println("LaunchSupport received illegal argument: " + args[i]);
|
||||
System.exit(exitCode);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
File installDir = new File(installDirPath).getCanonicalFile(); // change relative path to absolute
|
||||
JavaConfig javaConfig = new JavaConfig(installDir);
|
||||
JavaFinder javaFinder = JavaFinder.create();
|
||||
|
||||
// Pass control to a mode-specific handler
|
||||
switch (mode.toLowerCase()) {
|
||||
case "-java_home":
|
||||
exitCode = handleJavaHome(javaConfig, javaFinder, JavaFilter.ANY, ask, save);
|
||||
break;
|
||||
case "-jdk_home":
|
||||
exitCode =
|
||||
handleJavaHome(javaConfig, javaFinder, JavaFilter.JDK_ONLY, ask, save);
|
||||
break;
|
||||
case "-vmargs":
|
||||
exitCode = handleVmArgs(javaConfig);
|
||||
break;
|
||||
default:
|
||||
System.err.println("LaunchSupport received illegal argument: " + mode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
System.err.println(e.getMessage());
|
||||
}
|
||||
|
||||
System.exit(exitCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles figuring out a Java home directory to use for the launch. If it is successfully
|
||||
* determined, an exit code that indicates success is returned.
|
||||
*
|
||||
* @param javaConfig The Java configuration that defines what we support.
|
||||
* @param javaFinder The Java finder.
|
||||
* @param javaFilter A filter used to restrict what kind of Java installations we search for.
|
||||
* @param ask True to interact with the user to they can specify a Java home directory.
|
||||
* False if the Java home directory should be searched for and output on STDOUT once
|
||||
* discovered.
|
||||
* @param save True if the determined Java home directory should get saved to a file.
|
||||
* @return A suggested exit code based on whether or not a Java home directory was
|
||||
* successfully determined.
|
||||
* @throws IOException if there was a disk-related problem.
|
||||
*/
|
||||
private static int handleJavaHome(JavaConfig javaConfig, JavaFinder javaFinder,
|
||||
JavaFilter javaFilter, boolean ask, boolean save) throws IOException {
|
||||
if (ask) {
|
||||
return askJavaHome(javaConfig, javaFinder, javaFilter);
|
||||
}
|
||||
return findJavaHome(javaConfig, javaFinder, javaFilter, save);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles finding a Java home directory to use for the launch. If one is successfully
|
||||
* found, its path is printed to STDOUT and an exit code that indicates success is
|
||||
* returned. Otherwise, nothing is printed to STDOUT and an error exit code is returned.
|
||||
*
|
||||
* @param javaConfig The Java configuration that defines what we support.
|
||||
* @param javaFinder The Java finder.
|
||||
* @param javaFilter A filter used to restrict what kind of Java installations we search for.
|
||||
* @param save True if the determined Java home directory should get saved to a file.
|
||||
* @return A suggested exit code based on whether or not a supported Java home directory was
|
||||
* successfully determined.
|
||||
* @throws IOException if there was a problem saving the java home to disk.
|
||||
*/
|
||||
private static int findJavaHome(JavaConfig javaConfig, JavaFinder javaFinder,
|
||||
JavaFilter javaFilter, boolean save) throws IOException {
|
||||
|
||||
File javaHomeDir;
|
||||
LaunchProperties launchProperties = javaConfig.getLaunchProperties();
|
||||
|
||||
// PRIORITY 1: JAVA_HOME_OVERRIDE property
|
||||
// If a valid java home override is specified in the launch properties, use that.
|
||||
// Someone presumably wants to force that specific version.
|
||||
javaHomeDir = launchProperties.getJavaHomeOverride();
|
||||
if (javaConfig.isSupportedJavaHomeDir(javaHomeDir, javaFilter)) {
|
||||
if (save) {
|
||||
javaConfig.saveJavaHome(javaHomeDir);
|
||||
}
|
||||
System.out.println(javaHomeDir);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
// PRIORITY 2: Java on PATH
|
||||
// This program (LaunchSupport) was started with the Java on the PATH. Try to use this one
|
||||
// next because it is most likely the one that is being upgraded on the user's system.
|
||||
javaHomeDir = javaFinder.findSupportedJavaHomeFromCurrentJavaHome(javaConfig, javaFilter);
|
||||
if (javaHomeDir != null) {
|
||||
if (save) {
|
||||
javaConfig.saveJavaHome(javaHomeDir);
|
||||
}
|
||||
System.out.println(javaHomeDir);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
// PRIORITY 3: Last used Java
|
||||
// Check to see if a prior launch resulted in that Java being saved. If so, try to use that.
|
||||
javaHomeDir = javaConfig.getSavedJavaHome();
|
||||
if (javaConfig.isSupportedJavaHomeDir(javaHomeDir, javaFilter)) {
|
||||
System.out.println(javaHomeDir);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
// PRIORITY 4: Find all supported Java installations, and use the newest.
|
||||
List<File> javaHomeDirs =
|
||||
javaFinder.findSupportedJavaHomeFromInstallations(javaConfig, javaFilter);
|
||||
if (!javaHomeDirs.isEmpty()) {
|
||||
javaHomeDir = javaHomeDirs.iterator().next();
|
||||
if (save) {
|
||||
javaConfig.saveJavaHome(javaHomeDir);
|
||||
}
|
||||
System.out.println(javaHomeDir);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles interacting with the user to choose a Java home directory to use for the launch.
|
||||
* If a valid Java home directory was successfully determined, it is saved to the the user's
|
||||
* Java home save file, and an exit code that indicates success is returned.
|
||||
*
|
||||
* @param javaConfig The Java configuration that defines what we support.
|
||||
* @param javaFinder The Java finder.
|
||||
* @param javaFilter A filter used to restrict what kind of Java installations we search for.
|
||||
* * @return A suggested exit code based on whether or not a valid Java home directory was
|
||||
* successfully chosen.
|
||||
* @throws IOException if there was a problem interacting with the user, or saving the java
|
||||
* home location to disk.
|
||||
*/
|
||||
private static int askJavaHome(JavaConfig javaConfig, JavaFinder javaFinder,
|
||||
JavaFilter javaFilter) throws IOException {
|
||||
|
||||
String javaName = javaFilter.equals(JavaFilter.JDK_ONLY) ? "JDK" : "Java";
|
||||
String javaRange;
|
||||
int min = javaConfig.getMinSupportedJava();
|
||||
int max = javaConfig.getMaxSupportedJava();
|
||||
if (min == max) {
|
||||
javaRange = min + "";
|
||||
}
|
||||
else if (max == 0) {
|
||||
javaRange = min + "+";
|
||||
}
|
||||
else {
|
||||
javaRange = min + "-" + max;
|
||||
}
|
||||
|
||||
System.out.println("*******************************************************");
|
||||
System.out.println(
|
||||
javaName + " " + javaRange + " could not be found and must be manually chosen!");
|
||||
System.out.println("*******************************************************");
|
||||
|
||||
File javaHomeDir = null;
|
||||
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
|
||||
while (true) {
|
||||
boolean supportsDialog =
|
||||
!GraphicsEnvironment.isHeadless() && !(javaFinder instanceof MacJavaFinder);
|
||||
System.out.print("Enter path to " + javaName + " home directory");
|
||||
System.out.print(supportsDialog ? " (ENTER for dialog): " : ": ");
|
||||
String line = in.readLine().trim();
|
||||
if (supportsDialog && line.isEmpty()) {
|
||||
System.out.println("Opening selection dialog...");
|
||||
JFileChooser chooser = new JFileChooser();
|
||||
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
|
||||
chooser.setDialogTitle("Choose a " + javaName + " home directory");
|
||||
if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
|
||||
javaHomeDir = chooser.getSelectedFile();
|
||||
}
|
||||
}
|
||||
else if (!line.isEmpty()) {
|
||||
javaHomeDir = new File(line);
|
||||
}
|
||||
else {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
JavaVersion javaVersion = javaConfig.getJavaVersion(javaHomeDir, javaFilter);
|
||||
if (javaConfig.isJavaVersionSupported(javaVersion)) {
|
||||
break;
|
||||
}
|
||||
System.out.println(
|
||||
"Java version " + javaVersion + " is outside of supported range: [" +
|
||||
javaRange + "]");
|
||||
}
|
||||
catch (FileNotFoundException e) {
|
||||
System.out.println(
|
||||
"Not a valid " + javaName + " home directory. " + e.getMessage() + "!");
|
||||
}
|
||||
catch (IOException | ParseException e) {
|
||||
System.out.println("Failed to verify Java version. " + e.getMessage() + "!");
|
||||
}
|
||||
}
|
||||
|
||||
File javaHomeSaveFile = javaConfig.saveJavaHome(javaHomeDir);
|
||||
System.out.println("Saved changes to " + javaHomeSaveFile);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles getting the VM arguments. If they are successfully determined, they are printed
|
||||
* to STDOUT as a string that can be added to the command line, and an exit code that
|
||||
* indicates success is returned.
|
||||
|
||||
* @param javaConfig The Java configuration that defines what we support.
|
||||
* @return A suggested exit code based on whether or not the VM arguments were successfully
|
||||
* gotten.
|
||||
*/
|
||||
private static int handleVmArgs(JavaConfig javaConfig) {
|
||||
if (javaConfig.getLaunchProperties() == null) {
|
||||
System.out.println("Launch properties file was not specified!");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
System.out.println(javaConfig.getLaunchProperties().getVmArgs());
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,377 @@
|
|||
/* ###
|
||||
* 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.launch;
|
||||
|
||||
import java.io.*;
|
||||
import java.text.ParseException;
|
||||
import java.util.Properties;
|
||||
|
||||
import ghidra.launch.JavaFinder.JavaFilter;
|
||||
|
||||
/**
|
||||
* Class to determine and represent a required Java configuration, including minimum and maximum
|
||||
* supported versions, compiler compliance level, etc.
|
||||
*/
|
||||
public class JavaConfig {
|
||||
|
||||
private static final String LAUNCH_PROPERTIES_NAME = "launch.properties";
|
||||
private static final String JAVA_HOME_SAVE_NAME = "java_home.save";
|
||||
|
||||
private LaunchProperties launchProperties;
|
||||
private File javaHomeSaveFile;
|
||||
|
||||
private String applicationName;
|
||||
private String applicationVersion;
|
||||
private int minSupportedJava;
|
||||
private int maxSupportedJava;
|
||||
private String compilerComplianceLevel;
|
||||
|
||||
/**
|
||||
* Creates a new Java configuration for the given installation.
|
||||
*
|
||||
* @param installDir The installation directory.
|
||||
* @throws FileNotFoundException if a required file was not found.
|
||||
* @throws IOException if there was a problem reading a required file.
|
||||
* @throws ParseException if there was a problem parsing a required file.
|
||||
*/
|
||||
public JavaConfig(File installDir) throws FileNotFoundException, IOException, ParseException {
|
||||
initApplicationProperties(installDir);
|
||||
initLaunchProperties(installDir);
|
||||
initJavaHomeSaveFile(installDir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the launch properties associated with this Java configuration. Certain aspects of the
|
||||
* Java configuration are stored in the launch properties.
|
||||
*
|
||||
* @return The launch properties associated with this Java configuration. Could be null if
|
||||
* this Java configuration does not use launch properties.
|
||||
*/
|
||||
public LaunchProperties getLaunchProperties() {
|
||||
return launchProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Java configuration's minimum supported major Java version.
|
||||
*
|
||||
* @return The Java configuration's minimum supported major Java version.
|
||||
*/
|
||||
public int getMinSupportedJava() {
|
||||
return minSupportedJava;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Java configuration's maximum supported major Java version.
|
||||
*
|
||||
* @return The Java configuration's maximum supported major Java version. If there is no
|
||||
* restriction, the value will be 0.
|
||||
*/
|
||||
public int getMaxSupportedJava() {
|
||||
return maxSupportedJava;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Java configuration's compiler compliance level that was used to build the
|
||||
* associated installation.
|
||||
*
|
||||
* @return The Java configuration's compiler compliance level.
|
||||
*/
|
||||
public String getCompilerComplianceLevel() {
|
||||
return compilerComplianceLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Java home directory from the user's Java home save file.
|
||||
*
|
||||
* @return The Java home directory from the user's Java home save file, or null if the file
|
||||
* does not exist or is empty.
|
||||
* @throws IOException if there was a problem reading the Java home save file.
|
||||
*/
|
||||
public File getSavedJavaHome() throws IOException {
|
||||
try (BufferedReader reader = new BufferedReader(new FileReader(javaHomeSaveFile))) {
|
||||
String line = reader.readLine().trim();
|
||||
if (line != null && !line.isEmpty()) {
|
||||
return new File(line);
|
||||
}
|
||||
}
|
||||
catch (FileNotFoundException e) {
|
||||
// Fall through to return null
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the given Java home directory to the user's Java home save file. If the save
|
||||
* file does not exist, it will be created.
|
||||
*
|
||||
* @param javaHomeDir The Java home directory to save.
|
||||
* @return The user's Java home save file.
|
||||
* @throws IOException if there was a problem saving to the file.
|
||||
*/
|
||||
public File saveJavaHome(File javaHomeDir) throws IOException {
|
||||
if (!javaHomeSaveFile.getParentFile().exists() &&
|
||||
!javaHomeSaveFile.getParentFile().mkdirs()) {
|
||||
throw new IOException(
|
||||
"Failed to create directory: " + javaHomeSaveFile.getParentFile());
|
||||
}
|
||||
|
||||
try (PrintWriter writer = new PrintWriter(new FileWriter(javaHomeSaveFile))) {
|
||||
writer.println(javaHomeDir);
|
||||
}
|
||||
|
||||
return javaHomeSaveFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests to see if the given directory is a supported Java home directory for this Java
|
||||
* configuration.
|
||||
*
|
||||
* @param dir The directory to test.
|
||||
* @param javaFilter A filter used to restrict what kind of Java installations we support.
|
||||
* @return True if the given directory is a supported Java home directory for this Java
|
||||
* configuration.
|
||||
*/
|
||||
public boolean isSupportedJavaHomeDir(File dir, JavaFilter javaFilter) {
|
||||
try {
|
||||
return isJavaVersionSupported(getJavaVersion(dir, javaFilter));
|
||||
}
|
||||
catch (IOException | ParseException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests to see if the given Java version is supported by this Java launch configuration.
|
||||
*
|
||||
* @param javaVersion The java version to check.
|
||||
* @return True if the given Java version is supported by this Java launch configuration.
|
||||
*/
|
||||
public boolean isJavaVersionSupported(JavaVersion javaVersion) {
|
||||
int major = javaVersion.getMajor();
|
||||
return major >= minSupportedJava &&
|
||||
(maxSupportedJava == 0 || major <= maxSupportedJava);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Java version of the given Java home directory.
|
||||
*
|
||||
* @param javaHomeDir The Java home directory to get the version of.
|
||||
* @param javaFilter A filter used to restrict what kind of Java installations we support.
|
||||
* @return The Java version of the given Java home directory.
|
||||
* @throws FileNotFoundException if the given directory is missing a required Java file
|
||||
* or directory based on the provided filter. The exception's message will have more
|
||||
* details.
|
||||
* @throws IOException if there was a problem executing the java executable with the
|
||||
* "-version" argument.
|
||||
* @throws ParseException if the version string failed to parse.
|
||||
*/
|
||||
public JavaVersion getJavaVersion(File javaHomeDir, JavaFilter javaFilter)
|
||||
throws FileNotFoundException, IOException, ParseException {
|
||||
|
||||
if (javaHomeDir == null) {
|
||||
throw new FileNotFoundException("Directory not specified");
|
||||
}
|
||||
|
||||
if (!javaHomeDir.isDirectory()) {
|
||||
throw new FileNotFoundException("Not a directory");
|
||||
}
|
||||
|
||||
File binDir = new File(javaHomeDir, "bin");
|
||||
if (!binDir.isDirectory()) {
|
||||
throw new FileNotFoundException("Missing bin directory");
|
||||
}
|
||||
|
||||
File javaExecutable = null;
|
||||
File javacExecutable = null;
|
||||
for (File f : binDir.listFiles()) {
|
||||
if (f.getName().equals("java") || f.getName().equals("java.exe")) {
|
||||
javaExecutable = f;
|
||||
}
|
||||
if (f.getName().equals("javac") || f.getName().equals("javac.exe")) {
|
||||
javacExecutable = f;
|
||||
}
|
||||
}
|
||||
if (javaExecutable == null) {
|
||||
throw new FileNotFoundException("Missing java executable");
|
||||
}
|
||||
if (javaFilter.equals(JavaFilter.JDK_ONLY) && javacExecutable == null) {
|
||||
throw new FileNotFoundException("JDK is missing javac executable");
|
||||
}
|
||||
if (javaFilter.equals(JavaFilter.JRE_ONLY) && javacExecutable != null) {
|
||||
throw new FileNotFoundException("JRE should not have javac executable");
|
||||
}
|
||||
|
||||
return runAndGetJavaVersion(javaExecutable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the version of the given Java executable from the output of running "java -version".
|
||||
*
|
||||
* @param javaExecutable The Java executable to run and get the version of.
|
||||
* @return The version of the given Java executable.
|
||||
* @throws IOException if there was a problem executing the given Java executable with the
|
||||
* "-version" argument.
|
||||
* @throws ParseException if the version string failed to parse.
|
||||
*/
|
||||
private JavaVersion runAndGetJavaVersion(File javaExecutable)
|
||||
throws ParseException, IOException {
|
||||
Runtime rt = Runtime.getRuntime();
|
||||
Process proc = rt.exec(new String[] { javaExecutable.getAbsolutePath(), "-version" });
|
||||
try (BufferedReader reader =
|
||||
new BufferedReader(new InputStreamReader(proc.getErrorStream()))) {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
line = line.trim();
|
||||
|
||||
// If the _JAVA_OPTIONS or JAVA_TOOL_OPTIONS environment variables are set, STDERR
|
||||
// will start with "Picked up..." lines that need to be ignored so we can get to the
|
||||
// java version line.
|
||||
if (line.startsWith("Picked up")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String[] parts = line.split("\\s");
|
||||
if (parts.length < 3) {
|
||||
throw new ParseException("Failed to parse version: " + line, 0);
|
||||
}
|
||||
return new JavaVersion(parts[2]);
|
||||
}
|
||||
throw new ParseException("Failed to find Java version", 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the required application properties for the given installation.
|
||||
*
|
||||
* @param installDir The Ghidra installation directory. This is the directory that has the
|
||||
* "Ghidra" subdirectory in it.
|
||||
* @throws FileNotFoundException if the application.properties file was not found.
|
||||
* @throws IOException if there was a problem reading the application.properties file.
|
||||
* @throws ParseException if there was a problem parsing the required application properties.
|
||||
*/
|
||||
private void initApplicationProperties(File installDir) throws FileNotFoundException, IOException, ParseException {
|
||||
File applicationPropertiesFile = new File(installDir, "Ghidra/application.properties");
|
||||
if (!applicationPropertiesFile.isFile()) {
|
||||
throw new FileNotFoundException(
|
||||
"Application properties file does not exist: " + applicationPropertiesFile);
|
||||
}
|
||||
|
||||
Properties applicationProperties = new Properties();
|
||||
try (FileInputStream fin = new FileInputStream(applicationPropertiesFile)) {
|
||||
applicationProperties.load(fin);
|
||||
}
|
||||
|
||||
// Required properties
|
||||
applicationName = getDefinedProperty(applicationProperties, "application.name");
|
||||
applicationVersion = getDefinedProperty(applicationProperties, "application.version");
|
||||
compilerComplianceLevel =
|
||||
getDefinedProperty(applicationProperties, "application.java.compiler");
|
||||
try {
|
||||
minSupportedJava =
|
||||
Integer.parseInt(getDefinedProperty(applicationProperties, "application.java.min"));
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
throw new ParseException(
|
||||
"Failed to parse application's minimum supported Java major verison", 0);
|
||||
}
|
||||
|
||||
// Optional properties
|
||||
String max = applicationProperties.getProperty("application.java.max");
|
||||
if (max != null && !max.isEmpty()) {
|
||||
try {
|
||||
maxSupportedJava = Integer.parseInt(max);
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
throw new ParseException(
|
||||
"Failed to parse application's maximum supported Java major verison", 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
maxSupportedJava = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the launch properties for the given installation.
|
||||
*
|
||||
* @param installDir The Ghidra installation directory. This is the directory that has the
|
||||
* "Ghidra" subdirectory in it.
|
||||
* @throws FileNotFoundException if the given launch properties file does not exist.
|
||||
* @throws IOException if there was a problem reading the given launch properties file.
|
||||
* @throws ParseException if there was a problem parsing the given launch properties file.
|
||||
*/
|
||||
private void initLaunchProperties(File installDir)
|
||||
throws FileNotFoundException, IOException, ParseException {
|
||||
boolean isDev = new File(installDir, "build.gradle").isFile();
|
||||
|
||||
// Get the required launch properties file
|
||||
File launchPropertiesFile = new File(installDir,
|
||||
(isDev ? "Ghidra/RuntimeScripts/Common/" : "") + "support/" + LAUNCH_PROPERTIES_NAME);
|
||||
if (!launchPropertiesFile.isFile()) {
|
||||
throw new FileNotFoundException(
|
||||
"Launch properties file does not exist: " + launchPropertiesFile);
|
||||
}
|
||||
|
||||
launchProperties = new LaunchProperties(launchPropertiesFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the Java home save file.
|
||||
*
|
||||
* @param installDir The Ghidra installation directory. This is the directory that has the
|
||||
* "Ghidra" subdirectory in it.
|
||||
* @throws FileNotFoundException if the user's home directory was not found.
|
||||
*/
|
||||
private void initJavaHomeSaveFile(File installDir) throws FileNotFoundException {
|
||||
boolean isDev = new File(installDir, "build.gradle").isFile();
|
||||
|
||||
// Ensure there is a user home directory (there definitely should be)
|
||||
String userHomeDirPath = System.getProperty("user.home");
|
||||
if (userHomeDirPath == null || userHomeDirPath.isEmpty()) {
|
||||
throw new FileNotFoundException("User home directory is not known.");
|
||||
}
|
||||
File userHomeDir = new File(userHomeDirPath);
|
||||
if (!userHomeDir.isDirectory()) {
|
||||
throw new FileNotFoundException("User home directory does not exist: " + userHomeDir);
|
||||
}
|
||||
|
||||
// Get the java home save file from user home directory (it might not exist yet).
|
||||
String prefix = "." + applicationName.replaceAll("\\s", "").toLowerCase();
|
||||
String suffix = applicationVersion;
|
||||
if (isDev) {
|
||||
suffix += "_location_" + installDir.getParentFile().getName();
|
||||
}
|
||||
File userSettingsDir =
|
||||
new File(userHomeDir, prefix + File.separator + prefix + "-" + suffix);
|
||||
javaHomeSaveFile = new File(userSettingsDir, JAVA_HOME_SAVE_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the property value with the given key.
|
||||
*
|
||||
* @param properties The properties to get the property from.
|
||||
* @param key The property's key.
|
||||
* @return The property's corresponding value.
|
||||
* @throws ParseException if the property with the given key did not have a defined value.
|
||||
*/
|
||||
private String getDefinedProperty(Properties properties, String key) throws ParseException {
|
||||
String value = properties.getProperty(key);
|
||||
if (value == null || value.isEmpty()) {
|
||||
throw new ParseException("Property \"" + key + "\" is not defined.", 0);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,183 @@
|
|||
/* ###
|
||||
* 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.launch;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Class responsible for finding Java installations on a system.
|
||||
*/
|
||||
public abstract class JavaFinder {
|
||||
|
||||
/**
|
||||
* A filter used to restrict what kind of Java installations we search for.
|
||||
*/
|
||||
public enum JavaFilter {
|
||||
JRE_ONLY, JDK_ONLY, ANY
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Java finder to use for the current OS.
|
||||
*
|
||||
* @return The Java finder to use for the current OS.
|
||||
*/
|
||||
public static JavaFinder create() {
|
||||
JavaFinder javaFinder;
|
||||
String os = System.getProperty("os.name").toLowerCase();
|
||||
if (os != null && os.contains("win")) {
|
||||
javaFinder = new WindowsJavaFinder();
|
||||
}
|
||||
else if (os != null && os.contains("mac")) {
|
||||
javaFinder = new MacJavaFinder();
|
||||
}
|
||||
else {
|
||||
javaFinder = new LinuxJavaFinder();
|
||||
}
|
||||
return javaFinder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of supported Java home directories from discovered Java installations.
|
||||
* The list is sorted from newest Java version to oldest.
|
||||
*
|
||||
* @param javaConfig The Java configuration that defines what we support.
|
||||
* @param javaFilter A filter used to restrict what kind of Java installations we search for.
|
||||
* @return A sorted list of supported Java home directories from discovered Java installations.
|
||||
*/
|
||||
public List<File> findSupportedJavaHomeFromInstallations(JavaConfig javaConfig,
|
||||
JavaFilter javaFilter) {
|
||||
Set<File> potentialJavaHomeSet = new TreeSet<>();
|
||||
for (File javaRootInstallDir : getJavaRootInstallDirs()) {
|
||||
if (javaRootInstallDir.isDirectory()) {
|
||||
for (File dir : javaRootInstallDir.listFiles()) {
|
||||
if (dir.isDirectory()) {
|
||||
dir = new File(dir, getJavaHomeSubDirPath());
|
||||
if (javaFilter.equals(JavaFilter.ANY) ||
|
||||
javaFilter.equals(JavaFilter.JDK_ONLY)) {
|
||||
potentialJavaHomeSet.add(getJdkHomeFromJavaHome(dir));
|
||||
}
|
||||
if (javaFilter.equals(JavaFilter.ANY) ||
|
||||
javaFilter.equals(JavaFilter.JRE_ONLY)) {
|
||||
potentialJavaHomeSet.add(getJreHomeFromJavaHome(dir));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
final Map<File, JavaVersion> javaHomeToVersionMap = new HashMap<>();
|
||||
for (File potentialJavaHomeDir : potentialJavaHomeSet) {
|
||||
try {
|
||||
JavaVersion javaVersion =
|
||||
javaConfig.getJavaVersion(potentialJavaHomeDir, javaFilter);
|
||||
if (javaConfig.isJavaVersionSupported(javaVersion)) {
|
||||
javaHomeToVersionMap.put(potentialJavaHomeDir, javaVersion);
|
||||
}
|
||||
}
|
||||
catch (ParseException | IOException e) {
|
||||
// skip it
|
||||
}
|
||||
}
|
||||
List<File> javaHomeDirs = new ArrayList<>(javaHomeToVersionMap.keySet());
|
||||
Collections.sort(javaHomeDirs, new Comparator<File>() {
|
||||
@Override
|
||||
public int compare(File dir1, File dir2) {
|
||||
return javaHomeToVersionMap.get(dir2).compareTo(javaHomeToVersionMap.get(dir1));
|
||||
}
|
||||
});
|
||||
return javaHomeDirs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Java home directory corresponding to the current "java.home" system
|
||||
* property (if it supported).
|
||||
*
|
||||
* @param javaConfig The Java configuration that defines what we support.
|
||||
* @param javaFilter A filter used to restrict what kind of Java installations we search for.
|
||||
* @return The Java home directory corresponding to the current "java.home" system property.
|
||||
* Could be null if the current "java.home" is not supported.
|
||||
*/
|
||||
public File findSupportedJavaHomeFromCurrentJavaHome(JavaConfig javaConfig,
|
||||
JavaFilter javaFilter) {
|
||||
Set<File> potentialJavaHomeSet = new HashSet<>();
|
||||
String javaHomeProperty = System.getProperty("java.home");
|
||||
if (javaHomeProperty != null && !javaHomeProperty.isEmpty()) {
|
||||
File dir = new File(javaHomeProperty);
|
||||
if (javaFilter.equals(JavaFilter.ANY) || javaFilter.equals(JavaFilter.JDK_ONLY)) {
|
||||
potentialJavaHomeSet.add(getJdkHomeFromJavaHome(dir));
|
||||
}
|
||||
if (javaFilter.equals(JavaFilter.ANY) || javaFilter.equals(JavaFilter.JRE_ONLY)) {
|
||||
potentialJavaHomeSet.add(getJreHomeFromJavaHome(dir));
|
||||
}
|
||||
for (File potentialJavaHomeDir : potentialJavaHomeSet) {
|
||||
try {
|
||||
if (javaConfig.isJavaVersionSupported(
|
||||
javaConfig.getJavaVersion(potentialJavaHomeDir, javaFilter))) {
|
||||
return potentialJavaHomeDir;
|
||||
}
|
||||
}
|
||||
catch (ParseException | IOException e) {
|
||||
// skip it
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of possible Java root installation directories.
|
||||
*
|
||||
* @return A list of possible Java root installation directories.
|
||||
*/
|
||||
protected abstract List<File> getJavaRootInstallDirs();
|
||||
|
||||
/**
|
||||
* Gets the sub-directory path of a Java root installation directory where the Java
|
||||
* home lives. For example, for OS X, this is "Contents/Home". For other OS's, it may
|
||||
* just be the empty string.
|
||||
*
|
||||
* @return The sub-directory path of a Java root installation directory where the Java
|
||||
* home lives.
|
||||
*/
|
||||
protected abstract String getJavaHomeSubDirPath();
|
||||
|
||||
/**
|
||||
* Gets the JRE home directory corresponding to the given Java home directory.
|
||||
* <p>
|
||||
* If the Java home directory corresponds to a JDK, there is usually a corresponding
|
||||
* JRE somewhere either in the JDK directory, or adjacent to it.
|
||||
*
|
||||
* @param javaHomeDir The Java home directory.
|
||||
* @return The JRE home directory corresponding to the given Java home directory. Could
|
||||
* be the same directory if the given Java home is a JRE.
|
||||
*/
|
||||
protected abstract File getJreHomeFromJavaHome(File javaHomeDir);
|
||||
|
||||
/**
|
||||
* Gets the JDK home directory corresponding to the given Java home directory.
|
||||
* <p>
|
||||
* Often, the java from the PATH will run from a JRE bin directory instead of a JDK
|
||||
* bin directory. However, we can look in expected places to find the corresponding
|
||||
* JDK home directory.
|
||||
*
|
||||
* @param javaHomeDir The Java home directory.
|
||||
* @return The JDK home directory corresponding to the given Java home directory. Could
|
||||
* be the same directory if the given Java home is a JDK.
|
||||
*/
|
||||
protected abstract File getJdkHomeFromJavaHome(File javaHomeDir);
|
||||
}
|
|
@ -0,0 +1,208 @@
|
|||
/* ###
|
||||
* 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.launch;
|
||||
|
||||
import java.text.ParseException;
|
||||
|
||||
/**
|
||||
* Class to more conveniently represent a Java version string.
|
||||
*/
|
||||
public class JavaVersion implements Comparable<JavaVersion> {
|
||||
|
||||
private int major;
|
||||
private int minor;
|
||||
private int patch;
|
||||
|
||||
/**
|
||||
* Creates a new {@link JavaVersion} object from the given version string.
|
||||
*
|
||||
* @param version A version string.
|
||||
* @throws ParseException if the version string failed to parse. The exception's
|
||||
* message has more detailed information about why it failed.
|
||||
*/
|
||||
public JavaVersion(String version) throws ParseException {
|
||||
parse(version);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the major version.
|
||||
*
|
||||
* @return The major version.
|
||||
*/
|
||||
public int getMajor() {
|
||||
return major;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the minor version.
|
||||
*
|
||||
* @return The minor version.
|
||||
*/
|
||||
public int getMinor() {
|
||||
return minor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the patch version.
|
||||
*
|
||||
* @return The patch version.
|
||||
*/
|
||||
public int getPatch() {
|
||||
return patch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (major < 9) {
|
||||
return String.format("1.%d.%d_%d", major, minor, patch);
|
||||
}
|
||||
return String.format("%d.%d.%d", major, minor, patch);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(JavaVersion other) {
|
||||
if (major > other.major) {
|
||||
return 1;
|
||||
}
|
||||
if (major < other.major) {
|
||||
return -1;
|
||||
}
|
||||
if (minor > other.minor) {
|
||||
return 1;
|
||||
}
|
||||
if (minor < other.minor) {
|
||||
return -1;
|
||||
}
|
||||
if (patch > other.patch) {
|
||||
return 1;
|
||||
}
|
||||
if (patch < other.patch) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + major;
|
||||
result = prime * result + minor;
|
||||
result = prime * result + patch;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
JavaVersion other = (JavaVersion) obj;
|
||||
if (major != other.major) {
|
||||
return false;
|
||||
}
|
||||
if (minor != other.minor) {
|
||||
return false;
|
||||
}
|
||||
if (patch != other.patch) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the major, minor, and optional patch integers out of the given version string.
|
||||
*
|
||||
* @param version A version string.
|
||||
* @throws ParseException if the version string failed to parse. The exception's message
|
||||
* has more detailed information about why it failed.
|
||||
*/
|
||||
private void parse(String version) throws ParseException {
|
||||
if (version == null) {
|
||||
throw new ParseException("Version is null", 0);
|
||||
}
|
||||
|
||||
major = minor = patch = 0;
|
||||
|
||||
// Remove any surrounding double quotes
|
||||
if (version.startsWith("\"") && version.endsWith("\"")) {
|
||||
version = version.substring(1, version.length() - 1);
|
||||
}
|
||||
|
||||
// Remove any trailing dash section (9-Ubuntu is a thing).
|
||||
int dashIndex = version.indexOf('-');
|
||||
if (dashIndex > 0) {
|
||||
version = version.substring(0, dashIndex);
|
||||
}
|
||||
|
||||
String[] versionParts = version.split("[._]");
|
||||
int firstValue = parse(versionParts[0], "first value");
|
||||
if (firstValue == 1) {
|
||||
// Follows the Java 8 and earlier format of 1.major.minor_patch
|
||||
if (versionParts.length > 1) {
|
||||
major = parse(versionParts[1], "major");
|
||||
if (versionParts.length > 2) {
|
||||
minor = parse(versionParts[2], "minor");
|
||||
if (versionParts.length > 3) {
|
||||
patch = parse(versionParts[3], "patch");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (firstValue >= 9) {
|
||||
// Follows the Java 9 and later format of major.minor.patch
|
||||
major = parse(versionParts[0], "major");
|
||||
if (versionParts.length > 1) {
|
||||
minor = parse(versionParts[1], "minor");
|
||||
if (versionParts.length > 2) {
|
||||
patch = parse(versionParts[2], "patch");
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new ParseException("Failed to parse version: " + version, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a version part string to an integer.
|
||||
*
|
||||
* @param versionPart A version part string.
|
||||
* @param versionPartName The version part name (for error reporting).
|
||||
* @return The version part string as an integer.
|
||||
* @throws ParseException if the version part string failed to parse to a valid version part
|
||||
* integer.
|
||||
*/
|
||||
private int parse(String versionPart, String versionPartName) throws ParseException {
|
||||
try {
|
||||
int i = Integer.parseInt(versionPart);
|
||||
if (i < 0) {
|
||||
throw new ParseException(versionPartName + " cannot be negative", 0);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
throw new ParseException("Failed to convert " + versionPartName + " version to integer",
|
||||
0);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
/* ###
|
||||
* 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.launch;
|
||||
|
||||
import java.io.*;
|
||||
import java.text.ParseException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Parses and provides convenient access to the properties defined in a launch properties file.
|
||||
* <p>
|
||||
* Our launch properties file is a bit different than a file represented by a {@link Properties}
|
||||
* object because we allow for duplicate keys. The Apache commons config library can do this, but
|
||||
* this project cannot have any external dependencies.
|
||||
*/
|
||||
public class LaunchProperties {
|
||||
|
||||
/**
|
||||
* The home directory of the Java to use to launch.
|
||||
*/
|
||||
public static String JAVA_HOME_OVERRIDE = "JAVA_HOME_OVERRIDE";
|
||||
|
||||
/**
|
||||
* The VM arguments to use to launch.
|
||||
*/
|
||||
public static String VMARGS = "VMARGS";
|
||||
|
||||
private Map<String, List<String>> propertyMap;
|
||||
|
||||
/**
|
||||
* Creates a new launch properties object from the given launch properties file.
|
||||
*
|
||||
* @param launchPropertiesFile The launch properties file.
|
||||
* @throws FileNotFoundException if the given launch properties file does not exist.
|
||||
* @throws IOException if there was a problem reading the given launch properties file.
|
||||
* @throws ParseException if there was a problem parsing the given launch properties file.
|
||||
*/
|
||||
public LaunchProperties(File launchPropertiesFile)
|
||||
throws FileNotFoundException, IOException, ParseException {
|
||||
propertyMap = parseLaunchProperties(launchPropertiesFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Java home override directory to use for the launch.
|
||||
*
|
||||
* @return The Java home override directory to use for the launch. Could be null if the
|
||||
* property was not defined. The caller should ensure that the directory exists.
|
||||
*/
|
||||
public File getJavaHomeOverride() {
|
||||
List<String> javaHome = propertyMap.get(JAVA_HOME_OVERRIDE);
|
||||
if (javaHome != null && !javaHome.isEmpty()) {
|
||||
return new File(javaHome.get(0));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the command line string of VM arguments to use for the launch.
|
||||
* This will be the union of all VM arguments defined in both the user and installation launch
|
||||
* properties. If conflicting VM arguments are defined in both files, the user version
|
||||
* will override the installation version.
|
||||
*
|
||||
* @return The command line string of VM arguments to use for the launch.
|
||||
*/
|
||||
public String getVmArgs() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
List<String> vmargList = propertyMap.get(VMARGS);
|
||||
if (vmargList != null) {
|
||||
for (String arg : vmargList) {
|
||||
sb.append(arg);
|
||||
sb.append(" ");
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses and gets the launch properties from the given launch properties file.
|
||||
*
|
||||
* @param launchPropertiesFile The file to get the launch properties from.
|
||||
* @return The launch properties from the given launch properties file.
|
||||
* @throws FileNotFoundException if the given launch properties file does not exist.
|
||||
* @throws IOException if there was a problem reading the given launch properties file.
|
||||
* @throws ParseException if there was a problem parsing the given launch properties file.
|
||||
*/
|
||||
private static Map<String, List<String>> parseLaunchProperties(File launchPropertiesFile)
|
||||
throws FileNotFoundException, IOException, ParseException {
|
||||
HashMap<String, List<String>> map = new HashMap<>();
|
||||
if (launchPropertiesFile != null) {
|
||||
try (BufferedReader reader = new BufferedReader(new FileReader(launchPropertiesFile))) {
|
||||
int i = 0;
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
i++;
|
||||
line = line.trim();
|
||||
if (line.isEmpty() || line.startsWith("#") || line.startsWith("//")) {
|
||||
continue;
|
||||
}
|
||||
int equalsIndex = line.indexOf('=');
|
||||
if (equalsIndex <= 0) {
|
||||
throw new ParseException(
|
||||
"Error parsing line " + i + " of " + launchPropertiesFile, i);
|
||||
}
|
||||
String key = line.substring(0, equalsIndex).trim();
|
||||
String value = line.substring(equalsIndex + 1, line.length()).trim();
|
||||
List<String> valueList = map.get(key);
|
||||
if (valueList == null) {
|
||||
valueList = new ArrayList<>();
|
||||
map.put(key, valueList);
|
||||
}
|
||||
if (!value.isEmpty()) {
|
||||
valueList.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/* ###
|
||||
* 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.launch;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Class responsible for finding Java installations on a Linux system.
|
||||
*/
|
||||
public class LinuxJavaFinder extends JavaFinder {
|
||||
|
||||
@Override
|
||||
protected List<File> getJavaRootInstallDirs() {
|
||||
List<File> javaRootInstallDirs = new ArrayList<>();
|
||||
javaRootInstallDirs.add(new File("/usr/lib/jvm"));
|
||||
return javaRootInstallDirs;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getJavaHomeSubDirPath() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected File getJreHomeFromJavaHome(File javaHomeDir) {
|
||||
if (javaHomeDir.isDirectory() && !javaHomeDir.getName().equals("jre")) {
|
||||
for (File dir : javaHomeDir.listFiles()) {
|
||||
if (dir.isDirectory() && dir.getName().equals("jre")) {
|
||||
return dir;
|
||||
}
|
||||
}
|
||||
}
|
||||
return javaHomeDir;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected File getJdkHomeFromJavaHome(File javaHomeDir) {
|
||||
if (javaHomeDir.getName().equals("jre")) {
|
||||
return javaHomeDir.getParentFile();
|
||||
}
|
||||
return javaHomeDir;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/* ###
|
||||
* 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.launch;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Class responsible for finding Java installations on a Mac system.
|
||||
*/
|
||||
public class MacJavaFinder extends LinuxJavaFinder {
|
||||
|
||||
@Override
|
||||
protected List<File> getJavaRootInstallDirs() {
|
||||
List<File> javaRootInstallDirs = new ArrayList<>();
|
||||
javaRootInstallDirs.add(new File("/Library/Java/JavaVirtualMachines"));
|
||||
return javaRootInstallDirs;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getJavaHomeSubDirPath() {
|
||||
return "Contents/Home";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/* ###
|
||||
* 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.launch;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Class responsible for finding Java installations on a Windows system.
|
||||
*/
|
||||
public class WindowsJavaFinder extends JavaFinder {
|
||||
|
||||
@Override
|
||||
protected List<File> getJavaRootInstallDirs() {
|
||||
List<File> javaRootInstallDirs = new ArrayList<>();
|
||||
javaRootInstallDirs.add(new File("C:\\Program Files\\Java"));
|
||||
return javaRootInstallDirs;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getJavaHomeSubDirPath() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected File getJreHomeFromJavaHome(File javaHomeDir) {
|
||||
if (javaHomeDir.getName().startsWith("jdk")) {
|
||||
return new File(javaHomeDir.getParentFile(),
|
||||
javaHomeDir.getName().replaceFirst("jdk", "jre"));
|
||||
}
|
||||
return javaHomeDir;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected File getJdkHomeFromJavaHome(File javaHomeDir) {
|
||||
if (javaHomeDir.getName().startsWith("jre")) {
|
||||
return new File(javaHomeDir.getParentFile(),
|
||||
javaHomeDir.getName().replaceFirst("jre", "jdk"));
|
||||
}
|
||||
return javaHomeDir;
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue