diff --git a/debug/org.eclipse.debug.tests/src/org/eclipse/debug/tests/console/ProcessConsoleTests.java b/debug/org.eclipse.debug.tests/src/org/eclipse/debug/tests/console/ProcessConsoleTests.java index 3a6d09bd4e0..a50fc104071 100644 --- a/debug/org.eclipse.debug.tests/src/org/eclipse/debug/tests/console/ProcessConsoleTests.java +++ b/debug/org.eclipse.debug.tests/src/org/eclipse/debug/tests/console/ProcessConsoleTests.java @@ -619,6 +619,71 @@ public void testInputFromFileSendsEof() throws Exception { assertThat(receivedInput).as("received input").isEqualTo(input); } + /** + * Test that a process reads its standard input from a file set on its launch + * when it has no launch configuration. + */ + @Test + public void testInputFromLaunchAttribute() throws Exception { + byte[] input = "from launch\n".getBytes(StandardCharsets.US_ASCII); + String consoleEncoding = StandardCharsets.UTF_8.name(); + + final File inFile = createTmpFile("testinput-launch.txt"); + Files.write(inFile.toPath(), input); + final MockProcess mockProcess = new MockProcess(MockProcess.RUN_FOREVER); + try { + final IProcess process = mockProcess.toRuntimeProcess("inputFromLaunch"); + process.getLaunch().setAttribute(IDebugUIConstants.ATTR_CAPTURE_STDIN_FILE, inFile.getCanonicalPath()); + final ProcessConsole console = new ProcessConsole(process, new ConsoleColorProvider(), consoleEncoding); + try { + console.initialize(); + waitWhile(() -> !mockProcess.isStdinClosed(), () -> "Process stdin was not closed after input file was read."); + } finally { + console.destroy(); + } + } finally { + mockProcess.destroy(); + } + + assertThat(mockProcess.getReceivedInput()).as("received input").isEqualTo(input); + } + + /** + * Test that an input file set on the launch is supplied instead of the input + * file of its launch configuration. + */ + @Test + public void testInputFromLaunchAttributeOverridesConfiguration() throws Exception { + byte[] launchInput = "from launch\n".getBytes(StandardCharsets.US_ASCII); + byte[] configurationInput = "from configuration\n".getBytes(StandardCharsets.US_ASCII); + String consoleEncoding = StandardCharsets.UTF_8.name(); + + final File launchFile = createTmpFile("testinput-launch.txt"); + Files.write(launchFile.toPath(), launchInput); + final File configurationFile = createTmpFile("testinput-configuration.txt"); + Files.write(configurationFile.toPath(), configurationInput); + final MockProcess mockProcess = new MockProcess(MockProcess.RUN_FOREVER); + try { + Map launchConfigAttributes = new HashMap<>(); + launchConfigAttributes.put(DebugPlugin.ATTR_CONSOLE_ENCODING, consoleEncoding); + launchConfigAttributes.put(IDebugUIConstants.ATTR_CAPTURE_STDIN_FILE, configurationFile.getCanonicalPath()); + launchConfigAttributes.put(IDebugUIConstants.ATTR_CAPTURE_IN_CONSOLE, false); + final IProcess process = mockProcess.toRuntimeProcess("inputFromLaunchOverride", launchConfigAttributes); + process.getLaunch().setAttribute(IDebugUIConstants.ATTR_CAPTURE_STDIN_FILE, launchFile.getCanonicalPath()); + final ProcessConsole console = new ProcessConsole(process, new ConsoleColorProvider(), consoleEncoding); + try { + console.initialize(); + waitWhile(() -> !mockProcess.isStdinClosed(), () -> "Process stdin was not closed after input file was read."); + } finally { + console.destroy(); + } + } finally { + mockProcess.destroy(); + } + + assertThat(mockProcess.getReceivedInput()).as("received input").isEqualTo(launchInput); + } + /** * Test that console name updates (elapsed time) only happen for visible * consoles. Hidden consoles should not update their name. When a hidden diff --git a/debug/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/console/ProcessConsole.java b/debug/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/console/ProcessConsole.java index 7ae8c565346..55f129d14c7 100644 --- a/debug/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/console/ProcessConsole.java +++ b/debug/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/console/ProcessConsole.java @@ -183,15 +183,21 @@ public ProcessConsole(IProcess process, IConsoleColorProvider colorProvider, Str ILaunchConfiguration configuration = process.getLaunch().getLaunchConfiguration(); String file = null; boolean append = false; - if (configuration != null) { + // an input file set on the launch overrides the one of its configuration + fStdInFile = process.getLaunch().getAttribute(IDebugUIConstants.ATTR_CAPTURE_STDIN_FILE); + if (configuration != null || fStdInFile != null) { try { - file = configuration.getAttribute(IDebugUIConstants.ATTR_CAPTURE_IN_FILE, (String) null); - fStdInFile = configuration.getAttribute(IDebugUIConstants.ATTR_CAPTURE_STDIN_FILE, (String) null); + if (configuration != null) { + file = configuration.getAttribute(IDebugUIConstants.ATTR_CAPTURE_IN_FILE, (String) null); + append = configuration.getAttribute(IDebugUIConstants.ATTR_APPEND_TO_FILE, false); + if (fStdInFile == null) { + fStdInFile = configuration.getAttribute(IDebugUIConstants.ATTR_CAPTURE_STDIN_FILE, (String) null); + } + } if (file != null || fStdInFile != null) { IStringVariableManager stringVariableManager = VariablesPlugin.getDefault().getStringVariableManager(); if (file != null) { file = stringVariableManager.performStringSubstitution(file); - append = configuration.getAttribute(IDebugUIConstants.ATTR_APPEND_TO_FILE, false); } if (fStdInFile != null) { @@ -248,7 +254,7 @@ public ProcessConsole(IProcess process, IConsoleColorProvider colorProvider, Str } fFileOutputStream = outputStream; InputStream inputStream = null; - if (fStdInFile != null && configuration != null) { + if (fStdInFile != null) { String message = null; try { inputStream = new FileInputStream(new File(fStdInFile)); diff --git a/debug/org.eclipse.debug.ui/ui/org/eclipse/debug/ui/IDebugUIConstants.java b/debug/org.eclipse.debug.ui/ui/org/eclipse/debug/ui/IDebugUIConstants.java index c52ff715bca..cdf2de12416 100644 --- a/debug/org.eclipse.debug.ui/ui/org/eclipse/debug/ui/IDebugUIConstants.java +++ b/debug/org.eclipse.debug.ui/ui/org/eclipse/debug/ui/IDebugUIConstants.java @@ -970,6 +970,13 @@ public interface IDebugUIConstants { /** * Launch configuration attribute to specifying a file whose content is supplied * to the launched process input stream. Default value is null. + *

+ * The attribute may also be set on the {@link org.eclipse.debug.core.ILaunch} + * before its processes are created, for example by an + * {@link org.eclipse.debug.core.ILaunchListener} when the launch is added. A + * file set on the launch is supplied instead of the one of its launch + * configuration. + *

* * @since 3.11 */