changeset 3742:75b3b8e4530b

RT-29058: Need a macro in the config files to expand to the app bundle directory [ngthomas, ddehaven]
author mhowe
date Fri, 24 May 2013 16:05:51 -0700
parents 675c74a2806a
children 018368ab7327
files deploy/packager/native/linux/launcher.c deploy/packager/native/macosx/main.m deploy/packager/native/windows/WinLauncher.cpp
diffstat 3 files changed, 143 insertions(+), 36 deletions(-) [+]
line wrap: on
line diff
--- a/deploy/packager/native/linux/launcher.c	Thu May 09 15:35:03 2013 -0700
+++ b/deploy/packager/native/linux/launcher.c	Fri May 24 16:05:51 2013 -0700
@@ -218,6 +218,48 @@
     return TRUE;
 }
 
+/*
+ * Replace a pattern in a string (not regex, straight replace) with another
+ * string.
+ *
+ * All strings returned can be passed to free, i.e a new string is always created
+ * even if there is an error and the pattern can't be replaced
+ *
+ * @param str          - original string
+ * @param pattern      - pattern to replace (not regex)
+ * @param replaceWith  - string to replace pattern
+ * @return if pattern not found strdup(str) is returned
+ *         or a new str with the pattern replaced (strdup as well)
+ */
+char *dupAndReplacePattern(char *str, char *pattern, char *replaceWith) {
+    static char buffer[MAX_PATH*2] = {0};
+    char *p;
+
+    //Return orig if str is not in orig.
+    if(!(p = strstr(str, pattern))) {
+      return strdup(str);
+    }
+
+    int loc = p-str;
+    if (loc >= sizeof(buffer)) {
+        printf("Failed to replace pattern \"%s\" in string \"%s\" with \"%s\" because buffer not big enough\n",
+                pattern, str, replaceWith);
+        return strdup(str);
+    }
+
+    strncpy(buffer, str, loc); // Copy characters from 'str' start to 'orig' st$
+    buffer[loc] = '\0';
+
+    int remaingBufferSize = sizeof(buffer) - loc;
+    int len = snprintf(buffer+(loc), remaingBufferSize, "%s%s", replaceWith, p+strlen(pattern));
+    if(len > remaingBufferSize ) {
+        printf("Failed to replace pattern \"%s\" in string \"%s\" with \"%s\" because buffer not big enough\n",
+                pattern, str, replaceWith);
+        return strdup(str);
+    }
+    return strdup(buffer);
+}
+
 
 #define MAX_OPTIONS 100
 
@@ -310,7 +352,9 @@
        sprintf(argname, "jvmarg.%d", idx);
        found = getConfigValue(basedir, argname, argvalue, sizeof(argvalue));
        if (found) {
-          options[cnt].optionString = strdup(argvalue);
+          //jvmOption is always a new string via strdup
+          char* jvmOption = dupAndReplacePattern(argvalue, "$APPDIR", basedir);
+          options[cnt].optionString = jvmOption;
           idx++;
           cnt++;
        }
--- a/deploy/packager/native/macosx/main.m	Thu May 09 15:35:03 2013 -0700
+++ b/deploy/packager/native/macosx/main.m	Fri May 24 16:05:51 2013 -0700
@@ -51,16 +51,16 @@
 #define LIBJLI_DYLIB "/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/lib/jli/libjli.dylib"
 
 typedef int (JNICALL *JLI_Launch_t)(int argc, char ** argv,
-                                    int jargc, const char** jargv,
-                                    int appclassc, const char** appclassv,
-                                    const char* fullversion,
-                                    const char* dotversion,
-                                    const char* pname,
-                                    const char* lname,
-                                    jboolean javaargs,
-                                    jboolean cpwildcard,
-                                    jboolean javaw,
-                                    jint ergo);
+        int jargc, const char** jargv,
+        int appclassc, const char** appclassv,
+        const char* fullversion,
+        const char* dotversion,
+        const char* pname,
+        const char* lname,
+        jboolean javaargs,
+        jboolean cpwildcard,
+        jboolean javaw,
+        jint ergo);
 
 int launch(int appArgc, char *appArgv[]);
 
@@ -106,7 +106,7 @@
             void *libJLI = dlopen(jliPath, RTLD_LAZY);
             if (libJLI != NULL) {
                 jli_LaunchFxnPtr = dlsym(libJLI, "JLI_Launch");
-        }
+            }
         }
     } else {
         void *libJLI = dlopen(LIBJLI_DYLIB, RTLD_LAZY);
@@ -137,16 +137,16 @@
     NSString *mainBundlePath = [mainBundle bundlePath];
     NSString *javaPath = [mainBundlePath stringByAppendingString:@"/Contents/Java"];
     NSMutableString *classPath = [NSMutableString stringWithFormat:@"-Djava.class.path=%@/%@",
-         javaPath, mainJarName];
+                                                                   javaPath, mainJarName];
 
     NSString *extraClasspath = [infoDictionary objectForKey:@JVM_CLASSPATH_KEY];
     if ([extraClasspath length] > 0) { //unless key missing or has empty value
-       NSArray *elements = [extraClasspath componentsSeparatedByString:@" "];
-       for (NSString *file in elements) {
-          if ([file length] > 0) {
-             [classPath appendFormat:@":%@/%@", javaPath, file];
-          }
-       }
+        NSArray *elements = [extraClasspath componentsSeparatedByString:@" "];
+        for (NSString *file in elements) {
+            if ([file length] > 0) {
+                [classPath appendFormat:@":%@/%@", javaPath, file];
+            }
+        }
     }
     // Set the library path
     NSString *libraryPath = [NSString stringWithFormat:@"-Djava.library.path=%@/Contents/Java", mainBundlePath];
