From 88d576787efa9fd7f64bc58dbd75bfbfc6722200 Mon Sep 17 00:00:00 2001 From: Alex Ruiz Date: Tue, 21 Feb 2012 05:11:37 -0800 Subject: [PATCH] Code cleanup, to make CommandLauncher testable. --- .../externaltool/ExternalToolInvokerTest.java | 22 ++-- .../externaltool/ConfigurationSettings.java | 2 +- .../core/externaltool/ICommandLauncher.java | 42 ------- .../core/externaltool/IConsolePrinter.java | 42 +++++++ .../externaltool/IConsolePrinterFinder.java | 30 +++++ .../externaltool/InvocationParameters.java | 2 +- .../SingleConfigurationSetting.java | 1 + .../SpaceDelimitedArgsSeparator.java | 2 +- .../AbstractExternalToolBasedChecker.java | 9 +- .../core/externaltool/CommandLauncher.java | 116 ++++++++++++++++++ .../externaltool/ExternalToolInvoker.java | 38 +++--- .../core/externaltool/ProcessInvoker.java | 38 ++++++ .../AbstractCxxExternalToolBasedChecker.java | 6 +- .../ui/externaltool/CommandLauncher.java | 113 ----------------- .../codan/ui/externaltool/ConsolePrinter.java | 68 +++++----- ...terImpl.java => ConsolePrinterFinder.java} | 60 ++++----- ...erFactory.java => NullConsolePrinter.java} | 28 +++-- 17 files changed, 340 insertions(+), 279 deletions(-) delete mode 100644 codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/ICommandLauncher.java create mode 100644 codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/IConsolePrinter.java create mode 100644 codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/IConsolePrinterFinder.java create mode 100644 codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/externaltool/CommandLauncher.java create mode 100644 codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/externaltool/ProcessInvoker.java delete mode 100644 codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/ui/externaltool/CommandLauncher.java rename codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/ui/externaltool/{ConsolePrinterImpl.java => ConsolePrinterFinder.java} (64%) rename codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/ui/externaltool/{ConsolePrinterFactory.java => NullConsolePrinter.java} (55%) diff --git a/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/internal/core/externaltool/ExternalToolInvokerTest.java b/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/internal/core/externaltool/ExternalToolInvokerTest.java index 7d424ea7b4d..3b804103690 100644 --- a/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/internal/core/externaltool/ExternalToolInvokerTest.java +++ b/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/internal/core/externaltool/ExternalToolInvokerTest.java @@ -20,7 +20,6 @@ import java.util.List; import org.eclipse.cdt.codan.core.externaltool.AbstractOutputParser; import org.eclipse.cdt.codan.core.externaltool.ConfigurationSettings; import org.eclipse.cdt.codan.core.externaltool.IArgsSeparator; -import org.eclipse.cdt.codan.core.externaltool.ICommandLauncher; import org.eclipse.cdt.codan.core.externaltool.InvocationFailure; import org.eclipse.cdt.codan.core.externaltool.InvocationParameters; import org.eclipse.cdt.codan.core.externaltool.SingleConfigurationSetting; @@ -29,7 +28,6 @@ import org.eclipse.cdt.codan.core.param.BasicProblemPreference; import org.eclipse.cdt.codan.core.param.IProblemPreference; import org.eclipse.cdt.codan.core.param.MapProblemPreference; import org.eclipse.cdt.codan.core.test.CodanTestCase; -import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.IPath; /** @@ -92,7 +90,6 @@ public class ExternalToolInvokerTest extends CodanTestCase { InvocationParameters parameters = new InvocationParameters(currentIFile, currentIFile, currentIFile.getLocation().toOSString(), cproject.getProject().getLocation()); externalToolInvoker.invoke(parameters, settings, argsSeparator, parsers); - launcher.assertThatReceivedProject(cproject.getProject()); launcher.assertThatReceivedExternalToolName(settings.getExternalToolName()); launcher.assertThatReceivedExecutablePath(settings.getPath()); launcher.assertThatReceivedArgs(expectedArgs(parameters)); @@ -109,8 +106,7 @@ public class ExternalToolInvokerTest extends CodanTestCase { return expectedArgs; } - private static class CommandLauncherStub implements ICommandLauncher { - private IProject project; + private static class CommandLauncherStub extends CommandLauncher { private String externalToolName; private IPath executablePath; private String[] args; @@ -118,12 +114,14 @@ public class ExternalToolInvokerTest extends CodanTestCase { private boolean shouldDisplayOutput; private List parsers; + public CommandLauncherStub() { + super(null); + } + @Override - public void buildAndLaunchCommand(IProject project, String externalToolName, - IPath executablePath, String[] args, IPath workingDirectory, - boolean shouldDisplayOutput, List parsers) throws InvocationFailure, - Throwable { - this.project = project; + public void buildAndLaunchCommand(String externalToolName, IPath executablePath, + String[] args, IPath workingDirectory, boolean shouldDisplayOutput, + List parsers) throws InvocationFailure, Throwable { this.externalToolName = externalToolName; this.executablePath = executablePath; this.args = args; @@ -132,10 +130,6 @@ public class ExternalToolInvokerTest extends CodanTestCase { this.parsers = parsers; } - void assertThatReceivedProject(IProject expected) { - assertEquals(expected, project); - } - void assertThatReceivedExternalToolName(String expected) { assertEquals(expected, externalToolName); } diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/ConfigurationSettings.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/ConfigurationSettings.java index 52fafedf421..16d6e7e0aba 100644 --- a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/ConfigurationSettings.java +++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/ConfigurationSettings.java @@ -24,7 +24,7 @@ import org.eclipse.cdt.codan.internal.core.externaltool.ShouldDisplayOutputSetti * * @since 2.1 */ -public class ConfigurationSettings { +public final class ConfigurationSettings { private final PathSetting path; private final ArgsSetting args; private final ShouldDisplayOutputSetting shouldDisplayOutput; diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/ICommandLauncher.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/ICommandLauncher.java deleted file mode 100644 index 94322599cdf..00000000000 --- a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/ICommandLauncher.java +++ /dev/null @@ -1,42 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2012 Google, Inc. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Alex Ruiz - initial API and implementation - *******************************************************************************/ -package org.eclipse.cdt.codan.core.externaltool; - -import java.util.List; - -import org.eclipse.core.resources.IProject; -import org.eclipse.core.runtime.IPath; - -/** - * Builds and launches the command necessary to invoke an external tool. - * - * @author alruiz@google.com (Alex Ruiz) - * - * @since 2.1 - */ -public interface ICommandLauncher { - /** - * Builds and launches the command necessary to invoke an external tool. - * @param project the current project. - * @param externalToolName the name of the external tool. - * @param executablePath the path and name of the external tool executable. - * @param args the arguments to pass to the external tool executable. - * @param workingDirectory the directory where the external tool should be executed. - * @param shouldDisplayOutput indicates whether the output of the external tools should be - * displayed in an Eclipse console. - * @param parsers parse the output of the external tool. - * @throws InvocationFailure if the external tool reports that it cannot be executed. - * @throws Throwable if the external tool cannot be launched. - */ - void buildAndLaunchCommand(IProject project, String externalToolName, IPath executablePath, - String[] args, IPath workingDirectory, boolean shouldDisplayOutput, - List parsers) throws InvocationFailure, Throwable; -} \ No newline at end of file diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/IConsolePrinter.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/IConsolePrinter.java new file mode 100644 index 00000000000..b12669d1b2b --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/IConsolePrinter.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2012 Google, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alex Ruiz - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.core.externaltool; + +/** + * Prints the output of an external tool to an Eclipse console. It uses the name of the external + * tool as the console ID. + * + * @author alruiz@google.com (Alex Ruiz) + * + * @since 2.1 + */ +public interface IConsolePrinter { + /** + * Clears the contents of the console. + */ + void clear(); + + /** + * Prints the specified message to the console, followed by a line separator string. + * @param message the message to print. + */ + void println(String message); + + /** + * Prints a line separator to the console. + */ + void println(); + + /** + * Closes the output stream of the console. + */ + void close(); +} diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/IConsolePrinterFinder.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/IConsolePrinterFinder.java new file mode 100644 index 00000000000..93d54209153 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/IConsolePrinterFinder.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2012 Google, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alex Ruiz - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.core.externaltool; + +/** + * Finds an Eclipse console that uses the name of an external tool as its own. + * + * @author alruiz@google.com (Alex Ruiz) + * + * @since 2.1 + */ +public interface IConsolePrinterFinder { + /** + * Finds an Eclipse console that uses the name of an external tool as its own. + * @param externalToolName the name of the external tool that will be used as the name of the + * console. + * @param shouldDisplayOutput indicates whether the user wants to see the output of the external + * tool in the console. + * @return the created or found console. + */ + IConsolePrinter findConsole(String externalToolName, boolean shouldDisplayOutput); +} \ No newline at end of file diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/InvocationParameters.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/InvocationParameters.java index d9e24ff1491..58faad2c0dc 100644 --- a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/InvocationParameters.java +++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/InvocationParameters.java @@ -20,7 +20,7 @@ import org.eclipse.core.runtime.IPath; * * @since 2.1 */ -public class InvocationParameters { +public final class InvocationParameters { private final IResource originalFile; private final IResource actualFile; private final String actualFilePath; diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/SingleConfigurationSetting.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/SingleConfigurationSetting.java index c94df27a49f..7ae5a4e0db3 100644 --- a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/SingleConfigurationSetting.java +++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/SingleConfigurationSetting.java @@ -20,6 +20,7 @@ import org.eclipse.cdt.codan.core.param.MapProblemPreference; * * @author alruiz@google.com (Alex Ruiz) * + * @noextend This class is not intended to be extended by clients. * @since 2.1 */ public class SingleConfigurationSetting { diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/SpaceDelimitedArgsSeparator.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/SpaceDelimitedArgsSeparator.java index bcab3407376..8e9f092c5c9 100644 --- a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/SpaceDelimitedArgsSeparator.java +++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/externaltool/SpaceDelimitedArgsSeparator.java @@ -20,7 +20,7 @@ import java.util.regex.Pattern; * * @since 2.1 */ -public class SpaceDelimitedArgsSeparator implements IArgsSeparator { +public final class SpaceDelimitedArgsSeparator implements IArgsSeparator { private static final String[] NO_ARGS = new String[0]; private static final Pattern EMPTY_SPACE_PATTERN = Pattern.compile("\\s+"); //$NON-NLS-1$ diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/AbstractExternalToolBasedChecker.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/AbstractExternalToolBasedChecker.java index 467e7f9531c..70eafb9a600 100644 --- a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/AbstractExternalToolBasedChecker.java +++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/AbstractExternalToolBasedChecker.java @@ -8,7 +8,7 @@ import org.eclipse.cdt.codan.core.CodanCorePlugin; import org.eclipse.cdt.codan.core.externaltool.AbstractOutputParser; import org.eclipse.cdt.codan.core.externaltool.ConfigurationSettings; import org.eclipse.cdt.codan.core.externaltool.IArgsSeparator; -import org.eclipse.cdt.codan.core.externaltool.ICommandLauncher; +import org.eclipse.cdt.codan.core.externaltool.IConsolePrinterFinder; import org.eclipse.cdt.codan.core.externaltool.IInvocationParametersProvider; import org.eclipse.cdt.codan.core.externaltool.IProblemDisplay; import org.eclipse.cdt.codan.core.externaltool.ISupportedResourceVerifier; @@ -56,17 +56,18 @@ public abstract class AbstractExternalToolBasedChecker extends AbstractCheckerWi * external tool. * @param argsSeparator separates the arguments to pass to the external tool executable. These * arguments are stored in a single {@code String}. - * @param commandLauncher builds and launches the command necessary to invoke the external tool. + * @param consolePrinterFinder finds an Eclipse console that uses the name of an external tool + * as its own. * @param configurationSettings user-configurable external tool configuration settings. */ public AbstractExternalToolBasedChecker(IInvocationParametersProvider parametersProvider, ISupportedResourceVerifier supportedResourceVerifier, IArgsSeparator argsSeparator, - ICommandLauncher commandLauncher, ConfigurationSettings configurationSettings) { + IConsolePrinterFinder consolePrinterFinder, ConfigurationSettings configurationSettings) { this.parametersProvider = parametersProvider; this.supportedResourceVerifier = supportedResourceVerifier; this.argsSeparator = argsSeparator; this.configurationSettings = configurationSettings; - externalToolInvoker = new ExternalToolInvoker(commandLauncher); + externalToolInvoker = new ExternalToolInvoker(consolePrinterFinder); preferences = new SharedRootProblemPreference(); } diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/externaltool/CommandLauncher.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/externaltool/CommandLauncher.java new file mode 100644 index 00000000000..f70b5894021 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/externaltool/CommandLauncher.java @@ -0,0 +1,116 @@ +/******************************************************************************* + * Copyright (c) 2012 Google, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alex Ruiz - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.internal.core.externaltool; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.util.List; + +import org.eclipse.cdt.codan.core.externaltool.AbstractOutputParser; +import org.eclipse.cdt.codan.core.externaltool.IConsolePrinter; +import org.eclipse.cdt.codan.core.externaltool.IConsolePrinterFinder; +import org.eclipse.cdt.codan.core.externaltool.InvocationFailure; +import org.eclipse.core.runtime.IPath; + +/** + * Invokes an external tool command. + * + * @author alruiz@google.com (Alex Ruiz) + * + * @since 2.1 + */ +public class CommandLauncher { + private ProcessInvoker processInvoker = new ProcessInvoker(); + private final IConsolePrinterFinder consolePrinterFinder; + + /** + * Constructor. + * @param consolePrinter prints the output of an external tool to an Eclipse Console. + */ + public CommandLauncher(IConsolePrinterFinder consolePrinter) { + this.consolePrinterFinder = consolePrinter; + } + + /** + * Builds and launches the command necessary to invoke an external tool. + * @param externalToolName the name of the external tool. + * @param executablePath the path and name of the external tool executable. + * @param args the arguments to pass to the external tool executable. + * @param workingDirectory the directory where the external tool should be executed. + * @param shouldDisplayOutput indicates whether the output of the external tools should be + * displayed in an Eclipse console. + * @param parsers parse the output of the external tool. + * @throws InvocationFailure if the external tool cannot be executed. + * @throws Throwable if the external tool cannot be launched. + */ + public void buildAndLaunchCommand(String externalToolName, IPath executablePath, String[] args, + IPath workingDirectory, boolean shouldDisplayOutput, List parsers) + throws InvocationFailure, Throwable { + String command = buildCommand(executablePath, args); + Process process = null; + IConsolePrinter console = + consolePrinterFinder.findConsole(externalToolName, shouldDisplayOutput); + try { + console.clear(); + console.println(command); + console.println(); + process = processInvoker.invoke(command, workingDirectory); + processStream(process.getInputStream(), parsers, console); + processStream(process.getErrorStream(), parsers, console); + } finally { + if (process != null) { + process.destroy(); + } + console.close(); + } + } + + private String buildCommand(IPath executablePath, String[] args) { + StringBuilder builder = new StringBuilder(); + builder.append(executablePath.toOSString()); + for (String arg : args) { + builder.append(" ").append(arg); //$NON-NLS-1$ + } + return builder.toString(); + } + + private void processStream(InputStream inputStream, List parsers, + IConsolePrinter console) throws IOException, InvocationFailure { + Reader reader = null; + try { + reader = new InputStreamReader(inputStream); + BufferedReader bufferedReader = new BufferedReader(reader); + String line = null; + while ((line = bufferedReader.readLine()) != null) { + console.println(line); + for (AbstractOutputParser parser : parsers) { + if (parser.parse(line)) { + break; + } + } + } + } finally { + if (reader != null) { + try { + reader.close(); + } catch (IOException ignored) {} + } + } + } + + // Visible for testing. + void setProcessInvoker(ProcessInvoker newVal) { + processInvoker = newVal; + } +} diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/externaltool/ExternalToolInvoker.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/externaltool/ExternalToolInvoker.java index b7b85dd0846..8d0cf518924 100644 --- a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/externaltool/ExternalToolInvoker.java +++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/externaltool/ExternalToolInvoker.java @@ -16,10 +16,9 @@ import java.util.List; import org.eclipse.cdt.codan.core.externaltool.AbstractOutputParser; import org.eclipse.cdt.codan.core.externaltool.ConfigurationSettings; import org.eclipse.cdt.codan.core.externaltool.IArgsSeparator; -import org.eclipse.cdt.codan.core.externaltool.ICommandLauncher; +import org.eclipse.cdt.codan.core.externaltool.IConsolePrinterFinder; import org.eclipse.cdt.codan.core.externaltool.InvocationFailure; import org.eclipse.cdt.codan.core.externaltool.InvocationParameters; -import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; @@ -31,15 +30,19 @@ import org.eclipse.core.runtime.Path; * @since 2.1 */ public class ExternalToolInvoker { - private final ICommandLauncher commandLauncher; + private final CommandLauncher commandLauncher; /** * Constructor. - * - * @param commandLauncher builds and launches the command necessary to - * invoke the external tool. + * @param consolePrinterFinder finds an Eclipse console that uses the name of an external tool + * as its own. */ - public ExternalToolInvoker(ICommandLauncher commandLauncher) { + public ExternalToolInvoker(IConsolePrinterFinder consolePrinterFinder) { + this(new CommandLauncher(consolePrinterFinder)); + } + + // Visible for testing. + ExternalToolInvoker(CommandLauncher commandLauncher) { this.commandLauncher = commandLauncher; } @@ -48,23 +51,22 @@ public class ExternalToolInvoker { * * @param parameters the parameters to pass to the external tool executable. * @param configurationSettings user-configurable settings. - * @param argsSeparator separates the arguments to pass to the external tool - * executable. These + * @param argsSeparator separates the arguments to pass to the external tool executable. These * arguments are stored in a single {@code String}. * @param parsers parse the output of the external tool. - * @throws InvocationFailure if the external tool reports that it cannot be - * executed. + * @throws InvocationFailure if the external tool reports that it cannot be executed. * @throws Throwable if the external tool cannot be launched. */ - public void invoke(InvocationParameters parameters, ConfigurationSettings configurationSettings, IArgsSeparator argsSeparator, + public void invoke(InvocationParameters parameters, ConfigurationSettings configurationSettings, + IArgsSeparator argsSeparator, List parsers) throws InvocationFailure, Throwable { IPath executablePath = executablePath(configurationSettings); String[] args = argsToPass(parameters, configurationSettings, argsSeparator); boolean shouldDisplayOutput = configurationSettings.getShouldDisplayOutput().getValue(); - IProject project = parameters.getActualFile().getProject(); try { - commandLauncher.buildAndLaunchCommand(project, configurationSettings.getExternalToolName(), executablePath, args, - parameters.getWorkingDirectory(), shouldDisplayOutput, parsers); + commandLauncher.buildAndLaunchCommand(configurationSettings.getExternalToolName(), + executablePath, args, parameters.getWorkingDirectory(), shouldDisplayOutput, + parsers); } finally { reset(parsers); } @@ -75,13 +77,15 @@ public class ExternalToolInvoker { return new Path(executablePath.toString()); } - private String[] argsToPass(InvocationParameters parameters, ConfigurationSettings configurationSettings, IArgsSeparator argsSeparator) { + private String[] argsToPass(InvocationParameters parameters, + ConfigurationSettings configurationSettings, IArgsSeparator argsSeparator) { String[] configuredArgs = configuredArgs(configurationSettings, argsSeparator); String actualFilePath = parameters.getActualFilePath(); return addFilePathToArgs(actualFilePath, configuredArgs); } - private String[] configuredArgs(ConfigurationSettings configurationSettings, IArgsSeparator argsSeparator) { + private String[] configuredArgs(ConfigurationSettings configurationSettings, + IArgsSeparator argsSeparator) { String args = configurationSettings.getArgs().getValue(); return argsSeparator.separateArgs(args); } diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/externaltool/ProcessInvoker.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/externaltool/ProcessInvoker.java new file mode 100644 index 00000000000..81b1a6ee948 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/externaltool/ProcessInvoker.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2012 Google, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alex Ruiz - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.internal.core.externaltool; + +import java.io.IOException; + +import org.eclipse.cdt.codan.core.externaltool.InvocationFailure; +import org.eclipse.core.runtime.IPath; + +/** + * Executes a command in a separate process. + * + * @author alruiz@google.com (Alex Ruiz) + */ +class ProcessInvoker { + private static final String[] ENVIRONMENT_VARIABLE_SETTINGS = {}; + private static final String ERROR_FORMAT = "Unable to invoke command '%s'"; //$NON-NLS-1$ + + Process invoke(String command, IPath workingDirectory) throws InvocationFailure { + try { + Runtime runtime = Runtime.getRuntime(); + if (workingDirectory == null) { + return runtime.exec(command); + } + return runtime.exec(command, ENVIRONMENT_VARIABLE_SETTINGS, workingDirectory.toFile()); + } catch (IOException e) { + throw new InvocationFailure(String.format(ERROR_FORMAT, command), e); + } + } +} diff --git a/codan/org.eclipse.cdt.codan.ui.cxx/src/org/eclipse/cdt/codan/ui/cxx/externaltool/AbstractCxxExternalToolBasedChecker.java b/codan/org.eclipse.cdt.codan.ui.cxx/src/org/eclipse/cdt/codan/ui/cxx/externaltool/AbstractCxxExternalToolBasedChecker.java index 39a440e123a..0bc0a79c446 100644 --- a/codan/org.eclipse.cdt.codan.ui.cxx/src/org/eclipse/cdt/codan/ui/cxx/externaltool/AbstractCxxExternalToolBasedChecker.java +++ b/codan/org.eclipse.cdt.codan.ui.cxx/src/org/eclipse/cdt/codan/ui/cxx/externaltool/AbstractCxxExternalToolBasedChecker.java @@ -18,7 +18,7 @@ import org.eclipse.cdt.codan.core.externaltool.InvocationParametersProvider; import org.eclipse.cdt.codan.core.externaltool.SpaceDelimitedArgsSeparator; import org.eclipse.cdt.codan.core.model.AbstractExternalToolBasedChecker; import org.eclipse.cdt.codan.internal.ui.cxx.externaltool.CxxSupportedResourceVerifier; -import org.eclipse.cdt.codan.ui.externaltool.CommandLauncher; +import org.eclipse.cdt.codan.ui.externaltool.ConsolePrinterFinder; /** * Base class for checkers that invoke external command-line tools to perform code checking @@ -58,7 +58,7 @@ public abstract class AbstractCxxExternalToolBasedChecker extends AbstractExtern public AbstractCxxExternalToolBasedChecker(IInvocationParametersProvider parametersProvider, ISupportedResourceVerifier supportedResourceVerifier, IArgsSeparator argsSeparator, ConfigurationSettings configurationSettings) { - super(parametersProvider, supportedResourceVerifier, argsSeparator, new CommandLauncher(), - configurationSettings); + super(parametersProvider, supportedResourceVerifier, argsSeparator, + new ConsolePrinterFinder(), configurationSettings); } } diff --git a/codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/ui/externaltool/CommandLauncher.java b/codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/ui/externaltool/CommandLauncher.java deleted file mode 100644 index cf371943b3f..00000000000 --- a/codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/ui/externaltool/CommandLauncher.java +++ /dev/null @@ -1,113 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2012 Google, Inc. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Alex Ruiz - initial API and implementation - *******************************************************************************/ -package org.eclipse.cdt.codan.ui.externaltool; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.util.List; - -import org.eclipse.cdt.codan.core.externaltool.ICommandLauncher; -import org.eclipse.cdt.codan.core.externaltool.AbstractOutputParser; -import org.eclipse.cdt.codan.core.externaltool.InvocationFailure; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.runtime.IPath; - -/** - * Invokes an external tool command. - * - * @author alruiz@google.com (Alex Ruiz) - * - * @since 2.1 - */ -public class CommandLauncher implements ICommandLauncher { - private static final String[] ENVIRONMENT_VARIABLE_SETTINGS = {}; - - private ConsolePrinterFactory consolePrinterFactory = new ConsolePrinterFactory(); - - @Override - public void buildAndLaunchCommand(IProject project, String externalToolName, - IPath executablePath, String[] args, IPath workingDirectory, boolean shouldDisplayOutput, - List parsers) throws InvocationFailure, Throwable { - ConsolePrinter consolePrinter = consolePrinter(externalToolName, shouldDisplayOutput); - String command = buildCommand(executablePath, args); - Process process = null; - try { - consolePrinter.clear(); - consolePrinter.println(command); - consolePrinter.println(); - try { - process = invoke(command, workingDirectory); - } catch (IOException e) { - throw new InvocationFailure("Unable to start " + externalToolName, e); //$NON-NLS-1$ - } - processStream(process.getInputStream(), parsers, consolePrinter); - processStream(process.getErrorStream(), parsers, consolePrinter); - } finally { - if (process != null) { - process.destroy(); - } - consolePrinter.close(); - } - } - - private ConsolePrinter consolePrinter(String externalToolName, boolean shouldDisplayOutput) { - return consolePrinterFactory.createConsolePrinter(externalToolName, shouldDisplayOutput); - } - - private String buildCommand(IPath executablePath, String[] args) { - StringBuilder builder = new StringBuilder(); - builder.append(executablePath.toOSString()); - for (String arg : args) { - builder.append(" ").append(arg); //$NON-NLS-1$ - } - return builder.toString(); - } - - private Process invoke(String command, IPath workingDirectory) throws IOException { - Runtime runtime = Runtime.getRuntime(); - if (workingDirectory == null) { - return runtime.exec(command); - } - return runtime.exec(command, ENVIRONMENT_VARIABLE_SETTINGS, workingDirectory.toFile()); - } - - private void processStream(InputStream inputStream, List parsers, - ConsolePrinter consolePrinter) throws IOException, InvocationFailure { - Reader reader = null; - try { - reader = new InputStreamReader(inputStream); - BufferedReader bufferedReader = new BufferedReader(reader); - String line = null; - while ((line = bufferedReader.readLine()) != null) { - consolePrinter.println(line); - for (AbstractOutputParser parser : parsers) { - if (parser.parse(line)) { - break; - } - } - } - } finally { - if (reader != null) { - try { - reader.close(); - } catch (IOException ignored) {} - } - } - } - - // Visible for testing. - void setConsolePrinterFactory(ConsolePrinterFactory newVal) { - this.consolePrinterFactory = newVal; - } -} diff --git a/codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/ui/externaltool/ConsolePrinter.java b/codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/ui/externaltool/ConsolePrinter.java index 41ac71312b4..a10c751003c 100644 --- a/codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/ui/externaltool/ConsolePrinter.java +++ b/codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/ui/externaltool/ConsolePrinter.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012 Google, Inc. + * Copyright (c) 2012 Google, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -10,45 +10,43 @@ *******************************************************************************/ package org.eclipse.cdt.codan.ui.externaltool; +import java.io.IOException; + +import org.eclipse.cdt.codan.core.externaltool.IConsolePrinter; +import org.eclipse.ui.console.MessageConsole; +import org.eclipse.ui.console.MessageConsoleStream; + /** - * Prints the output of an external tool to an Eclipse console. It uses the name of the external - * tool as the console ID. - * + * Default implementation of {@link IConsolePrinter}. + * * @author alruiz@google.com (Alex Ruiz) + * + * @since 2.1 */ -interface ConsolePrinter { - ConsolePrinter NullImpl = new ConsolePrinter() { - @Override - public void clear() {} +class ConsolePrinter implements IConsolePrinter { + private final MessageConsole console; + private final MessageConsoleStream out; - @Override - public void println(String message) {} - - @Override - public void println() {} + ConsolePrinter(MessageConsole console) { + this.console = console; + out = console.newMessageStream(); + } - @Override - public void close() {} - }; + public void clear() { + console.clearConsole(); + } - /** - * Clears the contents of the console. - */ - void clear(); + public void println(String s) { + out.println(s); + } - /** - * Prints the specified message to the console, followed by a line separator string. - * @param message the message to print. - */ - void println(String message); - - /** - * Prints a line separator to the console. - */ - void println(); - - /** - * Closes the output stream of the console. - */ - void close(); + public void println() { + out.println(); + } + + public void close() { + try { + out.close(); + } catch (IOException ignored) {} + } } diff --git a/codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/ui/externaltool/ConsolePrinterImpl.java b/codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/ui/externaltool/ConsolePrinterFinder.java similarity index 64% rename from codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/ui/externaltool/ConsolePrinterImpl.java rename to codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/ui/externaltool/ConsolePrinterFinder.java index abaf246d10a..66faf996c32 100644 --- a/codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/ui/externaltool/ConsolePrinterImpl.java +++ b/codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/ui/externaltool/ConsolePrinterFinder.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012 Google, Inc. + * Copyright (c) 2012 Google, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -12,8 +12,9 @@ package org.eclipse.cdt.codan.ui.externaltool; import static org.eclipse.ui.console.IConsoleConstants.ID_CONSOLE_VIEW; -import java.io.IOException; - +import org.eclipse.cdt.codan.core.externaltool.IConsolePrinter; +import org.eclipse.cdt.codan.core.externaltool.IConsolePrinterFinder; +import org.eclipse.cdt.codan.internal.ui.CodanUIActivator; import org.eclipse.cdt.codan.ui.CodanEditorUtility; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.PartInitException; @@ -22,26 +23,38 @@ import org.eclipse.ui.console.IConsole; import org.eclipse.ui.console.IConsoleManager; import org.eclipse.ui.console.IConsoleView; import org.eclipse.ui.console.MessageConsole; -import org.eclipse.ui.console.MessageConsoleStream; /** - * Default implementation of {@link ConsolePrinter}. - * + * Default implementation of {@link IConsolePrinterFinder}. + * * @author alruiz@google.com (Alex Ruiz) + * + * @since 2.1 */ -class ConsolePrinterImpl implements ConsolePrinter { - private final MessageConsole console; - private final MessageConsoleStream out; +public class ConsolePrinterFinder implements IConsolePrinterFinder { + private static final NullConsolePrinter NULL_CONSOLE = new NullConsolePrinter(); + + /** {@inheritDoc} */ + @Override + public IConsolePrinter findConsole(String externalToolName, boolean shouldDisplayOutput) { + if (shouldDisplayOutput) { + try { + return createOrFindConsole(externalToolName); + } catch (Throwable e) { + CodanUIActivator.log("Unable to create/find console", e); //$NON-NLS-1$ + } + } + return NULL_CONSOLE; + } - static ConsolePrinter createOrFindConsole(String externalToolName) - throws PartInitException { + private IConsolePrinter createOrFindConsole(String externalToolName) throws PartInitException { MessageConsole console = findConsole(externalToolName); IWorkbenchPage page = CodanEditorUtility.getActivePage(); if (page != null) { IConsoleView view = (IConsoleView) page.showView(ID_CONSOLE_VIEW); view.display(console); } - return new ConsolePrinterImpl(console); + return new ConsolePrinter(console); } private static MessageConsole findConsole(String externalToolName) { @@ -55,27 +68,4 @@ class ConsolePrinterImpl implements ConsolePrinter { consoleManager.addConsoles(new IConsole[] { console }); return console; } - - private ConsolePrinterImpl(MessageConsole console) { - this.console = console; - out = console.newMessageStream(); - } - - public void clear() { - console.clearConsole(); - } - - public void println(String s) { - out.println(s); - } - - public void println() { - out.println(); - } - - public void close() { - try { - out.close(); - } catch (IOException ignored) {} - } } diff --git a/codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/ui/externaltool/ConsolePrinterFactory.java b/codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/ui/externaltool/NullConsolePrinter.java similarity index 55% rename from codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/ui/externaltool/ConsolePrinterFactory.java rename to codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/ui/externaltool/NullConsolePrinter.java index 7a86efef316..022ff99bb64 100644 --- a/codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/ui/externaltool/ConsolePrinterFactory.java +++ b/codan/org.eclipse.cdt.codan.ui/src/org/eclipse/cdt/codan/ui/externaltool/NullConsolePrinter.java @@ -10,21 +10,23 @@ *******************************************************************************/ package org.eclipse.cdt.codan.ui.externaltool; -import org.eclipse.cdt.codan.internal.ui.CodanUIActivator; -import org.eclipse.ui.PartInitException; +import org.eclipse.cdt.codan.core.externaltool.IConsolePrinter; /** + * No-op implementation of {@link IConsolePrinter}. + * * @author alruiz@google.com (Alex Ruiz) */ -class ConsolePrinterFactory { - ConsolePrinter createConsolePrinter(String externalToolName, boolean shouldDisplayOutput) { - if (shouldDisplayOutput) { - try { - return ConsolePrinterImpl.createOrFindConsole(externalToolName); - } catch (PartInitException e) { - CodanUIActivator.log("Unable to create/find console", e); //$NON-NLS-1$ - } - } - return ConsolePrinter.NullImpl; - } +class NullConsolePrinter implements IConsolePrinter { + @Override + public void clear() {} + + @Override + public void println(String message) {} + + @Override + public void println() {} + + @Override + public void close() {} }