1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 /* 18 * "find_java.exe", for Windows only. 19 * Tries to find a Java binary in a variety of places and prints the 20 * first one found on STDOUT and returns 0. 21 * 22 * If not found, returns error 1 with no message 23 * (unless ANDROID_SDKMAN_DEBUG or -d if set, in which case there's a message on STDERR). 24 * 25 * Implementation details: 26 * - We don't have access to ATL or MFC. 27 * - We don't want to pull in things like STL. 28 * - No Unicode/MBCS support for now. 29 * 30 * TODO for later version: 31 * - provide an env variable to let users override which version is being used. 32 * - if there's more than one java.exe found, enumerate them all. 33 * - and in that case take the one with the highest Java version number. 34 * - since that operation is expensive, do it only once and cache the result 35 * in a temp file. If the temp file is not found or the java binary no 36 * longer exists, re-run the enumaration. 37 */ 38 39 #ifdef _WIN32 40 41 #include "utils.h" 42 #include "find_java.h" 43 #include <io.h> 44 #include <fcntl.h> 45 46 static int showHelpMessage() { 47 printf( 48 "Outputs the path of the first Java.exe found on the local system.\n" 49 "Returns code 0 when found, 1 when not found.\n" 50 "Options:\n" 51 "-h / -help : This help.\n" 52 "-t / -test : Internal test.\n" 53 "-e / -error : Print an error message to the console if Java.exe isn't found.\n" 54 "-j / -jdk : Only returns java.exe found in a JDK.\n" 55 "-s / -short : Print path in short DOS form.\n" 56 "-p / -path `dir` : A custom path to search first. Pass in JDK base dir if -j is set.\n" 57 "-w / -javaw : Search a matching javaw.exe; defaults to java.exe if not found.\n" 58 "-m / -minv # : Pass in a minimum version to use (default: 1.6).\n" 59 "-v / -version: Only prints the Java version found.\n" 60 ); 61 return 2; 62 } 63 64 static void printError(const char *message) { 65 66 CString error; 67 error.setLastWin32Error(message); 68 printf(error.cstr()); 69 } 70 71 static void testFindJava(bool isJdk, int minVersion) { 72 73 CPath javaPath("<not found>"); 74 int v = findJavaInEnvPath(&javaPath, isJdk, minVersion); 75 printf(" findJavaInEnvPath: [%d] %s\n", v, javaPath.cstr()); 76 77 javaPath.set("<not found>"); 78 v = findJavaInRegistry(&javaPath, isJdk, minVersion); 79 printf(" findJavaInRegistry [%d] %s\n", v, javaPath.cstr()); 80 81 javaPath.set("<not found>"); 82 v = findJavaInProgramFiles(&javaPath, isJdk, minVersion); 83 printf(" findJavaInProgramFiles [%d] %s\n", v, javaPath.cstr()); 84 } 85 86 static void testFindJava(int minVersion) { 87 88 printf("Searching for version %d.%d or newer...\n", JAVA_MAJOR(minVersion), 89 JAVA_MINOR(minVersion)); 90 91 printf("\n"); 92 printf("Searching for any java.exe:\n"); 93 testFindJava(false, minVersion); 94 95 printf("\n"); 96 printf("Searching for java.exe within a JDK:\n"); 97 testFindJava(true, minVersion); 98 } 99 100 // Returns 0 on failure or a java version on success. 101 int parseMinVersionArg(char* arg) { 102 103 int versionMajor = -1; 104 int versionMinor = -1; 105 if (sscanf(arg, "%d.%d", &versionMajor, &versionMinor) != 2) { 106 // -m arg is malformatted 107 return 0; 108 } 109 return TO_JAVA_VERSION(versionMajor, versionMinor); 110 } 111 112 int main(int argc, char* argv[]) { 113 114 gIsConsole = true; // tell utils to to print errors to stderr 115 gIsDebug = (getenv("ANDROID_SDKMAN_DEBUG") != NULL); 116 bool doShortPath = false; 117 bool doVersion = false; 118 bool doJavaW = false; 119 bool isJdk = false; 120 bool shouldPrintError = false; 121 int minVersion = MIN_JAVA_VERSION; 122 const char *customPathStr = NULL; 123 124 for (int i = 1; i < argc; i++) { 125 if (strncmp(argv[i], "-t", 2) == 0) { 126 testFindJava(minVersion); 127 return 0; 128 129 } else if (strncmp(argv[i], "-j", 2) == 0) { 130 isJdk = true; 131 132 } else if (strncmp(argv[i], "-e", 2) == 0) { 133 shouldPrintError = true; 134 135 } else if (strncmp(argv[i], "-p", 2) == 0) { 136 i++; 137 if (i == argc) { 138 return showHelpMessage(); 139 } 140 customPathStr = argv[i]; 141 } else if (strncmp(argv[i], "-d", 2) == 0) { 142 gIsDebug = true; 143 144 } else if (strncmp(argv[i], "-s", 2) == 0) { 145 doShortPath = true; 146 147 } else if (strncmp(argv[i], "-v", 2) == 0) { 148 doVersion = true; 149 150 } else if (strncmp(argv[i], "-m", 2) == 0) { 151 i++; 152 if (i == argc || 153 ((minVersion = parseMinVersionArg(argv[i])) == 0)) { 154 return showHelpMessage(); 155 } 156 } 157 else if (strcmp(argv[i], "-w") == 0 || strcmp(argv[i], "-javaw") == 0) { 158 doJavaW = true; 159 160 } 161 else { 162 return showHelpMessage(); 163 } 164 } 165 166 // Find the first suitable version of Java we can use. 167 CPath javaPath; 168 169 int version = 0; 170 if (customPathStr != NULL) { 171 CPath customPath(customPathStr); 172 version = findJavaInPath(customPath, &javaPath, isJdk, minVersion); 173 } 174 if (version == 0) { 175 version = findJavaInEnvPath(&javaPath, isJdk, minVersion); 176 } 177 if (version == 0) { 178 version = findJavaInRegistry(&javaPath, isJdk, minVersion); 179 } 180 if (version == 0) { 181 version = findJavaInProgramFiles(&javaPath, isJdk, minVersion); 182 } 183 184 if (version == 0) { 185 CString s; 186 s.setf("Failed to find Java %d.%d (or newer) on your system. ", JAVA_MAJOR(minVersion), 187 JAVA_MINOR(minVersion)); 188 189 if (gIsDebug) { 190 fprintf(stderr, s.cstr()); 191 } 192 193 if (shouldPrintError) { 194 printError(s.cstr()); 195 } 196 197 return 1; 198 } 199 _ASSERT(!javaPath.isEmpty()); 200 201 if (doShortPath) { 202 if (!javaPath.toShortPath(&javaPath)) { 203 CString s; 204 s.setf("Failed to convert path (%s) to a short DOS path. ", javaPath.cstr()); 205 fprintf(stderr, s.cstr()); 206 207 if (shouldPrintError) { 208 printError(s.cstr()); 209 } 210 211 return 1; 212 } 213 } 214 215 if (doVersion) { 216 // Print version found. We already have the version as an integer 217 // so we don't need to run java -version a second time. 218 printf("%d.%d", JAVA_MAJOR(version), JAVA_MINOR(version)); 219 return 0; 220 } 221 222 if (doJavaW) { 223 // Try to find a javaw.exe instead of java.exe at the same location. 224 CPath javawPath(javaPath); 225 javawPath.replaceName("java.exe", "javaw.exe"); 226 // Only accept it if we can actually find the exec 227 if (javawPath.fileExists()) { 228 javaPath.set(javawPath.cstr()); 229 } 230 } 231 232 // Print java.exe path found 233 printf(javaPath.cstr()); 234 return 0; 235 } 236 237 #endif /* _WIN32 */ 238