diff --git a/java/java-runtime/src/com/intellij/rt/execution/CommandLineWrapper.java b/java/java-runtime/src/com/intellij/rt/execution/CommandLineWrapper.java index 8bbd52125f81..f6901fc5af67 100644 --- a/java/java-runtime/src/com/intellij/rt/execution/CommandLineWrapper.java +++ b/java/java-runtime/src/com/intellij/rt/execution/CommandLineWrapper.java @@ -32,8 +32,6 @@ import java.util.jar.Manifest; * @since 12-Aug-2008 */ public class CommandLineWrapper { - private static final String PREFIX = "-D"; - public static void main(String[] args) throws Exception { final File jarFile = new File(args[0]); final MainPair mainPair = args[0].endsWith(".jar") ? loadMainClassFromClasspathJar(jarFile, args) @@ -54,11 +52,9 @@ public class CommandLineWrapper { final Manifest manifest = inputStream.getManifest(); final String vmParams = manifest.getMainAttributes().getValue("VM-Options"); if (vmParams != null) { - final HashMap vmOptions = new HashMap(); - parseVmOptions(vmParams, vmOptions); - for (Iterator iterator = vmOptions.keySet().iterator(); iterator.hasNext(); ) { - String optionName = (String)iterator.next(); - System.setProperty(optionName, (String)vmOptions.get(optionName)); + String[] properties = splitBySpaces(vmParams); + for (int i = 0; i < properties.length; i++) { + setProperty(properties[i]); } } String programParameters = manifest.getMainAttributes().getValue("Program-Parameters"); @@ -149,26 +145,6 @@ public class CommandLineWrapper { } } - public static void parseVmOptions(String vmParams, Map vmOptions) { - int idx = vmParams.indexOf(PREFIX); - while (idx >= 0) { - final int indexOf = vmParams.indexOf(PREFIX, idx + PREFIX.length()); - final String vmParam = indexOf < 0 ? vmParams.substring(idx) : vmParams.substring(idx, indexOf - 1); - final int eqIdx = vmParam.indexOf('='); - String vmParamName; - String vmParamValue; - if (eqIdx > -1 && eqIdx < vmParam.length() - 1) { - vmParamName = vmParam.substring(0, eqIdx); - vmParamValue = vmParam.substring(eqIdx + 1); - } else { - vmParamName = vmParam; - vmParamValue = ""; - } - vmOptions.put(vmParamName.trim().substring(PREFIX.length()), vmParamValue); - idx = indexOf; - } - } - private static void ensureAccess(Object reflectionObject) { // need to call setAccessible here in order to be able to launch package-private classes // calling setAccessible() via reflection because the method is missing from java version 1.1.x @@ -180,6 +156,10 @@ public class CommandLineWrapper { catch (Exception ignored) { } } + /** + * args: "classpath file" [ @vm_params "VM options file" ] "main class" [ args ... ] + * @noinspection Duplicates + */ private static MainPair loadMainClassWithOldCustomLoader(File file, String[] args) throws Exception { final List urls = new ArrayList(); final StringBuffer buf = new StringBuffer(); @@ -213,6 +193,21 @@ public class CommandLineWrapper { int startArgsIdx = 2; + if (args.length >= 3 && "@vm_params".equals(args[1])) { + startArgsIdx = 4; + + BufferedReader vmParamsReader = new BufferedReader(new FileReader(args[2])); + try { + String property; + while ((property = vmParamsReader.readLine()) != null) { + setProperty(property); + } + } + finally { + vmParamsReader.close(); + } + } + String mainClassName = args[startArgsIdx - 1]; String[] mainArgs = new String[args.length - startArgsIdx]; System.arraycopy(args, startArgsIdx, mainArgs, 0, mainArgs.length); @@ -238,6 +233,18 @@ public class CommandLineWrapper { return new MainPair(mainClass, mainArgs); } + private static void setProperty(String property) { + if (property.startsWith("-D")) { + int p = property.indexOf('='); + if (p > 0) { + System.setProperty(property.substring(2, p), property.substring(p + 1)); + } + else { + System.setProperty(property.substring(2), ""); + } + } + } + private static URL internFileProtocol(URL url) { try { if ("file".equals(url.getProtocol())) { diff --git a/java/java-tests/testSrc/com/intellij/execution/CommandLineWrapperRunTest.kt b/java/java-tests/testSrc/com/intellij/execution/CommandLineWrapperRunTest.kt new file mode 100644 index 000000000000..823a53f7ce57 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/execution/CommandLineWrapperRunTest.kt @@ -0,0 +1,82 @@ +/* + * Copyright 2000-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.execution + +import com.intellij.execution.configurations.SimpleJavaParameters +import com.intellij.execution.util.ExecUtil +import com.intellij.openapi.application.PathManager +import com.intellij.openapi.projectRoots.JavaSdk +import com.intellij.openapi.projectRoots.Sdk +import com.intellij.testFramework.fixtures.BareTestFixtureTestCase +import org.junit.Assert.assertEquals +import org.junit.Before +import org.junit.Test + +class CommandLineWrapperRunTest : BareTestFixtureTestCase() { + private lateinit var sdk: Sdk + + @Before fun setUp() { + sdk = JavaSdk.getInstance().createJdk("test jdk", System.getProperty("java.home"), true) + } + + @Test fun `no dynamic classpath`() = doTest() + @Test fun `dynamic classpath, class loader`() = doTest(true, false) + @Test fun `dynamic classpath, classpath JAR`() = doTest(true, true) + @Test fun `dynamic parameters, class loader`() = doTest(true, false, true) + @Test fun `dynamic parameters, classpath JAR`() = doTest(true, true, true) + + @Suppress("UsePropertyAccessSyntax") + private fun doTest(dynamicCp: Boolean = false, classPathJar: Boolean = false, dynamicArgs: Boolean = false) { + val parameters = SimpleJavaParameters() + parameters.jdk = sdk + parameters.vmParametersList.addProperty(Helper.PROPERTY1) + parameters.vmParametersList.addProperty(Helper.PROPERTY2, "a value") + parameters.classPath.add(PathManager.getJarPathForClass(Helper::class.java)) + parameters.classPath.add(PathManager.getJarPathForClass(Unit::class.java)) + parameters.mainClass = Helper::class.java.name + parameters.programParametersList.add("first parameter") + parameters.programParametersList.add("next parameter") + + parameters.setUseDynamicClasspath(dynamicCp) + parameters.setUseClasspathJar(classPathJar) + parameters.setUseDynamicVMOptions(dynamicArgs) + if (classPathJar) { + parameters.setPassProgramParametersViaClasspathJar(dynamicArgs) + } + + val command = parameters.toCommandLine() + val out = ExecUtil.execAndGetOutput(command) + assertEquals(out.stderr, 0, out.exitCode) + assertEquals("${Helper.PROPERTY1}=\n" + + "${Helper.PROPERTY2}=a value\n" + + "arg[0]=first parameter\n" + + "arg[1]=next parameter\n", out.stdout) + } + + object Helper { + val PROPERTY1 = "idea.wrapper.exec.test.1" + val PROPERTY2 = "idea.wrapper.exec.test.2" + + @JvmStatic + fun main(args: Array) { + println(PROPERTY1 + "=" + System.getProperty(PROPERTY1)) + println(PROPERTY2 + "=" + System.getProperty(PROPERTY2)) + for (i in args.indices) { + println("arg[" + i + "]=" + args[i]) + } + } + } +} \ No newline at end of file