diff -r f60f09aecc4f extexecution/apichanges.xml --- a/extexecution/apichanges.xml Mon Nov 14 16:01:42 2011 +0100 +++ b/extexecution/apichanges.xml Mon Nov 14 19:03:18 2011 +0100 @@ -105,6 +105,7 @@ External Execution Input API External Execution Input Printing API External Execution Process Destroy SPI + External Execution SPI @@ -114,6 +115,22 @@ + New API/SPI to abstract process builder + + + + + + New API/SPI classes to allow different implementations + of process builders. + + + + + + + + New API method to avoid reset of custom IO diff -r f60f09aecc4f extexecution/arch.xml --- a/extexecution/arch.xml Mon Nov 14 16:01:42 2011 +0100 +++ b/extexecution/arch.xml Mon Nov 14 19:03:18 2011 +0100 @@ -51,7 +51,8 @@ that contains support for execution of external processes in the IDE. It also provide support class for the actual creation of the external process - and support for destroying the process tree. + and support for destroying the process tree. There is also abstraction of + process builder.

Another exported API @@ -66,6 +67,11 @@ org.openide.windows.OutputWriter. API provides common implementations too.

+ The SPI + + allows different implementations of process builder. +

+

There is also SPI allowing to register support for destroying the process tree .

@@ -205,6 +211,21 @@ LineConvertors.

+ +

+ Third party wants to implement custom process builder to provide + additional functionality, such as remote execution. +

+

+ In order to do so it will implement + + ProcessBuilderImplementation and pass + + ProcessBuilder to its clients. The API instances are created with + help of + ProcessBuilderFactory. +

+

Client wants to destroy the process, trying to kill whole process tree. diff -r f60f09aecc4f extexecution/manifest.mf --- a/extexecution/manifest.mf Mon Nov 14 16:01:42 2011 +0100 +++ b/extexecution/manifest.mf Mon Nov 14 19:03:18 2011 +0100 @@ -2,5 +2,5 @@ AutoUpdate-Show-In-Client: false OpenIDE-Module: org.netbeans.modules.extexecution/2 OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/extexecution/resources/Bundle.properties -OpenIDE-Module-Specification-Version: 1.27 +OpenIDE-Module-Specification-Version: 1.28 diff -r f60f09aecc4f extexecution/nbproject/project.xml --- a/extexecution/nbproject/project.xml Mon Nov 14 16:01:42 2011 +0100 +++ b/extexecution/nbproject/project.xml Mon Nov 14 19:03:18 2011 +0100 @@ -130,6 +130,7 @@ org.netbeans.api.extexecution org.netbeans.api.extexecution.print org.netbeans.api.extexecution.input + org.netbeans.spi.extexecution org.netbeans.spi.extexecution.destroy diff -r f60f09aecc4f extexecution/src/org/netbeans/api/extexecution/Bundle.properties --- a/extexecution/src/org/netbeans/api/extexecution/Bundle.properties Mon Nov 14 16:01:42 2011 +0100 +++ b/extexecution/src/org/netbeans/api/extexecution/Bundle.properties Mon Nov 14 19:03:18 2011 +0100 @@ -41,3 +41,4 @@ # made subject to such option by the copyright holder. Running=Running +LocalProcessFactory=Factory creating local processes diff -r f60f09aecc4f extexecution/src/org/netbeans/api/extexecution/ExternalProcessBuilder.java --- a/extexecution/src/org/netbeans/api/extexecution/ExternalProcessBuilder.java Mon Nov 14 16:01:42 2011 +0100 +++ b/extexecution/src/org/netbeans/api/extexecution/ExternalProcessBuilder.java Mon Nov 14 19:03:18 2011 +0100 @@ -64,11 +64,13 @@ import org.openide.util.Utilities; /** - * Utility class to make the external process creation easier. + * Utility class to make the local external process creation easier. *

* Builder handle command, working directory, PATH variable and HTTP proxy. *

* This class is immutable. + *

