This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

View | Details | Raw Unified | Return to bug 205104
Collapse All | Expand All

(-)a/extexecution/apichanges.xml (+17 lines)
Lines 105-110 Link Here
105
        <apidef name="extexecution_api_input">External Execution Input API</apidef>
105
        <apidef name="extexecution_api_input">External Execution Input API</apidef>
106
        <apidef name="extexecution_api_print">External Execution Input Printing API</apidef>
106
        <apidef name="extexecution_api_print">External Execution Input Printing API</apidef>
107
        <apidef name="extexecution_spi_destroy">External Execution Process Destroy SPI</apidef>
107
        <apidef name="extexecution_spi_destroy">External Execution Process Destroy SPI</apidef>
108
        <apidef name="extexecution_spi">External Execution SPI</apidef>
108
        <!-- etc. -->
109
        <!-- etc. -->
109
    </apidefs>
110
    </apidefs>
110
111
Lines 114-119 Link Here
114
115
115
        <change>
116
        <change>
116
            <api name="extexecution_api"/>
117
            <api name="extexecution_api"/>
118
            <summary>New API/SPI to abstract process builder</summary>
119
            <version major="1" minor="28"/>
120
            <date day="21" month="11" year="2011"/>
121
            <author login="phejl"/>
122
            <compatibility binary="compatible" source="compatible" semantic="compatible"/>
123
            <description>
124
                New API/SPI classes to allow different implementations
125
                of process builders.
126
            </description>
127
            <class package="org.netbeans.api.extexecution" name="ProcessBuilder"/>
128
            <class package="org.netbeans.spi.extexecution" name="ProcessBuilderFactory"/>
129
            <class package="org.netbeans.spi.extexecution" name="ProcessBuilderImplementation"/>
130
            <issue number="205104"/>
131
        </change>
132
        <change>
133
            <api name="extexecution_api"/>
117
            <summary>New API method to avoid reset of custom IO</summary>
134
            <summary>New API method to avoid reset of custom IO</summary>
118
            <version major="1" minor="20"/>
135
            <version major="1" minor="20"/>
119
            <date day="17" month="2" year="2010"/>
136
            <date day="17" month="2" year="2010"/>
(-)a/extexecution/arch.xml (-1 / +22 lines)
Lines 51-57 Link Here
51
   <api group="java" name="ExternalExecutionAPI" type="export" category="stable" url="@TOP@org/netbeans/api/extexecution/package-summary.html"/>
51
   <api group="java" name="ExternalExecutionAPI" type="export" category="stable" url="@TOP@org/netbeans/api/extexecution/package-summary.html"/>
52
   that contains support for execution of external processes in the IDE. It also
52
   that contains support for execution of external processes in the IDE. It also
53
   provide support class for the actual creation of the external process
53
   provide support class for the actual creation of the external process
54
   and support for destroying the process tree.
54
   and support for destroying the process tree. There is also abstraction of
55
   process builder.
55
  </p>
56
  </p>
56
  <p>
57
  <p>
57
   Another exported API
58
   Another exported API
Lines 66-71 Link Here
66
   <code>org.openide.windows.OutputWriter</code>. API provides common implementations too.
67
   <code>org.openide.windows.OutputWriter</code>. API provides common implementations too.
67
  </p>
68
  </p>
68
  <p>
69
  <p>
70
   The SPI
71
   <api group="java" name="ExternalExecutionSPI" type="export" category="stable" url="@TOP@org/netbeans/spi/extexecution/package-summary.html"/>
72
   allows different implementations of process builder.
73
  </p>
74
  <p>
69
   There is also SPI allowing to register support for destroying the process tree
75
   There is also SPI allowing to register support for destroying the process tree
70
   <api group="java" name="ExternalExecutionDestroySPI" type="export" category="stable" url="@TOP@org/netbeans/spi/extexecution/destroy/package-summary.html"/>.
76
   <api group="java" name="ExternalExecutionDestroySPI" type="export" category="stable" url="@TOP@org/netbeans/spi/extexecution/destroy/package-summary.html"/>.
