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

Last change on this file since 15093 was 15093, checked in by oranfry, 16 years ago

importing the search4j tool I wrote for the release kits

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