@@ -156,6 +156,19 @@
     if (options == nil) {
         options = [NSArray array];
     }
+    else {
+        //Do string substitutions - for now only one is $APPDIR
+        NSString *contentsPath = [mainBundlePath stringByAppendingString:@"/Contents"];
+        NSMutableArray *expandedOptions = [options mutableCopy];
+        NSUInteger index = 0;
+        for (id option in options) {
+            NSString *expandedOption =
+                    [option stringByReplacingOccurrencesOfString:@"$APPDIR" withString:contentsPath];
+            [expandedOptions replaceObjectAtIndex:index withObject:expandedOption];
+            index++;
+        }
+        options = expandedOptions;
+    }
 
     // Get the application arguments
     NSArray *arguments = [infoDictionary objectForKey:@JVM_ARGUMENTS_KEY];
@@ -174,7 +187,7 @@
     int argc;
     if (!mainThread) {
         argc = 1 + [options count] + 2 + 1 +
-               (appArgc > 1 ? (appArgc - 1) : [arguments count]);
+                (appArgc > 1 ? (appArgc - 1) : [arguments count]);
     } else {
         argc = 1 + (appArgc > 1 ? (appArgc - 1) : 0);
     }
@@ -199,16 +212,16 @@
         //command line arguments override plist
         if (appArgc > 1) {
             for (int j=1; j<appArgc; j++) {
-               argv[i++] = strdup(appArgv[j]);
+                argv[i++] = strdup(appArgv[j]);
             }
         } else {
             for (NSString *argument in arguments) {
-               argv[i++] = strdup([argument UTF8String]);
+                argv[i++] = strdup([argument UTF8String]);
             }
         }
     } else {
         for (int j=1; j<appArgc; j++) {
-           argv[i++] = strdup(appArgv[j]);
+            argv[i++] = strdup(appArgv[j]);
         }
     }
 
@@ -216,14 +229,14 @@
 
     // Invoke JLI_Launch()
     return jli_LaunchFxnPtr(argc, argv,
-                            0, NULL,
-                            0, NULL,
-                            "",
-                            "",
-                            "java",
-                            "java",
-                            FALSE,
-                            FALSE,
-                            FALSE,
-                            0);
+            0, NULL,
+            0, NULL,
+            "",
+            "",
+            "java",
+            "java",
+            FALSE,
+            FALSE,
+            FALSE,
+            0);
 }
--- a/deploy/packager/native/windows/WinLauncher.cpp	Thu May 09 15:35:03 2013 -0700
+++ b/deploy/packager/native/windows/WinLauncher.cpp	Fri May 24 16:05:51 2013 -0700
@@ -29,7 +29,6 @@
 #define _WIN32_WINNT 0x0501
 
 #include <Windows.h>
-#include <shellapi.h>
 #include <tchar.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -40,6 +39,8 @@
 
 #include "jni.h"
 
+#define snprintf _snprintf
+
 /*
    This is launcher program for application package on Windows.
 
@@ -296,6 +297,41 @@
     return 1;
 }
 
+/*
+ * Replace a pattern in a string (not regex, straight replace) with another
+ * string.
+ *
+ * @param str
+ * @param pattern
+ * @param replaceWith
+ * @return either original str or a new str (via strdup) that replaces the
+ *         pattern with the replaceWith string
+ */
+char *replaceStr(char *str, char *pattern, char *replaceWith) {
+	static char buffer[MAX_PATH*2] = {0};
+    char *p;
+
+    //Return orig if str is not in orig.
+    if(!(p = strstr(str, pattern))) {
+      return str;
+    }
+
+    int loc = p-str;
+    if (loc >= sizeof(buffer)) {
+        return str;
+    }
+
+    strncpy(buffer, str, loc); // Copy characters from 'str' start to 'orig' st$
+    buffer[loc] = '\0';
+
+    int remaingBufferSize = sizeof(buffer) - loc;
+    int len = snprintf(buffer+(loc), remaingBufferSize, "%s%s", replaceWith, p+strlen(pattern));
+    if(len > remaingBufferSize ) {
+        return str;
+    }
+    return strdup(buffer);
+}
+
 #define MAX_OPTIONS 100
 #define MAX_OPTION_NAME 50
 
@@ -417,8 +453,22 @@
        if (found) {
            size_t inLen = (size_t) wcslen(argvalue);
            //convert argument to ASCII string as this is what CreateJVM needs
-           wcstombs_s(&outlen, argvalueASCII, sizeof(argvalueASCII), argvalue, inLen + 1);
-           options[cnt].optionString = _strdup(argvalueASCII);
+           if (wcstombs_s(&outlen, argvalueASCII, sizeof(argvalueASCII), argvalue, inLen + 1) != 0) {
+ 	       showError(_T("Failed converting JVM Argument to ASCII"), argname);
+	       return false;
+	   }
+	   char* jvmOption = _strdup(argvalueASCII);
+
+	   //convert basedir to ASCII string - reuse argvalueASCII
+	   if (wcstombs_s(&outlen, argvalueASCII, sizeof(argvalueASCII), basedir, (size_t)wcslen(basedir) + 1)) {
+               showError(_T("Failed converting directory %s to ASCII", basedir), basedir);
+               return false;
+	   }
+	   //If jvmOption contains $APPDIR it will be replaced with basedir (argvalueASCII)
+	   //otherwise the orginal jvmOption is returned (from strdup above). If string is replaced
+	   //the new version is also from a strdup (i.e. can be passed to free)
+	   jvmOption = replaceStr(jvmOption, "$APPDIR", argvalueASCII);
+	   options[cnt].optionString = jvmOption;
            idx++;
            cnt++;
        }