/* * Search4j utility * Command Line utility to search a system for java, launch a jar, or compare java versions * base on launch4j */ #include #include #include #include using namespace std; #ifdef WINDOWS #include //minimal launch4j stuff #define NO_JAVA_FOUND 0 #define FOUND_JRE 1 #define FOUND_SDK 2 int foundJava = NO_JAVA_FOUND; char foundJavaVer[128] = {0}; //windows functions #define popen _popen #define strcmp _stricmp #endif /* WINDOWS */ //global variables bool verbose = false; bool use_minimum = false; string hint = ""; enum JvmProperty { JavaHome, Version, Executable }; enum Action { Find, Launch, Compare }; void replace_all ( std::string & str, std::string const & pattern, std::string const & replacement ) { std::string::size_type start = str.find( pattern, 0 ); while ( start != str.npos ) { str.replace( start, pattern.size(), replacement ); start = str.find( pattern, start+replacement.size() ); } } int process( string command, string &output ) { FILE *pPipe; /* Run command so that it writes its output to a pipe. Open this * pipe with read text attribute so that we can read it * like a text file. */ char cmd[1024]; strcpy(cmd, command.c_str()); //if ( verbose ) cout << "process(): running '" << command << "'" << endl; #ifdef WINDOWS if( (pPipe = popen( cmd, "rt" )) == NULL ) { if ( verbose ) cout << "could not start process" << endl; pclose( pPipe ); return -1; } #endif #ifndef WINDOWS if( (pPipe = popen( cmd, "r" )) == NULL ) { if ( verbose ) cout << "could not start process" << endl; pclose( pPipe ); return -1; } #endif //if ( verbose ) cout << "started process" << endl; /* Read pipe until end of file. */ while( !feof( pPipe ) ) { char psBuffer[128]; //if ( verbose ) cout << "get some data" << endl; if( fgets( psBuffer, 128, pPipe ) != NULL ) { //if ( verbose ) cout << "got: " << psBuffer << endl; output.append( psBuffer ); } else { //if ( verbose ) cout << "none left" << endl; } } /* Close pipe and return return value of pPipe. */ int code = pclose( pPipe ); return code; } class Jvm { string javaHome; // version string. era.major.minor_update. eg: 1.4.2_02 int era; int major; int minor; int update; bool isJdk; bool healthy; public: Jvm() { healthy = false; } void setJavaHome( string jh ) { healthy = true; javaHome = jh; setVersionFromExeOuput(); } string getJavaHome() { return javaHome; } string getExecutable() { string exec = ""; exec.append( javaHome ); #ifdef WINDOWS exec.append( "\\bin\\java.exe" ); #endif #ifndef WINDOWS exec.append( "/bin/java" ); #endif return exec; } string getVersion() { stringstream ss; ss << era << "." << major << "." << minor << "_" << update; return ss.str(); } bool check() { return healthy; } bool setVersionFromString( string version ) { era = atoi( version.substr(0,1).c_str() ); major = atoi( version.substr(2,1).c_str() ); minor = atoi( version.substr(4,1).c_str() ); update = atoi( version.substr(6,2).c_str() ); return true; } int compare( Jvm otherJvm ) { //era if ( era > otherJvm.getEra() ) return 1; else if ( era < otherJvm.getEra() ) return -1; //major if ( major > otherJvm.getMajor() ) return 1; else if ( major < otherJvm.getMajor() ) return -1; //minor if ( minor > otherJvm.getMinor() ) return 1; else if ( minor < otherJvm.getMinor() ) return -1; //update if ( update > otherJvm.getUpdate() ) return 1; else if ( update < otherJvm.getUpdate() ) return -1; //all the same so far, must be exactly the same return 0; } int getEra() { return era; } int getMajor() { return major; } int getMinor() { return minor; } int getUpdate() { return update; } private: void setVersionFromExeOuput() { string command = "", output = ""; command.append( "\"" ); command.append( getExecutable() ); command.append( "\"" ); command.append(" -version 2>&1"); //cout << "(command: " << command << ")"; int result = process( command, output ); //cout << "(output: " << output << ")"; if ( result == 0 ) { if ( strcmp( output.substr( 0, 12 ).c_str() , "java version" ) == 0 || true ) { era = atoi( output.substr(14,1).c_str() ); major = atoi( output.substr(16,1).c_str() ); minor = atoi( output.substr(18,1).c_str() ); update = atoi( output.substr(20,2).c_str() ); //if ( verbose) cout << "set version to: " << era << "." << major << "." << minor << "_" << update << endl; } else { healthy=false; } } else { healthy = false; } } }; string actionToString( Action a ) { if ( a == Find ) return "Find"; else if ( a == Launch ) return "Launch"; else if ( a == Compare ) return "Compare"; return "Unknown"; } string jvmPropertyToString( JvmProperty jp ) { if ( jp == JavaHome ) return "JavaHome"; else if ( jp == Version ) return "Version"; else if ( jp == Executable ) return "Executable"; return "Unknown"; } void usage() { cout << "-----------------" << endl << " search4j: usage" << endl << "-----------------" << endl << "Three usage methods: find, compare and launch" << endl << endl << "find: find java and print out information about it" << endl << endl << " search4j [-v|-e]" << endl << " eg: search4j -e" << endl << endl << " by default, print JAVA_HOME. E.g., C:\\Program Files\\jre1.5.0_15, or" << endl << " if -v is specified, print the java version string. E.g. 1.5.0_15, or" << endl << " 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 << endl << "compare: compare the found java with the given java version string" << endl << endl << " search4j -c VERSION_STRING" << endl << " eg: search4j -c VERSION_STRING" << endl << endl << " print -1 if found java is older" << endl << " print 0 if found java is same" << endl << " print 1 if found java is newer" << endl << endl << "launch: launch the given executable jar with the found java" << endl << endl << " search4j -l EXECUTABLE_JAR [-m VERSION_STRING]" << endl << " eg: search4j -l greenstone3.jar" << endl << endl << " specify the location of the jar relative to the current directory" << endl << endl << "Global Options:" << endl << " -m VERSION_STRING: (minimum) find a java of the given version or newer, or fail" << endl << " -h LOCATION: (hint) as a last resort look for java in LOCATION (treated as a JAVA_HOME)" << endl << " --verbose : have search4j print out information about what its doing" << endl << " --help : display this usage screen" << endl << endl ; } //another global Jvm minimum; #ifdef WINDOWS void regSearch(HKEY hKey, const char* keyName, int searchType) { DWORD x = 0; unsigned long size = 1024; FILETIME time; char buffer[1024] = {0}; while (RegEnumKeyEx( hKey, // handle to key to enumerate x++, // index of subkey to enumerate buffer, // address of buffer for subkey name &size, // address for size of subkey buffer NULL, // reserved NULL, // address of buffer for class string NULL, // address for size of class buffer &time) == ERROR_SUCCESS) { strcpy(foundJavaVer, buffer); foundJava = searchType; size = 1024; } } #endif /* * function to find java * implements the logic drawn on the dl lab whiteboard in feb 08 * return a Jvm object which represents the jvm on disk */ bool find( Jvm &jvm ) { if ( verbose ) cout << "Searching for a JVM" << endl; char *javaHome = ""; bool jvmFound = false; if ( !jvmFound ) { //try JAVA_HOME if ( verbose ) cout << " - trying JAVA_HOME: "; javaHome = getenv( "JAVA_HOME" ); if ( javaHome != NULL ) { if ( verbose ) cout << "(" << javaHome << ") "; jvm.setJavaHome( javaHome ); if ( jvm.check() ) { if ( use_minimum ) { if ( jvm.compare( minimum ) >= 0 ) { jvmFound = true; } } else { jvmFound = true; } } } if ( verbose ) { if( jvmFound ) cout << "yes" << endl; else cout << "no" << endl; } } if ( !jvmFound ) { //try JRE_HOME if ( verbose ) cout << " - trying JRE_HOME: "; javaHome = getenv( "JRE_HOME" ); if ( javaHome != NULL ) { if ( verbose ) cout << "(" << javaHome << ") "; jvm.setJavaHome( javaHome ); if ( jvm.check() ) { if ( use_minimum ) { if ( jvm.compare( minimum ) >= 0 ) { jvmFound = true; } } else { jvmFound = true; } } } if ( verbose ) { if( jvmFound ) cout << "yes" << endl; else cout << "no" << endl; } } #ifdef WINDOWS if ( !jvmFound ) { //try the registry - this code based on launch4j code if ( verbose ) cout << " - trying the registry: "; HKEY hKey; const char jre[] = "SOFTWARE\\JavaSoft\\Java Runtime Environment"; const char sdk[] = "SOFTWARE\\JavaSoft\\Java Development Kit"; if ( RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT(jre), 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &hKey) == ERROR_SUCCESS ) { regSearch(hKey, jre, FOUND_JRE); RegCloseKey(hKey); } if ( RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT(sdk), 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &hKey) == ERROR_SUCCESS ) { regSearch(hKey, sdk, FOUND_SDK); RegCloseKey(hKey); } if ( foundJava != NO_JAVA_FOUND ) { char path[1024] = {0}; char keyBuffer[1024]; unsigned long datatype; unsigned long bufferlength = 1024; if (foundJava == FOUND_JRE) { strcpy(keyBuffer, jre); } else { strcpy(keyBuffer, sdk); } strcat(keyBuffer, "\\"); strcat(keyBuffer, foundJavaVer); if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT(keyBuffer), 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) { unsigned char buffer[1024] = {0}; if (RegQueryValueEx(hKey, "JavaHome", NULL, &datatype, buffer, &bufferlength) == ERROR_SUCCESS) { int i = 0; do { path[i] = buffer[i]; } while (path[i++] != 0); if (foundJava == FOUND_SDK) { strcat(path, "\\jre"); } jvm.setJavaHome( path ); if ( jvm.check() ) { if ( use_minimum ) { if ( jvm.compare( minimum ) >= 0 ) { jvmFound = true; } } else { jvmFound = true; } } } RegCloseKey(hKey); } } if ( verbose ) { if( jvmFound ) cout << "yes" << endl; else cout << "no" << endl; } } #endif if ( !jvmFound ) { //try the hint if ( verbose ) cout << " - trying hint: "; if ( strcmp(hint.c_str(),"") != 0 ) { if ( verbose ) cout << "(" << hint << ") "; jvm.setJavaHome( hint ); if ( jvm.check() ) { if ( use_minimum ) { if ( jvm.compare( minimum ) >= 0 ) { jvmFound = true; } } else { jvmFound = true; } } } if ( verbose ) { if( jvmFound ) cout << "yes" << endl; else cout << "no" << endl; } } return jvmFound; } int main ( int argc, char** argv ) { //cout << "testing process()" << endl; //string out = ""; //process( "dir", out ); //cout << out << endl; //return 0; JvmProperty jvmProperty = JavaHome; Action action = Find; string arg1 = ""; //parse commandline arguments for (int i=1; i