1 /* 2 * Copyright 2012, Oracle and/or its affiliates. All rights reserved. 3 * 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. Oracle designates this 9 * particular file as subject to the "Classpath" exception as provided 10 * by Oracle in the LICENSE file that accompanied this code. 11 * 12 * This code is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 * version 2 for more details (a copy is included in the LICENSE file that 16 * accompanied this code). 17 * 18 * You should have received a copy of the GNU General Public License version 19 * 2 along with this work; if not, write to the Free Software Foundation, 20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 21 * 22 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 23 * or visit www.oracle.com if you need additional information or have any 24 * questions. 25 */ 26 27 #import <Cocoa/Cocoa.h> 28 #include <jni.h> 29 30 #define JAVA_LAUNCH_ERROR "JavaLaunchError" 31 32 #define JAVA_VM_KEY "JavaVM" 33 #define RUNTIME_KEY "Runtime" 34 #define MAIN_CLASS_NAME_KEY "MainClassName" 35 #define OPTIONS_KEY "Options" 36 #define ARGUMENTS_KEY "Arguments" 37 38 // TODO Remove these; they are defined by the makefile 39 #define FULL_VERSION "1.7.0" 40 #define DOT_VERSION "1.7.0" 41 #define DEFAULT_POLICY 0 42 43 typedef int (JNICALL *JLI_Launch_t)(int argc, char ** argv, 44 int jargc, const char** jargv, 45 int appclassc, const char** appclassv, 46 const char* fullversion, 47 const char* dotversion, 48 const char* pname, 49 const char* lname, 50 jboolean javaargs, 51 jboolean cpwildcard, 52 jboolean javaw, 53 jint ergo); 54 55 int launch(char *); 56 int jli_launch(char *, NSURL *, NSString *, NSString *, NSString *, NSArray *, NSArray *); 57 58 int main(int argc, char *argv[]) { 59 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 60 61 int result; 62 @try { 63 launch(argv[0]); 64 result = 0; 65 } @catch (NSException *exception) { 66 NSLog(@"%@: %@", exception, [exception callStackSymbols]); 67 result = 1; 68 } 69 70 [pool drain]; 71 72 return result; 73 } 74 75 int launch(char *commandName) { 76 // Get the main bundle 77 NSBundle *mainBundle = [NSBundle mainBundle]; 78 NSDictionary *infoDictionary = [mainBundle infoDictionary]; 79 80 NSString *javaVMPath = [[mainBundle bundlePath] stringByAppendingString:@"/Contents/JavaVM"]; 81 82 // Get the Java dictionary 83 NSDictionary *javaVMDictionary = [infoDictionary objectForKey:@JAVA_VM_KEY]; 84 if (javaVMDictionary == nil) { 85 [NSException raise:@JAVA_LAUNCH_ERROR format:@"%@ is required.", @JAVA_VM_KEY]; 86 } 87 88 // Get the runtime bundle URL 89 NSString *runtime = [javaVMDictionary objectForKey:@RUNTIME_KEY]; 90 91 // TODO If unspecified, use default runtime location 92 93 NSURL *runtimeBundleURL = [[mainBundle builtInPlugInsURL] URLByAppendingPathComponent:runtime]; 94 95 // Get the main class name 96 NSString *mainClassName = [javaVMDictionary objectForKey:@MAIN_CLASS_NAME_KEY]; 97 if (mainClassName == nil) { 98 [NSException raise:@JAVA_LAUNCH_ERROR format:@"%@ is required.", @MAIN_CLASS_NAME_KEY]; 99 } 100 101 // Set the class path 102 NSString *classPathFormat = @"-Djava.class.path=%@/Classes"; 103 NSMutableString *classPath = [[NSString stringWithFormat:classPathFormat, javaVMPath] mutableCopy]; 104 105 NSFileManager *defaultFileManager = [NSFileManager defaultManager]; 106 NSArray *javaDirectoryContents = [defaultFileManager contentsOfDirectoryAtPath:javaVMPath error:nil]; 107 if (javaDirectoryContents == nil) { 108 [NSException raise:@JAVA_LAUNCH_ERROR format:@"Could not enumerate Java directory contents."]; 109 } 110 111 for (NSString *file in javaDirectoryContents) { 112 if ([file hasSuffix:@".jar"]) { 113 [classPath appendFormat:@":%@/%@", javaVMPath, file]; 114 } 115 } 116 117 // Set the library path 118 NSString *libraryPathFormat = @"-Djava.library.path=%@"; 119 NSString *libraryPath = [NSString stringWithFormat:libraryPathFormat, javaVMPath]; 120 121 // Get the VM options 122 NSArray *options = [javaVMDictionary objectForKey:@OPTIONS_KEY]; 123 if (options == nil) { 124 options = [NSArray array]; 125 } 126 127 // Get the application arguments 128 NSArray *arguments = [javaVMDictionary objectForKey:@ARGUMENTS_KEY]; 129 if (arguments == nil) { 130 arguments = [NSArray array]; 131 } 132 133 return jli_launch(commandName, runtimeBundleURL, 134 mainClassName, classPath, libraryPath, 135 options, arguments); 136 } 137 138 int jli_launch(char *commandName, NSURL *runtimeBundleURL, 139 NSString *mainClassName, NSString *classPath, NSString *libraryPath, 140 NSArray *options, NSArray *arguments) { 141 // Load the runtime bundle 142 CFBundleRef runtimeBundle = CFBundleCreate(NULL, (CFURLRef)runtimeBundleURL); 143 144 NSError *bundleLoadError = nil; 145 Boolean runtimeBundleLoaded = CFBundleLoadExecutableAndReturnError(runtimeBundle, (CFErrorRef *)&bundleLoadError); 146 if (bundleLoadError != nil || !runtimeBundleLoaded) { 147 [NSException raise:@JAVA_LAUNCH_ERROR format:@"Could not load JRE from %@.", bundleLoadError]; 148 } 149 150 // Get the JLI_Launch() function pointer 151 JLI_Launch_t JLI_LaunchFxnPtr = CFBundleGetFunctionPointerForName(runtimeBundle, CFSTR("JLI_Launch")); 152 if (JLI_LaunchFxnPtr == NULL) { 153 [NSException raise:@JAVA_LAUNCH_ERROR format:@"Could not get function pointer for JLI_Launch."]; 154 } 155 156 // Initialize the arguments to JLI_Launch() 157 int argc = 1 + [options count] + 2 + [arguments count] + 1; 158 char *argv[argc]; 159 160 int i = 0; 161 argv[i++] = commandName; 162 argv[i++] = strdup([classPath UTF8String]); 163 argv[i++] = strdup([libraryPath UTF8String]); 164 165 for (NSString *option in options) { 166 argv[i++] = strdup([option UTF8String]); 167 } 168 169 argv[i++] = strdup([mainClassName UTF8String]); 170 171 for (NSString *argument in arguments) { 172 argv[i++] = strdup([argument UTF8String]); 173 } 174 175 // Invoke JLI_Launch() 176 return JLI_LaunchFxnPtr(argc, argv, 177 0, NULL, 178 0, NULL, 179 FULL_VERSION, 180 DOT_VERSION, 181 "java", 182 "java", 183 FALSE, 184 FALSE, 185 FALSE, 186 DEFAULT_POLICY); 187 }