71
  </p>
77
  </p>
Lines 205-210 Link Here
205
    <a href="@TOP@org/netbeans/api/extexecution/print/LineConvertors.html">LineConvertors</a>.
211
    <a href="@TOP@org/netbeans/api/extexecution/print/LineConvertors.html">LineConvertors</a>.
206
   </p>
212
   </p>
207
  </usecase>
213
  </usecase>
214
  <usecase id="process-builder" name="Custom process builder">
215
    <p>
216
      Third party wants to implement custom process builder to provide
217
      additional functionality, such as remote execution.
218
    </p>
219
    <p>
220
      In order to do so it will implement
221
      <a href="@TOP@org/netbeans/spi/extexecution/ProcessBuilderImplementation.html">
222
       ProcessBuilderImplementation</a> and pass
223
      <a href="@TOP@org/netbeans/api/extexecution/ProcessBuilder.html">
224
       ProcessBuilder</a> to its clients. The API instances are created with
225
      help of
226
      <a href="@TOP@org/netbeans/spi/extexecution/ProcessBuilderFactory.html">ProcessBuilderFactory</a>.
227
    </p>
228
  </usecase>
208
  <usecase id="destroy-process" name="Destroying a process">
229
  <usecase id="destroy-process" name="Destroying a process">
209
    <p>
230
    <p>
210
      Client wants to destroy the process, trying to kill whole process tree.
231
      Client wants to destroy the process, trying to kill whole process tree.
(-)a/extexecution/manifest.mf (-1 / +1 lines)
Lines 2-6 Link Here
2
AutoUpdate-Show-In-Client: false
2
AutoUpdate-Show-In-Client: false
3
OpenIDE-Module: org.netbeans.modules.extexecution/2
3
OpenIDE-Module: org.netbeans.modules.extexecution/2
4
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/extexecution/resources/Bundle.properties
4
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/extexecution/resources/Bundle.properties
5
OpenIDE-Module-Specification-Version: 1.27
5
OpenIDE-Module-Specification-Version: 1.28
6
6
(-)a/extexecution/nbproject/project.xml (+1 lines)
Lines 130-135 Link Here
130
                <package>org.netbeans.api.extexecution</package>
130
                <package>org.netbeans.api.extexecution</package>
131
                <package>org.netbeans.api.extexecution.print</package>
131
                <package>org.netbeans.api.extexecution.print</package>
132
                <package>org.netbeans.api.extexecution.input</package>
132
                <package>org.netbeans.api.extexecution.input</package>
133
                <package>org.netbeans.spi.extexecution</package>
133
                <package>org.netbeans.spi.extexecution.destroy</package>
134
                <package>org.netbeans.spi.extexecution.destroy</package>
134
            </public-packages>
135
            </public-packages>
135
        </data>
136
        </data>
(-)a/extexecution/src/org/netbeans/api/extexecution/Bundle.properties (+1 lines)
Lines 41-43 Link Here
41
# made subject to such option by the copyright holder.
41
# made subject to such option by the copyright holder.
42
42
43
Running=Running
43
Running=Running
44
LocalProcessFactory=Factory creating local processes
(-)a/extexecution/src/org/netbeans/api/extexecution/ExternalProcessBuilder.java (-4 / +6 lines)
Lines 64-74 Link Here
64
import org.openide.util.Utilities;
64
import org.openide.util.Utilities;
65
65
66
/**
66
/**
67
 * Utility class to make the external process creation easier.
67
 * Utility class to make the local external process creation easier.
68
 * <p>
68
 * <p>
69
 * Builder handle command, working directory, <code>PATH</code> variable and HTTP proxy.
69
 * Builder handle command, working directory, <code>PATH</code> variable and HTTP proxy.
70
 * <p>
70
 * <p>
71
 * This class is <i>immutable</i>.
71
 * This class is <i>immutable</i>.
72
 * <p>
73
 * Also see {@link ProcessBuilder#getLocal()}.
72
 *
74
 *
73
 * @author Petr Hejl
75
 * @author Petr Hejl
74
 * @see #call()
76
 * @see #call()
Lines 278-284 Link Here
278
        List<String> args = buildArguments();
280
        List<String> args = buildArguments();
279
        commandList.addAll(args);
281
        commandList.addAll(args);
280
282
281
        ProcessBuilder pb = new ProcessBuilder(commandList.toArray(new String[commandList.size()]));
283
        java.lang.ProcessBuilder pb = new java.lang.ProcessBuilder(commandList.toArray(new String[commandList.size()]));
282
        if (workingDirectory != null) {
284
        if (workingDirectory != null) {
283
            pb.directory(workingDirectory);
285
            pb.directory(workingDirectory);
284
        }
286
        }
Lines 301-307 Link Here
301
     * @param pb the ProcessBuilder to log.
303
     * @param pb the ProcessBuilder to log.
302
     * @param level the level for logging.
304
     * @param level the level for logging.
303
     */
