source: other-projects/trunk/search4j/libsearch4j.cpp@ 18237

Last change on this file since 18237 was 18237, checked in by oranfry, 14 years ago

added new options to search4j to only return a jre or only return a jre, and an option to display the type of the found jvm (whether jre or jdk)

File size: 11.1 KB
Line 
1/*
2* Library of functions for the Search4j utility
3*/
4
5#include "libsearch4j.h"
6
7
8#ifdef WINDOWS
9//minimal launch4j stuff
10#define NO_JAVA_FOUND 0
11#define FOUND_JRE 1
12#define FOUND_SDK 2
13
14//windows functions
15#define popen _popen
16#define pclose _pclose
17#define strcmp _stricmp
18
19#endif /* WINDOWS */
20
21void replace_all ( std::string & str, std::string const & pattern, std::string const & replacement ) {
22
23 std::string::size_type start = str.find( pattern, 0 );
24
25 while ( start != str.npos ) {
26 str.replace( start, pattern.size(), replacement );
27 start = str.find( pattern, start+replacement.size() );
28 }
29
30}
31
32
33int process( string command, bool render ) {
34
35 #ifdef WINDOWS
36
37 STARTUPINFO si;
38 PROCESS_INFORMATION pi;
39 memset(&pi, 0, sizeof(pi));
40 memset(&si, 0, sizeof(si));
41 si.cb = sizeof(si);
42
43 DWORD dwExitCode = -1;
44 char* cmd = (char*)command.c_str();
45
46 bool result;
47 if ( render ) {
48 result = CreateProcess(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);
49 } else {
50 result = CreateProcess(NULL, cmd, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi);
51 }
52
53 if ( result ) {
54 WaitForSingleObject(pi.hProcess, INFINITE);
55 GetExitCodeProcess(pi.hProcess, &dwExitCode);
56 CloseHandle(pi.hThread);
57 CloseHandle(pi.hProcess);
58 }
59 return dwExitCode;
60
61 #else
62
63 return system( command.c_str() );
64
65 #endif
66}
67
68
69
70int process_and_catch_output( string command, string &output ) {
71
72 #ifdef WINDOWS
73
74 char cmd[1024] = "cmd.exe /c ";
75 strcat(cmd, command.c_str());
76 strcat(cmd, " > cmd_output.txt 2>&1");
77 //cerr << "command: " << cmd << endl;
78 int code = process( cmd, false );
79 if ( code!= 0 )
80 return code;
81
82 string line;
83 ifstream myfile("cmd_output.txt");
84 if ( !myfile.is_open() ) {
85 return -1;
86 }
87
88 while ( !myfile.eof() ) {
89 getline(myfile,line);
90 output.append( line );
91 }
92
93 myfile.close();
94
95 _unlink( "cmd_output.txt" );
96
97 return code;
98
99 #else
100
101 FILE *pPipe;
102
103 char cmd[1024];
104 strcpy(cmd, command.c_str());
105 strcat(cmd, " 2>&1" );
106
107 //if ( verbose ) cout << "process(): running '" << command << "'" << endl;
108 if( (pPipe = popen( cmd, "r" )) == NULL ) {
109 //if ( verbose ) cout << "could not start process" << endl;
110 pclose( pPipe );
111 return -1;
112 }
113
114 //if ( verbose ) cout << "started process" << endl;
115
116 /* Read pipe until end of file. */
117 while( !feof( pPipe ) ) {
118 char psBuffer[128];
119 //if ( verbose ) cout << "get some data" << endl;
120 if( fgets( psBuffer, 128, pPipe ) != NULL ) {
121
122 //if ( verbose ) cout << "got: " << psBuffer << endl;
123 output.append( psBuffer );
124
125 } else {
126 //if ( verbose ) cout << "none left" << endl;
127 }
128
129 }
130
131 /* Close pipe and return return value of pPipe. */
132 int code = pclose( pPipe );
133 return code;
134
135 #endif
136
137}
138
139//Jvm class methods
140
141Jvm::Jvm() {
142 healthy = false;
143}
144
145void Jvm::setJavaHome( string jh ) {
146 healthy = true;
147 javaHome = jh;
148 setVersionFromExeOuput();
149 setIsJdkFromJavacPresence();
150}
151
152string Jvm::getJavaHome() {
153 return javaHome;
154}
155
156string Jvm::getExecutable() {
157 string exec = "";
158 exec.append( javaHome );
159
160 #ifdef WINDOWS
161 exec.append( "\\bin\\java.exe" );
162 #endif
163
164 #ifndef WINDOWS
165 exec.append( "/bin/java" );
166 #endif
167
168 return exec;
169}
170
171#ifdef WINDOWS
172string Jvm::getWinExecutable() {
173 string exec = "";
174 exec.append( javaHome );
175 exec.append( "\\bin\\javaw.exe" );
176 return exec;
177}
178#endif
179
180
181string Jvm::getVersion() {
182 stringstream ss;
183 ss << era << "." << major << "." << minor << "_" << update;
184 return ss.str();
185}
186
187bool Jvm::check() {
188 return healthy;
189}
190
191bool Jvm::setVersionFromString( string version ) {
192 era = atoi( version.substr(0,1).c_str() );
193 major = atoi( version.substr(2,1).c_str() );
194 minor = atoi( version.substr(4,1).c_str() );
195 update = atoi( version.substr(6,2).c_str() );
196 return true;
197}
198
199int Jvm::compare( Jvm otherJvm ) {
200 //era
201 if ( era > otherJvm.getEra() )
202 return 1;
203 else if ( era < otherJvm.getEra() )
204 return -1;
205
206 //major
207 if ( major > otherJvm.getMajor() )
208 return 1;
209 else if ( major < otherJvm.getMajor() )
210 return -1;
211
212 //minor
213 if ( minor > otherJvm.getMinor() )
214 return 1;
215 else if ( minor < otherJvm.getMinor() )
216 return -1;
217
218 //update
219 if ( update > otherJvm.getUpdate() )
220 return 1;
221 else if ( update < otherJvm.getUpdate() )
222 return -1;
223
224 //all the same so far, must be exactly the same
225 return 0;
226
227}
228
229int Jvm::getEra() { return era; }
230int Jvm::getMajor() { return major; }
231int Jvm::getMinor() { return minor; }
232int Jvm::getUpdate() { return update; }
233
234bool Jvm::getIsJdk() { return isJdk; }
235bool Jvm::getIsJre() { return !isJdk; }
236
237void Jvm::setVersionFromExeOuput() {
238 string command = "", output = "";
239 command.append( "\"" );
240 command.append( getExecutable() );
241 command.append( "\"" );
242 command.append(" -version");
243
244 //cerr << "command: " << command << endl;
245 int result = process_and_catch_output( command, output );
246 //cerr << "output: " << output << endl;
247
248 if ( result == 0 ) {
249 if ( strcmp( output.substr( 0, 12 ).c_str() , "java version" ) == 0 || true ) {
250 era = atoi( output.substr(14,1).c_str() );
251 major = atoi( output.substr(16,1).c_str() );
252 minor = atoi( output.substr(18,1).c_str() );
253 update = atoi( output.substr(20,2).c_str() );
254 } else {
255 healthy=false;
256 }
257 } else {
258 healthy = false;
259 }
260}
261void Jvm::setIsJdkFromJavacPresence() {
262 string javacFile = "";
263 javacFile.append( javaHome );
264
265 #ifdef WINDOWS
266 javacFile.append( "\\bin\\javac.exe" );
267 #endif
268 #ifndef WINDOWS
269 javacFile.append( "/bin/javac" );
270 #endif
271 struct stat stFileInfo;
272 isJdk = ( stat(javacFile.c_str(),&stFileInfo) == 0 );
273}
274
275//end of Jvm class methods
276
277
278#ifdef WINDOWS
279int regSearch(HKEY hKey, const char* keyName, int searchType, char* foundJavaVer ) {
280 DWORD x = 0;
281 unsigned long size = 1024;
282 FILETIME time;
283 char buffer[1024] = {0};
284
285 int foundJava = NO_JAVA_FOUND;
286
287 while (RegEnumKeyEx(
288 hKey, // handle to key to enumerate
289 x++, // index of subkey to enumerate
290 buffer, // address of buffer for subkey name
291 &size, // address for size of subkey buffer
292 NULL, // reserved
293 NULL, // address of buffer for class string
294 NULL, // address for size of class buffer
295 &time) == ERROR_SUCCESS) {
296 strcpy(foundJavaVer, buffer);
297 foundJava = searchType;
298 size = 1024;
299 }
300
301 return foundJava;
302
303}
304#endif
305
306/*
307* function to find java
308* implements the logic drawn on the dl lab whiteboard in feb 08
309* return a Jvm object which represents the jvm on disk
310*/
311bool find( Jvm &jvm, bool use_minimum, Jvm minimum, bool jreOnly, bool jdkOnly, string phint, string hint, bool verbose ) {
312
313 if ( verbose ) cout << "Searching for a JVM" << endl;
314
315 char *javaHome = "";
316 bool jvmFound = false;
317
318 if ( !jvmFound ) {
319
320 //try the priority hint
321 if ( verbose ) cout << " - trying priority hint: ";
322 if ( strcmp(phint.c_str(),"") != 0 ) {
323 if ( verbose ) cout << "(" << phint << ") ";
324 jvm.setJavaHome( phint );
325 if ( jvm.check() ) {
326 if ( use_minimum ) {
327 if ( jvm.compare( minimum ) >= 0 ) {
328 jvmFound = true;
329 }
330 } else {
331 jvmFound = true;
332 }
333 }
334 if ( (jreOnly && !jvm.getIsJre() ) || (jdkOnly && !jvm.getIsJdk()) ) {
335 jvmFound = false;
336 }
337
338 }
339 if ( verbose ) { if( jvmFound ) cout << "yes" << endl; else cout << "no" << endl; }
340 }
341
342 if ( !jvmFound ) {
343
344 //try JAVA_HOME
345 if ( verbose ) cout << " - trying JAVA_HOME: ";
346 javaHome = getenv( "JAVA_HOME" );
347 if ( javaHome != NULL ) {
348 if ( verbose ) cout << "(" << javaHome << ") ";
349 jvm.setJavaHome( javaHome );
350 if ( jvm.check() ) {
351 if ( use_minimum ) {
352 if ( jvm.compare( minimum ) >= 0 ) {
353 jvmFound = true;
354 }
355 } else {
356 jvmFound = true;
357 }
358 }
359 if ( (jreOnly && !jvm.getIsJre() ) || (jdkOnly && !jvm.getIsJdk()) ) {
360 jvmFound = false;
361 }
362
363 }
364 if ( verbose ) { if( jvmFound ) cout << "yes" << endl; else cout << "no" << endl; }
365 }
366
367 if ( !jvmFound ) {
368
369 //try JRE_HOME
370 if ( verbose ) cout << " - trying JRE_HOME: ";
371 javaHome = getenv( "JRE_HOME" );
372 if ( javaHome != NULL ) {
373 if ( verbose ) cout << "(" << javaHome << ") ";
374 jvm.setJavaHome( javaHome );
375 if ( jvm.check() ) {
376 if ( use_minimum ) {
377 if ( jvm.compare( minimum ) >= 0 ) {
378 jvmFound = true;
379 }
380 } else {
381 jvmFound = true;
382 }
383 }
384 if ( (jreOnly && !jvm.getIsJre() ) || (jdkOnly && !jvm.getIsJdk()) ) {
385 jvmFound = false;
386 }
387
388 }
389 if ( verbose ) { if( jvmFound ) cout << "yes" << endl; else cout << "no" << endl; }
390 }
391
392 #ifdef WINDOWS
393 if ( !jvmFound ) {
394
395 //try the registry - this code based on launch4j code
396 char foundJavaVer[8192] = {0};
397 int foundJava = NO_JAVA_FOUND;
398
399 if ( verbose ) cout << " - trying the registry: "; cout.flush();
400 HKEY hKey;
401 const char jre[] = "SOFTWARE\\JavaSoft\\Java Runtime Environment";
402 const char sdk[] = "SOFTWARE\\JavaSoft\\Java Development Kit";
403
404 if ( RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT(jre), 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &hKey) == ERROR_SUCCESS ) {
405 foundJava = regSearch(hKey, jre, FOUND_JRE, foundJavaVer);
406 RegCloseKey(hKey);
407 }
408
409 if ( RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT(sdk), 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &hKey) == ERROR_SUCCESS ) {
410 foundJava = regSearch(hKey, sdk, FOUND_SDK, foundJavaVer);
411 RegCloseKey(hKey);
412 }
413
414 if ( foundJava != NO_JAVA_FOUND ) {
415 char path[1024] = {0};
416 char keyBuffer[1024];
417 unsigned long datatype;
418 unsigned long bufferlength = 1024;
419 if (foundJava == FOUND_JRE) {
420 strcpy(keyBuffer, jre);
421 } else {
422 strcpy(keyBuffer, sdk);
423 }
424
425 strcat(keyBuffer, "\\");
426 strcat(keyBuffer, foundJavaVer);
427
428 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT(keyBuffer), 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) {
429 unsigned char buffer[1024] = {0};
430 if (RegQueryValueEx(hKey, "JavaHome", NULL, &datatype, buffer, &bufferlength) == ERROR_SUCCESS) {
431 int i = 0;
432 do {
433 path[i] = buffer[i];
434 } while (path[i++] != 0);
435 if (foundJava == FOUND_SDK) {
436 strcat(path, "\\jre");
437 }
438 if ( verbose ) cerr << "path: " << path << endl ;
439 jvm.setJavaHome( path );
440 if ( jvm.check() ) {
441 if ( use_minimum ) {
442 if ( jvm.compare( minimum ) >= 0 ) {
443 jvmFound = true;
444 }
445 } else {
446 jvmFound = true;
447 }
448 }
449 if ( (jreOnly && !jvm.getIsJre() ) || (jdkOnly && !jvm.getIsJdk()) ) {
450 jvmFound = false;
451 }
452 }
453 RegCloseKey(hKey);
454 }
455 }
456 if ( verbose ) { if( jvmFound ) cout << "yes" << endl; else cout << "no" << endl; }
457 }
458 #endif
459
460 if ( !jvmFound ) {
461
462 //try the hint
463 if ( verbose ) cout << " - trying hint: ";
464 if ( strcmp(hint.c_str(),"") != 0 ) {
465 if ( verbose ) cout << "(" << hint << ") ";
466 jvm.setJavaHome( hint );
467 if ( jvm.check() ) {
468 if ( use_minimum ) {
469 if ( jvm.compare( minimum ) >= 0 ) {
470 jvmFound = true;
471 }
472 } else {
473 jvmFound = true;
474 }
475 }
476 if ( (jreOnly && !jvm.getIsJre() ) || (jdkOnly && !jvm.getIsJdk()) ) {
477 jvmFound = false;
478 }
479
480 }
481 if ( verbose ) { if( jvmFound ) cout << "yes" << endl; else cout << "no" << endl; }
482 }
483
484
485 return jvmFound;
486}
Note: See TracBrowser for help on using the repository browser.