aboutsummaryrefslogtreecommitdiff
path: root/find_java/src/source/find_java_lib.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'find_java/src/source/find_java_lib.cpp')
-rwxr-xr-xfind_java/src/source/find_java_lib.cpp573
1 files changed, 0 insertions, 573 deletions
diff --git a/find_java/src/source/find_java_lib.cpp b/find_java/src/source/find_java_lib.cpp
deleted file mode 100755
index fe50f8396..000000000
--- a/find_java/src/source/find_java_lib.cpp
+++ /dev/null
@@ -1,573 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * 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.
- */
-
-#ifdef _WIN32
-
-// Indicate we want at least all Windows Server 2003 (5.2) APIs.
-// Note: default is set by system/core/include/arch/windows/AndroidConfig.h to 0x0500
-// which is Win2K. However our minimum SDK tools requirement is Win XP (0x0501).
-// However we do need 0x0502 to get access to the WOW-64-32 constants for the
-// registry, except we'll need to be careful since they are not available on XP.
-#undef _WIN32_WINNT
-#define _WIN32_WINNT 0x0502
-// Indicate we want at least all IE 5 shell APIs
-#define _WIN32_IE 0x0500
-
-#include "find_java.h"
-#include <shlobj.h>
-#include <ctype.h>
-
-// Define some types missing in MingW
-#ifndef LSTATUS
-typedef LONG LSTATUS;
-#endif
-
-// Check to see if the application is running in 32-bit or 64-bit mode. In other words, this will
-// return false if you run a 32-bit build even on a 64-bit machine.
-static bool isApplication64() {
- SYSTEM_INFO sysInfo;
- GetSystemInfo(&sysInfo);
-
- // Note: The constant name here is a bit misleading, as it actually covers all 64-bit processors
- // and not just AMD.
- // See also: http://msdn.microsoft.com/en-us/library/windows/desktop/ms724958(v=vs.85).aspx
- return (sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64);
-}
-
-// Extract the first thing that looks like (digit.digit+).
-// Note: this will break when java reports a version with major > 9.
-// However it will reasonably cope with "1.10", if that ever happens.
-static bool extractJavaVersion(const char *start,
- int length,
- CString *outVersionStr,
- int *outVersionInt) {
- const char *end = start + length;
- for (const char *c = start; c < end - 2; c++) {
- if (isdigit(c[0]) &&
- c[1] == '.' &&
- isdigit(c[2])) {
- const char *e = c+2;
- while (isdigit(e[1])) {
- e++;
- }
- if (outVersionStr != NULL) {
- outVersionStr->set(c, e - c + 1);
- }
- if (outVersionInt != NULL) {
- // add major * 1000, currently only 1 digit
- int value = (*c - '0') * 1000;
- // add minor
- for (int m = 1; *e != '.'; e--, m *= 10) {
- value += (*e - '0') * m;
- }
- *outVersionInt = value;
- }
- return true;
- }
- }
- return false;
-}
-
-// Check if the passed in path is a path to a JDK
-static bool isJdkPath(const CPath &path) {
-
- // If the files "bin/java.exe" and "lib/tools.jar" exist, we're probably a JDK.
- CPath pathBin(path);
- pathBin.addPath("bin");
- pathBin.addPath("java.exe");
-
- CPath pathTools(path);
- pathTools.addPath("lib");
- pathTools.addPath("tools.jar");
-
- return (pathBin.fileExists() && pathTools.fileExists());
-}
-
-// Check whether we can find $PATH/java.exe.
-// inOutPath should be the directory where we're looking at.
-// In output, it will be the java path we tested.
-// Returns the java version integer found (e.g. 1006 for 1.6).
-// Return 0 in case of error.
-static int checkPath(CPath *inOutPath) {
- inOutPath->addPath("java.exe");
-
- int result = 0;
- if (inOutPath->fileExists()) {
- // Run java -version
- // Reject the version if it's not at least our current minimum.
- if (!getJavaVersion(*inOutPath, NULL /*versionStr*/, &result)) {
- result = 0;
- }
- }
-
- return result;
-}
-
-// Check whether we can find $PATH/bin/java.exe
-// Returns the Java version found (e.g. 1006 for 1.6) or 0 in case of error.
-static int checkBinPath(CPath *inOutPath) {
- inOutPath->addPath("bin");
- return checkPath(inOutPath);
-}
-
-// Test for the existence of java.exe in a custom path
-int findJavaInPath(const CPath &path, CPath *outJavaPath, bool isJdk, int minVersion) {
- SetLastError(0);
-
- int version = 0;
- CPath temp(path);
- if (!isJdk) {
- version = checkPath(&temp);
- }
- else {
- if (isJdkPath(temp)) {
- version = checkBinPath(&temp);
- }
- }
-
- if (version >= minVersion) {
- if (gIsDebug) {
- fprintf(stderr, "Java %d found in path: %s\n", version, temp.cstr());
- }
- *outJavaPath = temp;
- return version;
- }
- return 0;
-}
-
-// Search java.exe in the environment
-int findJavaInEnvPath(CPath *outJavaPath, bool isJdk, int minVersion) {
- SetLastError(0);
-
- const char* envPath = getenv("JAVA_HOME");
- if (envPath != NULL) {
- CPath p(envPath);
-
- if (!isJdk || isJdkPath(p)) {
- int v = checkBinPath(&p);
- if (v >= minVersion) {
- if (gIsDebug) {
- fprintf(stderr, "Java %d found via JAVA_HOME: %s\n", v, p.cstr());
- }
- *outJavaPath = p;
- // As an optimization for runtime, if we find a suitable java
- // version in JAVA_HOME we won't waste time looking at the PATH.
- return v;
- }
- }
- }
-
- int currVersion = 0;
- envPath = getenv("PATH");
- if (!envPath) return currVersion;
-
- // Otherwise look at the entries in the current path.
- // If we find more than one, keep the one with the highest version.
-
- CArray<CString> *paths = CString(envPath).split(';');
- for(int i = 0; i < paths->size(); i++) {
- CPath p((*paths)[i].cstr());
-
- if (isJdk && !isJdkPath(p)) {
- continue;
- }
-
- int v = checkPath(&p);
- if (v >= minVersion && v > currVersion) {
- if (gIsDebug) {
- fprintf(stderr, "Java %d found via env PATH: %s\n", v, p.cstr());
- }
-
- currVersion = v;
- *outJavaPath = p;
- }
- }
-
- delete paths;
- return currVersion;
-}
-
-// --------------
-
-static bool getRegValue(const char *keyPath,
- const char *keyName,
- REGSAM access,
- CString *outValue) {
- HKEY key;
- LSTATUS status = RegOpenKeyExA(
- HKEY_LOCAL_MACHINE, // hKey
- keyPath, // lpSubKey
- 0, // ulOptions
- KEY_READ | access, // samDesired,
- &key); // phkResult
- if (status == ERROR_SUCCESS) {
-
- LSTATUS ret = ERROR_MORE_DATA;
- DWORD size = 4096; // MAX_PATH is 260, so 4 KB should be good enough
- char* buffer = (char*) malloc(size);
-
- while (ret == ERROR_MORE_DATA && size < (1<<16) /*64 KB*/) {
- ret = RegQueryValueExA(
- key, // hKey
- keyName, // lpValueName
- NULL, // lpReserved
- NULL, // lpType
- (LPBYTE) buffer, // lpData
- &size); // lpcbData
-
- if (ret == ERROR_MORE_DATA) {
- size *= 2;
- buffer = (char*) realloc(buffer, size);
- } else {
- buffer[size] = 0;
- }
- }
-
- if (ret != ERROR_MORE_DATA) outValue->set(buffer);
-
- free(buffer);
- RegCloseKey(key);
-
- return (ret != ERROR_MORE_DATA);
- }
-
- return false;
-}
-
-// Explore the registry to find a suitable version of Java.
-// Returns an int which is the version of Java found (e.g. 1006 for 1.6) and the
-// matching path in outJavaPath.
-// Returns 0 if nothing suitable was found.
-static int exploreJavaRegistry(const char *entry, REGSAM access, int minVersion,
- CPath *outJavaPath) {
-
- // Let's visit HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment [CurrentVersion]
- CPath rootKey("SOFTWARE\\JavaSoft\\");
- rootKey.addPath(entry);
-
- int versionInt = 0;
- CString currentVersion;
- CPath subKey(rootKey);
- if (getRegValue(subKey.cstr(), "CurrentVersion", access, &currentVersion)) {
- // CurrentVersion should be something like "1.7".
- // We want to read HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment\1.7 [JavaHome]
- subKey.addPath(currentVersion);
- CPath javaHome;
- if (getRegValue(subKey.cstr(), "JavaHome", access, &javaHome)) {
- versionInt = checkBinPath(&javaHome);
- if (versionInt >= 0) {
- if (gIsDebug) {
- fprintf(stderr,
- "Java %d found via registry: %s\n",
- versionInt, javaHome.cstr());
- }
- *outJavaPath = javaHome;
- }
- if (versionInt >= minVersion) {
- // Heuristic: if the current version is good enough, stop here
- return versionInt;
- }
- }
- }
-
- // Try again, but this time look at all the versions available
- HKEY javaHomeKey;
- LSTATUS status = RegOpenKeyExA(
- HKEY_LOCAL_MACHINE, // hKey
- "SOFTWARE\\JavaSoft", // lpSubKey
- 0, // ulOptions
- KEY_READ | access, // samDesired
- &javaHomeKey); // phkResult
- if (status == ERROR_SUCCESS) {
- char name[256];
- DWORD index = 0;
- CPath javaHome;
- for (LONG result = ERROR_SUCCESS; result == ERROR_SUCCESS; index++) {
- DWORD nameLen = 255;
- name[nameLen] = 0;
- result = RegEnumKeyExA(
- javaHomeKey, // hKey
- index, // dwIndex
- name, // lpName
- &nameLen, // lpcName
- NULL, // lpReserved
- NULL, // lpClass
- NULL, // lpcClass,
- NULL); // lpftLastWriteTime
- if (result == ERROR_SUCCESS && nameLen < 256) {
- name[nameLen] = 0;
- CPath subKey(rootKey);
- subKey.addPath(name);
-
- if (getRegValue(subKey.cstr(), "JavaHome", access, &javaHome)) {
- int v = checkBinPath(&javaHome);
- if (v > versionInt) {
- if (gIsDebug) {
- fprintf(stderr,
- "Java %d found via registry: %s\n",
- versionInt, javaHome.cstr());
- }
- *outJavaPath = javaHome;
- versionInt = v;
- }
- }
- }
- }
-
- RegCloseKey(javaHomeKey);
- }
-
- return 0;
-}
-
-static bool getMaxJavaInRegistry(const char *entry, REGSAM access, CPath *outJavaPath, int *inOutVersion) {
- CPath path;
- int version = exploreJavaRegistry(entry, access, *inOutVersion, &path);
- if (version > *inOutVersion) {
- *outJavaPath = path;
- *inOutVersion = version;
- return true;
- }
- return false;
-}
-
-int findJavaInRegistry(CPath *outJavaPath, bool isJdk, int minVersion) {
- // Check the JRE first, then the JDK.
- int version = minVersion - 1; // Inner methods check if they're greater than this version.
- bool result = false;
- result |= (!isJdk && getMaxJavaInRegistry("Java Runtime Environment", 0, outJavaPath, &version));
- result |= getMaxJavaInRegistry("Java Development Kit", 0, outJavaPath, &version);
-
- // Even if we're 64-bit, try again but check the 32-bit registry, looking for 32-bit java.
- if (isApplication64()) {
- result |= (!isJdk &&
- getMaxJavaInRegistry("Java Runtime Environment", KEY_WOW64_32KEY, outJavaPath, &version));
- result |= getMaxJavaInRegistry("Java Development Kit", KEY_WOW64_32KEY, outJavaPath, &version);
- }
-
- return result ? version : 0;
-}
-
-// --------------
-
-static bool checkProgramFiles(CPath *outJavaPath, int *inOutVersion, bool isJdk,
- bool force32bit) {
-
- char programFilesPath[MAX_PATH + 1];
- int nFolder = force32bit ? CSIDL_PROGRAM_FILESX86 : CSIDL_PROGRAM_FILES;
- HRESULT result = SHGetFolderPathA(
- NULL, // hwndOwner
- nFolder,
- NULL, // hToken
- SHGFP_TYPE_CURRENT, // dwFlags
- programFilesPath); // pszPath
- if (FAILED(result)) return false;
-
- CPath path(programFilesPath);
- path.addPath("Java");
-
- // Do we have a C:\Program Files\Java directory?
- if (!path.dirExists()) return false;
-
- CPath glob(path);
- glob.addPath("j*");
-
- bool found = false;
- WIN32_FIND_DATAA findData;
- HANDLE findH = FindFirstFileA(glob.cstr(), &findData);
- if (findH == INVALID_HANDLE_VALUE) return false;
- do {
- if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
- CPath temp(path);
- temp.addPath(findData.cFileName);
- // Check C:\Program Files\Java\j*\bin\java.exe
-
- if (!isJdk || isJdkPath(temp)) {
- int v = checkBinPath(&temp);
- if (v > *inOutVersion) {
- found = true;
- *inOutVersion = v;
- *outJavaPath = temp;
- }
- }
- }
- } while (!found && FindNextFileA(findH, &findData) != 0);
- FindClose(findH);
-
- return found;
-}
-
-int findJavaInProgramFiles(CPath *outJavaPath, bool isJdk, int minVersion) {
-
- // Check the C:\Program Files directory
- bool result = false;
- int version = minVersion - 1; // Inner methods check if they're greater than this version.
- result |= checkProgramFiles(outJavaPath, &version, isJdk, false);
-
- // Even if we're 64-bit, try again but check the C:\Program Files (x86) directory, looking for
- // 32-bit java.
- if (isApplication64()) {
- result |= checkProgramFiles(outJavaPath, &version, isJdk, true);
- }
-
- return result ? version : 0;
-}
-
-// --------------
-
-// Tries to invoke the java.exe at the given path and extract it's
-// version number.
-// - outVersionStr: if not null, will capture version as a string (e.g. "1.6")
-// - outVersionInt: if not null, will capture version as an int (major * 1000 + minor, e.g. 1006).
-bool getJavaVersion(CPath &javaPath, CString *outVersionStr, int *outVersionInt) {
- bool result = false;
-
- // Run "java -version", which outputs something like to *STDERR*:
- //
- // java version "1.6.0_29"
- // Java(TM) SE Runtime Environment (build 1.6.0_29-b11)
- // Java HotSpot(TM) Client VM (build 20.4-b02, mixed mode, sharing)
- //
- // We want to capture the first line, and more exactly the "1.6" part.
-
-
- CString cmd;
- cmd.setf("\"%s\" -version", javaPath.cstr());
-
- SECURITY_ATTRIBUTES saAttr;
- STARTUPINFO startup;
- PROCESS_INFORMATION pinfo;
-
- // Want to inherit pipe handle
- ZeroMemory(&saAttr, sizeof(saAttr));
- saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
- saAttr.bInheritHandle = TRUE;
- saAttr.lpSecurityDescriptor = NULL;
-
- // Create pipe for stdout
- HANDLE stdoutPipeRd, stdoutPipeWt;
- if (!CreatePipe(
- &stdoutPipeRd, // hReadPipe,
- &stdoutPipeWt, // hWritePipe,
- &saAttr, // lpPipeAttributes,
- 0)) { // nSize (0=default buffer size)
- if (gIsConsole || gIsDebug) displayLastError("CreatePipe failed: ");
- return false;
- }
- if (!SetHandleInformation(stdoutPipeRd, HANDLE_FLAG_INHERIT, 0)) {
- if (gIsConsole || gIsDebug) displayLastError("SetHandleInformation failed: ");
- return false;
- }
-
- ZeroMemory(&pinfo, sizeof(pinfo));
-
- ZeroMemory(&startup, sizeof(startup));
- startup.cb = sizeof(startup);
- startup.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
- startup.wShowWindow = SW_HIDE|SW_MINIMIZE;
- // Capture both stderr and stdout
- startup.hStdError = stdoutPipeWt;
- startup.hStdOutput = stdoutPipeWt;
- startup.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
-
- BOOL ok = CreateProcessA(
- NULL, // program path
- (LPSTR) cmd.cstr(), // command-line
- NULL, // process handle is not inheritable
- NULL, // thread handle is not inheritable
- TRUE, // yes, inherit some handles
- 0, // process creation flags
- NULL, // use parent's environment block
- NULL, // use parent's starting directory
- &startup, // startup info, i.e. std handles
- &pinfo);
-
- if ((gIsConsole || gIsDebug) && !ok) displayLastError("CreateProcess failed: ");
-
- // Close the write-end of the output pipe (we're only reading from it)
- CloseHandle(stdoutPipeWt);
-
- // Read from the output pipe. We don't need to read everything,
- // the first line should be 'Java version "1.2.3_45"\r\n'
- // so reading about 32 chars is all we need.
- char first32[32 + 1];
- int index = 0;
- first32[0] = 0;
-
- if (ok) {
-
- #define SIZE 1024
- char buffer[SIZE];
- DWORD sizeRead = 0;
-
- while (ok) {
- // Keep reading in the same buffer location
- ok = ReadFile(stdoutPipeRd, // hFile
- buffer, // lpBuffer
- SIZE, // DWORD buffer size to read
- &sizeRead, // DWORD buffer size read
- NULL); // overlapped
- if (!ok || sizeRead == 0 || sizeRead > SIZE) break;
-
- // Copy up to the first 32 characters
- if (index < 32) {
- DWORD n = 32 - index;
- if (n > sizeRead) n = sizeRead;
- // copy as lowercase to simplify checks later
- for (char *b = buffer; n > 0; n--, b++, index++) {
- char c = *b;
- if (c >= 'A' && c <= 'Z') c += 'a' - 'A';
- first32[index] = c;
- }
- first32[index] = 0;
- }
- }
-
- WaitForSingleObject(pinfo.hProcess, INFINITE);
-
- DWORD exitCode;
- if (GetExitCodeProcess(pinfo.hProcess, &exitCode)) {
- // this should not return STILL_ACTIVE (259)
- result = exitCode == 0;
- }
-
- CloseHandle(pinfo.hProcess);
- CloseHandle(pinfo.hThread);
- }
- CloseHandle(stdoutPipeRd);
-
- if (result && index > 0) {
- // Look for a few keywords in the output however we don't
- // care about specific ordering or case-senstiviness.
- // We only captures roughtly the first line in lower case.
- char *j = strstr(first32, "java");
- if (!j) {
- j = strstr(first32, "openjdk");
- }
- char *v = strstr(first32, "version");
- if ((gIsConsole || gIsDebug) && (!j || !v)) {
- fprintf(stderr, "Error: keywords 'java|openjdk version' not found in '%s'\n", first32);
- }
- if (j != NULL && v != NULL) {
- result = extractJavaVersion(first32, index, outVersionStr, outVersionInt);
- }
- }
-
- return result;
-}
-
-
-#endif /* _WIN32 */