source: main/trunk/search4j/libsearch4j.cpp@ 32485

Last change on this file since 32485 was 30172, checked in by ak19, 9 years ago

John Thompson fixed a search4j bug that manifested on his Ubuntu and made the java version 0.0.0_00 because search4j expected a certain line of output (starting 'java version') to appear at the very start of the response returned from running java -version. However there may be other lines in the output that precede this, which John's patch allows for.

File size: 11.0 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 major_ = atoi( version.substr(2,1).c_str() );
179 if(version.length() >= 5) {
180 minor_ = atoi( version.substr(4,1).c_str() );
181 } else {
182 minor_ = 0;
183 }
184 if(version.length() >= 7) {
185 update_ = atoi( version.substr(6,2).c_str() );
186 } else {
187 update_ = 0;
188 }
189 return true;
190}
191
192int Jvm::compare( Jvm otherJvm ) {
193 //era
194 if ( era_ > otherJvm.getEra() )
195 return 1;
196 else if ( era_ < otherJvm.getEra() )
197 return -1;
198
199 //major
200 if ( major_ > otherJvm.getMajor() )
201 return 1;
202 else if ( major_ < otherJvm.getMajor() )
203 return -1;
204
205 //minor
206 if ( minor_ > otherJvm.getMinor() )
207 return 1;
208 else if ( minor_ < otherJvm.getMinor() )
209 return -1;
210
211 //update
212 if ( update_ > otherJvm.getUpdate() )
213 return 1;
214 else if ( update_ < otherJvm.getUpdate() )
215 return -1;
216
217 //all the same so far, must be exactly the same
218 return 0;
219
220}
221
222int Jvm::getEra() { return era_; }
223int Jvm::getMajor() { return major_; }
224int Jvm::getMinor() { return minor_; }
225int Jvm::getUpdate() { return update_; }
226
227bool Jvm::getIsJdk() { return isJdk_; }
228bool Jvm::getIsJre() { return !isJdk_; }
229
230void Jvm::setVersionFromExeOuput() {
231 string command = "", output = "";
232 command.append( "\"" );
233 command.append( getExecutable() );
234 command.append( "\"" );
235 command.append(" -version");
236
237 //cerr << "command: " << command << endl;
238 int result = process_and_catch_output( command, output );
239 //cerr << "output: " << output << endl;
240
241 if ( result == 0 ) {
242 // 22 is the length of sentinel string plus typical version value
243 int max_search_length = output.length() - 22;
244 int caret = 0;
245 bool found = false;
246 while (caret < max_search_length && !found) {
247 if ( strcmp( output.substr( caret, 12 ).c_str() , "java version" ) == 0 ) {
248 era_ = atoi( output.substr(caret + 14,1).c_str() );
249 major_ = atoi( output.substr(caret + 16,1).c_str() );
250 minor_ = atoi( output.substr(caret + 18,1).c_str() );
251 update_ = atoi( output.substr(caret + 20,2).c_str() );
252 found = true;
253 }
254 else {
255 caret++;
256 }
257 }
258 if (!found) {
259 healthy_ = false;
260 }
261 }
262 else {
263 healthy_ = false;
264 }
265}
266void Jvm::setIsJdkFromJavacPresence() {
267 string javacFile = "";
268 javacFile.append( javaHome_ );
269
270 #ifdef WINDOWS
271 javacFile.append( "\\bin\\javac.exe" );
272 #endif
273 #ifndef WINDOWS
274 javacFile.append( "/bin/javac" );
275 #endif
276 struct stat stFileInfo;
277 isJdk_ = ( stat(javacFile.c_str(),&stFileInfo) == 0 );
278}
279
280//end of Jvm class methods
281
282
283#ifdef WINDOWS
284int regSearch(HKEY hKey, const char* keyName, int searchType, char* foundJavaVer ) {
285 DWORD x = 0;
286 unsigned long size = 1024;
287 FILETIME time;
288 char buffer[1024] = {0};
289
290 int foundJava = NO_JAVA_FOUND;
291
292 while (RegEnumKeyEx(
293 hKey, // handle to key to enumerate
294 x++, // index of subkey to enumerate
295 buffer, // address of buffer for subkey name
296 &size, // address for size of subkey buffer
297 NULL, // reserved
298 NULL, // address of buffer for class string
299 NULL, // address for size of class buffer
300 &time) == ERROR_SUCCESS) {
301 strcpy(foundJavaVer, buffer);
302 foundJava = searchType;
303 size = 1024;
304 }
305
306 return foundJava;
307
308}
309#endif
310
311/*
312* function to find java
313* implements the logic drawn on the dl lab whiteboard in feb 08
314* return a Jvm object which represents the jvm on disk
315*/
316bool find( Jvm &jvm, bool use_minimum, const Jvm& minimum, bool jreOnly, bool jdkOnly, string phint, string hint, bool verbose ) {
317
318 if ( verbose ) cout << "Searching for a JVM" << endl;
319
320 char *javaHomeEnv = "";
321 bool jvmFound = false;
322
323 if ( !jvmFound ) {
324
325 //try the priority hint
326 if ( verbose ) cout << " - trying priority hint: ";
327 if ( strcmp(phint.c_str(),"") != 0 ) {
328 if ( verbose ) cout << "(" << phint << ") ";
329 jvm.setJavaHome( phint );
330 if ( jvm.check() ) {
331 if ( use_minimum ) {
332 if ( jvm.compare( minimum ) >= 0 ) {
333 jvmFound = true;
334 }
335 } else {
336 jvmFound = true;
337 }
338 }
339 if ( (jreOnly && !jvm.getIsJre() ) || (jdkOnly && !jvm.getIsJdk()) ) {
340 jvmFound = false;
341 }
342
343 }
344 if ( verbose ) { if( jvmFound ) cout << "yes" << endl; else cout << "no" << endl; }
345 }
346
347 if ( !jvmFound ) {
348
349 //try JAVA_HOME
350 if ( verbose ) cout << " - trying JAVA_HOME: ";
351 javaHomeEnv = getenv( "JAVA_HOME" );
352 if ( javaHomeEnv != NULL ) {
353 if ( verbose ) cout << "(" << javaHomeEnv << ") ";
354 jvm.setJavaHome( javaHomeEnv );
355 if ( jvm.check() ) {
356 if ( use_minimum ) {
357 if ( jvm.compare( minimum ) >= 0 ) {
358 jvmFound = true;
359 }
360 } else {
361 jvmFound = true;
362 }
363 }
364 if ( (jreOnly && !jvm.getIsJre() ) || (jdkOnly && !jvm.getIsJdk()) ) {
365 jvmFound = false;
366 }
367
368 }
369 if ( verbose ) { if( jvmFound ) cout << "yes" << endl; else cout << "no" << endl; }
370 }
371
372 if ( !jvmFound ) {
373
374 //try JRE_HOME
375 if ( verbose ) cout << " - trying JRE_HOME: ";
376 javaHomeEnv = getenv( "JRE_HOME" );
377 if ( javaHomeEnv != NULL ) {
378 if ( verbose ) cout << "(" << javaHomeEnv << ") ";
379 jvm.setJavaHome( javaHomeEnv );
380 if ( jvm.check() ) {
381 if ( use_minimum ) {
382 if ( jvm.compare( minimum ) >= 0 ) {
383 jvmFound = true;
384 }
385 } else {
386 jvmFound = true;
387 }
388 }
389 if ( (jreOnly && !jvm.getIsJre() ) || (jdkOnly && !jvm.getIsJdk()) ) {
390 jvmFound = false;
391 }
392
393 }
394 if ( verbose ) { if( jvmFound ) cout << "yes" << endl; else cout << "no" << endl; }
395 }
396
397 #ifdef WINDOWS
398 if ( !jvmFound ) {
399
400 //try the registry - this code based on launch4j code
401 char foundJavaVer[8192] = {0};
402 int foundJava = NO_JAVA_FOUND;
403
404 if ( verbose ) cout << " - trying the registry: "; cout.flush();
405 HKEY hKey;
406 const char jre[] = "SOFTWARE\\JavaSoft\\Java Runtime Environment";
407 const char sdk[] = "SOFTWARE\\JavaSoft\\Java Development Kit";
408
409 if ( RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT(jre), 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &hKey) == ERROR_SUCCESS ) {
410 foundJava = regSearch(hKey, jre, FOUND_JRE, foundJavaVer);
411 RegCloseKey(hKey);
412 }
413
414 if ( RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT(sdk), 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &hKey) == ERROR_SUCCESS ) {
415 foundJava = regSearch(hKey, sdk, FOUND_SDK, foundJavaVer);
416 RegCloseKey(hKey);
417 }
418
419 if ( foundJava != NO_JAVA_FOUND ) {
420 char path[1024] = {0};
421 char keyBuffer[1024];
422 unsigned long datatype;
423 unsigned long bufferlength = 1024;
424 if (foundJava == FOUND_JRE) {
425 strcpy(keyBuffer, jre);
426 } else {
427 strcpy(keyBuffer, sdk);
428 }
429
430 strcat(keyBuffer, "\\");
431 strcat(keyBuffer, foundJavaVer);
432
433 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT(keyBuffer), 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) {
434 unsigned char buffer[1024] = {0};
435 if (RegQueryValueEx(hKey, "JavaHome", NULL, &datatype, buffer, &bufferlength) == ERROR_SUCCESS) {
436 int i = 0;
437 do {
438 path[i] = buffer[i];
439 } while (path[i++] != 0);
440 if (foundJava == FOUND_SDK) {
441 strcat(path, "\\jre");
442 }
443 if ( verbose ) cerr << "path: " << path << endl ;
444 jvm.setJavaHome( path );
445 if ( jvm.check() ) {
446 if ( use_minimum ) {
447 if ( jvm.compare( minimum ) >= 0 ) {
448 jvmFound = true;
449 }
450 } else {
451 jvmFound = true;
452 }
453 }
454 if ( (jreOnly && !jvm.getIsJre() ) || (jdkOnly && !jvm.getIsJdk()) ) {
455 jvmFound = false;
456 }
457 }
458 RegCloseKey(hKey);
459 }
460 }
461 if ( verbose ) { if( jvmFound ) cout << "yes" << endl; else cout << "no" << endl; }
462 }
463 #endif
464
465 if ( !jvmFound ) {
466
467 //try the hint
468 if ( verbose ) cout << " - trying hint: ";
469 if ( strcmp(hint.c_str(),"") != 0 ) {
470 if ( verbose ) cout << "(" << hint << ") ";
471 jvm.setJavaHome( hint );
472 if ( jvm.check() ) {
473 if ( use_minimum ) {
474 if ( jvm.compare( minimum ) >= 0 ) {
475 jvmFound = true;
476 }
477 } else {
478 jvmFound = true;
479 }
480 }
481 if ( (jreOnly && !jvm.getIsJre() ) || (jdkOnly && !jvm.getIsJdk()) ) {
482 jvmFound = false;
483 }
484
485 }
486 if ( verbose ) { if( jvmFound ) cout << "yes" << endl; else cout << "no" << endl; }
487 }
488
489
490 return jvmFound;
491}
Note: See TracBrowser for help on using the repository browser.