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