source: release-kits/shared/search4j/search4j.cpp@ 15133

Last change on this file since 15133 was 15133, checked in by oranfry, 13 years ago

added a hint option to search4j

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