305
     */
304
    private void logProcess(final Level level, final ProcessBuilder pb) {
306
    private void logProcess(final Level level, final java.lang.ProcessBuilder pb) {
305
307
306
        if (!LOGGER.isLoggable(level)) {
308
        if (!LOGGER.isLoggable(level)) {
307
            return;
309
            return;
Lines 406-412 Link Here
406
        return sb.toString();
408
        return sb.toString();
407
    }
409
    }
408
410
409
    private void adjustProxy(ProcessBuilder pb) {
411
    private void adjustProxy(java.lang.ProcessBuilder pb) {
410
        String proxy = getNetBeansHttpProxy();
412
        String proxy = getNetBeansHttpProxy();
411
        if (proxy != null) {
413
        if (proxy != null) {
412
            Map<String, String> env = pb.environment();
414
            Map<String, String> env = pb.environment();
(-)f60f09aecc4f (+290 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2011 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.api.extexecution;
43
44
import java.io.File;
45
import java.io.IOException;
46
import java.util.ArrayList;
47
import java.util.HashMap;
48
import java.util.List;
49
import java.util.Map;
50
import java.util.concurrent.Callable;
51
import org.netbeans.api.annotations.common.NonNull;
52
import org.netbeans.api.annotations.common.NullAllowed;
53
import org.netbeans.spi.extexecution.ProcessBuilderFactory;
54
import org.netbeans.spi.extexecution.ProcessBuilderImplementation;
55
import org.openide.util.NbBundle;
56
import org.openide.util.Parameters;
57
58
/**
59
 * Abstraction of process builders. You can freely configure the parameters
60
 * and then create a process by calling the {@link #call()} method. You can
61
 * also (re)configure the builder and spawn a different process.
62
 * <p>
63
 * Note the API does not prescribe the actual meaning of {@link Process}.
64
 * It may be local process, remote process or some other implementation.
65
 * <p>
66
 * You can use the default implementation returned by {@link #getLocal()}
67
 * for creating the local machine OS processes.
68
 * <p>
69
 * <i>Thread safety</i> of this class depends on thread safety of
70
 * the {@link ProcessBuilderImplementation} the class is using. If it is thread
71
 * safe (if possible the implementation should be even stateless) this class
72
 * is thread safe as well.
73
 *
74
 * @author Petr Hejl
75
 * @since 1.28
76
 */
77
public final class ProcessBuilder implements Callable<Process> {
78
79
    private final ProcessBuilderImplementation implementation;
80
81
    private final String description;
82
83
    /**<i>GuardedBy("this")</i>*/
84
    private String executable;
85
86
    /**<i>GuardedBy("this")</i>*/
87
    private String workingDirectory;
88
89
    /**<i>GuardedBy("this")</i>*/
90
    private List<String> arguments = new ArrayList<String>();
91
92
    /**<i>GuardedBy("this")</i>*/
93
    private List<String> paths = new ArrayList<String>();
94
95
    /**<i>GuardedBy("this")</i>*/
96
    private Map<String, String> envVariables = new HashMap<String, String>();
97
98
    /**<i>GuardedBy("this")</i>*/
99
    private boolean redirectErrorStream;
100
101
    static {
102
        ProcessBuilderFactory.Accessor.DEFAULT = new ProcessBuilderFactory.Accessor() {
103
104
            @Override
105
            public ProcessBuilder createProcessBuilder(ProcessBuilderImplementation impl, String description) {
106
                return new ProcessBuilder(impl, description);
107
            }
108
        };
109
    }
110
111
    private ProcessBuilder(ProcessBuilderImplementation implementation, String description) {
112
        this.implementation = implementation;
113
        this.description = description;
114
    }
115
116
    /**
117
     * Returns the {@link ProcessBuilder} creating the OS process on local
118
     * machine. Returned implementation is <code>thread safe</code>.
119
     *
120
     * @return the {@link ProcessBuilder} creating the OS process on local
121
     *             machine
122
     */
123
    public static ProcessBuilder getLocal() {
124
        return new ProcessBuilder(new LocalProcessFactory(),
125
                NbBundle.getMessage(ProcessBuilder.class, "LocalProcessFactory"));
126
    }
127
128
    /**
129
     * Returns the human readable description of this builder.
130
     *
131
     * @return the human readable description of this builder
132
     */
133
    @NonNull
134
    public String getDescription() {
135
        return description;
136
    }
137
138
    /**
139
     * Sets the executable to run. There is no default value. The {@link #call()}
140
     * methods throws {@link IllegalStateException} when there is no executable
141
     * configured.
142
     *
143
     * @param executable the executable to run
144
     */
145
    public void setExecutable(@NonNull String executable) {
146
        Parameters.notNull("executable", executable);
147
148
        synchronized (this) {
149
            this.executable = executable;
150
        }
151
    }
152
153
    /**
154
     * Sets the working directory for the process created by subsequent call
155
     * of {@link #call()}. The default value is implementation specific.
156
     *
157
     * @param workingDirectory the working directory of the process
158
     */
159
    public void setWorkingDirectory(@NullAllowed String workingDirectory) {
160
        synchronized (this) {
161
            this.workingDirectory = workingDirectory;
162
        }
163
    }
164
165
    /**
166
     * Sets the arguments passed to the process created by subsequent call
167
     * of {@link #call()}. By default there are no arguments.
168
     *
169
     * @param arguments the arguments passed to the process
170
     */
171
    public void setArguments(@NonNull List<String> arguments) {
172
        Parameters.notNull("arguments", arguments);
173
174
        synchronized (this) {
175
            this.arguments.clear();
176
            this.arguments.addAll(arguments);
177
        }
178
    }
179
180
    /**
181
     * Sets the environment variables for the process created by subsequent call
182
     * of {@link #call()}. By default there are no environment variables with
183
     * exception of <code>PATH</code> possibly configured by {@link #setPaths(java.util.List)}.
184
     *
185
     * @param envVariables the environment variables for the process
186
     */
187
    public void setEnvironmentVariables(@NonNull Map<String, String> envVariables) {
188
        Parameters.notNull("envVariables", envVariables);
189
190
        synchronized (this) {
191
            this.envVariables.clear();
192
            this.envVariables.putAll(envVariables);
193
        }
194
    }
195
196
    /**
197
     * Sets the additional paths to be included in <code>PATH</code> environment
198
     * variable for the process.
199
     *
200
     * @param paths the additional paths to be included in <code>PATH</code>
201
     *             environment variable
202
     */
203
    public void setPaths(@NonNull List<String> paths) {
204
        Parameters.notNull("paths", paths);
205
206
        synchronized (this) {
207
            this.paths.clear();
208
            this.paths.addAll(paths);
209
        }
210
    }
211
212
    /**
213
     * Configures the error stream redirection. If <code>true</code> the error
214
     * stream of process created by subsequent call of {@link #call()} method
215
     * will be redirected to standard output stream.
216
     *
217
     * @param redirectErrorStream the error stream redirection
218
     */
219
    public void setRedirectErrorStream(boolean redirectErrorStream) {
220
        synchronized (this) {
221
            this.redirectErrorStream = redirectErrorStream;
222
        }
223
    }
224
225
    /**
226
     * Creates the new {@link Process} based on the properties configured
227
     * in this builder.
228
     * <p>
229
     * Actual behavior depends on the builder implementation, but it should
230
     * respect all the properties configured on this builder.
231
     *
232
     * @see ProcessBuilderImplementation
233
     * @return the new {@link Process} based on the properties configured
234
     *             in this builder
235
     * @throws IOException if the process could not be created
236
     * @throws IllegalStateException if there is no executable configured
237
     *             by {@link #setExecutable(java.lang.String)}
238
     */
239
    @NonNull
240
    @Override
241
    public Process call() throws IOException {
242
        String currentExecutable = null;
243
        String currentWorkingDirectory = null;
244
        List<String> currentArguments = new ArrayList<String>();
245
        List<String> currentPaths = new ArrayList<String>();
246
        Map<String, String> currentEnvVariables = new HashMap<String, String>();
247
        boolean currentRedirectErrorStream = false;
248
249
        synchronized (this) {
250
            currentExecutable = executable;
251
            currentWorkingDirectory = workingDirectory;
252
            currentArguments.addAll(arguments);
253
            currentPaths.addAll(paths);
254
            currentEnvVariables.putAll(envVariables);
255
            currentRedirectErrorStream = redirectErrorStream;
256
        }
257
258
        if (currentExecutable == null) {
259
            throw new IllegalStateException("The executable has not been configured");
260
        }
261
262
        return implementation.createProcess(currentExecutable, currentWorkingDirectory, currentArguments,
263
                currentPaths, currentEnvVariables, currentRedirectErrorStream);
264
    }
265
266
    private static class LocalProcessFactory implements ProcessBuilderImplementation {
267
268
        @Override
269
        public Process createProcess(String executable, String workingDirectory, List<String> arguments,
270
                List<String> paths, Map<String, String> environment, boolean redirectErrorStream) throws IOException {
271
272
            ExternalProcessBuilder builder = new ExternalProcessBuilder(executable);
273
            if (workingDirectory != null) {
274
                builder = builder.workingDirectory(new File(workingDirectory));
275
            }
276
            for (String argument : arguments) {
277
                builder = builder.addArgument(argument);
278
            }
279
            for (String path : paths) {
280
                builder = builder.prependPath(new File(path));
281
            }
282
            for (Map.Entry<String, String> entry : environment.entrySet()) {
283
                builder = builder.addEnvironmentVariable(entry.getKey(), entry.getValue());
284
            }
285
            builder = builder.redirectErrorStream(redirectErrorStream);
286
287
            return builder.call();
288
        }
289
    }
290
}
(-)f60f09aecc4f (+101 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2011 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.spi.extexecution;
43
44
/**
45
 * The factory allowing SPI implementors of {@link ProcessBuilderImplementation}
46
 * to create its API instances {@link org.netbeans.api.extexecution.ProcessBuilder}.
47
 *
48
 * @author Petr Hejl
49
 * @since 1.28
50
 */
51
public class ProcessBuilderFactory {
52
53
    private ProcessBuilderFactory() {
54
        super();
55
    }
56
57
    /**
58
     * Creates the instance of {@link org.netbeans.api.extexecution.ProcessBuilder}
59
     * from its SPI representation.
60
     *
61
     * @param impl SPI representation
62
     * @param description human readable description of the builder
63
     * @return the API instance
64
     */
65
    public static org.netbeans.api.extexecution.ProcessBuilder createProcessBuilder(
66
            ProcessBuilderImplementation impl, String description) {
67
        return Accessor.DEFAULT.createProcessBuilder(impl, description);
68
    }
69
70
    /**
71
     * The accessor pattern class.
72
     */
73
    public abstract static class Accessor {
74
75
        /** The default accessor. */
76
        public static Accessor DEFAULT;
77
78
        static {
79
            // invokes static initializer of ProcessBuilder.class
80
            // that will assign value to the DEFAULT field above
81
            Class c = org.netbeans.api.extexecution.ProcessBuilder.class;
82
            try {
83
                Class.forName(c.getName(), true, c.getClassLoader());
84
            } catch (ClassNotFoundException ex) {
85
                assert false : ex;
86
            }
87
        }
88
89
        /**
90
         * Creates the instance of {@link org.netbeans.api.extexecution.ProcessBuilder}
91
         * from its SPI representation.
92
         *
93
         * @param impl SPI representation
94
         * @param description human readable description of the builder
95
         * @return the API instance
96
         */
97
        public abstract org.netbeans.api.extexecution.ProcessBuilder createProcessBuilder(
98
                ProcessBuilderImplementation impl, String description);
99
100
    }
101
}
(-)f60f09aecc4f (+88 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2011 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.spi.extexecution;
43
44
import java.io.IOException;
45
import java.util.List;
46
import java.util.Map;
47
import org.netbeans.api.annotations.common.NonNull;
48
import org.netbeans.api.annotations.common.NullAllowed;
49
50
/**
51
 * The interface representing the implementation
52
 * of {@link org.netbeans.api.extexecution.ProcessBuilder}.
53
 *
54
 * <div class="nonnormative">
55
 * <p>
56
 * Although it is not required it is reasonable to have implementation of this
57
 * interface stateless. In such case instances of {@link org.netbeans.api.extexecution.ProcessBuilder}
58
 * using it will be <i>thread safe</i>.
59
 * </div>
60
 *
61
 * @see org.netbeans.api.extexecution.ProcessBuilder
62
 * @author Petr Hejl
63
 * @since 1.28
64
 */
65
public interface ProcessBuilderImplementation {
66
67
    /**
68
     * Creates a process using the specified parameters and environment
69
     * configuration.
70
     *
71
     * @param executable the name of the executable to run
72
     * @param workingDirectory the working directory of the created process or
73
     *             <code>null</code> as implementation specific default
74
     * @param arguments the arguments passed to the process
75
     * @param paths the additional paths to add to <code>PATH</code> environment
76
     *             variable
77
     * @param environment environment variables to configure for the process
78
     * @param redirectErrorStream when <code>true</code> the error stream of
79
     *             the process should be redirected to standard output stream
80
     * @return a process created with specified parameters and environment
81
     *             configuration
82
     * @throws IOException IOException if the process could not be created
83
     */
84
    @NonNull
85
    Process createProcess(@NonNull String executable, @NullAllowed String workingDirectory, @NonNull List<String> arguments,
86
            @NonNull List<String> paths, @NonNull Map<String, String> environment, boolean redirectErrorStream) throws IOException;
87
88
}
(-)f60f09aecc4f (+51 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * Contributor(s):
28
 *
29
 * The Original Software is NetBeans. The Initial Developer of the Original
30
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
31
 * Microsystems, Inc. All Rights Reserved.
32
 *
33
 * If you wish your version of this file to be governed by only the CDDL
34
 * or only the GPL Version 2, indicate your decision by adding
35
 * "[Contributor] elects to include this software in this distribution
36
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
37
 * single choice of license, a recipient has the option to distribute
38
 * your version of this file under either the CDDL, the GPL Version 2 or
39
 * to extend the choice of license to its licensees as provided above.
40
 * However, if you add GPL Version 2 code and therefore, elected the GPL
41
 * Version 2 license, then the option applies only if the new code is
42
 * made subject to such option by the copyright holder.
43
 */
44
45
/**
46
 * The support SPI for creation of external processes.
47
 *
48
 * @see org.netbeans.spi.extexecution.ProcessBuilderImplementation
49
 */
50
package org.netbeans.spi.extexecution;
51
(-)f60f09aecc4f (+166 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2011 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.api.extexecution;
43
44
import java.io.IOException;
45
import java.util.List;
46
import java.util.Map;
47
import org.netbeans.junit.NbTestCase;
48
import org.netbeans.spi.extexecution.ProcessBuilderFactory;
49
import org.netbeans.spi.extexecution.ProcessBuilderImplementation;
50
51
/**
52
 *
53
 * @author Petr Hejl
54
 */
55
public class ProcessBuilderTest extends NbTestCase {
56
57
    public ProcessBuilderTest(String name) {
58
        super(name);
59
    }
60
61
    public void testExecutable() throws IOException {
62
        TestProcessBuilder testBuilder = new TestProcessBuilder();
63
        ProcessBuilder builder = ProcessBuilderFactory.createProcessBuilder(testBuilder, "Test builder");
64
65
        try {
66
            builder.call();
67
            fail("Empty executable does not throw exception");
68
        } catch (IllegalStateException ex) {
69
            // expected
70
        }
71
72
        builder.setExecutable("ls");
73
        builder.call();
74
        assertEquals("ls", testBuilder.getExecutable());
75
76
        builder.setExecutable("cd");
77
        assertEquals("ls", testBuilder.getExecutable());
78
79
        builder.call();
80
        assertEquals("cd", testBuilder.getExecutable());
81
    }
82
83
    public void testWorkingDirectory() throws IOException {
84
        TestProcessBuilder testBuilder = new TestProcessBuilder();
85
        ProcessBuilder builder = ProcessBuilderFactory.createProcessBuilder(testBuilder, "Test builder");
86
        builder.setExecutable("ls");
87
88
        builder.call();
89
        assertNull(testBuilder.getWorkingDirectory());
90
91
        builder.setWorkingDirectory("test");
92
        assertNull(testBuilder.getWorkingDirectory());
93
94
        builder.call();
95
        assertEquals("test", testBuilder.getWorkingDirectory());
96
    }
97
98
    public void testRedirectErrorStream() throws IOException {
99
        TestProcessBuilder testBuilder = new TestProcessBuilder();
100
        ProcessBuilder builder = ProcessBuilderFactory.createProcessBuilder(testBuilder, "Test builder");
101
        builder.setExecutable("ls");
102
103
        builder.call();
104
        assertFalse(testBuilder.isRedirectErrorStream());
105
106
        builder.setRedirectErrorStream(true);
107
        assertFalse(testBuilder.isRedirectErrorStream());
108
109
        builder.call();
110
        assertTrue(testBuilder.isRedirectErrorStream());
111
    }
112
113
    private class TestProcessBuilder implements ProcessBuilderImplementation {
114
115
        private String executable;
116
117
        private String workingDirectory;
118
119
        private List<String> arguments;
120
121
        private List<String> paths;
122
123
        private Map<String, String> environment;
124
125
        private boolean redirectErrorStream;
126
127
        @Override
128
        public Process createProcess(String executable, String workingDirectory,
129
                List<String> arguments, List<String> paths, Map<String, String> environment, boolean redirectErrorStream) throws IOException {
130
131
            this.executable = executable;
132
            this.workingDirectory = workingDirectory;
133
            this.arguments = arguments;
134
            this.paths = paths;
135
            this.environment = environment;
136
            this.redirectErrorStream = redirectErrorStream;
137
138
            return null;
139
        }
140
141
        public String getExecutable() {
142
            return executable;
143
        }
144
145
        public List<String> getArguments() {
146
            return arguments;
147
        }
148
149
        public List<String> getPaths() {
150
            return paths;
151
        }
152
153
        public Map<String, String> getEnvironment() {
154
            return environment;
155
        }
156
157
        public boolean isRedirectErrorStream() {
158
            return redirectErrorStream;
159
        }
160
161
        public String getWorkingDirectory() {
162
            return workingDirectory;
163
        }
164
165
    }
166
}

Return to bug 205104