(TWILL-242) Fixed the dropping of extra jvm opts

This closes #60 on Github

Signed-off-by: Terence Yim <chtyim@apache.org>
diff --git a/twill-yarn/src/main/java/org/apache/twill/yarn/YarnTwillPreparer.java b/twill-yarn/src/main/java/org/apache/twill/yarn/YarnTwillPreparer.java
index 0eba62b..1ea2ab3 100644
--- a/twill-yarn/src/main/java/org/apache/twill/yarn/YarnTwillPreparer.java
+++ b/twill-yarn/src/main/java/org/apache/twill/yarn/YarnTwillPreparer.java
@@ -473,7 +473,7 @@
       return extraOptions;
     }
     String classLoaderProperty = "-D" + Constants.TWILL_CONTAINER_CLASSLOADER + "=" + classLoaderClassName;
-    return extraOptions.isEmpty() ? classLoaderProperty : " " + classLoaderProperty;
+    return extraOptions.isEmpty() ? classLoaderProperty : extraOptions + " " + classLoaderProperty;
   }
 
   private void setEnv(String runnableName, Map<String, String> env, boolean overwrite) {
@@ -774,17 +774,16 @@
   }
 
   private JvmOptions saveJvmOptions(final Path targetPath) throws IOException {
-    // Updates the extra options with the classloader name if necessary
-    final String globalOptions = addClassLoaderClassName(extraOptions);
     // Append runnable specific extra options.
     Map<String, String> runnableExtraOptions = Maps.newHashMap(
       Maps.transformValues(this.runnableExtraOptions, new Function<String, String>() {
         @Override
-        public String apply(String extraOptions) {
-          return globalOptions.isEmpty() ? extraOptions : globalOptions + " " + extraOptions;
+        public String apply(String options) {
+          return addClassLoaderClassName(extraOptions.isEmpty() ? options : extraOptions + " " + options);
         }
       }));
 
+    String globalOptions = addClassLoaderClassName(extraOptions);
     JvmOptions jvmOptions = new JvmOptions(globalOptions, runnableExtraOptions, debugOptions);
     if (globalOptions.isEmpty() && runnableExtraOptions.isEmpty()
       && JvmOptions.DebugOptions.NO_DEBUG.equals(debugOptions)) {
diff --git a/twill-yarn/src/test/java/org/apache/twill/yarn/CustomClassLoaderRunnable.java b/twill-yarn/src/test/java/org/apache/twill/yarn/CustomClassLoaderRunnable.java
index 591f931..d088b07 100644
--- a/twill-yarn/src/test/java/org/apache/twill/yarn/CustomClassLoaderRunnable.java
+++ b/twill-yarn/src/test/java/org/apache/twill/yarn/CustomClassLoaderRunnable.java
@@ -41,7 +41,8 @@
     try {
       Class<?> cls = Class.forName(GENERATED_CLASS_NAME);
       java.lang.reflect.Method announce = cls.getMethod("announce", ServiceAnnouncer.class, String.class, int.class);
-      announce.invoke(cls.newInstance(), getContext(), System.getProperty("service.name"), 54321);
+      announce.invoke(cls.newInstance(), getContext(), System.getProperty("service.name"),
+                      Integer.getInteger("service.port"));
       Uninterruptibles.awaitUninterruptibly(stopLatch);
     } catch (Exception e) {
       LOG.error("Failed to call announce on " + GENERATED_CLASS_NAME, e);
diff --git a/twill-yarn/src/test/java/org/apache/twill/yarn/CustomClassLoaderTestRun.java b/twill-yarn/src/test/java/org/apache/twill/yarn/CustomClassLoaderTestRun.java
index f0a75b2..ba12e0f 100644
--- a/twill-yarn/src/test/java/org/apache/twill/yarn/CustomClassLoaderTestRun.java
+++ b/twill-yarn/src/test/java/org/apache/twill/yarn/CustomClassLoaderTestRun.java
@@ -34,6 +34,7 @@
     TwillController controller = getTwillRunner().prepare(new CustomClassLoaderRunnable())
       .setClassLoader(CustomClassLoader.class.getName())
       .addLogHandler(new PrinterLogHandler(new PrintWriter(System.out, true)))
+      .setJVMOptions("-Dservice.port=54321")
       .setJVMOptions(CustomClassLoaderRunnable.class.getSimpleName(), "-Dservice.name=custom")
       .start();