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

Last change on this file since 21107 was 20709, checked in by ak19, 15 years ago

Dr Bainbridge edited the code to make it safer C++ and to fix bugs and possibly memory issues, since there is a bus error on MacOs 10.4 (Tiger) on Veronica's Macbook Pro.

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