New src/macosx/bundle/appbundler/native/main.m (original) (raw)
1 /* 2 * Copyright 2012 Oracle and/or its affiliates. All rights reserved. 3 / 4 5 #import <Cocoa/Cocoa.h> 6 #include <jni.h> 7 8 #define JAVA_LAUNCH_ERROR "JavaLaunchError" 9 10 #define JAVA_KEY "Java" 11 #define RUNTIME_KEY "Runtime" 12 #define MAIN_CLASS_NAME_KEY "MainClassName" 13 #define OPTIONS_KEY "Options" 14 #define ARGUMENTS_KEY "Arguments" 15 16 // TODO Remove these; they are defined by the makefile 17 #define FULL_VERSION "1.7.0" 18 #define DOT_VERSION "1.7.0" 19 #define DEFAULT_POLICY 0 20 21 typedef int (JNICALL JLI_Launch_t)(int argc, char ** argv, 22 int jargc, const char jargv, 23 int appclassc, const char** appclassv, 24 const char* fullversion, 25 const char* dotversion, 26 const char* pname, 27 const char* lname, 28 jboolean javaargs, 29 jboolean cpwildcard, 30 jboolean javaw, 31 jint ergo); 32 33 int launch(char *); 34 int jli_launch(char *, NSURL *, NSString *, NSString *, NSString *, NSArray *, NSArray *); 35 36 int main(int argc, char *argv[]) { 37 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 38 39 int result; 40 @try { 41 launch(argv[0]); 42 result = 0; 43 } @catch (NSException *exception) { 44 NSLog(@"%@: %@", exception, [exception callStackSymbols]); 45 result = 1; 46 } 47 48 [pool drain]; 49 50 return result; 51 } 52 53 int launch(char *commandName) { 54 // Get the main bundle 55 NSBundle *mainBundle = [NSBundle mainBundle]; 56 NSDictionary *infoDictionary = [mainBundle infoDictionary]; 57 58 NSString *javaPath = [[mainBundle bundlePath] stringByAppendingString:@"/Contents/Java"]; 59 60 // Get the Java dictionary 61 NSDictionary *javaDictionary = [infoDictionary objectForKey:@JAVA_KEY]; 62 if (javaDictionary == nil) { 63 [NSException raise:@JAVA_LAUNCH_ERROR format:@"%@ is required.", @JAVA_KEY]; 64 } 65 66 // Get the runtime bundle URL 67 NSString *runtime = [javaDictionary objectForKey:@RUNTIME_KEY]; 68 69 // TODO If unspecified, use default runtime location 70 71 NSURL *runtimeBundleURL = [[mainBundle builtInPlugInsURL] URLByAppendingPathComponent:runtime]; 72 73 // Get the main class name 74 NSString *mainClassName = [javaDictionary objectForKey:@MAIN_CLASS_NAME_KEY]; 75 if (mainClassName == nil) { 76 [NSException raise:@JAVA_LAUNCH_ERROR format:@"%@ is required.", @MAIN_CLASS_NAME_KEY]; 77 } 78 79 // Set the class path 80 NSString *classPathFormat = @"-Djava.class.path=%@/Classes"; 81 NSMutableString *classPath = [[NSString stringWithFormat:classPathFormat, javaPath] mutableCopy]; 82 83 NSFileManager *defaultFileManager = [NSFileManager defaultManager]; 84 NSArray *javaDirectoryContents = [defaultFileManager contentsOfDirectoryAtPath:javaPath error:nil]; 85 if (javaDirectoryContents == nil) { 86 [NSException raise:@JAVA_LAUNCH_ERROR format:@"Could not enumerate Java directory contents."]; 87 } 88 89 for (NSString *file in javaDirectoryContents) { 90 if ([file hasSuffix:@".jar"]) { 91 [classPath appendFormat:@":%@/%@", javaPath, file]; 92 } 93 } 94 95 // Set the library path 96 NSString *libraryPathFormat = @"-Djava.library.path=%@"; 97 NSString *libraryPath = [NSString stringWithFormat:libraryPathFormat, javaPath]; 98 99 // Get the VM options 100 NSArray *options = [javaDictionary objectForKey:@OPTIONS_KEY]; 101 if (options == nil) { 102 options = [NSArray array]; 103 } 104 105 // Get the application arguments 106 NSArray *arguments = [javaDictionary objectForKey:@ARGUMENTS_KEY]; 107 if (arguments == nil) { 108 arguments = [NSArray array]; 109 } 110 111 return jli_launch(commandName, runtimeBundleURL, 112 mainClassName, classPath, libraryPath, 113 options, arguments); 114 } 115 116 int jli_launch(char *commandName, NSURL *runtimeBundleURL, 117 NSString *mainClassName, NSString *classPath, NSString *libraryPath, 118 NSArray *options, NSArray *arguments) { 119 // Load the runtime bundle 120 CFBundleRef runtimeBundle = CFBundleCreate(NULL, (CFURLRef)runtimeBundleURL); 121 122 NSError *bundleLoadError = nil; 123 Boolean runtimeBundleLoaded = CFBundleLoadExecutableAndReturnError(runtimeBundle, (CFErrorRef *)&bundleLoadError); 124 if (bundleLoadError != nil || !runtimeBundleLoaded) { 125 [NSException raise:@JAVA_LAUNCH_ERROR format:@"Could not load JRE from %@.", bundleLoadError]; 126 } 127 128 // Get the JLI_Launch() function pointer 129 JLI_Launch_t JLI_LaunchFxnPtr = CFBundleGetFunctionPointerForName(runtimeBundle, CFSTR("JLI_Launch")); 130 if (JLI_LaunchFxnPtr == NULL) { 131 [NSException raise:@JAVA_LAUNCH_ERROR format:@"Could not get function pointer for JLI_Launch."]; 132 } 133 134 // Initialize the arguments to JLI_Launch() 135 int argc = 1 + [options count] + 2 + [arguments count] + 1; 136 char *argv[argc]; 137 138 int i = 0; 139 argv[i++] = commandName; 140 argv[i++] = strdup([classPath UTF8String]); 141 argv[i++] = strdup([libraryPath UTF8String]); 142 143 for (NSString *option in options) { 144 argv[i++] = strdup([option UTF8String]); 145 } 146 147 argv[i++] = strdup([mainClassName UTF8String]); 148 149 for (NSString *argument in arguments) { 150 argv[i++] = strdup([argument UTF8String]); 151 } 152 153 // Invoke JLI_Launch() 154 return JLI_LaunchFxnPtr(argc, argv, 155 0, NULL, 156 0, NULL, 157 FULL_VERSION, 158 DOT_VERSION, 159 "java", 160 "java", 161 FALSE, 162 TRUE, 163 FALSE, 164 DEFAULT_POLICY); 165 }