1 /*
2 * Copyright (C) 2014 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 #include "stdafx.h"
18 #include "FindJava2.h"
19 #include "utils.h"
20 #include "JavaFinder.h"
21 #include "FindJava2Dlg.h"
22
23 #ifdef _DEBUG
24 #define new DEBUG_NEW
25 #endif
26
27 // The one and only MFC application object
28 class CFindJava2App : public CWinApp {
29 public:
CFindJava2App()30 CFindJava2App() {
31 }
32
33 // Set CWinApp default registry key. Must be consistent with all apps using findjava2.
initRegistryKey()34 void initRegistryKey() {
35 SetRegistryKey(_T("Android-FindJava2"));
36 }
37 };
38
39 CFindJava2App theApp;
40
41 using namespace std;
42
_tmain(int argc,TCHAR * argv[],TCHAR * envp[])43 int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) {
44
45 // Init utils; use default app name based on VERSIONINFO.FileDescription
46 initUtils(NULL);
47
48 // initialize MFC and print and error on failure
49 HMODULE hModule = ::GetModuleHandle(NULL);
50 if (hModule == NULL) {
51 displayLastError(_T("Fatal Error: "));
52 return -2;
53 }
54 if (!AfxWinInit(hModule, NULL, ::GetCommandLine(), 0)) {
55 displayLastError(_T("Fatal Error: "));
56 return -3;
57 }
58
59 theApp.initRegistryKey();
60
61 gIsConsole = true; // tell utils to to print errors to stderr
62 gIsDebug = (getenv("ANDROID_SDKMAN_DEBUG") != NULL);
63
64 // Parse command line
65 bool doTests = false;
66 bool doShortPath = false;
67 bool doVersion = false;
68 bool doJavaW = false;
69 bool doForceUi = false;
70 bool doJava1_7 = false;
71
72 for (int i = 1; i < argc; i++) {
73 if (_tcsnccmp(argv[i], _T("-t"), 2) == 0) {
74 doTests = true;
75
76 } else if (_tcsnccmp(argv[i], _T("-d"), 2) == 0) {
77 gIsDebug = true;
78
79 } else if (_tcsnccmp(argv[i], _T("-s"), 2) == 0) {
80 doShortPath = true;
81
82 } else if (_tcsnccmp(argv[i], _T("-v"), 2) == 0) {
83 doVersion = true;
84
85 } else if (_tcsnccmp(argv[i], _T("-f"), 2) == 0) {
86 doForceUi = true;
87
88 } else if (_tcsnccmp(argv[i], _T("-7"), 2) == 0) {
89 doJava1_7 = true;
90
91 } else if (_tcscmp(argv[i], _T("-w")) == 0 || _tcscmp(argv[i], _T("-javaw")) == 0) {
92 doJavaW = true;
93
94 } else {
95 printf(
96 "Outputs the path of the first Java.exe found on the local system.\n"
97 "Returns code 0 when found, 1 when not found.\n"
98 "Options:\n"
99 "-h / -help : This help.\n"
100 "-t / -test : Internal test.\n"
101 "-f / -force : Force UI selection.\n"
102 "-7 : Java 1.7 minimum instead of 1.6.\n"
103 "-s / -short : Print path in short DOS form.\n"
104 "-w / -javaw : Search a matching javaw.exe; defaults to java.exe if not found.\n"
105 "-v / -version: Only prints the Java version found.\n"
106 );
107 return 2;
108 }
109 }
110
111
112 CJavaFinder javaFinder(JAVA_VERS_TO_INT(1, doJava1_7 ? 7 : 6));
113 CJavaPath javaPath = javaFinder.getRegistryPath();
114
115 if (doTests) {
116 std::set<CJavaPath> paths;
117 javaFinder.findJavaPaths(&paths);
118 bool regPrinted = false;
119 for (const CJavaPath &p : paths) {
120 bool isReg = (p == javaPath);
121 if (isReg) {
122 regPrinted = true;
123 }
124 _tprintf(_T("%c [%s] %s\n"), isReg ? '*' : ' ', p.getVersion(), p.mPath);
125 }
126
127 if (!regPrinted && !javaPath.isEmpty()) {
128 const CJavaPath &p = javaPath;
129 _tprintf(_T("* [%s] %s\n"), p.getVersion(), p.mPath);
130 }
131 return 0;
132 }
133
134 if (doForceUi || javaPath.isEmpty()) {
135 CFindJava2Dlg dlg;
136 dlg.setJavaFinder(&javaFinder);
137 INT_PTR nResponse = dlg.DoModal();
138
139 if (nResponse == IDOK) {
140 // Get java path selected by user and save into registry for later re-use
141 javaPath = dlg.getSelectedPath();
142 javaFinder.setRegistryPath(javaPath);
143 } else if (nResponse == -1) { // MFC boilerplate
144 TRACE(traceAppMsg, 0, "Warning: dialog creation failed, so application is terminating unexpectedly.\n");
145 return 1;
146 }
147 }
148
149 if (javaPath.isEmpty()) {
150 fprintf(stderr, "No java.exe path found");
151 return 1;
152 }
153
154 if (doShortPath) {
155 PVOID oldWow64Value = disableWow64FsRedirection();
156 if (!javaPath.toShortPath()) {
157 revertWow64FsRedirection(&oldWow64Value);
158 _ftprintf(stderr,
159 _T("Failed to convert path to a short DOS path: %s\n"),
160 javaPath.mPath);
161 return 1;
162 }
163 revertWow64FsRedirection(&oldWow64Value);
164 }
165
166 if (doVersion) {
167 // Print version found. We already have the version as an integer
168 // so we don't need to run java -version a second time.
169 _tprintf(_T("%s"), javaPath.getVersion());
170 return 0;
171 }
172
173 if (doJavaW) {
174 // Try to find a javaw.exe instead of java.exe at the same location.
175 CPath javawPath = javaPath.mPath;
176 javawPath.RemoveFileSpec();
177 javawPath.Append(_T("javaw.exe"));
178 javawPath.Canonicalize();
179
180 // Only accept it if we can actually find the exec
181 PVOID oldWow64Value = disableWow64FsRedirection();
182 bool exists = javawPath.FileExists() == TRUE; // skip BOOL-to-bool warning
183 revertWow64FsRedirection(&oldWow64Value);
184
185 if (!exists) {
186 _ftprintf(stderr,
187 _T("Failed to find javaw at: %s\n"),
188 javawPath);
189 return 1;
190 }
191
192 javaPath.mPath = javawPath;
193 }
194
195 // Print java.exe path found
196 _tprintf(_T("%s"), javaPath.mPath);
197 return 0;
198
199 }
200