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 0b2702f7b899..d7db6991b159 100644 --- a/java/java-runtime/src/com/intellij/rt/execution/CommandLineWrapper.java +++ b/java/java-runtime/src/com/intellij/rt/execution/CommandLineWrapper.java @@ -151,7 +151,7 @@ public class CommandLineWrapper { } /** - * args: "classpath file" [ @vm_params "VM options file" ] "main class" [ args ... ] + * args: "classpath file" [ @vm_params "VM options file" ] [ @app_params "args file" ] "main class" [ args ... ] * @noinspection Duplicates, ResultOfMethodCallIgnored */ private static AppData loadMainClassWithCustomLoader(File classpathFile, String[] args) throws Exception { @@ -175,11 +175,9 @@ public class CommandLineWrapper { int startArgsIdx = 2; List properties = Collections.EMPTY_LIST; - if (args.length >= 3 && "@vm_params".equals(args[1])) { - startArgsIdx = 4; - - File vmParamsFile = new File(args[2]); - BufferedReader vmParamsReader = new BufferedReader(new FileReader(args[2])); + if (args.length > startArgsIdx && "@vm_params".equals(args[startArgsIdx - 1])) { + File vmParamsFile = new File(args[startArgsIdx]); + BufferedReader vmParamsReader = new BufferedReader(new FileReader(vmParamsFile)); try { properties = new ArrayList(); String property; @@ -191,12 +189,35 @@ public class CommandLineWrapper { vmParamsReader.close(); vmParamsFile.delete(); } + + startArgsIdx += 2; + } + + String[] mainArgs; + if (args.length > startArgsIdx && "@app_params".equals(args[startArgsIdx - 1])) { + File appParamsFile = new File(args[startArgsIdx]); + BufferedReader appParamsReader = new BufferedReader(new FileReader(appParamsFile)); + try { + List list = new ArrayList(); + String arg; + while ((arg = appParamsReader.readLine()) != null) { + list.add(arg); + } + mainArgs = (String[])list.toArray(new String[list.size()]); + } + finally { + appParamsReader.close(); + appParamsFile.delete(); + } + + startArgsIdx += 2; + } + else { + mainArgs = new String[args.length - startArgsIdx]; + System.arraycopy(args, startArgsIdx, mainArgs, 0, mainArgs.length); } String mainClassName = args[startArgsIdx - 1]; - String[] mainArgs = new String[args.length - startArgsIdx]; - System.arraycopy(args, startArgsIdx, mainArgs, 0, mainArgs.length); - ClassLoader loader = new URLClassLoader((URL[])classpathUrls.toArray(new URL[classpathUrls.size()]), null); String systemLoaderName = System.getProperty("java.system.class.loader"); if (systemLoaderName != null) { diff --git a/java/java-tests/testSrc/com/intellij/execution/CommandLineWrapperRunTest.kt b/java/java-tests/testSrc/com/intellij/execution/CommandLineWrapperRunTest.kt index 824da79ea4e7..d561bb7181d4 100644 --- a/java/java-tests/testSrc/com/intellij/execution/CommandLineWrapperRunTest.kt +++ b/java/java-tests/testSrc/com/intellij/execution/CommandLineWrapperRunTest.kt @@ -53,9 +53,7 @@ class CommandLineWrapperRunTest : BareTestFixtureTestCase() { parameters.setUseDynamicClasspath(dynamicCp) parameters.setUseClasspathJar(classPathJar) parameters.setUseDynamicVMOptions(dynamicArgs) - if (classPathJar) { - parameters.setPassProgramParametersViaClasspathJar(dynamicArgs) - } + parameters.setUseDynamicParameters(dynamicArgs) val command = parameters.toCommandLine() val out = ExecUtil.execAndGetOutput(command) diff --git a/platform/lang-api/src/com/intellij/execution/configurations/SimpleJavaParameters.java b/platform/lang-api/src/com/intellij/execution/configurations/SimpleJavaParameters.java index b6ce7aad42ab..411c81dfebc2 100644 --- a/platform/lang-api/src/com/intellij/execution/configurations/SimpleJavaParameters.java +++ b/platform/lang-api/src/com/intellij/execution/configurations/SimpleJavaParameters.java @@ -45,8 +45,8 @@ public class SimpleJavaParameters extends SimpleProgramParameters { private Charset myCharset = CharsetToolkit.getDefaultSystemCharset(); private boolean myUseDynamicClasspath; private boolean myUseDynamicVMOptions; - private boolean myUseClasspathJar = false; - private boolean myPassProgramParametersViaClasspathJar; + private boolean myUseDynamicParameters; + private boolean myUseClasspathJar; private String myJarPath; @Nullable @@ -111,35 +111,29 @@ public class SimpleJavaParameters extends SimpleProgramParameters { return myUseDynamicVMOptions; } + /** Allows to pass system properties via a temporary file in order to avoid "too long command line" problem. */ public void setUseDynamicVMOptions(boolean useDynamicVMOptions) { myUseDynamicVMOptions = useDynamicVMOptions; } + public boolean isDynamicParameters() { + return myUseDynamicParameters; + } + + /** Allows to pass program parameters via a temporary file in order to avoid "too long command line" problem. */ + public void setUseDynamicParameters(boolean useDynamicParameters) { + myUseDynamicParameters = useDynamicParameters; + } + public boolean isUseClasspathJar() { return myUseClasspathJar; } - /** - * Call this method and pass {@code true} to pass classpath of the application via MANIFEST.MF file in a specially generated classpath.jar - * archive instead of passing it via -classpath command line option. This may be needed to avoid problems with too long command line on Windows. - */ + /** Allows to use a specially crafted .jar file instead of a custom class loader to pass classpath/properties/parameters. */ public void setUseClasspathJar(boolean useClasspathJar) { myUseClasspathJar = useClasspathJar; } - public boolean isPassProgramParametersViaClasspathJar() { - return myPassProgramParametersViaClasspathJar; - } - - /** - * Call this method and pass {@code true} to pass program parameters via attribute in MANIFEST.MF of the classpath jar instead of passing - * them via command line. This may be needed to avoid problems with too long command line on Windows. - */ - public void setPassProgramParametersViaClasspathJar(@SuppressWarnings("SameParameterValue") boolean passProgramParametersViaClasspathJar) { - LOG.assertTrue(myUseClasspathJar); - myPassProgramParametersViaClasspathJar = passProgramParametersViaClasspathJar; - } - public String getJarPath() { return myJarPath; } @@ -163,4 +157,17 @@ public class SimpleJavaParameters extends SimpleProgramParameters { ProcessTerminatedListener.attach(processHandler); return processHandler; } + + // + /** @deprecated use {@link #isDynamicParameters()} (to be removed in IDEA 2018) */ + public boolean isPassProgramParametersViaClasspathJar() { + return isDynamicParameters(); + } + + /** @deprecated use {@link #setUseDynamicParameters(boolean)} (to be removed in IDEA 2018) */ + public void setPassProgramParametersViaClasspathJar(@SuppressWarnings("SameParameterValue") boolean passProgramParametersViaClasspathJar) { + LOG.assertTrue(myUseClasspathJar); + setUseDynamicParameters(passProgramParametersViaClasspathJar); + } + // } \ No newline at end of file diff --git a/platform/lang-api/src/com/intellij/openapi/projectRoots/JdkUtil.java b/platform/lang-api/src/com/intellij/openapi/projectRoots/JdkUtil.java index c4b12f559001..39ffa5732b19 100644 --- a/platform/lang-api/src/com/intellij/openapi/projectRoots/JdkUtil.java +++ b/platform/lang-api/src/com/intellij/openapi/projectRoots/JdkUtil.java @@ -167,17 +167,16 @@ public class JdkUtil { commandLine.withParentEnvironmentType(javaParameters.isPassParentEnvs() ? ParentEnvironmentType.CONSOLE : ParentEnvironmentType.NONE); final Class commandLineWrapper; - boolean passProgramParametersViaClassPathJar = false; + boolean dynamicParameters = false; if (javaParameters.isDynamicClasspath() && !explicitClassPath(vmParameters) && javaParameters.getModulePath().isEmpty() && (commandLineWrapper = getCommandLineWrapperClass()) != null) { if (isClassPathJarEnabled(javaParameters, PathUtil.getJarPathForClass(ClassPath.class))) { - passProgramParametersViaClassPathJar = javaParameters.isPassProgramParametersViaClasspathJar(); - appendJarClasspathParams(javaParameters, commandLine, vmParameters, commandLineWrapper, passProgramParametersViaClassPathJar); + dynamicParameters = setClasspathJarParams(javaParameters, commandLine, vmParameters, commandLineWrapper); } else { - appendOldCommandLineWrapper(javaParameters, commandLine, vmParameters, commandLineWrapper); + dynamicParameters = setCommandLineWrapperParams(javaParameters, commandLine, vmParameters, commandLineWrapper); } } else { @@ -202,7 +201,7 @@ public class JdkUtil { throw new CantRunException(ExecutionBundle.message("main.class.is.not.specified.error.message")); } - if (!passProgramParametersViaClassPathJar) { + if (!dynamicParameters) { commandLine.addParameters(javaParameters.getProgramParametersList().getList()); } @@ -217,14 +216,17 @@ public class JdkUtil { return vmParameters.hasParameter("-p") || vmParameters.hasParameter("--module-path"); } - private static void appendOldCommandLineWrapper(SimpleJavaParameters javaParameters, - GeneralCommandLine commandLine, - ParametersList vmParametersList, - Class commandLineWrapper) throws CantRunException { + private static boolean setCommandLineWrapperParams(SimpleJavaParameters javaParameters, + GeneralCommandLine commandLine, + ParametersList vmParametersList, + Class commandLineWrapper) throws CantRunException { + boolean dynamicVMOptions = javaParameters.isDynamicVMOptions() && useDynamicVMOptions(); + boolean dynamicParameters = javaParameters.isDynamicParameters() && useDynamicParameters(); + File vmParamsFile = null; - if (javaParameters.isDynamicVMOptions() && useDynamicVMOptions()) { + if (dynamicVMOptions) { try { - vmParamsFile = FileUtil.createTempFile("vm_params", null); + vmParamsFile = FileUtil.createTempFile("idea_vm_params", null); try (PrintWriter writer = new PrintWriter(vmParamsFile)) { for (String param : vmParametersList.getList()) { if (param.startsWith("-D")) { @@ -244,18 +246,29 @@ public class JdkUtil { commandLine.addParameters(vmParametersList.getList()); } + File appParamsFile = null; + if (dynamicParameters) { + try { + appParamsFile = FileUtil.createTempFile("idea_app_params", null); + try (PrintWriter writer = new PrintWriter(appParamsFile)) { + for (String path : javaParameters.getProgramParametersList().getList()) { + writer.println(path); + } + } + } + catch (IOException e) { + throwUnableToCreateTempFile(e); + } + } + File classpathFile = null; try { - classpathFile = FileUtil.createTempFile("classpath", null); - final PrintWriter writer = new PrintWriter(classpathFile); - try { + classpathFile = FileUtil.createTempFile("idea_classpath", null); + try (PrintWriter writer = new PrintWriter(classpathFile)) { for (String path : javaParameters.getClassPath().getPathList()) { writer.println(path); } } - finally { - writer.close(); - } String classpath = PathUtil.getJarPathForClass(commandLineWrapper); final String utilRtPath = PathUtil.getJarPathForClass(StringUtilRt.class); @@ -284,39 +297,47 @@ public class JdkUtil { commandLine.addParameter(vmParamsFile.getAbsolutePath()); } - final Set filesToDelete = getFilesToDeleteUserData(commandLine); + if (appParamsFile != null) { + commandLine.addParameter("@app_params"); + commandLine.addParameter(appParamsFile.getAbsolutePath()); + } + + Set filesToDelete = getFilesToDeleteUserData(commandLine); ContainerUtil.addIfNotNull(filesToDelete, classpathFile); ContainerUtil.addIfNotNull(filesToDelete, vmParamsFile); + ContainerUtil.addIfNotNull(filesToDelete, appParamsFile); + + return dynamicParameters; } - private static void appendJarClasspathParams(SimpleJavaParameters javaParameters, + private static boolean setClasspathJarParams(SimpleJavaParameters javaParameters, GeneralCommandLine commandLine, ParametersList vmParametersList, - Class commandLineWrapper, - boolean storeProgramParametersInJar) throws CantRunException { + Class commandLineWrapper) throws CantRunException { + boolean dynamicVMOptions = javaParameters.isDynamicVMOptions() && useDynamicVMOptions(); + boolean dynamicParameters = javaParameters.isDynamicParameters() && useDynamicParameters(); + try { final Manifest manifest = new Manifest(); manifest.getMainAttributes().putValue("Created-By", ApplicationNamesInfo.getInstance().getFullProductName()); - final boolean writeDynamicVMOptions = javaParameters.isDynamicVMOptions() && useDynamicVMOptions(); - if (writeDynamicVMOptions) { - List dParams = new ArrayList<>(); + if (dynamicVMOptions) { + List properties = new ArrayList<>(); for (String param : vmParametersList.getList()) { if (param.startsWith("-D")) { - dParams.add(param); + properties.add(param); } else { commandLine.addParameter(param); } } - - manifest.getMainAttributes().putValue("VM-Options", ParametersListUtil.join(dParams)); + manifest.getMainAttributes().putValue("VM-Options", ParametersListUtil.join(properties)); } else { commandLine.addParameters(vmParametersList.getList()); } - if (storeProgramParametersInJar) { + if (dynamicParameters) { manifest.getMainAttributes().putValue("Program-Parameters", ParametersListUtil.join(javaParameters.getProgramParametersList().getList())); } @@ -328,7 +349,7 @@ public class JdkUtil { final String jarFile = classpathJarFile.getAbsolutePath(); commandLine.addParameter("-classpath"); - if (writeDynamicVMOptions || storeProgramParametersInJar) { + if (dynamicVMOptions || dynamicParameters) { commandLine.addParameter(PathUtil.getJarPathForClass(commandLineWrapper) + File.pathSeparator + jarFile); appendEncoding(javaParameters, commandLine, vmParametersList); commandLine.addParameter(commandLineWrapper.getName()); @@ -342,6 +363,8 @@ public class JdkUtil { catch (IOException e) { throwUnableToCreateTempFile(e); } + + return dynamicParameters; } private static void throwUnableToCreateTempFile(IOException cause) throws CantRunException { @@ -439,7 +462,11 @@ public class JdkUtil { } public static boolean useDynamicVMOptions() { - return PropertiesComponent.getInstance().getBoolean("dynamic.vmoptions", true); + return PropertiesComponent.getInstance().getBoolean("idea.dynamic.vmoptions", true); + } + + public static boolean useDynamicParameters() { + return PropertiesComponent.getInstance().getBoolean("idea.dynamic.parameters", true); } public static boolean useClasspathJar() {