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

Last change on this file since 15103 was 15103, checked in by oranfry, 14 years ago

massaged search4j to work in windows and linux

File size: 13.6 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;
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 repository browser.