+ * Also see {@link ProcessBuilder#getLocal()}. * * @author Petr Hejl * @see #call() @@ -278,7 +280,7 @@ List args = buildArguments(); commandList.addAll(args); - ProcessBuilder pb = new ProcessBuilder(commandList.toArray(new String[commandList.size()])); + java.lang.ProcessBuilder pb = new java.lang.ProcessBuilder(commandList.toArray(new String[commandList.size()])); if (workingDirectory != null) { pb.directory(workingDirectory); } @@ -301,7 +303,7 @@ * @param pb the ProcessBuilder to log. * @param level the level for logging. */ - private void logProcess(final Level level, final ProcessBuilder pb) { + private void logProcess(final Level level, final java.lang.ProcessBuilder pb) { if (!LOGGER.isLoggable(level)) { return; @@ -406,7 +408,7 @@ return sb.toString(); } - private void adjustProxy(ProcessBuilder pb) { + private void adjustProxy(java.lang.ProcessBuilder pb) { String proxy = getNetBeansHttpProxy(); if (proxy != null) { Map env = pb.environment(); diff -r f60f09aecc4f extexecution/src/org/netbeans/api/extexecution/ProcessBuilder.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extexecution/src/org/netbeans/api/extexecution/ProcessBuilder.java Mon Nov 14 19:03:18 2011 +0100 @@ -0,0 +1,290 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2011 Sun Microsystems, Inc. + */ +package org.netbeans.api.extexecution; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Callable; +import org.netbeans.api.annotations.common.NonNull; +import org.netbeans.api.annotations.common.NullAllowed; +import org.netbeans.spi.extexecution.ProcessBuilderFactory; +import org.netbeans.spi.extexecution.ProcessBuilderImplementation; +import org.openide.util.NbBundle; +import org.openide.util.Parameters; + +/** + * Abstraction of process builders. You can freely configure the parameters + * and then create a process by calling the {@link #call()} method. You can + * also (re)configure the builder and spawn a different process. + *

+ * Note the API does not prescribe the actual meaning of {@link Process}. + * It may be local process, remote process or some other implementation. + *

+ * You can use the default implementation returned by {@link #getLocal()} + * for creating the local machine OS processes. + *

+ * Thread safety of this class depends on thread safety of + * the {@link ProcessBuilderImplementation} the class is using. If it is thread + * safe (if possible the implementation should be even stateless) this class + * is thread safe as well. + * + * @author Petr Hejl + * @since 1.28 + */ +public final class ProcessBuilder implements Callable { + + private final ProcessBuilderImplementation implementation; + + private final String description; + + /**GuardedBy("this")*/ + private String executable; + + /**GuardedBy("this")*/ + private String workingDirectory; + + /**GuardedBy("this")*/ + private List arguments = new ArrayList(); + + /**GuardedBy("this")*/ + private List paths = new ArrayList(); + + /**GuardedBy("this")*/ + private Map envVariables = new HashMap(); + + /**GuardedBy("this")*/ + private boolean redirectErrorStream; + + static { + ProcessBuilderFactory.Accessor.DEFAULT = new ProcessBuilderFactory.Accessor() { + + @Override + public ProcessBuilder createProcessBuilder(ProcessBuilderImplementation impl, String description) { + return new ProcessBuilder(impl, description); + } + }; + } + + private ProcessBuilder(ProcessBuilderImplementation implementation, String description) { + this.implementation = implementation; + this.description = description; + } + + /** + * Returns the {@link ProcessBuilder} creating the OS process on local + * machine. Returned implementation is thread safe. + * + * @return the {@link ProcessBuilder} creating the OS process on local + * machine + */ + public static ProcessBuilder getLocal() { + return new ProcessBuilder(new LocalProcessFactory(), + NbBundle.getMessage(ProcessBuilder.class, "LocalProcessFactory")); + } + + /** + * Returns the human readable description of this builder. + * + * @return the human readable description of this builder + */ + @NonNull + public String getDescription() { + return description; + } + + /** + * Sets the executable to run. There is no default value. The {@link #call()} + * methods throws {@link IllegalStateException} when there is no executable + * configured. + * + * @param executable the executable to run + */ + public void setExecutable(@NonNull String executable) { + Parameters.notNull("executable", executable); + + synchronized (this) { + this.executable = executable; + } + } + + /** + * Sets the working directory for the process created by subsequent call + * of {@link #call()}. The default value is implementation specific. + * + * @param workingDirectory the working directory of the process + */ + public void setWorkingDirectory(@NullAllowed String workingDirectory) { + synchronized (this) { + this.workingDirectory = workingDirectory; + } + } + + /** + * Sets the arguments passed to the process created by subsequent call + * of {@link #call()}. By default there are no arguments. + * + * @param arguments the arguments passed to the process + */ + public void setArguments(@NonNull List arguments) { + Parameters.notNull("arguments", arguments); + + synchronized (this) { + this.arguments.clear(); + this.arguments.addAll(arguments); + } + } + + /** + * Sets the environment variables for the process created by subsequent call + * of {@link #call()}. By default there are no environment variables with + * exception of PATH possibly configured by {@link #setPaths(java.util.List)}. + * + * @param envVariables the environment variables for the process + */ + public void setEnvironmentVariables(@NonNull Map envVariables) { + Parameters.notNull("envVariables", envVariables); + + synchronized (this) { + this.envVariables.clear(); + this.envVariables.putAll(envVariables); + } + } + + /** + * Sets the additional paths to be included in PATH environment + * variable for the process. + * + * @param paths the additional paths to be included in PATH + * environment variable + */ + public void setPaths(@NonNull List paths) { + Parameters.notNull("paths", paths); + + synchronized (this) { + this.paths.clear(); + this.paths.addAll(paths); + } + } + + /** + * Configures the error stream redirection. If true the error + * stream of process created by subsequent call of {@link #call()} method + * will be redirected to standard output stream. + * + * @param redirectErrorStream the error stream redirection + */ + public void setRedirectErrorStream(boolean redirectErrorStream) { + synchronized (this) { + this.redirectErrorStream = redirectErrorStream; + } + } + + /** + * Creates the new {@link Process} based on the properties configured + * in this builder. + *

+ * Actual behavior depends on the builder implementation, but it should + * respect all the properties configured on this builder. + * + * @see ProcessBuilderImplementation + * @return the new {@link Process} based on the properties configured + * in this builder + * @throws IOException if the process could not be created + * @throws IllegalStateException if there is no executable configured + * by {@link #setExecutable(java.lang.String)} + */ + @NonNull + @Override + public Process call() throws IOException { + String currentExecutable = null; + String currentWorkingDirectory = null; + List currentArguments = new ArrayList(); + List currentPaths = new ArrayList(); + Map currentEnvVariables = new HashMap(); + boolean currentRedirectErrorStream = false; + + synchronized (this) { + currentExecutable = executable; + currentWorkingDirectory = workingDirectory; + currentArguments.addAll(arguments); + currentPaths.addAll(paths); + currentEnvVariables.putAll(envVariables); + currentRedirectErrorStream = redirectErrorStream; + } + + if (currentExecutable == null) { + throw new IllegalStateException("The executable has not been configured"); + } + + return implementation.createProcess(currentExecutable, currentWorkingDirectory, currentArguments, + currentPaths, currentEnvVariables, currentRedirectErrorStream); + } + + private static class LocalProcessFactory implements ProcessBuilderImplementation { + + @Override + public Process createProcess(String executable, String workingDirectory, List arguments, + List paths, Map environment, boolean redirectErrorStream) throws IOException { + + ExternalProcessBuilder builder = new ExternalProcessBuilder(executable); + if (workingDirectory != null) { + builder = builder.workingDirectory(new File(workingDirectory)); + } + for (String argument : arguments) { + builder = builder.addArgument(argument); + } + for (String path : paths) { + builder = builder.prependPath(new File(path)); + } + for (Map.Entry entry : environment.entrySet()) { + builder = builder.addEnvironmentVariable(entry.getKey(), entry.getValue()); + } + builder = builder.redirectErrorStream(redirectErrorStream); + + return builder.call(); + } + } +} diff -r f60f09aecc4f extexecution/src/org/netbeans/spi/extexecution/ProcessBuilderFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extexecution/src/org/netbeans/spi/extexecution/ProcessBuilderFactory.java Mon Nov 14 19:03:18 2011 +0100 @@ -0,0 +1,101 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2011 Sun Microsystems, Inc. + */ +package org.netbeans.spi.extexecution; + +/** + * The factory allowing SPI implementors of {@link ProcessBuilderImplementation} + * to create its API instances {@link org.netbeans.api.extexecution.ProcessBuilder}. + * + * @author Petr Hejl + * @since 1.28 + */ +public class ProcessBuilderFactory { + + private ProcessBuilderFactory() { + super(); + } + + /** + * Creates the instance of {@link org.netbeans.api.extexecution.ProcessBuilder} + * from its SPI representation. + * + * @param impl SPI representation + * @param description human readable description of the builder + * @return the API instance + */ + public static org.netbeans.api.extexecution.ProcessBuilder createProcessBuilder( + ProcessBuilderImplementation impl, String description) { + return Accessor.DEFAULT.createProcessBuilder(impl, description); + } + + /** + * The accessor pattern class. + */ + public abstract static class Accessor { + + /** The default accessor. */ + public static Accessor DEFAULT; + + static { + // invokes static initializer of ProcessBuilder.class + // that will assign value to the DEFAULT field above + Class c = org.netbeans.api.extexecution.ProcessBuilder.class; + try { + Class.forName(c.getName(), true, c.getClassLoader()); + } catch (ClassNotFoundException ex) { + assert false : ex; + } + } + + /** + * Creates the instance of {@link org.netbeans.api.extexecution.ProcessBuilder} + * from its SPI representation. + * + * @param impl SPI representation + * @param description human readable description of the builder + * @return the API instance + */ + public abstract org.netbeans.api.extexecution.ProcessBuilder createProcessBuilder( + ProcessBuilderImplementation impl, String description); + + } +} diff -r f60f09aecc4f extexecution/src/org/netbeans/spi/extexecution/ProcessBuilderImplementation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extexecution/src/org/netbeans/spi/extexecution/ProcessBuilderImplementation.java Mon Nov 14 19:03:18 2011 +0100 @@ -0,0 +1,88 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2011 Sun Microsystems, Inc. + */ +package org.netbeans.spi.extexecution; + +import java.io.IOException; +import java.util.List; +import java.util.Map; +import org.netbeans.api.annotations.common.NonNull; +import org.netbeans.api.annotations.common.NullAllowed; + +/** + * The interface representing the implementation + * of {@link org.netbeans.api.extexecution.ProcessBuilder}. + * + *

+ *

+ * Although it is not required it is reasonable to have implementation of this + * interface stateless. In such case instances of {@link org.netbeans.api.extexecution.ProcessBuilder} + * using it will be thread safe. + *

+ * + * @see org.netbeans.api.extexecution.ProcessBuilder + * @author Petr Hejl + * @since 1.28 + */ +public interface ProcessBuilderImplementation { + + /** + * Creates a process using the specified parameters and environment + * configuration. + * + * @param executable the name of the executable to run + * @param workingDirectory the working directory of the created process or + * null as implementation specific default + * @param arguments the arguments passed to the process + * @param paths the additional paths to add to PATH environment + * variable + * @param environment environment variables to configure for the process + * @param redirectErrorStream when true the error stream of + * the process should be redirected to standard output stream + * @return a process created with specified parameters and environment + * configuration + * @throws IOException IOException if the process could not be created + */ + @NonNull + Process createProcess(@NonNull String executable, @NullAllowed String workingDirectory, @NonNull List arguments, + @NonNull List paths, @NonNull Map environment, boolean redirectErrorStream) throws IOException; + +} diff -r f60f09aecc4f extexecution/src/org/netbeans/spi/extexecution/package-info.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extexecution/src/org/netbeans/spi/extexecution/package-info.java Mon Nov 14 19:03:18 2011 +0100 @@ -0,0 +1,51 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun + * Microsystems, Inc. All Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + */ + +/** + * The support SPI for creation of external processes. + * + * @see org.netbeans.spi.extexecution.ProcessBuilderImplementation + */ +package org.netbeans.spi.extexecution; + diff -r f60f09aecc4f extexecution/test/unit/src/org/netbeans/api/extexecution/ProcessBuilderTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extexecution/test/unit/src/org/netbeans/api/extexecution/ProcessBuilderTest.java Mon Nov 14 19:03:18 2011 +0100 @@ -0,0 +1,166 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2011 Sun Microsystems, Inc. + */ +package org.netbeans.api.extexecution; + +import java.io.IOException; +import java.util.List; +import java.util.Map; +import org.netbeans.junit.NbTestCase; +import org.netbeans.spi.extexecution.ProcessBuilderFactory; +import org.netbeans.spi.extexecution.ProcessBuilderImplementation; + +/** + * + * @author Petr Hejl + */ +public class ProcessBuilderTest extends NbTestCase { + + public ProcessBuilderTest(String name) { + super(name); + } + + public void testExecutable() throws IOException { + TestProcessBuilder testBuilder = new TestProcessBuilder(); + ProcessBuilder builder = ProcessBuilderFactory.createProcessBuilder(testBuilder, "Test builder"); + + try { + builder.call(); + fail("Empty executable does not throw exception"); + } catch (IllegalStateException ex) { + // expected + } + + builder.setExecutable("ls"); + builder.call(); + assertEquals("ls", testBuilder.getExecutable()); + + builder.setExecutable("cd"); + assertEquals("ls", testBuilder.getExecutable()); + + builder.call(); + assertEquals("cd", testBuilder.getExecutable()); + } + + public void testWorkingDirectory() throws IOException { + TestProcessBuilder testBuilder = new TestProcessBuilder(); + ProcessBuilder builder = ProcessBuilderFactory.createProcessBuilder(testBuilder, "Test builder"); + builder.setExecutable("ls"); + + builder.call(); + assertNull(testBuilder.getWorkingDirectory()); + + builder.setWorkingDirectory("test"); + assertNull(testBuilder.getWorkingDirectory()); + + builder.call(); + assertEquals("test", testBuilder.getWorkingDirectory()); + } + + public void testRedirectErrorStream() throws IOException { + TestProcessBuilder testBuilder = new TestProcessBuilder(); + ProcessBuilder builder = ProcessBuilderFactory.createProcessBuilder(testBuilder, "Test builder"); + builder.setExecutable("ls"); + + builder.call(); + assertFalse(testBuilder.isRedirectErrorStream()); + + builder.setRedirectErrorStream(true); + assertFalse(testBuilder.isRedirectErrorStream()); + + builder.call(); + assertTrue(testBuilder.isRedirectErrorStream()); + } + + private class TestProcessBuilder implements ProcessBuilderImplementation { + + private String executable; + + private String workingDirectory; + + private List arguments; + + private List paths; + + private Map environment; + + private boolean redirectErrorStream; + + @Override + public Process createProcess(String executable, String workingDirectory, + List arguments, List paths, Map environment, boolean redirectErrorStream) throws IOException { + + this.executable = executable; + this.workingDirectory = workingDirectory; + this.arguments = arguments; + this.paths = paths; + this.environment = environment; + this.redirectErrorStream = redirectErrorStream; + + return null; + } + + public String getExecutable() { + return executable; + } + + public List getArguments() { + return arguments; + } + + public List getPaths() { + return paths; + } + + public Map getEnvironment() { + return environment; + } + + public boolean isRedirectErrorStream() { + return redirectErrorStream; + } + + public String getWorkingDirectory() { + return workingDirectory; + } + + } +}