Snapshot of commit d5ec1d5018ed24f1b4f32b1d09df6dbd7e2fc425
from branch master of git://git.jetbrains.org/idea/community.git
diff --git a/native/MacLauncher/.idea/.name b/native/MacLauncher/.idea/.name
new file mode 100644
index 0000000..dc9c257
--- /dev/null
+++ b/native/MacLauncher/.idea/.name
@@ -0,0 +1 @@
+MacLauncher
\ No newline at end of file
diff --git a/native/MacLauncher/.idea/AppLauncher.iml b/native/MacLauncher/.idea/AppLauncher.iml
new file mode 100644
index 0000000..f9b36de
--- /dev/null
+++ b/native/MacLauncher/.idea/AppLauncher.iml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="CIDR_MODULE" version="4">
+ <component name="NewModuleRootManager">
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$" isTestSource="false" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ </component>
+</module>
+
diff --git a/native/MacLauncher/.idea/dictionaries/max.xml b/native/MacLauncher/.idea/dictionaries/max.xml
new file mode 100644
index 0000000..81b3e8d
--- /dev/null
+++ b/native/MacLauncher/.idea/dictionaries/max.xml
@@ -0,0 +1,3 @@
+<component name="ProjectDictionaryState">
+ <dictionary name="max" />
+</component>
\ No newline at end of file
diff --git a/native/MacLauncher/.idea/encodings.xml b/native/MacLauncher/.idea/encodings.xml
new file mode 100644
index 0000000..e206d70
--- /dev/null
+++ b/native/MacLauncher/.idea/encodings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" />
+</project>
+
diff --git a/native/MacLauncher/.idea/find.xml b/native/MacLauncher/.idea/find.xml
new file mode 100644
index 0000000..6892330
--- /dev/null
+++ b/native/MacLauncher/.idea/find.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="OCFindUsagesOptions" text="true" ivars="false" properties="true" derivedClasses="false" />
+</project>
+
diff --git a/native/MacLauncher/.idea/misc.xml b/native/MacLauncher/.idea/misc.xml
new file mode 100644
index 0000000..11e74ae
--- /dev/null
+++ b/native/MacLauncher/.idea/misc.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ProjectResources">
+ <default-html-doctype>http://www.w3.org/1999/xhtml</default-html-doctype>
+ </component>
+ <component name="ProjectRootManager" version="2" />
+</project>
+
diff --git a/native/MacLauncher/.idea/modules.xml b/native/MacLauncher/.idea/modules.xml
new file mode 100644
index 0000000..e774462
--- /dev/null
+++ b/native/MacLauncher/.idea/modules.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ProjectModuleManager">
+ <modules>
+ <module fileurl="file://$PROJECT_DIR$/.idea/AppLauncher.iml" filepath="$PROJECT_DIR$/.idea/AppLauncher.iml" />
+ </modules>
+ </component>
+</project>
+
diff --git a/native/MacLauncher/.idea/scopes/scope_settings.xml b/native/MacLauncher/.idea/scopes/scope_settings.xml
new file mode 100644
index 0000000..922003b
--- /dev/null
+++ b/native/MacLauncher/.idea/scopes/scope_settings.xml
@@ -0,0 +1,5 @@
+<component name="DependencyValidationManager">
+ <state>
+ <option name="SKIP_IMPORT_STATEMENTS" value="false" />
+ </state>
+</component>
\ No newline at end of file
diff --git a/native/MacLauncher/.idea/vcs.xml b/native/MacLauncher/.idea/vcs.xml
new file mode 100644
index 0000000..9ab281a
--- /dev/null
+++ b/native/MacLauncher/.idea/vcs.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="VcsDirectoryMappings">
+ <mapping directory="$PROJECT_DIR$/../.." vcs="Git" />
+ </component>
+</project>
+
diff --git a/native/MacLauncher/.idea/xcode.xml b/native/MacLauncher/.idea/xcode.xml
new file mode 100644
index 0000000..28f4cb3
--- /dev/null
+++ b/native/MacLauncher/.idea/xcode.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="XcodeMetaData" PROJECT_FILE="$PROJECT_DIR$/MacLauncher.xcodeproj" />
+</project>
+
diff --git a/native/MacLauncher/Info.plist b/native/MacLauncher/Info.plist
new file mode 100644
index 0000000..a189b85
--- /dev/null
+++ b/native/MacLauncher/Info.plist
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>en</string>
+ <key>CFBundleExecutable</key>
+ <string>${EXECUTABLE_NAME}</string>
+ <key>CFBundleIconFile</key>
+ <string></string>
+ <key>CFBundleIdentifier</key>
+ <string>JetBrains.${PRODUCT_NAME:rfc1034identifier}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+ <key>Java</key>
+ <dict>
+ <key>ClassPath</key>
+ <string>$APP_PACKAGE</string>
+ <key>MainClass</key>
+ <string>com.intellij.idea.Main</string>
+ <key>Properties</key>
+ <dict>
+ <key>CVS_PASSFILE</key>
+ <string>~/.cvspass</string>
+ <key>apple.laf.useScreenMenuBar</key>
+ <string>true</string>
+ <key>com.apple.mrj.application.live-resize</key>
+ <string>false</string>
+ <key>idea.config.path</key>
+ <string>~/Library/Preferences/IntelliJIdea10CE/</string>
+ <key>idea.is.internal</key>
+ <string>true</string>
+ <key>idea.log.path</key>
+ <string>~/Library/Logs/IntelliJIdea10CE/</string>
+ <key>idea.platform.prefix</key>
+ <string>Idea</string>
+ <key>idea.plugins.path</key>
+ <string>~/Library/Application Support/IntelliJIdea10CE/</string>
+ <key>idea.system.path</key>
+ <string>~/Library/Caches/IntelliJIdea10CE/</string>
+ <key>idea.use.default.antialiasing.in.editor</key>
+ <string>true</string>
+ </dict>
+ <key>VMOptions</key>
+ <string>-ea</string>
+ <key>VMOptions.i386</key>
+ <string>-Xms128m -Xmx512m -XX:MaxPermSize=250m</string>
+ <key>VMOptions.x86_64</key>
+ <string>-Xms128m -Xmx800m -XX:MaxPermSize=350m -XX:+UseCompressedOops -XX:ReservedCodeCacheSize=256m</string>
+ <key>WorkingDirectory</key>
+ <string>$APP_PACKAGE/bin</string>
+ </dict>
+ <key>LSMinimumSystemVersion</key>
+ <string>${MACOSX_DEPLOYMENT_TARGET}</string>
+ <key>NSHumanReadableCopyright</key>
+ <string>Copyright © 2012 JetBrains inc. All rights reserved.</string>
+ <key>NSMainNibFile</key>
+ <string>MainMenu</string>
+ <key>NSPrincipalClass</key>
+ <string>NSApplication</string>
+</dict>
+</plist>
diff --git a/native/MacLauncher/Launcher.h b/native/MacLauncher/Launcher.h
new file mode 100644
index 0000000..ec34086
--- /dev/null
+++ b/native/MacLauncher/Launcher.h
@@ -0,0 +1,20 @@
+//
+// Created by max on 5/4/12.
+//
+// To change the template use AppCode | Preferences | File Templates.
+//
+
+
+#import <Foundation/Foundation.h>
+#import <JavaVM/jni.h>
+
+
+@interface Launcher : NSObject {
+ int argc;
+ char **argv;
+}
+- (id)initWithArgc:(int)anArgc argv:(char **)anArgv;
+
+
+- (void) launch;
+@end
\ No newline at end of file
diff --git a/native/MacLauncher/Launcher.m b/native/MacLauncher/Launcher.m
new file mode 100644
index 0000000..f00945c
--- /dev/null
+++ b/native/MacLauncher/Launcher.m
@@ -0,0 +1,388 @@
+//
+// Created by max on 5/4/12.
+//
+// To change the template use AppCode | Preferences | File Templates.
+//
+
+
+#import "Launcher.h"
+#import "VMOptionsReader.h"
+#import "PropertyFileReader.h"
+#import "utils.h"
+#import <dlfcn.h>
+
+typedef jint (JNICALL *fun_ptr_t_CreateJavaVM)(JavaVM **pvm, void **env, void *args);
+
+
+@interface NSString (CustomReplacements)
+- (NSString *)replaceAll:(NSString *)pattern to:(NSString *)replacement;
+
+@end
+
+@implementation NSString (CustomReplacements)
+- (NSString *)replaceAll:(NSString *)pattern to:(NSString *)replacement {
+ if ([self rangeOfString:pattern].length == 0) return self;
+
+ NSMutableString *answer = [[self mutableCopy] autorelease];
+ [answer replaceOccurrencesOfString:pattern withString:replacement options:0 range:NSMakeRange(0, [self length])];
+ return answer;
+}
+@end
+
+@interface NSDictionary (TypedGetters)
+- (NSDictionary *)dictionaryForKey:(id)key;
+- (id)valueForKey:(NSString *)key inDictionary:(NSString *)dictKey defaultObject:(NSString *)defaultValue;
+@end
+
+@implementation NSDictionary (TypedGetters)
+- (NSDictionary *)dictionaryForKey:(id)key {
+ id answer = [self objectForKey:key];
+ if ([answer isKindOfClass:[NSDictionary class]]) {
+ return answer;
+ }
+ return nil;
+}
+
+- (id)valueForKey:(NSString *)key inDictionary:(NSString *)dictKey defaultObject: (NSString*) defaultValue {
+ NSDictionary *dict = [self dictionaryForKey:dictKey];
+ if (dict == nil) return nil;
+ id answer = [dict valueForKey:key];
+ return answer != nil ? answer : defaultValue;
+}
+@end
+
+@implementation Launcher
+
+- (id)initWithArgc:(int)anArgc argv:(char **)anArgv {
+ self = [super init];
+ if (self) {
+ argc = anArgc;
+ argv = anArgv;
+ }
+
+ return self;
+}
+
+
+void appendJvmBundlesAt(NSString *path, NSMutableArray *sink) {
+ NSError *error = nil;
+ NSArray *names = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:&error];
+
+ if (names != nil) {
+ for (NSString *name in names) {
+ if ([name hasSuffix:@".jdk"] || [name hasSuffix:@".jre"]) {
+ NSBundle *bundle = [NSBundle bundleWithPath:[path stringByAppendingPathComponent:name]];
+ if (bundle != nil) {
+ [sink addObject:bundle];
+ }
+ }
+ }
+ }
+}
+
+NSArray *allVms() {
+ NSMutableArray *jvmBundlePaths = [NSMutableArray array];
+
+ NSString *explicit = [[[NSProcessInfo processInfo] environment] objectForKey:@"IDEA_JDK"];
+
+ if (explicit != nil) {
+ appendJvmBundlesAt(explicit, jvmBundlePaths);
+ }
+ else {
+ NSBundle *bundle = [NSBundle mainBundle];
+ NSString *appDir = bundle.bundlePath;
+
+ appendJvmBundlesAt([appDir stringByAppendingPathComponent:@"jre"], jvmBundlePaths);
+ if (jvmBundlePaths.count > 0) return jvmBundlePaths;
+
+ appendJvmBundlesAt([NSHomeDirectory() stringByAppendingPathComponent:@"Library/Java/JavaVirtualMachines"], jvmBundlePaths);
+ appendJvmBundlesAt(@"/Library/Java/JavaVirtualMachines", jvmBundlePaths);
+ appendJvmBundlesAt(@"/System/Library/Java/JavaVirtualMachines", jvmBundlePaths);
+ }
+
+ return jvmBundlePaths;
+}
+
+NSString *jvmVersion(NSBundle *bundle) {
+ return [bundle.infoDictionary valueForKey:@"JVMVersion" inDictionary:@"JavaVM" defaultObject:@"0"];
+}
+
+NSString *requiredJvmVersion() {
+ return [[NSBundle mainBundle].infoDictionary valueForKey:@"JVMVersion" inDictionary:@"Java" defaultObject:@"1.7*"];
+}
+
+BOOL satisfies(NSString *vmVersion, NSString *requiredVersion) {
+ if ([requiredVersion hasSuffix:@"+"]) {
+ requiredVersion = [requiredVersion substringToIndex:[requiredVersion length] - 1];
+ return [requiredVersion compare:vmVersion options:NSNumericSearch] <= 0;
+ }
+
+ if ([requiredVersion hasSuffix:@"*"]) {
+ requiredVersion = [requiredVersion substringToIndex:[requiredVersion length] - 1];
+ }
+
+ return [vmVersion hasPrefix:requiredVersion];
+}
+
+NSComparisonResult compareVMVersions(id vm1, id vm2, void *context) {
+ return [jvmVersion(vm2) compare:jvmVersion(vm1) options:NSNumericSearch];
+}
+
+NSBundle *findMatchingVm() {
+ NSArray *vmBundles = [allVms() sortedArrayUsingFunction:compareVMVersions context:NULL];
+
+ if (isDebugEnabled()) {
+ debugLog(@"Found Java Virtual Machines:");
+ for (NSBundle *vm in vmBundles) {
+ debugLog([vm bundlePath]);
+ }
+ }
+
+ NSString *required = requiredJvmVersion();
+ debugLog([NSString stringWithFormat:@"Required VM: %@", required]);
+
+ for (NSBundle *vm in vmBundles) {
+ if (satisfies(jvmVersion(vm), required)) {
+ debugLog(@"Chosen VM:");
+ debugLog([vm bundlePath]);
+ return vm;
+ }
+ }
+
+ debugLog(@"No matching VM found");
+
+ return nil;
+}
+
+CFBundleRef NSBundle2CFBundle(NSBundle *bundle) {
+ CFURLRef bundleURL = (CFURLRef) ([NSURL fileURLWithPath:bundle.bundlePath]);
+ return CFBundleCreate(kCFAllocatorDefault, bundleURL);
+}
+
+- (NSString *)expandMacros:(NSString *)str {
+ return [[str
+ replaceAll:@"$APP_PACKAGE" to:[[NSBundle mainBundle] bundlePath]]
+ replaceAll:@"$USER_HOME" to:NSHomeDirectory()];
+}
+
+- (NSMutableString *)buildClasspath:(NSBundle *)jvm {
+ NSDictionary *jvmInfo = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"Java"];
+ NSMutableString *classpathOption = [NSMutableString stringWithString:@"-Djava.class.path="];
+ [classpathOption appendString:[jvmInfo objectForKey:@"ClassPath"]];
+
+ NSString *toolsJar = [[jvm bundlePath] stringByAppendingString:@"/Contents/Home/lib/tools.jar"];
+ if ([[NSFileManager defaultManager] fileExistsAtPath:toolsJar]) {
+ [classpathOption appendString:@":"];
+ [classpathOption appendString:toolsJar];
+ }
+ return classpathOption;
+}
+
+
+NSString *getSelector() {
+ NSDictionary *jvmInfo = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"Java"];
+ NSDictionary *properties = [jvmInfo dictionaryForKey:@"Properties"];
+ if (properties != nil) {
+ return [properties objectForKey:@"idea.paths.selector"];
+ }
+ return nil;
+}
+
+NSString *getPreferencesFolderPath() {
+ return [NSString stringWithFormat:@"%@/Library/Preferences/%@", NSHomeDirectory(), getSelector()];
+}
+
+NSString *getPropertiesFilePath() {
+ return [getPreferencesFolderPath() stringByAppendingString:@"/idea.properites"];
+}
+
+NSString *getDefaultPropertiesFilePath() {
+ return [[[NSBundle mainBundle] bundlePath] stringByAppendingString:@"/bin/idea.properties"];
+}
+
+NSString *getDefaultVMOptionsFilePath() {
+ return [[[NSBundle mainBundle] bundlePath] stringByAppendingString:@"/bin/idea.vmoptions"];
+}
+
+NSString *getVMOptionsFilePath() {
+ return [getPreferencesFolderPath() stringByAppendingString:@"/idea.vmoptions"];
+}
+
+NSArray *parseVMOptions() {
+ NSArray *inConfig=[VMOptionsReader readFile:getVMOptionsFilePath()];
+ if (inConfig) return inConfig;
+ return [VMOptionsReader readFile:getDefaultVMOptionsFilePath()];
+}
+
+NSDictionary *parseProperties() {
+ NSDictionary *inConfig = [PropertyFileReader readFile:getPropertiesFilePath()];
+ if (inConfig) return inConfig;
+ return [PropertyFileReader readFile:getDefaultPropertiesFilePath()];
+}
+
+- (void)fillArgs:(NSMutableArray *)args_array fromProperties:(NSDictionary *)properties {
+ if (properties != nil) {
+ for (id key in properties) {
+ [args_array addObject:[NSString stringWithFormat:@"-D%@=%@", key, [properties objectForKey:key]]];
+ }
+ }
+}
+
+- (JavaVMInitArgs)buildArgsFor:(NSBundle *)jvm {
+ NSMutableString *classpathOption = [self buildClasspath:jvm];
+
+ NSDictionary *jvmInfo = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"Java"];
+ NSMutableArray *args_array = [NSMutableArray array];
+
+ [args_array addObject:classpathOption];
+
+ [args_array addObjectsFromArray:[[jvmInfo objectForKey:@"VMOptions"] componentsSeparatedByString:@" "]];
+ [args_array addObjectsFromArray:parseVMOptions()];
+
+ [self fillArgs:args_array fromProperties:[jvmInfo dictionaryForKey:@"Properties"]];
+ [self fillArgs:args_array fromProperties:parseProperties()];
+
+ JavaVMInitArgs args;
+ args.version = JNI_VERSION_1_6;
+ args.ignoreUnrecognized = JNI_TRUE;
+
+ args.nOptions = (jint)[args_array count];
+ args.options = calloc((size_t) args.nOptions, sizeof(JavaVMOption));
+ for (NSUInteger idx = 0; idx < args.nOptions; idx++) {
+ id obj = [args_array objectAtIndex:idx];
+ args.options[idx].optionString = strdup([[self expandMacros:[obj description]] UTF8String]);
+ }
+ return args;
+}
+
+- (const char *)mainClassName {
+ NSDictionary *jvmInfo = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"Java"];
+ char *answer = strdup([[jvmInfo objectForKey:@"MainClass"] UTF8String]);
+
+ char *cur = answer;
+ while (*cur) {
+ if (*cur == '.') {
+ *cur = '/';
+ }
+ cur++;
+ }
+
+ return answer;
+}
+
+- (void)process_cwd {
+ NSDictionary *jvmInfo = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"Java"];
+ NSString *cwd = [jvmInfo objectForKey:@"WorkingDirectory"];
+ if (cwd != nil) {
+ cwd = [self expandMacros:cwd];
+ if (chdir([cwd UTF8String]) != 0) {
+ NSLog(@"Cannot chdir to working directory at %@", cwd);
+ }
+ }
+}
+
+- (void)launch {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ NSBundle *vm = findMatchingVm();
+ if (vm == nil) {
+ NSString *old_launcher = [self expandMacros:@"$APP_PACKAGE/Contents/MacOS/idea_appLauncher"];
+ execv([old_launcher fileSystemRepresentation], self->argv);
+
+ NSLog(@"Cannot find matching VM, aborting");
+ exit(-1);
+ }
+
+ NSError *error = nil;
+ BOOL ok = [vm loadAndReturnError:&error];
+ if (!ok) {
+ NSLog(@"Cannot load JVM bundle: %@", error);
+ exit(-1);
+ }
+
+ CFBundleRef cfvm = NSBundle2CFBundle(vm);
+
+ fun_ptr_t_CreateJavaVM create_vm = CFBundleGetFunctionPointerForName(cfvm, CFSTR("JNI_CreateJavaVM"));
+
+ if (create_vm == NULL) {
+ // We have Apple VM chosen here...
+/*
+ [self execCommandLineJava:vm];
+ return;
+*/
+
+ NSString *serverLibUrl = [vm.bundlePath stringByAppendingPathComponent:@"Contents/Libraries/libserver.dylib"];
+
+ void *libHandle = dlopen(serverLibUrl.UTF8String, RTLD_NOW + RTLD_GLOBAL);
+ if (libHandle) {
+ create_vm = dlsym(libHandle, "JNI_CreateJavaVM_Impl");
+ }
+ }
+
+ if (create_vm == NULL) {
+ NSLog(@"Cannot find JNI_CreateJavaVM in chosen JVM bundle at %@", vm.bundlePath);
+ exit(-1);
+ }
+
+ [self process_cwd];
+
+ JNIEnv *env;
+ JavaVM *jvm;
+
+ JavaVMInitArgs args = [self buildArgsFor:vm];
+
+ jint create_vm_rc = create_vm(&jvm, &env, &args);
+ if (create_vm_rc != JNI_OK || jvm == NULL) {
+ NSLog(@"JNI_CreateJavaVM (%@) failed: %d", vm.bundlePath, create_vm_rc);
+ exit(-1);
+ }
+
+ jclass string_class = (*env)->FindClass(env, "java/lang/String");
+ if (string_class == NULL) {
+ NSLog(@"No java.lang.String in classpath!");
+ exit(-1);
+ }
+
+ const char *mainClassName = [self mainClassName];
+ jclass mainClass = (*env)->FindClass(env, mainClassName);
+ if (mainClass == NULL || (*env)->ExceptionOccurred(env)) {
+ NSLog(@"Main class %s not found", mainClassName);
+ (*env)->ExceptionDescribe(env);
+ exit(-1);
+ }
+
+ jmethodID mainMethod = (*env)->GetStaticMethodID(env, mainClass, "main", "([Ljava/lang/String;)V");
+ if (mainMethod == NULL || (*env)->ExceptionOccurred(env)) {
+ NSLog(@"Cant't find main() method");
+ (*env)->ExceptionDescribe(env);
+ exit(-1);
+ }
+
+ // See http://stackoverflow.com/questions/10242115/os-x-strange-psn-command-line-parameter-when-launched-from-finder
+ // about psn_ stuff
+ int arg_count = 0;
+ for (int i = 1; i < argc; i++) {
+ if (memcmp(argv[i], "-psn_", 4) != 0) arg_count++;
+ }
+
+ jobject jni_args = (*env)->NewObjectArray(env, arg_count, string_class, NULL);
+
+ arg_count = 0;
+ for (int i = 1; i < argc; i++) {
+ if (memcmp(argv[i], "-psn_", 4) != 0) {
+ jstring jni_arg = (*env)->NewStringUTF(env, argv[i]);
+ (*env)->SetObjectArrayElement(env, jni_args, arg_count, jni_arg);
+ arg_count++;
+ }
+ }
+
+ (*env)->CallStaticVoidMethod(env, mainClass, mainMethod, jni_args);
+
+ (*jvm)->DetachCurrentThread(jvm);
+ (*jvm)->DestroyJavaVM(jvm);
+
+ [pool release];
+}
+
+
+@end
\ No newline at end of file
diff --git a/native/MacLauncher/Launcher.pch b/native/MacLauncher/Launcher.pch
new file mode 100644
index 0000000..7504e2d
--- /dev/null
+++ b/native/MacLauncher/Launcher.pch
@@ -0,0 +1,7 @@
+//
+// Prefix header for all source files of the 'Launcher' target in the 'Launcher' project
+//
+
+#ifdef __OBJC__
+ #import <Cocoa/Cocoa.h>
+#endif
diff --git a/native/MacLauncher/MacLauncher.xcodeproj/project.pbxproj b/native/MacLauncher/MacLauncher.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..2e2d7d9
--- /dev/null
+++ b/native/MacLauncher/MacLauncher.xcodeproj/project.pbxproj
@@ -0,0 +1,263 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 1A5645DB6F789D018FF4A4AF /* PropertyFileReader.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A5645FEAD4A0FF166644D97 /* PropertyFileReader.m */; };
+ 1A564BCFE66693BF0B2DD4A9 /* VMOptionsReader.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A564EDDE28564EF1AEBCD13 /* VMOptionsReader.m */; };
+ 1A564C27F0BA05F900F34907 /* utils.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A564EEF77B93DBD7FD23161 /* utils.m */; };
+ 50E17738155444B900E97451 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 50E17737155444B900E97451 /* Cocoa.framework */; };
+ 50E1775715552D2900E97451 /* JavaVM.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C0B58A123544A15DA59B13E3 /* JavaVM.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
+ C0B58A123544A15DA59B13E4 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C0B58A123544A15DA59B13DC /* main.m */; };
+ C0B58A123544A15DA59B13E5 /* Launcher.m in Sources */ = {isa = PBXBuildFile; fileRef = C0B58A123544A15DA59B13E0 /* Launcher.m */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ 1A5645FEAD4A0FF166644D97 /* PropertyFileReader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PropertyFileReader.m; sourceTree = "<group>"; };
+ 1A564A1031F4C91C464C1B75 /* utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = utils.h; sourceTree = "<group>"; };
+ 1A564D7CEEAA02F14A6D4F20 /* VMOptionsReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VMOptionsReader.h; sourceTree = "<group>"; };
+ 1A564EDDE28564EF1AEBCD13 /* VMOptionsReader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VMOptionsReader.m; sourceTree = "<group>"; };
+ 1A564EEF77B93DBD7FD23161 /* utils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = utils.m; sourceTree = "<group>"; };
+ 1A564F6D5833A0B9CE6E2839 /* PropertyFileReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PropertyFileReader.h; sourceTree = "<group>"; };
+ 50E17735155444B900E97451 /* Launcher.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Launcher.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 50E17737155444B900E97451 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
+ 50E1773F155444B900E97451 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+ 50E17745155444B900E97451 /* Launcher.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Launcher.pch; sourceTree = "<group>"; };
+ C0B58A123544A15DA59B13DC /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
+ C0B58A123544A15DA59B13DE /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+ C0B58A123544A15DA59B13E0 /* Launcher.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Launcher.m; sourceTree = "<group>"; };
+ C0B58A123544A15DA59B13E2 /* Launcher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Launcher.h; sourceTree = "<group>"; };
+ C0B58A123544A15DA59B13E3 /* JavaVM.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaVM.framework; path = System/Library/Frameworks/JavaVM.framework; sourceTree = SDKROOT; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 50E17732155444B900E97451 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 50E1775715552D2900E97451 /* JavaVM.framework in Frameworks */,
+ 50E17738155444B900E97451 /* Cocoa.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ C0B58A123544A15DA59B13CA = {
+ isa = PBXGroup;
+ children = (
+ C0B58A123544A15DA59B13DC /* main.m */,
+ C0B58A123544A15DA59B13E0 /* Launcher.m */,
+ C0B58A123544A15DA59B13E2 /* Launcher.h */,
+ 50E17745155444B900E97451 /* Launcher.pch */,
+ 50E1773F155444B900E97451 /* Info.plist */,
+ C0B58A123544A15DA59B13CB /* Products */,
+ C0B58A123544A15DA59B13D6 /* Frameworks */,
+ 1A5645FEAD4A0FF166644D97 /* PropertyFileReader.m */,
+ 1A564F6D5833A0B9CE6E2839 /* PropertyFileReader.h */,
+ 1A564EDDE28564EF1AEBCD13 /* VMOptionsReader.m */,
+ 1A564D7CEEAA02F14A6D4F20 /* VMOptionsReader.h */,
+ 1A564A1031F4C91C464C1B75 /* utils.h */,
+ 1A564EEF77B93DBD7FD23161 /* utils.m */,
+ );
+ sourceTree = "<group>";
+ };
+ C0B58A123544A15DA59B13CB /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 50E17735155444B900E97451 /* Launcher.app */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ C0B58A123544A15DA59B13D6 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ C0B58A123544A15DA59B13E3 /* JavaVM.framework */,
+ C0B58A123544A15DA59B13DE /* Foundation.framework */,
+ 50E17737155444B900E97451 /* Cocoa.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 50E17734155444B900E97451 /* Launcher */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 50E17751155444BA00E97451 /* Build configuration list for PBXNativeTarget "Launcher" */;
+ buildPhases = (
+ 50E17731155444B900E97451 /* Sources */,
+ 50E17732155444B900E97451 /* Frameworks */,
+ 50E17733155444B900E97451 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = Launcher;
+ productName = Launcher;
+ productReference = 50E17735155444B900E97451 /* Launcher.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ C0B58A123544A15DA59B13C8 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 0450;
+ };
+ buildConfigurationList = C0B58A123544A15DA59B13C9 /* Build configuration list for PBXProject "MacLauncher" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = English;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ );
+ mainGroup = C0B58A123544A15DA59B13CA;
+ productRefGroup = C0B58A123544A15DA59B13CB /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 50E17734155444B900E97451 /* Launcher */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 50E17733155444B900E97451 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 50E17731155444B900E97451 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ C0B58A123544A15DA59B13E4 /* main.m in Sources */,
+ C0B58A123544A15DA59B13E5 /* Launcher.m in Sources */,
+ 1A5645DB6F789D018FF4A4AF /* PropertyFileReader.m in Sources */,
+ 1A564BCFE66693BF0B2DD4A9 /* VMOptionsReader.m in Sources */,
+ 1A564C27F0BA05F900F34907 /* utils.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ 50E1774F155444BA00E97451 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+ COMBINE_HIDPI_IMAGES = YES;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = Launcher.pch;
+ GCC_VERSION = com.apple.compilers.llvmgcc42;
+ INFOPLIST_FILE = Info.plist;
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
+ ONLY_ACTIVE_ARCH = NO;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = macosx10.7;
+ WRAPPER_EXTENSION = app;
+ };
+ name = Release;
+ };
+ 50E17750155444BA00E97451 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+ COMBINE_HIDPI_IMAGES = YES;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = Launcher.pch;
+ GCC_VERSION = com.apple.compilers.llvmgcc42;
+ INFOPLIST_FILE = Info.plist;
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
+ ONLY_ACTIVE_ARCH = NO;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = macosx10.7;
+ WRAPPER_EXTENSION = app;
+ };
+ name = Debug;
+ };
+ C0B58A123544A15DA59B13CC /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ARCHS = "$(ARCHS_STANDARD_64_BIT)";
+ CLANG_ENABLE_OBJC_ARC = YES;
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
+ SDKROOT = macosx;
+ };
+ name = Release;
+ };
+ C0B58A123544A15DA59B13CD /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ARCHS = "$(ARCHS_STANDARD_64_BIT)";
+ CLANG_ENABLE_OBJC_ARC = YES;
+ COPY_PHASE_STRIP = NO;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.5;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = macosx;
+ };
+ name = Debug;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 50E17751155444BA00E97451 /* Build configuration list for PBXNativeTarget "Launcher" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 50E1774F155444BA00E97451 /* Release */,
+ 50E17750155444BA00E97451 /* Debug */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ C0B58A123544A15DA59B13C9 /* Build configuration list for PBXProject "MacLauncher" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ C0B58A123544A15DA59B13CC /* Release */,
+ C0B58A123544A15DA59B13CD /* Debug */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = C0B58A123544A15DA59B13C8 /* Project object */;
+}
diff --git a/native/MacLauncher/PropertyFileReader.h b/native/MacLauncher/PropertyFileReader.h
new file mode 100644
index 0000000..44e46a9
--- /dev/null
+++ b/native/MacLauncher/PropertyFileReader.h
@@ -0,0 +1,13 @@
+//
+// Created by max on 11/6/12.
+//
+// To change the template use AppCode | Preferences | File Templates.
+//
+
+
+#import <Foundation/Foundation.h>
+
+
+@interface PropertyFileReader : NSObject
++ (NSDictionary *)readFile:(NSString *)path;
+@end
\ No newline at end of file
diff --git a/native/MacLauncher/PropertyFileReader.m b/native/MacLauncher/PropertyFileReader.m
new file mode 100644
index 0000000..43b0682
--- /dev/null
+++ b/native/MacLauncher/PropertyFileReader.m
@@ -0,0 +1,46 @@
+//
+// Created by max on 11/6/12.
+//
+// To change the template use AppCode | Preferences | File Templates.
+//
+
+
+#import "PropertyFileReader.h"
+#import "utils.h"
+
+
+@implementation PropertyFileReader {
+}
+
++ (void)parseProperty:(NSString *)string to:(NSMutableDictionary *)to {
+ NSRange delimiter = [string rangeOfString:@"="];
+ if (delimiter.length > 0 && delimiter.location + 1 <= string.length) {
+ NSString *key = [string substringToIndex:delimiter.location];
+ NSString *value=[string substringFromIndex:delimiter.location + 1];
+ [to setObject:value forKey:key];
+ }
+}
+
++ (NSDictionary *)readFile:(NSString *)path {
+ NSMutableDictionary *answer = [NSMutableDictionary dictionary];
+
+ NSString *contents = readFile(path);
+
+ if (contents) {
+ NSArray *lines = [contents componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
+ for (NSString *line in lines) {
+ NSString *trimmedLine = trim(line);
+ if ([trimmedLine length] > 0) {
+ if ([trimmedLine characterAtIndex:0] != '#') {
+ [self parseProperty:trimmedLine to:answer];
+ }
+ }
+ }
+
+ return answer;
+ }
+
+ return nil;
+}
+
+@end
\ No newline at end of file
diff --git a/native/MacLauncher/VMOptionsReader.h b/native/MacLauncher/VMOptionsReader.h
new file mode 100644
index 0000000..bb4dbea
--- /dev/null
+++ b/native/MacLauncher/VMOptionsReader.h
@@ -0,0 +1,13 @@
+//
+// Created by max on 11/6/12.
+//
+// To change the template use AppCode | Preferences | File Templates.
+//
+
+
+#import <Foundation/Foundation.h>
+
+
+@interface VMOptionsReader : NSObject
++ (NSArray *) readFile: (NSString *)path;
+@end
\ No newline at end of file
diff --git a/native/MacLauncher/VMOptionsReader.m b/native/MacLauncher/VMOptionsReader.m
new file mode 100644
index 0000000..19237cb
--- /dev/null
+++ b/native/MacLauncher/VMOptionsReader.m
@@ -0,0 +1,36 @@
+//
+// Created by max on 11/6/12.
+//
+// To change the template use AppCode | Preferences | File Templates.
+//
+
+
+#import "VMOptionsReader.h"
+#import "utils.h"
+
+
+@implementation VMOptionsReader {
+
+}
++ (NSArray *)readFile:(NSString *)path {
+ NSMutableArray *answer = [NSMutableArray array];
+
+ NSString *contents = readFile(path);
+ if (contents) {
+ NSArray *lines = [contents componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
+ for (NSString *line in lines) {
+ NSString *trimmedLine = trim(line);
+ if ([trimmedLine length] > 0) {
+ if ([trimmedLine characterAtIndex:0] != '#') {
+ [answer addObject:trimmedLine];
+ }
+ }
+ }
+
+ return answer;
+ }
+
+ return nil;
+}
+
+@end
\ No newline at end of file
diff --git a/native/MacLauncher/main.m b/native/MacLauncher/main.m
new file mode 100644
index 0000000..c9ef36a
--- /dev/null
+++ b/native/MacLauncher/main.m
@@ -0,0 +1,41 @@
+#import "Launcher.h"
+
+#define FOREVER ((CFTimeInterval) 1e20)
+
+static void timer_empty(CFRunLoopTimerRef timer, void *info) {
+}
+
+static void parkRunLoop() {
+ CFRunLoopTimerRef t = CFRunLoopTimerCreate(kCFAllocatorDefault, FOREVER, (CFTimeInterval)0.0, 0, 0, timer_empty, NULL);
+ CFRunLoopAddTimer(CFRunLoopGetCurrent(), t, kCFRunLoopDefaultMode);
+ CFRelease(t);
+
+ SInt32 result;
+ do {
+ result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, FOREVER, false);
+ } while (result != kCFRunLoopRunFinished);
+}
+
+static void makeSameStackSize(NSThread *thread) {
+ struct rlimit l;
+ int err = getrlimit(RLIMIT_STACK, &l);
+ if (err == ERR_SUCCESS && l.rlim_cur > 0) {
+ thread.stackSize = (NSUInteger) l.rlim_cur;
+ }
+}
+
+static void launchInNewThread(Launcher *launcher) {
+ NSThread *thread = [[[NSThread alloc] initWithTarget:launcher selector:@selector(launch) object:nil] autorelease];
+ makeSameStackSize(thread);
+ [thread start];
+}
+
+int main(int argc, char *argv[]) {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ launchInNewThread([[[Launcher alloc] initWithArgc:argc argv:argv] autorelease]);
+ parkRunLoop();
+
+ [pool release];
+ return 0;
+}
diff --git a/native/MacLauncher/utils.h b/native/MacLauncher/utils.h
new file mode 100644
index 0000000..4c28b35
--- /dev/null
+++ b/native/MacLauncher/utils.h
@@ -0,0 +1,5 @@
+NSString *readFile(NSString *path);
+NSString *trim(NSString *line);
+
+void debugLog(NSString *message);
+BOOL isDebugEnabled();
diff --git a/native/MacLauncher/utils.m b/native/MacLauncher/utils.m
new file mode 100644
index 0000000..63c3922
--- /dev/null
+++ b/native/MacLauncher/utils.m
@@ -0,0 +1,30 @@
+#include "utils.h"
+
+NSString *readFile(NSString *path) {
+ NSError *err = nil;
+ NSString *contents = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&err];
+ if (contents == nil) {
+ debugLog([NSString stringWithFormat:@"Reading at %@ failed, Error is: %@", path, err.localizedDescription]);
+ return nil;
+ }
+
+ debugLog([NSString stringWithFormat: @"Reading at %@ OK", path]);
+
+ return contents;
+}
+
+NSString *trim(NSString *line) {
+ return [line stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@" \t"]];
+}
+
+BOOL isDebugEnabled() {
+ return getenv("IDEA_LAUNCHER_DEBUG") != NULL;
+}
+
+void debugLog(NSString *message) {
+ if (isDebugEnabled()) {
+ NSLog(@"%@", message);
+ }
+}
+
+