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

Revision 28699, 10.7 KB (checked in by ak19, 6 years ago)

Jeremy (jts21) has fixed a bug in search4j. In the past the -m flag to set the minimum Java version needed to be of the form 1.8.0_0 and could not accept 1.8.0 and would crash. Now the java minor and update version numbers are optional.

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        if ( strcmp( output.substr( 0, 12 ).c_str() , "java version" ) == 0 || true ) {
243            era_ = atoi( output.substr(14,1).c_str() );
244            major_ = atoi( output.substr(16,1).c_str() );
245            minor_ = atoi( output.substr(18,1).c_str() );
246            update_ = atoi( output.substr(20,2).c_str() );
247        } else {
248            healthy_=false;
249        }
250    } else {
251        healthy_ = false;
252    }
253}
254void Jvm::setIsJdkFromJavacPresence() {
255    string javacFile = "";
256    javacFile.append( javaHome_ );
257
258    #ifdef WINDOWS
259    javacFile.append( "\\bin\\javac.exe" );
260    #endif
261    #ifndef WINDOWS
262    javacFile.append( "/bin/javac" );
263    #endif
264    struct stat stFileInfo;
265    isJdk_ = ( stat(javacFile.c_str(),&stFileInfo) == 0 );
266}
267
268//end of Jvm class methods
269
270
271#ifdef WINDOWS
272int regSearch(HKEY hKey, const char* keyName, int searchType, char* foundJavaVer ) {
273    DWORD x = 0;
274    unsigned long size = 1024;
275    FILETIME time;
276    char buffer[1024] = {0};
277
278    int foundJava = NO_JAVA_FOUND;
279
280    while (RegEnumKeyEx(
281                hKey,           // handle to key to enumerate
282                x++,            // index of subkey to enumerate
283                buffer,         // address of buffer for subkey name
284                &size,          // address for size of subkey buffer
285                NULL,           // reserved
286                NULL,           // address of buffer for class string
287                NULL,           // address for size of class buffer
288                &time) == ERROR_SUCCESS) {
289        strcpy(foundJavaVer, buffer);
290        foundJava = searchType;
291        size = 1024;
292    }
293   
294    return foundJava;
295   
296}
297#endif
298
299/*
300* function to find java
301* implements the logic drawn on the dl lab whiteboard in feb 08
302* return a Jvm object which represents the jvm on disk
303*/
304bool find( Jvm &jvm, bool use_minimum, const Jvm& minimum, bool jreOnly, bool jdkOnly, string phint, string hint, bool verbose ) {
305   
306    if ( verbose ) cout << "Searching for a JVM" << endl;
307   
308    char *javaHomeEnv = "";
309    bool jvmFound = false;
310   
311    if ( !jvmFound ) {
312       
313        //try the priority hint
314        if ( verbose ) cout << " - trying priority hint: ";
315        if ( strcmp(phint.c_str(),"") != 0  ) {
316            if ( verbose ) cout << "(" << phint << ") ";
317            jvm.setJavaHome( phint );
318            if ( jvm.check() ) {
319                if ( use_minimum ) {
320                    if ( jvm.compare( minimum ) >= 0 ) {
321                        jvmFound = true;
322                    }
323                } else {
324                    jvmFound = true;
325                }
326            }
327            if ( (jreOnly && !jvm.getIsJre() ) || (jdkOnly && !jvm.getIsJdk()) ) {
328                jvmFound = false;
329            }
330
331        }
332        if ( verbose ) { if( jvmFound ) cout << "yes" << endl; else cout << "no" << endl; }
333    }
334
335    if ( !jvmFound ) {
336       
337        //try JAVA_HOME
338        if ( verbose ) cout << " - trying JAVA_HOME: ";
339        javaHomeEnv = getenv( "JAVA_HOME" );
340        if ( javaHomeEnv != NULL ) {
341            if ( verbose ) cout << "(" << javaHomeEnv << ") ";
342            jvm.setJavaHome( javaHomeEnv );
343            if ( jvm.check() ) {
344                if ( use_minimum ) {
345                    if ( jvm.compare( minimum ) >= 0 ) {
346                        jvmFound = true;
347                    }
348                } else {
349                    jvmFound = true;
350                }
351            }
352            if ( (jreOnly && !jvm.getIsJre() ) || (jdkOnly && !jvm.getIsJdk()) ) {
353                jvmFound = false;
354            }
355
356        }
357        if ( verbose ) { if( jvmFound ) cout << "yes" << endl; else cout << "no" << endl; }
358    }
359   
360    if ( !jvmFound ) {
361       
362        //try JRE_HOME
363        if ( verbose ) cout << " - trying JRE_HOME: ";
364        javaHomeEnv = getenv( "JRE_HOME" );
365        if ( javaHomeEnv != NULL ) {
366            if ( verbose ) cout << "(" << javaHomeEnv << ") ";
367            jvm.setJavaHome( javaHomeEnv );
368            if ( jvm.check() ) {
369                if ( use_minimum ) {
370                    if ( jvm.compare( minimum ) >= 0 ) {
371                        jvmFound = true;
372                    }
373                } else {
374                    jvmFound = true;
375                }
376            }
377            if ( (jreOnly && !jvm.getIsJre() ) || (jdkOnly && !jvm.getIsJdk()) ) {
378                jvmFound = false;
379            }
380
381        }
382        if ( verbose ) { if( jvmFound ) cout << "yes" << endl; else cout << "no" << endl; }
383    }
384
385    #ifdef WINDOWS
386    if ( !jvmFound ) {
387
388        //try the registry - this code based on launch4j code
389        char foundJavaVer[8192] = {0};
390        int foundJava = NO_JAVA_FOUND;
391       
392        if ( verbose ) cout << " - trying the registry: "; cout.flush();
393        HKEY hKey;
394        const char jre[] = "SOFTWARE\\JavaSoft\\Java Runtime Environment";
395        const char sdk[] = "SOFTWARE\\JavaSoft\\Java Development Kit";
396       
397        if ( RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT(jre), 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &hKey) == ERROR_SUCCESS ) {
398            foundJava = regSearch(hKey, jre, FOUND_JRE, foundJavaVer);
399            RegCloseKey(hKey);
400        }
401       
402        if ( RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT(sdk), 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &hKey) == ERROR_SUCCESS ) {
403            foundJava = regSearch(hKey, sdk, FOUND_SDK, foundJavaVer);
404            RegCloseKey(hKey);
405        }
406       
407        if ( foundJava != NO_JAVA_FOUND ) {
408            char path[1024] = {0};
409            char keyBuffer[1024];
410            unsigned long datatype;
411            unsigned long bufferlength = 1024;
412            if (foundJava == FOUND_JRE) {
413                strcpy(keyBuffer, jre);
414            } else {
415                strcpy(keyBuffer, sdk);
416            }
417           
418            strcat(keyBuffer, "\\");
419            strcat(keyBuffer, foundJavaVer);
420           
421            if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT(keyBuffer), 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) {
422                unsigned char buffer[1024] = {0};
423                if (RegQueryValueEx(hKey, "JavaHome", NULL, &datatype, buffer, &bufferlength) == ERROR_SUCCESS) {
424                    int i = 0;
425                    do {
426                        path[i] = buffer[i];
427                    } while (path[i++] != 0);
428                    if (foundJava == FOUND_SDK) {
429                        strcat(path, "\\jre");
430                    }
431                    if ( verbose ) cerr << "path: " << path << endl ;
432                    jvm.setJavaHome( path );
433                    if ( jvm.check() ) {
434                        if ( use_minimum ) {
435                            if ( jvm.compare( minimum ) >= 0 ) {
436                                jvmFound = true;
437                            }
438                        } else {
439                            jvmFound = true;
440                        }
441                    }
442                    if ( (jreOnly && !jvm.getIsJre() ) || (jdkOnly && !jvm.getIsJdk()) ) {
443                        jvmFound = false;
444                    }
445                }
446                RegCloseKey(hKey);
447            }
448        }
449        if ( verbose ) { if( jvmFound ) cout << "yes" << endl; else cout << "no" << endl; }
450    }
451    #endif
452
453    if ( !jvmFound ) {
454       
455        //try the hint
456        if ( verbose ) cout << " - trying hint: ";
457        if ( strcmp(hint.c_str(),"") != 0  ) {
458            if ( verbose ) cout << "(" << hint << ") ";
459            jvm.setJavaHome( hint );
460            if ( jvm.check() ) {
461                if ( use_minimum ) {
462                    if ( jvm.compare( minimum ) >= 0 ) {
463                        jvmFound = true;
464                    }
465                } else {
466                    jvmFound = true;
467                }
468            }
469            if ( (jreOnly && !jvm.getIsJre() ) || (jdkOnly && !jvm.getIsJdk()) ) {
470                jvmFound = false;
471            }
472
473        }
474        if ( verbose ) { if( jvmFound ) cout << "yes" << endl; else cout << "no" << endl; }
475    }
476
477
478    return jvmFound;
479}
Note: See TracBrowser for help on using the browser.