root/other-projects/trunk/search4j/libsearch4j.cpp @ 18237

Revision 18237, 11.1 KB (checked in by oranfry, 11 years ago)

added new options to search4j to only return a jre or only return a jre, and an option to display the type of the found jvm (whether jre or jdk)

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