root/main/trunk/search4j/libsearch4j.cpp @ 32094

Revision 30172, 11.0 KB (checked in by ak19, 4 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.

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 browser.