source: main/branches/search4j-branchtest/libsearch4j.cpp@ 36022

Last change on this file since 36022 was 33930, checked in by davidb, 4 years ago

Code used to assume that major number was a single digit, as in 1.6 or 1.8. Now we have JDK 1.10 and above, and that the way version numbers are displayed has dropped the first part (the era), then search4j code needed to be updated to allow for this

File size: 11.9 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 FILE *pPipe;
73
74 char cmd[1024];
75 strcpy(cmd, command.c_str());
76 strcat(cmd, " 2>&1" );
77
78 //if ( verbose ) cout << "process(): running '" << command << "'" << endl;
79#ifdef WINDOWS
80 if( (pPipe = _popen( cmd, "rt" )) == NULL ) {
81 _pclose( pPipe );
82#else
83 if( (pPipe = popen( cmd, "r" )) == NULL ) {
84 pclose( pPipe );
85#endif
86 return -1;
87 }
88 //if ( verbose ) cout << "started process" << endl;
89
90 /* Read pipe until end of file. */
91 while( !feof( pPipe ) ) {
92 char psBuffer[128];
93 //if ( verbose ) cout << "get some data" << endl;
94 if( fgets( psBuffer, 128, pPipe ) != NULL ) {
95
96 //if ( verbose ) cout << "got: " << psBuffer << endl;
97 output.append( psBuffer );
98
99 } else {
100 //if ( verbose ) cout << "none left" << endl;
101 }
102
103 }
104
105 /* Close pipe and return return value of pPipe. */
106#ifdef WINDOWS
107 int code = _pclose( pPipe );
108#else
109 int code = pclose( pPipe );
110#endif
111
112 return code;
113
114}
115
116//Jvm class methods
117
118Jvm::Jvm()
119 : era_(1), major_(0), minor_(0), update_(0),
120 javaHome_(),
121 isJdk_(false), healthy_(false)
122{}
123
124Jvm::~Jvm()
125{
126 // javaHome automatically destructed
127}
128
129
130void Jvm::setJavaHome( string jh ) {
131 healthy_ = true;
132 javaHome_ = jh;
133 setVersionFromExeOuput();
134 setIsJdkFromJavacPresence();
135}
136
137string Jvm::getJavaHome() {
138 return javaHome_;
139}
140
141string Jvm::getExecutable() {
142 string exec = "";
143 exec.append( javaHome_ );
144
145 #ifdef WINDOWS
146 exec.append( "\\bin\\java.exe" );
147 #endif
148
149 #ifndef WINDOWS
150 exec.append( "/bin/java" );
151 #endif
152
153 return exec;
154}
155
156#ifdef WINDOWS
157string Jvm::getWinExecutable() {
158 string exec = "";
159 exec.append( javaHome_ );
160 exec.append( "\\bin\\javaw.exe" );
161 return exec;
162}
163#endif
164
165
166string Jvm::getVersion() {
167 stringstream ss;
168 ss << era_ << "." << major_ << "." << minor_ << "_" << update_;
169 return ss.str();
170}
171
172bool Jvm::check() {
173 return healthy_;
174}
175
176bool Jvm::setVersionFromString( string version ) {
177 era_ = atoi( version.substr(0,1).c_str() );
178 if (version[3] == '.') {
179 // Parsing something like 1.8.0_24
180 major_ = atoi( version.substr(2,1).c_str() );
181 if(version.length() >= 5) {
182 minor_ = atoi( version.substr(4,1).c_str() );
183 } else {
184 minor_ = 0;
185 }
186 if(version.length() >= 7) {
187 update_ = atoi( version.substr(6,2).c_str() );
188 } else {
189 update_ = 0;
190 }
191 }
192 else {
193 // Parsing something like 1.8.0_242
194 major_ = atoi( version.substr(2,2).c_str() );
195 if(version.length() >= 6) {
196 minor_ = atoi( version.substr(5,1).c_str() );
197 } else {
198 minor_ = 0;
199 }
200 if(version.length() >= 8) {
201 update_ = atoi( version.substr(7,2).c_str() );
202 } else {
203 update_ = 0;
204 }
205
206 }
207
208 return true;
209}
210
211int Jvm::compare( Jvm otherJvm ) {
212 //era
213 if ( era_ > otherJvm.getEra() )
214 return 1;
215 else if ( era_ < otherJvm.getEra() )
216 return -1;
217
218 //major
219 if ( major_ > otherJvm.getMajor() )
220 return 1;
221 else if ( major_ < otherJvm.getMajor() )
222 return -1;
223
224 //minor
225 if ( minor_ > otherJvm.getMinor() )
226 return 1;
227 else if ( minor_ < otherJvm.getMinor() )
228 return -1;
229
230 //update
231 if ( update_ > otherJvm.getUpdate() )
232 return 1;
233 else if ( update_ < otherJvm.getUpdate() )
234 return -1;
235
236 //all the same so far, must be exactly the same
237 return 0;
238
239}
240
241int Jvm::getEra() { return era_; }
242int Jvm::getMajor() { return major_; }
243int Jvm::getMinor() { return minor_; }
244int Jvm::getUpdate() { return update_; }
245
246bool Jvm::getIsJdk() { return isJdk_; }
247bool Jvm::getIsJre() { return !isJdk_; }
248
249void Jvm::setVersionFromExeOuput() {
250 string command = "", output = "";
251 command.append( "\"" );
252 command.append( getExecutable() );
253 command.append( "\"" );
254 command.append(" -version");
255
256 //cerr << "command: " << command << endl;
257 int result = process_and_catch_output( command, output );
258 //cerr << "output: " << output << endl;
259
260 if ( result == 0 ) {
261 // 22 is the length of sentinel string plus typical version value
262 int max_search_length = output.length() - 22;
263 int caret = 0;
264 bool found = false;
265 while (caret < max_search_length && !found) {
266 const int to_match_len = 8;
267 if ( strcmp( output.substr( caret, to_match_len ).c_str() , " version" ) == 0 ) {
268 if (output[caret+to_match_len+3] == '.') {
269 // Version of the form 1.8.0_24
270 era_ = atoi( output.substr(caret + to_match_len + 2,1).c_str() );
271 major_ = atoi( output.substr(caret + to_match_len + 4,1).c_str() );
272 minor_ = atoi( output.substr(caret + to_match_len + 6,1).c_str() );
273 update_ = atoi( output.substr(caret + to_match_len + 8,2).c_str() );
274 }
275 else {
276 // Version of the form 11.0.6
277 era_ = 1;
278 major_ = atoi( output.substr(caret + to_match_len + 2,2).c_str() );
279 minor_ = atoi( output.substr(caret + to_match_len + 5,1).c_str() );
280 update_ = atoi( output.substr(caret + to_match_len + 7,2).c_str() );
281
282 }
283 found = true;
284 }
285 else {
286 caret++;
287 }
288 }
289 if (!found) {
290 healthy_ = false;
291 }
292 }
293 else {
294 healthy_ = false;
295 }
296}
297void Jvm::setIsJdkFromJavacPresence() {
298 string javacFile = "";
299 javacFile.append( javaHome_ );
300
301 #ifdef WINDOWS
302 javacFile.append( "\\bin\\javac.exe" );
303 #endif
304 #ifndef WINDOWS
305 javacFile.append( "/bin/javac" );
306 #endif
307 struct stat stFileInfo;
308 isJdk_ = ( stat(javacFile.c_str(),&stFileInfo) == 0 );
309}
310
311//end of Jvm class methods
312
313
314#ifdef WINDOWS
315int regSearch(HKEY hKey, const char* keyName, int searchType, char* foundJavaVer ) {
316 DWORD x = 0;
317 unsigned long size = 1024;
318 FILETIME time;
319 char buffer[1024] = {0};
320
321 int foundJava = NO_JAVA_FOUND;
322
323 while (RegEnumKeyEx(
324 hKey, // handle to key to enumerate
325 x++, // index of subkey to enumerate
326 buffer, // address of buffer for subkey name
327 &size, // address for size of subkey buffer
328 NULL, // reserved
329 NULL, // address of buffer for class string
330 NULL, // address for size of class buffer
331 &time) == ERROR_SUCCESS) {
332 strcpy(foundJavaVer, buffer);
333 foundJava = searchType;
334 size = 1024;
335 }
336
337 return foundJava;
338
339}
340#endif
341
342/*
343* function to find java
344* implements the logic drawn on the dl lab whiteboard in feb 08
345* return a Jvm object which represents the jvm on disk
346*/
347bool find( Jvm &jvm, bool use_minimum, const Jvm& minimum, bool jreOnly, bool jdkOnly, string phint, string hint, bool verbose ) {
348
349 if ( verbose ) cout << "Searching for a JVM" << endl;
350
351 char *javaHomeEnv = NULL;
352 bool jvmFound = false;
353
354 if ( !jvmFound ) {
355
356 //try the priority hint
357 if ( verbose ) cout << " - trying priority hint: ";
358 if ( strcmp(phint.c_str(),"") != 0 ) {
359 if ( verbose ) cout << "(" << phint << ") ";
360 jvm.setJavaHome( phint );
361 if ( jvm.check() ) {
362 if ( use_minimum ) {
363 if ( jvm.compare( minimum ) >= 0 ) {
364 jvmFound = true;
365 }
366 } else {
367 jvmFound = true;
368 }
369 }
370 if ( (jreOnly && !jvm.getIsJre() ) || (jdkOnly && !jvm.getIsJdk()) ) {
371 jvmFound = false;
372 }
373
374 }
375 if ( verbose ) { if( jvmFound ) cout << "yes" << endl; else cout << "no" << endl; }
376 }
377
378 if ( !jvmFound ) {
379
380 //try JAVA_HOME
381 if ( verbose ) cout << " - trying JAVA_HOME: ";
382 javaHomeEnv = getenv( "JAVA_HOME" );
383 if ( javaHomeEnv != NULL ) {
384 if ( verbose ) cout << "(" << javaHomeEnv << ") ";
385 jvm.setJavaHome( javaHomeEnv );
386 if ( jvm.check() ) {
387 if ( use_minimum ) {
388 if ( jvm.compare( minimum ) >= 0 ) {
389 jvmFound = true;
390 }
391 } else {
392 jvmFound = true;
393 }
394 }
395 if ( (jreOnly && !jvm.getIsJre() ) || (jdkOnly && !jvm.getIsJdk()) ) {
396 jvmFound = false;
397 }
398
399 }
400 if ( verbose ) { if( jvmFound ) cout << "yes" << endl; else cout << "no" << endl; }
401 }
402
403 if ( !jvmFound ) {
404
405 //try JRE_HOME
406 if ( verbose ) cout << " - trying JRE_HOME: ";
407 javaHomeEnv = getenv( "JRE_HOME" );
408 if ( javaHomeEnv != NULL ) {
409 if ( verbose ) cout << "(" << javaHomeEnv << ") ";
410 jvm.setJavaHome( javaHomeEnv );
411 if ( jvm.check() ) {
412 if ( use_minimum ) {
413 if ( jvm.compare( minimum ) >= 0 ) {
414 jvmFound = true;
415 }
416 } else {
417 jvmFound = true;
418 }
419 }
420 if ( (jreOnly && !jvm.getIsJre() ) || (jdkOnly && !jvm.getIsJdk()) ) {
421 jvmFound = false;
422 }
423
424 }
425 if ( verbose ) { if( jvmFound ) cout << "yes" << endl; else cout << "no" << endl; }
426 }
427
428 #ifdef WINDOWS
429 if ( !jvmFound ) {
430
431 //try the registry - this code based on launch4j code
432 char foundJavaVer[8192] = {0};
433 int foundJava = NO_JAVA_FOUND;
434
435 if ( verbose ) cout << " - trying the registry: "; cout.flush();
436 HKEY hKey;
437 const char jre[] = "SOFTWARE\\JavaSoft\\Java Runtime Environment";
438 const char sdk[] = "SOFTWARE\\JavaSoft\\Java Development Kit";
439
440 if ( RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT(jre), 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &hKey) == ERROR_SUCCESS ) {
441 foundJava = regSearch(hKey, jre, FOUND_JRE, foundJavaVer);
442 RegCloseKey(hKey);
443 }
444
445 if ( RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT(sdk), 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &hKey) == ERROR_SUCCESS ) {
446 foundJava = regSearch(hKey, sdk, FOUND_SDK, foundJavaVer);
447 RegCloseKey(hKey);
448 }
449
450 if ( foundJava != NO_JAVA_FOUND ) {
451 char path[1024] = {0};
452 char keyBuffer[1024];
453 unsigned long datatype;
454 unsigned long bufferlength = 1024;
455 if (foundJava == FOUND_JRE) {
456 strcpy(keyBuffer, jre);
457 } else {
458 strcpy(keyBuffer, sdk);
459 }
460
461 strcat(keyBuffer, "\\");
462 strcat(keyBuffer, foundJavaVer);
463
464 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT(keyBuffer), 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) {
465 unsigned char buffer[1024] = {0};
466 if (RegQueryValueEx(hKey, "JavaHome", NULL, &datatype, buffer, &bufferlength) == ERROR_SUCCESS) {
467 int i = 0;
468 do {
469 path[i] = buffer[i];
470 } while (path[i++] != 0);
471 if (foundJava == FOUND_SDK) {
472 strcat(path, "\\jre");
473 }
474 if ( verbose ) cerr << "path: " << path << endl ;
475 jvm.setJavaHome( path );
476 if ( jvm.check() ) {
477 if ( use_minimum ) {
478 if ( jvm.compare( minimum ) >= 0 ) {
479 jvmFound = true;
480 }
481 } else {
482 jvmFound = true;
483 }
484 }
485 if ( (jreOnly && !jvm.getIsJre() ) || (jdkOnly && !jvm.getIsJdk()) ) {
486 jvmFound = false;
487 }
488 }
489 RegCloseKey(hKey);
490 }
491 }
492 if ( verbose ) { if( jvmFound ) cout << "yes" << endl; else cout << "no" << endl; }
493 }
494 #endif
495
496 if ( !jvmFound ) {
497
498 //try the hint
499 if ( verbose ) cout << " - trying hint: ";
500 if ( strcmp(hint.c_str(),"") != 0 ) {
501 if ( verbose ) cout << "(" << hint << ") ";
502 jvm.setJavaHome( hint );
503 if ( jvm.check() ) {
504 if ( use_minimum ) {
505 if ( jvm.compare( minimum ) >= 0 ) {
506 jvmFound = true;
507 }
508 } else {
509 jvmFound = true;
510 }
511 }
512 if ( (jreOnly && !jvm.getIsJre() ) || (jdkOnly && !jvm.getIsJdk()) ) {
513 jvmFound = false;
514 }
515
516 }
517 if ( verbose ) { if( jvmFound ) cout << "yes" << endl; else cout << "no" << endl; }
518 }
519
520
521 return jvmFound;
522}
Note: See TracBrowser for help on using the repository browser.