root/release-kits/shared/search4j/search4j.cpp @ 15103

Revision 15103, 13.6 KB (checked in by oranfry, 11 years ago)

massaged search4j to work in windows and linux

Line 
1/*
2* Search4j utility
3* Command Line utility to search a system for java, launch a jar, or compare java versions
4* base on launch4j
5*/
6
7#include <iostream>
8#include <fstream>
9#include <string>
10#include <sstream>
11
12using namespace std;
13
14#ifdef WINDOWS
15#include <windows.h>
16
17//minimal launch4j stuff
18#define NO_JAVA_FOUND 0
19#define FOUND_JRE 1
20#define FOUND_SDK 2
21int foundJava = NO_JAVA_FOUND;
22char foundJavaVer[128] = {0};
23
24//windows functions
25#define popen _popen
26#define strcmp _stricmp
27#endif /* WINDOWS */
28
29
30//global variables
31bool verbose = false;
32bool use_minimum = false;
33
34enum JvmProperty {
35    JavaHome,
36    Version,
37    Executable
38};
39
40enum Action {
41    Find,
42    Launch,
43    Compare
44};
45
46void replace_all ( std::string & str, std::string const & pattern, std::string const & replacement ) {
47
48    std::string::size_type start = str.find( pattern, 0 );
49
50    while ( start != str.npos ) {
51        str.replace( start, pattern.size(), replacement );
52        start = str.find( pattern, start+replacement.size() );
53    }
54
55}
56
57int process( string command, string &output ) {
58   
59    FILE *pPipe;
60
61    /* Run command so that it writes its output to a pipe. Open this
62    * pipe with read text attribute so that we can read it
63    * like a text file. */
64    char cmd[1024]; strcpy(cmd, command.c_str());
65    //if ( verbose ) cout << "process(): running '" << command << "'" << endl;
66    #ifdef WINDOWS
67    if( (pPipe = popen( cmd, "rt" )) == NULL ) {
68        if ( verbose ) cout << "could not start process" << endl;
69        pclose( pPipe );
70        return -1;
71    }
72    #endif
73    #ifndef WINDOWS
74    if( (pPipe = popen( cmd, "r" )) == NULL ) {
75        if ( verbose ) cout << "could not start process" << endl;
76        pclose( pPipe );
77        return -1;
78    }
79    #endif
80
81    //if ( verbose ) cout << "started process" << endl;
82
83    /* Read pipe until end of file. */
84    while( !feof( pPipe ) ) {
85        char psBuffer[128];
86        //if ( verbose ) cout << "get some data" << endl;
87        if( fgets( psBuffer, 128, pPipe ) != NULL ) {
88           
89            //if ( verbose ) cout << "got: " << psBuffer << endl;
90            output.append( psBuffer );
91           
92        } else {
93            //if ( verbose ) cout << "none left" << endl;
94        }
95       
96    }
97
98    /* Close pipe and return return value of pPipe. */
99    int code = pclose( pPipe );
100    return code;
101}
102
103class Jvm {
104
105    string javaHome;
106   
107    // version string. era.major.minor_update. eg: 1.4.2_02
108    int era;
109    int major;
110    int minor;
111    int update;
112
113    bool isJdk;
114    bool healthy;   
115
116
117    public:
118    Jvm() {
119        healthy = false;
120    }
121
122    void setJavaHome( string jh ) {
123        healthy = true;
124        javaHome = jh;
125        setVersionFromExeOuput();
126    }
127
128    string getJavaHome() {
129        return javaHome;
130    }
131
132    string getExecutable() {
133        string exec = "";
134        exec.append( javaHome );
135       
136        #ifdef WINDOWS
137        exec.append( "\\bin\\java.exe" );
138        #endif
139
140        #ifndef WINDOWS
141        exec.append( "/bin/java" );
142        #endif
143       
144        return exec;
145    }
146
147    string getVersion() {
148        stringstream ss;
149        ss << era << "." << major << "." << minor << "_" << update;
150        return ss.str();
151    }
152   
153    bool check() {
154        return healthy;
155    }
156
157    bool setVersionFromString( string version ) {
158        era = atoi( version.substr(0,1).c_str() );
159        major = atoi( version.substr(2,1).c_str() );
160        minor = atoi( version.substr(4,1).c_str() );
161        update = atoi( version.substr(6,2).c_str() );
162        return true;
163    }
164   
165    int compare( Jvm otherJvm ) {
166        //era
167        if ( era > otherJvm.getEra() )
168            return 1;
169        else if ( era < otherJvm.getEra() )
170            return -1;
171       
172        //major
173        if ( major > otherJvm.getMajor() )
174            return 1;
175        else if ( major < otherJvm.getMajor() )
176            return -1;
177           
178        //minor
179        if ( minor > otherJvm.getMinor() )
180            return 1;
181        else if ( minor < otherJvm.getMinor() )
182            return -1;
183
184        //update
185        if ( update > otherJvm.getUpdate() )
186            return 1;
187        else if ( update < otherJvm.getUpdate() )
188            return -1;
189
190        //all the same so far, must be exactly the same
191        return 0;
192
193    }
194   
195    int getEra() { return era; }
196    int getMajor() { return major; }
197    int getMinor() { return minor; }
198    int getUpdate() { return update; }
199   
200    private:
201   
202    void setVersionFromExeOuput() {
203        string command = "", output = "";
204        command.append( "\"" );
205        command.append( getExecutable() );
206        command.append( "\"" );
207        command.append(" -version 2>&1");
208        //cout << "(command: " << command << ")";
209        int result = process( command, output );
210        //cout << "(output: " << output << ")";
211        if ( result == 0 ) {
212            if ( strcmp( output.substr( 0, 12 ).c_str() , "java version" ) == 0 || true ) {
213                era = atoi( output.substr(14,1).c_str() );
214                major = atoi( output.substr(16,1).c_str() );
215                minor = atoi( output.substr(18,1).c_str() );
216                update = atoi( output.substr(20,2).c_str() );
217                //if ( verbose) cout << "set version to: " << era << "." << major << "." << minor << "_" << update << endl;
218            } else {
219                healthy=false;
220            }
221        } else {
222            healthy = false;
223        }
224    }
225   
226   
227};
228
229string actionToString( Action a ) {
230    if ( a == Find )
231        return "Find";
232    else if ( a == Launch )
233        return "Launch";
234    else if ( a == Compare )
235        return "Compare";
236    return "Unknown";
237}
238
239string jvmPropertyToString( JvmProperty jp ) {
240    if ( jp == JavaHome )
241        return "JavaHome";
242    else if ( jp == Version )
243        return "Version";
244    else if ( jp == Executable )
245        return "Executable";
246    return "Unknown";
247}
248
249void usage() {
250   
251    cout
252        << "-----------------" << endl
253        << " search4j: usage" << endl
254        << "-----------------" << endl
255        << "Three usage methods: find, compare and launch" << endl
256        << endl
257        << "find:     find java and print out information about it" << endl
258        << endl
259        << "          search4j [-v|-e] [-m VERSION_STRING]" << endl
260        << "          eg: search4j -m 1.4.1_01 -e" << endl
261        << endl
262        << "          by default, print JAVA_HOME. E.g., C:\\Program Files\\jre1.5.0_15, or" << endl
263        << "          if -v is specified, print the java version string. E.g. 1.5.0_15, or" << endl
264        << "          if -e is specified, print the path the to the java executable. E.g. C:\\Program Files\\jre1.5.0_15\\bin\\java.exe" << endl
265        << "          if -m option is used, find a java of the given version or newer, or fail" << endl
266        << endl
267        << "compare:  compare the found java with the given java version string" << endl
268        << endl
269        << "          search4j -c VERSION_STRING" << endl
270        << "          eg: search4j -c VERSION_STRING" << endl
271        << endl
272        << "          print -1 if found java is older" << endl
273        << "          print 0 if found java is same" << endl
274        << "          print 1 if found java is newer" << endl
275        << endl
276        << "launch:   launch the given executable jar with the found java" << endl
277        << endl
278        << "          search4j -l EXECUTABLE_JAR [-m VERSION_STRING]" << endl
279        << "          eg: search4j -l greenstone3.jar" << endl
280        << endl
281        << "          specify the location of the jar relative to the current directory" << endl
282        << "          if -m option is used, find a java of the given version or newer" << endl
283        << endl
284        << "Global Options:" << endl
285        << "          --verbose : have search4j print out information about what its doing" << endl
286        << "          --help : display this usage screen" << endl
287        << endl
288        ;
289}
290
291//another global
292Jvm minimum;
293
294#ifdef WINDOWS
295void regSearch(HKEY hKey, const char* keyName, int searchType) {
296    DWORD x = 0;
297    unsigned long size = 1024;
298    FILETIME time;
299    char buffer[1024] = {0};
300    while (RegEnumKeyEx(
301                hKey,           // handle to key to enumerate
302                x++,            // index of subkey to enumerate
303                buffer,         // address of buffer for subkey name
304                &size,          // address for size of subkey buffer
305                NULL,           // reserved
306                NULL,           // address of buffer for class string
307                NULL,           // address for size of class buffer
308                &time) == ERROR_SUCCESS) {
309        strcpy(foundJavaVer, buffer);
310        foundJava = searchType;
311        size = 1024;
312    }
313}
314#endif
315
316/*
317* function to find java
318* implements the logic drawn on the dl lab whiteboard in feb 08
319* return a Jvm object which represents the jvm on disk
320*/
321bool find( Jvm &jvm ) {
322   
323    if ( verbose ) cout << "Searching for a JVM" << endl;
324    char *javaHome = "";
325    bool jvmFound = false;
326   
327    if ( !jvmFound ) {
328        //try JAVA_HOME
329        if ( verbose ) cout << " - trying JAVA_HOME: ";
330        javaHome = getenv( "JAVA_HOME" );
331        if ( javaHome != NULL ) {
332            if ( verbose ) cout << "(" << javaHome << ")";
333            jvm.setJavaHome( javaHome );
334            if ( jvm.check() ) {
335                if ( use_minimum ) {
336                    if ( jvm.compare( minimum ) >= 0 ) {
337                        jvmFound = true;
338                    }
339                } else {
340                    jvmFound = true;
341                }
342            }
343        }
344        if ( verbose ) { if( jvmFound ) cout << "yes" << endl; else cout << "no" << endl; }
345    }
346   
347    if ( !jvmFound ) {
348        //try JRE_HOME
349        if ( verbose ) cout << " - trying JRE_HOME: ";
350        javaHome = getenv( "JRE_HOME" );
351        if ( javaHome != NULL ) {
352            if ( verbose ) cout << "(" << javaHome << ")";
353            jvm.setJavaHome( javaHome );
354            if ( jvm.check() ) {
355                if ( use_minimum ) {
356                    if ( jvm.compare( minimum ) >= 0 ) {
357                        jvmFound = true;
358                    }
359                } else {
360                    jvmFound = true;
361                }
362            }
363        }
364        if ( verbose ) { if( jvmFound ) cout << "yes" << endl; else cout << "no" << endl; }
365    }
366
367    #ifdef WINDOWS
368    if ( !jvmFound ) {
369        //try the registry - this code based on launch4j code
370        if ( verbose ) cout << " - trying the registry: ";
371        HKEY hKey;
372        const char jre[] = "SOFTWARE\\JavaSoft\\Java Runtime Environment";
373        const char sdk[] = "SOFTWARE\\JavaSoft\\Java Development Kit";
374       
375        if ( RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT(jre), 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &hKey) == ERROR_SUCCESS ) {
376            regSearch(hKey, jre, FOUND_JRE);
377            RegCloseKey(hKey);
378        }
379       
380        if ( RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT(sdk), 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &hKey) == ERROR_SUCCESS ) {
381            regSearch(hKey, sdk, FOUND_SDK);
382            RegCloseKey(hKey);
383        }
384       
385        if ( foundJava != NO_JAVA_FOUND ) {
386            char path[1024] = {0};
387            char keyBuffer[1024];
388            unsigned long datatype;
389            unsigned long bufferlength = 1024;
390            if (foundJava == FOUND_JRE) {
391                strcpy(keyBuffer, jre);
392            } else {
393                strcpy(keyBuffer, sdk);
394            }
395            strcat(keyBuffer, "\\");
396            strcat(keyBuffer, foundJavaVer);
397            if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT(keyBuffer), 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) {
398                unsigned char buffer[1024] = {0};
399                if (RegQueryValueEx(hKey, "JavaHome", NULL, &datatype, buffer, &bufferlength) == ERROR_SUCCESS) {
400                    int i = 0;
401                    do {
402                        path[i] = buffer[i];
403                    } while (path[i++] != 0);
404                    if (foundJava == FOUND_SDK) {
405                        strcat(path, "\\jre");
406                    }
407                    jvm.setJavaHome( path );
408                    if ( jvm.check() ) {
409                        if ( use_minimum ) {
410                            if ( jvm.compare( minimum ) >= 0 ) {
411                                jvmFound = true;
412                            }
413                        } else {
414                            jvmFound = true;
415                        }
416                    }
417                }
418                RegCloseKey(hKey);
419            }
420        }
421        if ( verbose ) { if( jvmFound ) cout << "yes" << endl; else cout << "no" << endl; }
422    }
423    #endif
424
425    return jvmFound;
426}
427
428int main ( int argc, char** argv ) {
429    //cout << "testing process()" << endl;
430    //string out = "";
431    //process( "dir", out );
432    //cout << out << endl;
433    //return 0;
434
435
436    JvmProperty jvmProperty = JavaHome;
437    Action action = Find;
438    string arg1 = "";
439   
440    //parse commandline arguments
441    for (int i=1; i<argc; i++) {
442        if ( strcmp(argv[i], "--verbose") == 0 ) {
443            verbose = true;
444        } else if ( strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "--usage") == 0 ) {
445            usage();
446            return 0;
447        } else if ( strcmp(argv[i], "-v") == 0 ) {
448            jvmProperty = Version;
449        } else if ( strcmp(argv[i], "-e") == 0 ) {
450            jvmProperty = Executable;
451        } else if ( strcmp(argv[i], "-c") == 0 ) {
452            action = Compare;
453            if ( i == argc-1 ) {
454                usage();
455                return 0;
456            } else {
457                arg1 = argv[++i];
458            }
459
460            } else if ( strcmp(argv[i], "-m") == 0 ) {
461            if ( i == argc-1 ) {
462                usage();
463                return 0;
464            } else {
465                if ( !minimum.setVersionFromString( argv[++i] ) ) {
466                    usage();
467                    return 0;
468                }
469                use_minimum = true;
470            }
471
472        } else if ( strcmp(argv[i], "-l") == 0 ) {
473            action = Launch;
474            arg1 = argv[++i];
475
476        } else {
477            cout << "unknown option: " << argv[i] << endl;
478            return -1;
479        }
480    }
481   
482    //summarise commandline arguments
483    if ( verbose ) {
484        cout << "Action: " << actionToString( action ) << endl;
485    }
486
487    //find java
488    Jvm foundJvm;
489    bool found = find( foundJvm );
490
491    //check if it was found
492    if ( found ) {
493        if ( verbose ) cout << "Found JVM at '" << foundJvm.getJavaHome() << "'" << endl;
494    } else {
495        //not found - exit with -1
496        if ( verbose ) cout << "JVM not found" << endl;
497        return -1;
498    }
499
500
501    //Find Action
502    //---------------
503    if ( action == Find ) {
504
505        if ( verbose ) cout << "Property to print: " << jvmPropertyToString( jvmProperty ) << endl;     
506
507        //found - print out info about it
508        if ( jvmProperty == JavaHome ) {
509            cout << foundJvm.getJavaHome() << endl;
510        } else if ( jvmProperty == Version ) {
511            cout << foundJvm.getVersion() << endl;
512        } else if ( jvmProperty == Executable ) {
513            cout << foundJvm.getExecutable() << endl;
514        } else {
515            return -1; //should never happen
516        }
517           
518
519    //Compare Action
520    //---------------
521    } else if ( action == Compare ) {
522       
523        if ( verbose ) cout << "Compare to java at: " << arg1 << endl;
524
525        //load a dummy jvm for comparison
526        Jvm givenJvm;
527        if ( !givenJvm.setVersionFromString(arg1) ) {
528            if ( verbose ) cout << "Could not parse that version string" << endl;
529            return -1;
530        }
531       
532        //compare
533        cout << foundJvm.compare( givenJvm );
534        return 0;
535
536       
537    //Launch Action
538    //---------------
539    } else if ( action == Launch ) {
540
541        if ( verbose ) cout << "Jar to launch: " << arg1 << endl;
542       
543        string cmd = "\"", output = "";
544        cmd.append( foundJvm.getExecutable() );
545        cmd.append( "\" -jar " );
546        cmd.append( arg1 );
547       
548        process( cmd, output );
549       
550    }
551   
552    return 0;
553}
554
Note: See TracBrowser for help on using the browser.