aboutsummaryrefslogtreecommitdiff
path: root/find_java2/src/JavaFinder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'find_java2/src/JavaFinder.cpp')
-rwxr-xr-xfind_java2/src/JavaFinder.cpp594
1 files changed, 0 insertions, 594 deletions
diff --git a/find_java2/src/JavaFinder.cpp b/find_java2/src/JavaFinder.cpp
deleted file mode 100755
index 60a2e230e..000000000
--- a/find_java2/src/JavaFinder.cpp
+++ /dev/null
@@ -1,594 +0,0 @@
-/*
-* Copyright (C) 2014 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.
-*/
-
-#include "stdafx.h"
-#include "JavaFinder.h"
-#include "utils.h"
-
-#include <algorithm> // std::sort and std::unique
-
-#define _CRT_SECURE_NO_WARNINGS
-
-// --------------
-
-#define JF_REGISTRY_KEY _T("Software\\Android\\FindJava2")
-#define JF_REGISTRY_VALUE_PATH _T("JavaPath")
-#define JF_REGISTRY_VALUE_VERS _T("JavaVers")
-
-// --------------
-
-
-// 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 TCHAR *start,
- int length,
- CString *outVersionStr,
- int *outVersionInt) {
- const TCHAR *end = start + length;
- for (const TCHAR *c = start; c < end - 2; c++) {
- if (isdigit(c[0]) &&
- c[1] == '.' &&
- isdigit(c[2])) {
- const TCHAR *e = c + 2;
- while (isdigit(e[1])) {
- e++;
- }
- outVersionStr->SetString(c, e - c + 1);
-
- // major is currently only 1 digit
- int major = (*c - '0');
- // add minor
- int minor = 0;
- for (int m = 1; *e != '.'; e--, m *= 10) {
- minor += (*e - '0') * m;
- }
- *outVersionInt = JAVA_VERS_TO_INT(major, minor);
- return true;
- }
- }
- return false;
-}
-
-// Tries to invoke the java.exe at the given path and extract it's
-// version number.
-// - outVersionStr: not null, will capture version as a string (e.g. "1.6")
-// - outVersionInt: not null, will capture version as an int (see JavaPath.h).
-bool getJavaVersion(CPath &javaPath, CString *outVersionStr, int *outVersionInt) {
- bool result = false;
-
- // Run "java -version", which outputs something to *STDERR* like this:
- //
- // 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.Format(_T("\"%s\" -version"), (LPCTSTR) javaPath);
-
- 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)
- // In FindJava2, we do not report these errors. Leave commented for reference.
- // // if (gIsConsole || gIsDebug) displayLastError("CreatePipe failed: ");
- return false;
- }
- if (!SetHandleInformation(stdoutPipeRd, HANDLE_FLAG_INHERIT, 0)) {
- // In FindJava2, we do not report these errors. Leave commented for reference.
- // // 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 = CreateProcess(
- NULL, // program path
- (LPTSTR)((LPCTSTR) cmd),// 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);
-
- // In FindJava2, we do not report these errors. Leave commented for reference.
- // // 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.
- TCHAR 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
- // Note: ReadFile uses a char buffer, not a TCHAR one.
- 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 capture roughtly the first line in lower case.
- TCHAR *j = _tcsstr(first32, _T("java"));
- TCHAR *v = _tcsstr(first32, _T("version"));
- // In FindJava2, we do not report these errors. Leave commented for reference.
- // // if ((gIsConsole || gIsDebug) && (!j || !v)) {
- // // fprintf(stderr, "Error: keywords 'java version' not found in '%s'\n", first32);
- // // }
- if (j != NULL && v != NULL) {
- result = extractJavaVersion(first32, index, outVersionStr, outVersionInt);
- }
- }
-
- return result;
-}
-
-// --------------
-
-// Checks 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) {
-
- // Append java.exe to path if not already present
- CString &p = (CString&)*inOutPath;
- int n = p.GetLength();
- if (n < 9 || p.Right(9).CompareNoCase(_T("\\java.exe")) != 0) {
- inOutPath->Append(_T("java.exe"));
- }
-
- int result = 0;
- PVOID oldWow64Value = disableWow64FsRedirection();
- if (inOutPath->FileExists()) {
- // Run java -version
- // Reject the version if it's not at least our current minimum.
- CString versionStr;
- if (!getJavaVersion(*inOutPath, &versionStr, &result)) {
- result = 0;
- }
- }
-
- revertWow64FsRedirection(oldWow64Value);
- 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) {
-
- // Append bin to path if not already present
- CString &p = (CString&)*inOutPath;
- int n = p.GetLength();
- if (n < 4 || p.Right(4).CompareNoCase(_T("\\bin")) != 0) {
- inOutPath->Append(_T("bin"));
- }
-
- return checkPath(inOutPath);
-}
-
-// Search java.exe in the environment
-static void findJavaInEnvPath(std::set<CJavaPath> *outPaths) {
- ::SetLastError(0);
-
- const TCHAR* envPath = _tgetenv(_T("JAVA_HOME"));
- if (envPath != NULL) {
- CPath p(envPath);
- int v = checkBinPath(&p);
- if (v > 0) {
- outPaths->insert(CJavaPath(v, p));
- }
- }
-
- envPath = _tgetenv(_T("PATH"));
- if (envPath != NULL) {
- // Otherwise look at the entries in the current path.
- // If we find more than one, keep the one with the highest version.
- CString pathTokens(envPath);
- int curPos = 0;
- CString tok;
- do {
- tok = pathTokens.Tokenize(_T(";"), curPos);
- if (!tok.IsEmpty()) {
- CPath p(tok);
- int v = checkPath(&p);
- if (v > 0) {
- outPaths->insert(CJavaPath(v, p));
- }
- }
- } while (!tok.IsEmpty());
- }
-}
-
-
-// --------------
-
-static bool getRegValue(const TCHAR *keyPath,
- const TCHAR *keyName,
- REGSAM access,
- CString *outValue) {
- HKEY key;
- LSTATUS status = RegOpenKeyEx(
- 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
- TCHAR* buffer = (TCHAR*)malloc(size);
-
- while (ret == ERROR_MORE_DATA && size < (1 << 16) /*64 KB*/) {
- ret = RegQueryValueEx(
- key, // hKey
- keyName, // lpValueName
- NULL, // lpReserved
- NULL, // lpType
- (LPBYTE)buffer, // lpData
- &size); // lpcbData
-
- if (ret == ERROR_MORE_DATA) {
- size *= 2;
- buffer = (TCHAR*)realloc(buffer, size);
- } else {
- buffer[size] = 0;
- }
- }
-
- if (ret != ERROR_MORE_DATA) {
- outValue->SetString(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 TCHAR *entry, REGSAM access, std::set<CJavaPath> *outPaths) {
-
- // Let's visit HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment [CurrentVersion]
- CPath rootKey(_T("SOFTWARE\\JavaSoft\\"));
- rootKey.Append(entry);
-
- CString currentVersion;
- CPath subKey(rootKey);
- if (getRegValue(subKey, _T("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.Append(currentVersion);
- CString value;
- if (getRegValue(subKey, _T("JavaHome"), access, &value)) {
- CPath javaHome(value);
- int v = checkBinPath(&javaHome);
- if (v > 0) {
- outPaths->insert(CJavaPath(v, javaHome));
- }
- }
- }
-
- // Try again, but this time look at all the versions available
- HKEY javaHomeKey;
- LSTATUS status = RegOpenKeyEx(
- HKEY_LOCAL_MACHINE, // hKey
- _T("SOFTWARE\\JavaSoft"), // lpSubKey
- 0, // ulOptions
- KEY_READ | access, // samDesired
- &javaHomeKey); // phkResult
- if (status == ERROR_SUCCESS) {
- TCHAR name[MAX_PATH + 1];
- DWORD index = 0;
- CPath javaHome;
- for (LONG result = ERROR_SUCCESS; result == ERROR_SUCCESS; index++) {
- DWORD nameLen = MAX_PATH;
- name[nameLen] = 0;
- result = RegEnumKeyEx(
- javaHomeKey, // hKey
- index, // dwIndex
- name, // lpName
- &nameLen, // lpcName
- NULL, // lpReserved
- NULL, // lpClass
- NULL, // lpcClass,
- NULL); // lpftLastWriteTime
- if (result == ERROR_SUCCESS && nameLen < MAX_PATH) {
- name[nameLen] = 0;
- CPath subKey(rootKey);
- subKey.Append(name);
-
- CString value;
- if (getRegValue(subKey, _T("JavaHome"), access, &value)) {
- CPath javaHome(value);
- int v = checkBinPath(&javaHome);
- if (v > 0) {
- outPaths->insert(CJavaPath(v, javaHome));
- }
- }
- }
- }
-
- RegCloseKey(javaHomeKey);
- }
-
- return 0;
-}
-
-static void findJavaInRegistry(std::set<CJavaPath> *outPaths) {
- // We'll do the registry test 3 times: first using the default mode,
- // then forcing the use of the 32-bit registry then forcing the use of
- // 64-bit registry. On Windows 2k, the 2 latter will fail since the
- // flags are not supported. On a 32-bit OS the 64-bit is obviously
- // useless and the 2 first tests should be equivalent so we just
- // need the first case.
-
- // Check the JRE first, then the JDK.
- exploreJavaRegistry(_T("Java Runtime Environment"), 0, outPaths);
- exploreJavaRegistry(_T("Java Development Kit"), 0, outPaths);
-
- // Get the app sysinfo state (the one hidden by WOW64)
- SYSTEM_INFO sysInfo;
- GetSystemInfo(&sysInfo);
- WORD programArch = sysInfo.wProcessorArchitecture;
- // Check the real sysinfo state (not the one hidden by WOW64) for x86
- GetNativeSystemInfo(&sysInfo);
- WORD actualArch = sysInfo.wProcessorArchitecture;
-
- // Only try to access the WOW64-32 redirected keys on a 64-bit system.
- // There's no point in doing this on a 32-bit system.
- if (actualArch == PROCESSOR_ARCHITECTURE_AMD64) {
- if (programArch != PROCESSOR_ARCHITECTURE_INTEL) {
- // If we did the 32-bit case earlier, don't do it twice.
- exploreJavaRegistry(_T("Java Runtime Environment"), KEY_WOW64_32KEY, outPaths);
- exploreJavaRegistry(_T("Java Development Kit"), KEY_WOW64_32KEY, outPaths);
-
- } else if (programArch != PROCESSOR_ARCHITECTURE_AMD64) {
- // If we did the 64-bit case earlier, don't do it twice.
- exploreJavaRegistry(_T("Java Runtime Environment"), KEY_WOW64_64KEY, outPaths);
- exploreJavaRegistry(_T("Java Development Kit"), KEY_WOW64_64KEY, outPaths);
- }
- }
-}
-
-// --------------
-
-static void checkProgramFiles(std::set<CJavaPath> *outPaths) {
-
- TCHAR programFilesPath[MAX_PATH + 1];
- HRESULT result = SHGetFolderPath(
- NULL, // hwndOwner
- CSIDL_PROGRAM_FILES, // nFolder
- NULL, // hToken
- SHGFP_TYPE_CURRENT, // dwFlags
- programFilesPath); // pszPath
-
- CPath path(programFilesPath);
- path.Append(_T("Java"));
-
- // Do we have a C:\\Program Files\\Java directory?
- if (!path.IsDirectory()) {
- return;
- }
-
- CPath glob(path);
- glob.Append(_T("j*"));
-
- WIN32_FIND_DATA findData;
- HANDLE findH = FindFirstFile(glob, &findData);
- if (findH == INVALID_HANDLE_VALUE) {
- return;
- }
- do {
- if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
- CPath temp(path);
- temp.Append(findData.cFileName);
- // Check C:\\Program Files[x86]\\Java\\j*\\bin\\java.exe
- int v = checkBinPath(&temp);
- if (v > 0) {
- outPaths->insert(CJavaPath(v, temp));
- }
- }
- } while (FindNextFile(findH, &findData) != 0);
- FindClose(findH);
-}
-
-static void findJavaInProgramFiles(std::set<CJavaPath> *outPaths) {
- // Check the C:\\Program Files (x86) directory
- // With WOW64 fs redirection in place by default, we should get the x86
- // version on a 64-bit OS since this app is a 32-bit itself.
- checkProgramFiles(outPaths);
-
- // Check the real sysinfo state (not the one hidden by WOW64) for x86
- SYSTEM_INFO sysInfo;
- GetNativeSystemInfo(&sysInfo);
-
- if (sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) {
- // On a 64-bit OS, try again by disabling the fs redirection so
- // that we can try the real C:\\Program Files directory.
- PVOID oldWow64Value = disableWow64FsRedirection();
- checkProgramFiles(outPaths);
- revertWow64FsRedirection(oldWow64Value);
- }
-}
-
-//------
-
-
-CJavaFinder::CJavaFinder(int minVersion) : mMinVersion(minVersion) {
-}
-
-
-CJavaFinder::~CJavaFinder() {
-}
-
-/*
- * Checks whether there's a recorded path in the registry and whether
- * this path still points to a valid Java executable.
- * Returns false if any of these do not match,
- * Returns true if both condition match,
- * outPath contains the result path when returning true.
-*/
-CJavaPath CJavaFinder::getRegistryPath() {
- CString existing;
- CRegKey rk;
-
- if (rk.Open(HKEY_CURRENT_USER, JF_REGISTRY_KEY, KEY_READ) == ERROR_SUCCESS) {
- ULONG sLen = MAX_PATH;
- TCHAR s[MAX_PATH + 1];
- if (rk.QueryStringValue(JF_REGISTRY_VALUE_PATH, s, &sLen) == ERROR_SUCCESS) {
- existing.SetString(s);
- }
- rk.Close();
- }
-
- if (!existing.IsEmpty()) {
- CJavaPath javaPath;
- if (checkJavaPath(existing, &javaPath)) {
- return javaPath;
- }
- }
-
- return CJavaPath::sEmpty;
-}
-
-bool CJavaFinder::setRegistryPath(const CJavaPath &javaPath) {
- CRegKey rk;
-
- if (rk.Create(HKEY_CURRENT_USER, JF_REGISTRY_KEY) == ERROR_SUCCESS) {
- bool ok = rk.SetStringValue(JF_REGISTRY_VALUE_PATH, javaPath.mPath, REG_SZ) == ERROR_SUCCESS &&
- rk.SetStringValue(JF_REGISTRY_VALUE_VERS, javaPath.getVersion(), REG_SZ) == ERROR_SUCCESS;
- rk.Close();
- return ok;
- }
-
- return false;
-}
-
-void CJavaFinder::findJavaPaths(std::set<CJavaPath> *paths) {
- findJavaInEnvPath(paths);
- findJavaInProgramFiles(paths);
- findJavaInRegistry(paths);
-
- // Exclude any entries that do not match the minimum version.
- // The set is going to be fairly small so it's easier to do it here
- // than add the filter logic in all the static methods above.
- if (mMinVersion > 0) {
- for (auto it = paths->begin(); it != paths->end(); ) {
- if (it->mVersion < mMinVersion) {
- it = paths->erase(it); // C++11 set.erase returns an iterator to the *next* element
- } else {
- ++it;
- }
- }
- }
-}
-
-bool CJavaFinder::checkJavaPath(const CString &path, CJavaPath *outPath) {
- CPath p(path);
-
- // try this path (if it ends with java.exe) or path\\java.exe
- int v = checkPath(&p);
- if (v == 0) {
- // reset path and try path\\bin\\java.exe
- p = CPath(path);
- v = checkBinPath(&p);
- }
-
- if (v > 0) {
- outPath->set(v, p);
- return v >= mMinVersion;
- }
-
- return false;
-}
-