1/* 2 * JavaAppLauncher: a simple Java application launcher for Mac OS X. 3 * SetJVMVersion.mm 4 * 5 * Paul J. Lucas [paul@lightcrafts.com] 6 */ 7 8// standard 9#import <Cocoa/Cocoa.h> 10#ifdef DEBUG 11#import <iostream> 12#endif 13#import <sys/types.h> 14#import <dirent.h> 15 16// local 17#import "LC_CocoaUtils.h" 18#import "UI.h" 19 20using namespace std; 21using namespace LightCrafts; 22 23/** 24 * Set the preferred JVM version via the JAVA_JVM_VERSION environment variable. 25 */ 26void setJVMVersion( char const *jvmVersion ) { 27 auto_obj<NSAutoreleasePool> pool; 28 29 enum match_mode_t { 30 // 31 // Must exactly match the specified version. 32 // 33 MatchSpecifiedOnly, 34 35 // 36 // Must match the specified version or any later version, but within 37 // the same minor revision, e.g., "1.4.2" is a match for "1.4*" but 38 // "1.5" is not. 39 // 40 MatchSpecifiedOrLater, 41 42 // 43 // Must match the specified version or any later version. 44 // 45 MatchSpecifiedOrLatest 46 }; 47 match_mode_t matchMode; 48 49 // 50 // Determine the match mode we should use. 51 // 52 int const len = ::strlen( jvmVersion ); 53 switch ( jvmVersion[ len - 1 ] ) { 54 case '*': 55 matchMode = MatchSpecifiedOrLater; 56 break; 57 case '+': 58 matchMode = MatchSpecifiedOrLatest; 59 break; 60 default: 61 matchMode = MatchSpecifiedOnly; 62 } 63 64 // 65 // Get the path to the Java Versions directory. 66 // 67 NSBundle *const javaBundle = 68 [NSBundle bundleWithIdentifier:@"com.apple.JavaVM"]; 69 if ( !javaBundle ) 70 LC_die( @"Unexpected", @"Missing Java" ); 71 NSString *const javaVersionsPath = 72 [[javaBundle bundlePath] stringByAppendingPathComponent:@"Versions"]; 73 74 // 75 // Read the names of all the subdirectories (or symbolic links thereto) 76 // that list the Java versions available and look for the best match. 77 // 78 DIR *const dir = ::opendir( [javaVersionsPath fileSystemRepresentation] ); 79 if ( !dir ) 80 LC_die( @"Unexpected", @"Couldn't read Versions directory" ); 81 82 int jvmMajor, jvmMinor = 0, jvmPoint = 0; 83 ::sscanf( jvmVersion, "%d.%d.%d", &jvmMajor, &jvmMinor, &jvmPoint ); 84 85 char bestJVMVersion[ 16 ]; // more than enough 86 *bestJVMVersion = '\0'; 87 int bestMajor = 0, bestMinor = 0, bestPoint = 0; 88 89 for ( struct dirent const *entry; entry = ::readdir( dir ); ) { 90 if ( !isdigit( *entry->d_name ) ) 91 continue; 92 int dirMajor, dirMinor, dirPoint; 93 ::sscanf( entry->d_name, "%d.%d.%d", &dirMajor, &dirMinor, &dirPoint ); 94 switch ( matchMode ) { 95 96 case MatchSpecifiedOnly: 97 if ( dirMajor == jvmMajor && dirMinor == jvmMinor && 98 dirPoint == jvmPoint 99 ) { 100 ::strcpy( bestJVMVersion, entry->d_name ); 101 goto done; 102 } 103 break; 104 105 case MatchSpecifiedOrLater: 106 if ( dirMajor == jvmMajor && dirMinor == jvmMinor && 107 dirPoint >= jvmPoint && dirPoint >= bestPoint 108 ) { 109 ::strcpy( bestJVMVersion, entry->d_name ); 110 bestPoint = dirPoint; 111 } 112 break; 113 114 case MatchSpecifiedOrLatest: 115 if ( dirMajor >= jvmMajor && dirMinor >= jvmMinor && 116 dirPoint >= jvmPoint 117 ) { 118 ::strcpy( bestJVMVersion, entry->d_name ); 119 bestMajor = dirMajor; 120 bestMinor = dirMinor; 121 bestPoint = dirPoint; 122 } 123 break; 124 } 125 } 126 127done: 128 ::closedir( dir ); 129 if ( !*bestJVMVersion ) 130 LC_dieWithoutLocalizedInfo( @"Required Java version not found", 131 [NSString stringWithFormat: 132 NSLocalizedString( @"Couldn't match Java version", nil ), 133 jvmVersion] 134 ); 135 136#ifdef DEBUG 137 cout << "Setting JAVA_JVM_VERSION=" << bestJVMVersion << endl; 138#endif 139 ::setenv( "JAVA_JVM_VERSION", bestJVMVersion, 1 ); 140} 141 142/* vim:set et sw=4 ts=4: */ 143