1d2d6999d779fffe976c55db04bf523907a8743edRaphael/*
2d2d6999d779fffe976c55db04bf523907a8743edRaphael * Copyright (C) 2012 The Android Open Source Project
3d2d6999d779fffe976c55db04bf523907a8743edRaphael *
4d2d6999d779fffe976c55db04bf523907a8743edRaphael * Licensed under the Apache License, Version 2.0 (the "License");
5d2d6999d779fffe976c55db04bf523907a8743edRaphael * you may not use this file except in compliance with the License.
6d2d6999d779fffe976c55db04bf523907a8743edRaphael * You may obtain a copy of the License at
7d2d6999d779fffe976c55db04bf523907a8743edRaphael *
8d2d6999d779fffe976c55db04bf523907a8743edRaphael *      http://www.apache.org/licenses/LICENSE-2.0
9d2d6999d779fffe976c55db04bf523907a8743edRaphael *
10d2d6999d779fffe976c55db04bf523907a8743edRaphael * Unless required by applicable law or agreed to in writing, software
11d2d6999d779fffe976c55db04bf523907a8743edRaphael * distributed under the License is distributed on an "AS IS" BASIS,
12d2d6999d779fffe976c55db04bf523907a8743edRaphael * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d2d6999d779fffe976c55db04bf523907a8743edRaphael * See the License for the specific language governing permissions and
14d2d6999d779fffe976c55db04bf523907a8743edRaphael * limitations under the License.
15d2d6999d779fffe976c55db04bf523907a8743edRaphael */
16d2d6999d779fffe976c55db04bf523907a8743edRaphael
17d2d6999d779fffe976c55db04bf523907a8743edRaphael/*
18d2d6999d779fffe976c55db04bf523907a8743edRaphael * "find_java.exe", for Windows only.
19d2d6999d779fffe976c55db04bf523907a8743edRaphael * Tries to find a Java binary in a variety of places and prints the
20d2d6999d779fffe976c55db04bf523907a8743edRaphael * first one found on STDOUT and returns 0.
21d2d6999d779fffe976c55db04bf523907a8743edRaphael *
22d2d6999d779fffe976c55db04bf523907a8743edRaphael * If not found, returns error 1 with no message
23d2d6999d779fffe976c55db04bf523907a8743edRaphael * (unless ANDROID_SDKMAN_DEBUG or -d if set, in which case there's a message on STDERR).
24d2d6999d779fffe976c55db04bf523907a8743edRaphael *
25d2d6999d779fffe976c55db04bf523907a8743edRaphael * Implementation details:
26d2d6999d779fffe976c55db04bf523907a8743edRaphael * - We don't have access to ATL or MFC.
27d2d6999d779fffe976c55db04bf523907a8743edRaphael * - We don't want to pull in things like STL.
28d2d6999d779fffe976c55db04bf523907a8743edRaphael * - No Unicode/MBCS support for now.
29d2d6999d779fffe976c55db04bf523907a8743edRaphael *
30d2d6999d779fffe976c55db04bf523907a8743edRaphael * TODO for later version:
31d2d6999d779fffe976c55db04bf523907a8743edRaphael * - provide an env variable to let users override which version is being used.
32d2d6999d779fffe976c55db04bf523907a8743edRaphael * - if there's more than one java.exe found, enumerate them all.
33d2d6999d779fffe976c55db04bf523907a8743edRaphael * - and in that case take the one with the highest Java version number.
34d2d6999d779fffe976c55db04bf523907a8743edRaphael * - since that operation is expensive, do it only once and cache the result
35d2d6999d779fffe976c55db04bf523907a8743edRaphael *   in a temp file. If the temp file is not found or the java binary no
36d2d6999d779fffe976c55db04bf523907a8743edRaphael *   longer exists, re-run the enumaration.
37d2d6999d779fffe976c55db04bf523907a8743edRaphael */
38d2d6999d779fffe976c55db04bf523907a8743edRaphael
39d2d6999d779fffe976c55db04bf523907a8743edRaphael#ifdef _WIN32
40d2d6999d779fffe976c55db04bf523907a8743edRaphael
41d2d6999d779fffe976c55db04bf523907a8743edRaphael#include "utils.h"
42d2d6999d779fffe976c55db04bf523907a8743edRaphael#include "find_java.h"
43d2d6999d779fffe976c55db04bf523907a8743edRaphael#include <io.h>
44d2d6999d779fffe976c55db04bf523907a8743edRaphael#include <fcntl.h>
45d2d6999d779fffe976c55db04bf523907a8743edRaphael
46d2d6999d779fffe976c55db04bf523907a8743edRaphaelstatic void testFindJava() {
47d2d6999d779fffe976c55db04bf523907a8743edRaphael
48d2d6999d779fffe976c55db04bf523907a8743edRaphael    CPath javaPath("<not found>");
496123b532fc0e57e33a09dc429f8ec708a88aedccRaphael    int v = findJavaInEnvPath(&javaPath);
506123b532fc0e57e33a09dc429f8ec708a88aedccRaphael    printf("findJavaInEnvPath: [%d] %s\n", v, javaPath.cstr());
51d2d6999d779fffe976c55db04bf523907a8743edRaphael
52d2d6999d779fffe976c55db04bf523907a8743edRaphael    javaPath.set("<not found>");
536123b532fc0e57e33a09dc429f8ec708a88aedccRaphael    v = findJavaInRegistry(&javaPath);
546123b532fc0e57e33a09dc429f8ec708a88aedccRaphael    printf("findJavaInRegistry [%d] %s\n", v, javaPath.cstr());
55d2d6999d779fffe976c55db04bf523907a8743edRaphael
56d2d6999d779fffe976c55db04bf523907a8743edRaphael    javaPath.set("<not found>");
576123b532fc0e57e33a09dc429f8ec708a88aedccRaphael    v = findJavaInProgramFiles(&javaPath);
586123b532fc0e57e33a09dc429f8ec708a88aedccRaphael    printf("findJavaInProgramFiles [%d] %s\n", v, javaPath.cstr());
59d2d6999d779fffe976c55db04bf523907a8743edRaphael}
60d2d6999d779fffe976c55db04bf523907a8743edRaphael
61d2d6999d779fffe976c55db04bf523907a8743edRaphael
62d2d6999d779fffe976c55db04bf523907a8743edRaphaelint main(int argc, char* argv[]) {
63d2d6999d779fffe976c55db04bf523907a8743edRaphael
64d2d6999d779fffe976c55db04bf523907a8743edRaphael    gIsConsole = true; // tell utils to to print errors to stderr
65d2d6999d779fffe976c55db04bf523907a8743edRaphael    gIsDebug = (getenv("ANDROID_SDKMAN_DEBUG") != NULL);
66d2d6999d779fffe976c55db04bf523907a8743edRaphael    bool doShortPath = false;
67d2d6999d779fffe976c55db04bf523907a8743edRaphael    bool doVersion = false;
68a418de56908e413187e1144b7d1d430bbfc459d5Raphael    bool doJavaW = false;
69d2d6999d779fffe976c55db04bf523907a8743edRaphael
70d2d6999d779fffe976c55db04bf523907a8743edRaphael    for (int i = 1; i < argc; i++) {
71d2d6999d779fffe976c55db04bf523907a8743edRaphael        if (strncmp(argv[i], "-t", 2) == 0) {
72d2d6999d779fffe976c55db04bf523907a8743edRaphael            testFindJava();
73d2d6999d779fffe976c55db04bf523907a8743edRaphael            return 0;
74d2d6999d779fffe976c55db04bf523907a8743edRaphael
75d2d6999d779fffe976c55db04bf523907a8743edRaphael        } else if (strncmp(argv[i], "-d", 2) == 0) {
76d2d6999d779fffe976c55db04bf523907a8743edRaphael            gIsDebug = true;
77d2d6999d779fffe976c55db04bf523907a8743edRaphael
78d2d6999d779fffe976c55db04bf523907a8743edRaphael        } else if (strncmp(argv[i], "-s", 2) == 0) {
79d2d6999d779fffe976c55db04bf523907a8743edRaphael            doShortPath = true;
80d2d6999d779fffe976c55db04bf523907a8743edRaphael
81d2d6999d779fffe976c55db04bf523907a8743edRaphael        } else if (strncmp(argv[i], "-v", 2) == 0) {
82d2d6999d779fffe976c55db04bf523907a8743edRaphael            doVersion = true;
83d2d6999d779fffe976c55db04bf523907a8743edRaphael
84a418de56908e413187e1144b7d1d430bbfc459d5Raphael        } else if (strcmp(argv[i], "-w") == 0 || strcmp(argv[i], "-javaw") == 0) {
85a418de56908e413187e1144b7d1d430bbfc459d5Raphael            doJavaW = true;
86a418de56908e413187e1144b7d1d430bbfc459d5Raphael
87d2d6999d779fffe976c55db04bf523907a8743edRaphael        } else {
88d2d6999d779fffe976c55db04bf523907a8743edRaphael            printf(
89d2d6999d779fffe976c55db04bf523907a8743edRaphael                "Outputs the path of the first Java.exe found on the local system.\n"
90d2d6999d779fffe976c55db04bf523907a8743edRaphael                "Returns code 0 when found, 1 when not found.\n"
91d2d6999d779fffe976c55db04bf523907a8743edRaphael                "Options:\n"
92d2d6999d779fffe976c55db04bf523907a8743edRaphael                "-h / -help   : This help.\n"
93d2d6999d779fffe976c55db04bf523907a8743edRaphael                "-t / -test   : Internal test.\n"
94d2d6999d779fffe976c55db04bf523907a8743edRaphael                "-s / -short  : Print path in short DOS form.\n"
95a418de56908e413187e1144b7d1d430bbfc459d5Raphael                "-w / -javaw  : Search a matching javaw.exe; defaults to java.exe if not found.\n"
96d2d6999d779fffe976c55db04bf523907a8743edRaphael                "-v / -version: Only prints the Java version found.\n"
97d2d6999d779fffe976c55db04bf523907a8743edRaphael                );
98d2d6999d779fffe976c55db04bf523907a8743edRaphael            return 2;
99d2d6999d779fffe976c55db04bf523907a8743edRaphael        }
100d2d6999d779fffe976c55db04bf523907a8743edRaphael    }
101d2d6999d779fffe976c55db04bf523907a8743edRaphael
1026123b532fc0e57e33a09dc429f8ec708a88aedccRaphael    // Find the first suitable version of Java we can use.
103d2d6999d779fffe976c55db04bf523907a8743edRaphael    CPath javaPath;
1046123b532fc0e57e33a09dc429f8ec708a88aedccRaphael    int version = findJavaInEnvPath(&javaPath);
1056123b532fc0e57e33a09dc429f8ec708a88aedccRaphael    if (version < MIN_JAVA_VERSION) {
1066123b532fc0e57e33a09dc429f8ec708a88aedccRaphael        version = findJavaInRegistry(&javaPath);
1076123b532fc0e57e33a09dc429f8ec708a88aedccRaphael    }
1086123b532fc0e57e33a09dc429f8ec708a88aedccRaphael    if (version < MIN_JAVA_VERSION) {
1096123b532fc0e57e33a09dc429f8ec708a88aedccRaphael        version = findJavaInProgramFiles(&javaPath);
1106123b532fc0e57e33a09dc429f8ec708a88aedccRaphael    }
1116123b532fc0e57e33a09dc429f8ec708a88aedccRaphael    if (version < MIN_JAVA_VERSION || javaPath.isEmpty()) {
1126123b532fc0e57e33a09dc429f8ec708a88aedccRaphael        if (gIsDebug) {
1136123b532fc0e57e33a09dc429f8ec708a88aedccRaphael            fprintf(stderr, "Failed to find Java on your system.\n");
1146123b532fc0e57e33a09dc429f8ec708a88aedccRaphael        }
1156123b532fc0e57e33a09dc429f8ec708a88aedccRaphael        return 1;
116d2d6999d779fffe976c55db04bf523907a8743edRaphael    }
117d2d6999d779fffe976c55db04bf523907a8743edRaphael    _ASSERT(!javaPath.isEmpty());
118d2d6999d779fffe976c55db04bf523907a8743edRaphael
119d2d6999d779fffe976c55db04bf523907a8743edRaphael    if (doShortPath) {
12026a423a5de4b715a980a0c0f0a16ec50bf39aef2Raphael Moll        PVOID oldWow64Value = disableWow64FsRedirection();
121d2d6999d779fffe976c55db04bf523907a8743edRaphael        if (!javaPath.toShortPath(&javaPath)) {
12226a423a5de4b715a980a0c0f0a16ec50bf39aef2Raphael Moll            revertWow64FsRedirection(&oldWow64Value);
123d2d6999d779fffe976c55db04bf523907a8743edRaphael            fprintf(stderr,
124d2d6999d779fffe976c55db04bf523907a8743edRaphael                "Failed to convert path to a short DOS path: %s\n",
125d2d6999d779fffe976c55db04bf523907a8743edRaphael                javaPath.cstr());
126d2d6999d779fffe976c55db04bf523907a8743edRaphael            return 1;
127d2d6999d779fffe976c55db04bf523907a8743edRaphael        }
12826a423a5de4b715a980a0c0f0a16ec50bf39aef2Raphael Moll        revertWow64FsRedirection(&oldWow64Value);
129d2d6999d779fffe976c55db04bf523907a8743edRaphael    }
130d2d6999d779fffe976c55db04bf523907a8743edRaphael
131d2d6999d779fffe976c55db04bf523907a8743edRaphael    if (doVersion) {
1326123b532fc0e57e33a09dc429f8ec708a88aedccRaphael        // Print version found. We already have the version as an integer
1336123b532fc0e57e33a09dc429f8ec708a88aedccRaphael        // so we don't need to run java -version a second time.
1346123b532fc0e57e33a09dc429f8ec708a88aedccRaphael        printf("%d.%d", version / 1000, version % 1000);
1356123b532fc0e57e33a09dc429f8ec708a88aedccRaphael        return 0;
136d2d6999d779fffe976c55db04bf523907a8743edRaphael    }
137d2d6999d779fffe976c55db04bf523907a8743edRaphael
138a418de56908e413187e1144b7d1d430bbfc459d5Raphael    if (doJavaW) {
139a418de56908e413187e1144b7d1d430bbfc459d5Raphael        // Try to find a javaw.exe instead of java.exe at the same location.
140a418de56908e413187e1144b7d1d430bbfc459d5Raphael        CPath javawPath(javaPath);
141a418de56908e413187e1144b7d1d430bbfc459d5Raphael        javawPath.replaceName("java.exe", "javaw.exe");
142a418de56908e413187e1144b7d1d430bbfc459d5Raphael        // Only accept it if we can actually find the exec
143a418de56908e413187e1144b7d1d430bbfc459d5Raphael        PVOID oldWow64Value = disableWow64FsRedirection();
144a418de56908e413187e1144b7d1d430bbfc459d5Raphael        if (javawPath.fileExists()) {
145a418de56908e413187e1144b7d1d430bbfc459d5Raphael            javaPath.set(javawPath.cstr());
146a418de56908e413187e1144b7d1d430bbfc459d5Raphael        }
147a418de56908e413187e1144b7d1d430bbfc459d5Raphael        revertWow64FsRedirection(&oldWow64Value);
148a418de56908e413187e1144b7d1d430bbfc459d5Raphael    }
149a418de56908e413187e1144b7d1d430bbfc459d5Raphael
150d2d6999d779fffe976c55db04bf523907a8743edRaphael    // Print java.exe path found
151d2d6999d779fffe976c55db04bf523907a8743edRaphael    printf("%s", javaPath.cstr());
152d2d6999d779fffe976c55db04bf523907a8743edRaphael    return 0;
153d2d6999d779fffe976c55db04bf523907a8743edRaphael}
154d2d6999d779fffe976c55db04bf523907a8743edRaphael
155d2d6999d779fffe976c55db04bf523907a8743edRaphael#endif /* _WIN32 */
156