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 232434
Collapse All | Expand All

(-)a/extexecution/apichanges.xml (-1 / +45 lines)
Lines 104-109 Link Here
104
        <apidef name="extexecution_api">External Execution API</apidef>
104
        <apidef name="extexecution_api">External Execution API</apidef>
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_api_process">External Execution Process API</apidef>
107
        <apidef name="extexecution_api_startup">External Execution Startup Arguments API</apidef>
108
        <apidef name="extexecution_api_startup">External Execution Startup Arguments API</apidef>
108
        <apidef name="extexecution_spi">External Execution SPI</apidef>
109
        <apidef name="extexecution_spi">External Execution SPI</apidef>
109
        <apidef name="extexecution_spi_destroy">External Execution Process Destroy SPI</apidef>
110
        <apidef name="extexecution_spi_destroy">External Execution Process Destroy SPI</apidef>
Lines 115-121 Link Here
115
    <!-- ACTUAL CHANGES BEGIN HERE: -->
116
    <!-- ACTUAL CHANGES BEGIN HERE: -->
116
117
117
    <changes>
118
    <changes>
118
119
        <change>
120
            <summary>Enhance API and SPI to make it usable as a proxy to native execution</summary>
121
            <version major="1" minor="37"/>
122
            <date day="1" month="9" year="2013"/>
123
            <author login="phejl"/>
124
            <compatibility addition="yes"/>
125
            <description>
126
                <p>
127
                There is new SPI for <code>ProcessBuilder</code> named
128
                <code>ProcessBuilderImplementation2</code> which now implements
129
                <code>Lookup.Provider</code> to be extensible and provides
130
                a separate <code>Environment</code> object represented by
131
                the <code>EnvironmentImplementation</code> in the SPI.
132
                The <code>ProcessBuilder</code> itself allows access to those
133
                new features via <code>getLookup()</code> and
134
                <code>getEnvironment()</code> methods and it now also
135
                implements <code>Lookup.Provider</code>. The utility class
136
                <code>ProcessParameters</code> wraps up the parameters passed
137
                to the SPI for process creation. Instances of
138
                <code>Environment</code> API are created via
139
                <code>EnvironmentFactory</code> support class.
140
                </p>
141
                <p>
142
                There are also new classes extending a <code>Process</code>
143
                functionality named <code>ProcessCharset</code>,
144
                <code>ProcessId</code> and <code>ProcessSignal</code> allowing
145
                client to get the charset, to get ID and to send signal to
146
                a process. This might not be always supported and the support
147
                may be pre-checked.
148
                </p>
149
            </description>
150
            <class package="org.netbeans.api.extexecution" name="Environment"/>
151
            <class package="org.netbeans.api.extexecution" name="ExecutionService"/>
152
            <class package="org.netbeans.api.extexecution" name="ProcessBuilder"/>
153
            <class package="org.netbeans.api.extexecution.process" name="ProcessCharset"/>
154
            <class package="org.netbeans.api.extexecution.process" name="ProcessId"/>
155
            <class package="org.netbeans.api.extexecution.process" name="ProcessSignal"/>
156
            <class package="org.netbeans.spi.extexecution" name="EnvironmentFactory"/>
157
            <class package="org.netbeans.spi.extexecution" name="EnvironmentImplementation"/>
158
            <class package="org.netbeans.spi.extexecution" name="ProcessBuilderFactory"/>
159
            <class package="org.netbeans.spi.extexecution" name="ProcessBuilderImplementation2"/>
160
            <class package="org.netbeans.spi.extexecution" name="ProcessParameters"/>
161
            <issue number="232434"/>
162
        </change>
119
        <change>
163
        <change>
120
            <api name="extexecution_spi"/>
164
            <api name="extexecution_spi"/>
121
            <summary>Advice to throw UserQuestionException</summary>
165
            <summary>Advice to throw UserQuestionException</summary>
(-)a/extexecution/arch.xml (-5 / +20 lines)
Lines 67-72 Link Here
67
   <code>org.openide.windows.OutputWriter</code>. API provides common implementations too.
67
   <code>org.openide.windows.OutputWriter</code>. API provides common implementations too.
68
  </p>
68
  </p>
69
  <p>
69
  <p>
70
   The support API/SPI
71
   <api group="java" name="ExternalExecutionProcessAPI" type="export" category="stable" url="@TOP@org/netbeans/api/extexecution/process/package-summary.html"/>
72
   allows enhancement of process with additional data such as ID, character set
73
   and ability to send signals. Client can later easily check the feature is
74
   supported and perform the query or action.
75
  </p>
76
  <p>
70
   The SPI
77
   The SPI
71
   <api group="java" name="ExternalExecutionSPI" type="export" category="stable" url="@TOP@org/netbeans/spi/extexecution/package-summary.html"/>
78
   <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.
79
   allows different implementations of process builder.
Lines 170-177 Link Here
170
   <p>
177
   <p>
171
    The creation of the external process is supported by
178
    The creation of the external process is supported by
172
    <a href="@TOP@org/netbeans/api/extexecution/ExternalProcessBuilder.html">ExternalProcessBuilder</a>
179
    <a href="@TOP@org/netbeans/api/extexecution/ExternalProcessBuilder.html">ExternalProcessBuilder</a>
180
    and <a href="@TOP@org/netbeans/api/extexecution/ProcessBuilder.html">ProcessBuilder</a>
173
    to make things easier.
181
    to make things easier.
174
   </p>
182
   </p>
183
   <p>
184
    The process returned by default or custom builders may support additional
185
    features. To do so the process must be a Lookup.Provider and put
186
    the implementation of the feature to lookup. The possible extensions are
187
    located in <a href="@TOP@org/netbeans/api/extexecution/process/package-summary.html">org.netbeans.api.extexecution.process</a>
188
    package. The client then use static methods on respective classes in order
189
    to use the extended functionality.
190
   </p>
175
  </usecase>
191
  </usecase>
176
  <usecase id="handle-input" name="Processing the input">
192
  <usecase id="handle-input" name="Processing the input">
177
   <p>
193
   <p>
Lines 232-239 Link Here
232
    </p>
248
    </p>
233
    <p>
249
    <p>
234
      In order to do so it will implement
250
      In order to do so it will implement
235
      <a href="@TOP@org/netbeans/spi/extexecution/ProcessBuilderImplementation.html">
251
      <a href="@TOP@org/netbeans/spi/extexecution/ProcessBuilderImplementation2.html">
236
       ProcessBuilderImplementation</a> and pass
252
       ProcessBuilderImplementation2</a> and pass
237
      <a href="@TOP@org/netbeans/api/extexecution/ProcessBuilder.html">
253
      <a href="@TOP@org/netbeans/api/extexecution/ProcessBuilder.html">
238
       ProcessBuilder</a> to its clients. The API instances are created with
254
       ProcessBuilder</a> to its clients. The API instances are created with
239
      help of
255
      help of
Lines 510-518 Link Here
510
-->
526
-->
511
 <answer id="dep-platform">
527
 <answer id="dep-platform">
512
  <p>
528
  <p>
513
   No known platform dependencies. In future there could be need for native code
529
   No known platform dependencies. The platform dependent way of process
514
   in order to terminate the whole process tree created by execution of external
530
   termination is in a separate implementation module.
515
   process.
516
  </p>
531
  </p>
517
 </answer>
532
 </answer>
518
533
(-)a/extexecution/nbproject/project.xml (+1 lines)
Lines 88-93 Link Here
88
            <public-packages>
88
            <public-packages>
89
                <package>org.netbeans.api.extexecution</package>
89
                <package>org.netbeans.api.extexecution</package>
90
                <package>org.netbeans.api.extexecution.print</package>
90
                <package>org.netbeans.api.extexecution.print</package>
91
                <package>org.netbeans.api.extexecution.process</package>
91
                <package>org.netbeans.api.extexecution.input</package>
92
                <package>org.netbeans.api.extexecution.input</package>
92
                <package>org.netbeans.api.extexecution.startup</package>
93
                <package>org.netbeans.api.extexecution.startup</package>
93
                <package>org.netbeans.spi.extexecution</package>
94
                <package>org.netbeans.spi.extexecution</package>
(-)a/extexecution/src/org/netbeans/api/extexecution/Environment.java (+156 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2012 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 2012 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.api.extexecution;
43
44
import java.util.Map;
45
import org.netbeans.api.annotations.common.CheckForNull;
46
import org.netbeans.api.annotations.common.NonNull;
47
import org.netbeans.modules.extexecution.EnvironmentAccessor;
48
import org.netbeans.spi.extexecution.EnvironmentImplementation;
49
import org.openide.util.Parameters;
50
51
/**
52
 * The class that provides an access to environment variables.
53
 *
54
 * @see ProcessBuilder#getEnvironment()
55
 * @see EnvironmentImplementation
56
 * @author Petr Hejl
57
 * @since 1.37
58
 */
59
public final class Environment {
60
61
    private final EnvironmentImplementation implementation;
62
63
    static {
64
        EnvironmentAccessor.setDefault(new EnvironmentAccessor() {
65
66
            @Override
67
            public Environment createEnvironment(EnvironmentImplementation impl) {
68
                return new Environment(impl);
69
            }
70
        });
71
    }
72
73
    private Environment(EnvironmentImplementation implementation) {
74
        this.implementation = implementation;
75
    }
76
77
    /**
78
     * Returns the value of the variable or <code>null</code>.
79
     *
80
     * @param name the name of the variable
81
     * @return the value of the variable or <code>null</code>
82
     */
83
    @CheckForNull
84
    public String getVariable(@NonNull String name) {
85
        Parameters.notNull("name", name);
86
87
        return implementation.getVariable(name);
88
    }
89
90
    /**
91
     * Appends a path to a path-like variable. The proper path separator is used
92
     * to separate the new value.
93
     *
94
     * @param name the name of the variable such as for example
95
     *             <code>PATH</code> or <code>LD_LIBRARY_PATH</code>
96
     * @param value the value (path to append)
97
     */
98
    public void appendPath(@NonNull String name, @NonNull String value) {
99
        Parameters.notNull("name", name);
100
        Parameters.notNull("value", value);
101
102
        implementation.appendPath(name, value);
103
    }
104
105
    /**
106
     * Prepends a path to a path-like variable. The proper path separator is used
107
     * to separate the new value.
108
     *
109
     * @param name the name of the variable such as for example
110
     *             <code>PATH</code> or <code>LD_LIBRARY_PATH</code>
111
     * @param value the value (path to prepend)
112
     */
113
    public void prependPath(@NonNull String name, @NonNull String value) {
114
        Parameters.notNull("name", name);
115
        Parameters.notNull("value", value);
116
117
        implementation.prependPath(name, value);
118
    }
119
120
    /**
121
     * Sets a value for a variable with the given name.
122
     *
123
     * @param name the name of the variable
124
     * @param value the value
125
     */
126
    public void setVariable(@NonNull String name, @NonNull String value) {
127
        Parameters.notNull("name", name);
128
        Parameters.notNull("value", value);
129
130
        implementation.setVariable(name, value);
131
    }
132
133
    /**
134
     * Removes a variable with the given name. The subsequent call to
135
     * {@link #getVariable(java.lang.String)} with the same argument will return
136
     * <code>null</code>.
137
     * 
138
     * @param name the name of the variable
139
     */
140
    public void removeVariable(@NonNull String name) {
141
        Parameters.notNull("name", name);
142
143
        implementation.removeVariable(name);
144
    }
145
146
    /**
147
     * Returns all variable names and associated values as a {@link Map}.
148
     * Changes to the map are not propagated back to the {@link Environment}.
149
     *
150
     * @return all variable names and associated values
151
     */
152
    @NonNull
153
    public Map<String, String> values() {
154
        return implementation.values();
155
    }
156
}
(-)a/extexecution/src/org/netbeans/api/extexecution/ExecutionService.java (-42 / +220 lines)
Lines 52-57 Link Here
52
import java.io.OutputStream;
52
import java.io.OutputStream;
53
import java.io.OutputStreamWriter;
53
import java.io.OutputStreamWriter;
54
import java.io.Reader;
54
import java.io.Reader;
55
import java.io.Writer;
55
import java.nio.charset.Charset;
56
import java.nio.charset.Charset;
56
import java.security.AccessController;
57
import java.security.AccessController;
57
import java.security.PrivilegedAction;
58
import java.security.PrivilegedAction;
Lines 66-75 Link Here
66
import java.util.concurrent.Future;
67
import java.util.concurrent.Future;
67
import java.util.concurrent.FutureTask;
68
import java.util.concurrent.FutureTask;
68
import java.util.concurrent.TimeUnit;
69
import java.util.concurrent.TimeUnit;
70
import java.util.concurrent.atomic.AtomicInteger;
69
import java.util.logging.Level;
71
import java.util.logging.Level;
70
import java.util.logging.Logger;
72
import java.util.logging.Logger;
71
import javax.swing.AbstractAction;
73
import javax.swing.AbstractAction;
72
import org.netbeans.api.annotations.common.NonNull;
74
import org.netbeans.api.annotations.common.NonNull;
75
import org.netbeans.api.annotations.common.NullAllowed;
73
import org.netbeans.api.progress.ProgressHandle;
76
import org.netbeans.api.progress.ProgressHandle;
74
import org.netbeans.api.progress.ProgressHandleFactory;
77
import org.netbeans.api.progress.ProgressHandleFactory;
75
import org.netbeans.modules.extexecution.ProcessInputStream;
78
import org.netbeans.modules.extexecution.ProcessInputStream;
Lines 79-85 Link Here
79
import org.netbeans.api.extexecution.input.InputProcessors;
82
import org.netbeans.api.extexecution.input.InputProcessors;
80
import org.netbeans.api.extexecution.input.InputReaderTask;
83
import org.netbeans.api.extexecution.input.InputReaderTask;
81
import org.netbeans.api.extexecution.input.InputReaders;
84
import org.netbeans.api.extexecution.input.InputReaders;
85
import org.netbeans.api.extexecution.input.LineProcessor;
82
import org.netbeans.api.extexecution.input.LineProcessors;
86
import org.netbeans.api.extexecution.input.LineProcessors;
87
import org.netbeans.api.extexecution.process.ProcessCharset;
83
import org.openide.util.Cancellable;
88
import org.openide.util.Cancellable;
84
import org.openide.util.Mutex;
89
import org.openide.util.Mutex;
85
import org.openide.util.NbBundle;
90
import org.openide.util.NbBundle;
Lines 91-110 Link Here
91
 * Execution service provides the facility to execute the process while
96
 * Execution service provides the facility to execute the process while
92
 * displaying the output and handling the input.
97
 * displaying the output and handling the input.
93
 * <p>
98
 * <p>
94
 * It will execute the program with an associated I/O window, with stop and
99
 * It will execute the program with an associated I/O window, possibly with
95
 * restart buttons. It will also obey various descriptor properties such as
100
 * stop and restart buttons. It will also obey various descriptor properties
96
 * whether or not to show a progress bar.
101
 * such as whether or not to show a progress bar.
97
 * <p>
102
 * <p>
98
 * All processes launched by this class are terminated on VM exit (if
103
 * All processes launched by this class are terminated on VM exit (if
99
 * these are not finished or terminated earlier).
104
 * these are not finished or terminated earlier).
100
 * <p>
105
 * <p>
101
 * Note that once service is run for the first time, subsequents runs can be
106
 * Note that once service is run for the first time, subsequent runs can be
102
 * invoked by the user (rerun button) if it is allowed to do so
107
 * invoked by the user (rerun button) if it is allowed to do so
103
 * ({@link ExecutionDescriptor#isControllable()}).
108
 * ({@link ExecutionDescriptor#isControllable()}).
104
 *
109
 *
105
 * <div class="nonnormative">
110
 * <div class="nonnormative">
106
 * <p>
111
 * <p>
107
 * Sample usage - executing ls command:
112
 * Sample usage (ls command):
108
 * <pre>
113
 * <pre>
109
 *     ExecutionDescriptor descriptor = new ExecutionDescriptor()
114
 *     ExecutionDescriptor descriptor = new ExecutionDescriptor()
110
 *          .frontWindow(true).controllable(true);
115
 *          .frontWindow(true).controllable(true);
Lines 114-119 Link Here
114
 *     ExecutionService service = ExecutionService.newService(processBuilder, descriptor, "ls command");
119
 *     ExecutionService service = ExecutionService.newService(processBuilder, descriptor, "ls command");
115
 *     Future&lt;Integer&gt task = service.run();
120
 *     Future&lt;Integer&gt task = service.run();
116
 * </pre>
121
 * </pre>
122
 * <p>
123
 * Even simpler usage but without displaying output (ls command):
124
 * <pre>
125
 *     ExternalProcessBuilder processBuilder = new ExternalProcessBuilder("ls");
126
 *
127
 *     ExecutionService service = ExecutionService.newService(processBuilder, null, null);
128
 *     Future&lt;Integer&gt task = service.run();
129
 * </pre>
117
 * </div>
130
 * </div>
118
 *
131
 *
119
 * @author Petr Hejl
132
 * @author Petr Hejl
Lines 130-135 Link Here
130
143
131
    private static final ExecutorService EXECUTOR_SERVICE = new RequestProcessor(ExecutionService.class.getName(), Integer.MAX_VALUE);
144
    private static final ExecutorService EXECUTOR_SERVICE = new RequestProcessor(ExecutionService.class.getName(), Integer.MAX_VALUE);
132
145
146
    private static final InputProcessor NULL_PROCESSOR = new InputProcessor() {
147
148
        @Override
149
        public void processInput(char[] chars) throws IOException {
150
        }
151
152
        @Override
153
        public void reset() throws IOException {
154
        }
155
156
        @Override
157
        public void close() throws IOException {
158
        }
159
    };
160
133
    static {
161
    static {
134
        // rerun accessor
162
        // rerun accessor
135
        RerunAction.Accessor.setDefault(new RerunAction.Accessor() {
163
        RerunAction.Accessor.setDefault(new RerunAction.Accessor() {
Lines 156-171 Link Here
156
        });
184
        });
157
    }
185
    }
158
186
159
    private final Callable<Process> processCreator;
187
    private final Callable<? extends Process> processCreator;
160
188
161
    private final ExecutionDescriptor descriptor;
189
    private final ExecutionDescriptor descriptor;
162
190
163
    private final String originalDisplayName;
191
    private final String originalDisplayName;
164
192
165
    private ExecutionService(Callable<Process> processCreator, String displayName, ExecutionDescriptor descriptor) {
193
    private final Reader processInput;
194
195
    private final boolean rerunAllowed;
196
197
    private final AtomicInteger runCount = new AtomicInteger();
198
199
    private ExecutionService(Callable<? extends Process> processCreator, String displayName,
200
            ExecutionDescriptor descriptor, Reader processInput, boolean rerunAllowed) {
166
        this.processCreator = processCreator;
201
        this.processCreator = processCreator;
167
        this.originalDisplayName = displayName;
202
        this.originalDisplayName = displayName;
168
        this.descriptor = descriptor;
203
        this.descriptor = descriptor;
204
        this.processInput = processInput;
205
        this.rerunAllowed = rerunAllowed;
169
    }
206
    }
170
207
171
    /**
208
    /**
Lines 178-201 Link Here
178
     * @return new execution service
215
     * @return new execution service
179
     */
216
     */
180
    @NonNull
217
    @NonNull
181
    public static ExecutionService newService(@NonNull Callable<Process> processCreator,
218
    public static ExecutionService newService(@NonNull Callable<? extends Process> processCreator,
182
            @NonNull ExecutionDescriptor descriptor, @NonNull String displayName) {
219
            @NonNull ExecutionDescriptor descriptor, @NonNull String displayName) {
183
        return new ExecutionService(processCreator, displayName, descriptor);
220
        return new ExecutionService(processCreator, displayName, descriptor, null, true);
221
    }
222
223
    /**
224
     * Creates new execution service. Service will wrap up the processes
225
     * created by <code>processCreator</code> and will manage them. The service
226
     * <i>may not</i> be run more than once otherwise {@link IllegalStateException}
227
     * is thrown on {@link #run()}. No UI will be displayed.
228
     * <p>
229
     * Passed processInput will be implicitly closed when the execution (invoked by
230
     * {@link #run()}) is finished. The client should not use the reader passed
231
     * as argument anymore or the reader should be designed thread safe.
232
     *
233
     * @param processCreator callable returning the process to wrap up
234
     * @param outputProcessor processor processing lines of standard output;
235
     *             may be <code>null</code>
236
     * @param errorProcessor processor processing lines of standard error
237
     *             output; may be <code>null</code>
238
     * @param processorInput reader providing input for standard input of
239
     *             the created process. Once passed it either should not be
240
     *             used anymore or it should be designed to be thread safe.
241
     *             May be <code>null</code>.
242
     * @return new execution service
243
     * @since 1.37
244
     */
245
    @NonNull
246
    public static ExecutionService newService(@NonNull Callable<? extends Process> processCreator,
247
            @NullAllowed final LineProcessor outputProcessor, @NullAllowed final LineProcessor errorProcessor,
248
            @NullAllowed final Reader processorInput) {
249
        ExecutionDescriptor descriptor = new ExecutionDescriptor()
250
                .inputOutput(InputOutput.NULL);
251
252
        if (outputProcessor != null) {
253
            descriptor = descriptor.outProcessorFactory(new InputProcessorFactory() {
254
                @Override
255
                public InputProcessor newInputProcessor(InputProcessor defaultProcessor) {
256
                    return InputProcessors.bridge(outputProcessor);
257
                }
258
            });
259
        }
260
        if (errorProcessor != null) {
261
            descriptor = descriptor.errProcessorFactory(new InputProcessorFactory() {
262
                @Override
263
                public InputProcessor newInputProcessor(InputProcessor defaultProcessor) {
264
                    return InputProcessors.bridge(errorProcessor);
265
                }
266
            });
267
        }
268
269
        return new ExecutionService(processCreator, null, descriptor, processorInput, false);
270
    }
271
272
    /**
273
     * Creates new execution service. Service will wrap up the processes
274
     * created by <code>processCreator</code> and will manage them. The service
275
     * <i>may not</i> be run more than once otherwise {@link IllegalStateException}
276
     * is thrown on {@link #run()}. No UI will be displayed.
277
     * <p>
278
     * Passed inputWriter and errorWriter will be implicitly closed when the
279
     * execution (invoked by {@link #run()}) is finished. The client either
280
     * <i>should not use the passed writers anymore or these should be designed
281
     * to be thread safe</i>.
282
     *
283
     * @param processCreator callable returning the process to wrap up
284
     * @param outputWriter where to write standard output of the process. Once
285
     *             passed it either should not be used anymore or it should
286
     *             be designed to be thread safe. May be <code>null</code>.
287
     * @param errorWriter where to write standard error output of the process.
288
     *             Once passed it either should not be used anymore or it should
289
     *             be designed to be thread safe. May be <code>null</code>.
290
     * @return new execution service
291
     * @since 1.37
292
     */
293
    public static ExecutionService newService(@NonNull Callable<? extends Process> processCreator,
294
            @NullAllowed final Writer outputWriter, @NullAllowed final Writer errorWriter) {
295
        ExecutionDescriptor descriptor = new ExecutionDescriptor()
296
                .inputOutput(InputOutput.NULL);
297
298
        if (outputWriter != null) {
299
            descriptor = descriptor.outProcessorFactory(new InputProcessorFactory() {
300
                @Override
301
                public InputProcessor newInputProcessor(InputProcessor defaultProcessor) {
302
                    return InputProcessors.copying(outputWriter);
303
                }
304
            });
305
        }
306
        if (errorWriter != null) {
307
            descriptor = descriptor.errProcessorFactory(new InputProcessorFactory() {
308
                @Override
309
                public InputProcessor newInputProcessor(InputProcessor defaultProcessor) {
310
                    return InputProcessors.copying(errorWriter);
311
                }
312
            });
313
        }
314
315
        return new ExecutionService(processCreator, null, descriptor, null, false);
184
    }
316
    }
185
317
186
    /**
318
    /**
187
     * Runs the process described by this service. The call does not block
319
     * Runs the process described by this service. The call does not block
188
     * and the task is represented by the returned value. Integer returned
320
     * and the task is represented by the returned value. Integer returned
189
     * as a result of the {@link Future} is exit code of the process.
321
     * as a result of the {@link Future} is exit code of the process.
322
     * The ability to call this method multiple times depends on a way
323
     * in which the service has been created. Only service created by
324
     * {@link #newService(java.util.concurrent.Callable, org.netbeans.api.extexecution.ExecutionDescriptor, java.lang.String)}
325
     * may be run more than once.
190
     * <p>
326
     * <p>
191
     * The output tabs are reused (if caller does not use the custom one,
327
     * The output tabs are reused (if caller does not use the custom one,
192
     * see {@link ExecutionDescriptor#getInputOutput()}) - the tab to reuse
328
     * see {@link ExecutionDescriptor#getInputOutput()} or if it is not being
193
     * (if any) is selected by having the same name and same buttons
329
     * run without output tab, see {@link #newService(java.util.concurrent.Callable, org.netbeans.api.extexecution.input.LineProcessor, org.netbeans.api.extexecution.input.LineProcessor, java.io.Reader)})
194
     * (control and option). If there is no output tab to reuse new one
330
     * - the tab to reuse (if any) is selected by having the same name
195
     * is opened.
331
     * and same buttons (control and option). If there is no output tab to
332
     * reuse new one is opened.
196
     * <p>
333
     * <p>
197
     * This method can be invoked multiple times returning the different and
334
     * If the service has been created by {@link #newService(java.util.concurrent.Callable, org.netbeans.api.extexecution.input.LineProcessor, org.netbeans.api.extexecution.input.LineProcessor, java.io.Reader)}
198
     * unrelated {@link Future}s. On each call <code>Callable&lt;Process&gt;</code>
335
     * this method may be called only once. Subsequent calls will cause an
336
     * {@link IllegalStateException} to be thrown.
337
     * If the service has been created by {@link #newService(java.util.concurrent.Callable, org.netbeans.api.extexecution.ExecutionDescriptor, java.lang.String)}
338
     * this method can be invoked multiple times returning the different and
339
     * unrelated {@link Future}s.
340
     * <p>
341
     * On each call <code>Callable&lt;Process&gt;</code>
199
     * passed to {@link #newService(java.util.concurrent.Callable, org.netbeans.api.extexecution.ExecutionDescriptor, java.lang.String)}
342
     * passed to {@link #newService(java.util.concurrent.Callable, org.netbeans.api.extexecution.ExecutionDescriptor, java.lang.String)}
200
     * is invoked in order to create the process. If the process creation fails
343
     * is invoked in order to create the process. If the process creation fails
201
     * (throwing an exception) returned <code>Future</code> will throw
344
     * (throwing an exception) returned <code>Future</code> will throw
Lines 213-218 Link Here
213
    }
356
    }
214
357
215
    private Future<Integer> run(InputOutput required) {
358
    private Future<Integer> run(InputOutput required) {
359
        if (!rerunAllowed && runCount.incrementAndGet() > 1) {
360
            throw new IllegalStateException("Run invoked multimple times");
361
        }
362
216
        final InputOutputManager.InputOutputData ioData = getInputOutput(required);
363
        final InputOutputManager.InputOutputData ioData = getInputOutput(required);
217
364
218
        final String displayName = ioData.getDisplayName();
365
        final String displayName = ioData.getDisplayName();
Lines 220-228 Link Here
220
        final ProgressHandle handle = createProgressHandle(ioData.getInputOutput(), displayName, cancellable);
367
        final ProgressHandle handle = createProgressHandle(ioData.getInputOutput(), displayName, cancellable);
221
        final InputOutput io = ioData.getInputOutput();
368
        final InputOutput io = ioData.getInputOutput();
222
369
223
        final OutputWriter out = io.getOut();
370
        assert processInput == null || io == InputOutput.NULL;
224
        final OutputWriter err = io.getErr();
371
225
        final Reader in = io.getIn();
372
        final Reader in;
373
        if (processInput != null) {
374
            in = processInput;
375
        } else if (descriptor.isInputVisible() && io != InputOutput.NULL) {
376
            in = io.getIn();
377
        } else {
378
            in = null;
379
        }
226
380
227
        final CountDownLatch finishedLatch = new CountDownLatch(1);
381
        final CountDownLatch finishedLatch = new CountDownLatch(1);
228
382
Lines 267-289 Link Here
267
                    outStream = new ProcessInputStream(process, process.getInputStream());
421
                    outStream = new ProcessInputStream(process, process.getInputStream());
268
                    errStream = new ProcessInputStream(process, process.getErrorStream());
422
                    errStream = new ProcessInputStream(process, process.getErrorStream());
269
423
270
                    executor = Executors.newFixedThreadPool(descriptor.isInputVisible() ? 3 : 2);
424
                    executor = Executors.newFixedThreadPool(in != null ? 3 : 2);
271
425
272
                    Charset charset = descriptor.getCharset();
426
                    Charset charset = descriptor.getCharset();
427
                    Charset inputCharset = charset;
428
                    Charset outputCharset = charset;
429
                    Charset errorCharset = charset;
273
                    if (charset == null) {
430
                    if (charset == null) {
274
                        charset = Charset.defaultCharset();
431
                        inputCharset = ProcessCharset.getInputCharset(process);
432
                        outputCharset = ProcessCharset.getOutputCharset(process);
433
                        errorCharset = ProcessCharset.getErrorCharset(process);
434
                    }
435
                    if (inputCharset == null) {
436
                        inputCharset = Charset.defaultCharset();
437
                    }
438
                    if (outputCharset == null) {
439
                        outputCharset = Charset.defaultCharset();
440
                    }
441
                    if (errorCharset == null) {
442
                        errorCharset = Charset.defaultCharset();
275
                    }
443
                    }
276
444
277
                    tasks.add(InputReaderTask.newDrainingTask(
445
                    tasks.add(InputReaderTask.newDrainingTask(
278
                        InputReaders.forStream(new BufferedInputStream(outStream), charset),
446
                        InputReaders.forStream(new BufferedInputStream(outStream), outputCharset),
279
                        createOutProcessor(out)));
447
                        createOutProcessor(io)));
280
                    tasks.add(InputReaderTask.newDrainingTask(
448
                    tasks.add(InputReaderTask.newDrainingTask(
281
                        InputReaders.forStream(new BufferedInputStream(errStream), charset),
449
                        InputReaders.forStream(new BufferedInputStream(errStream), errorCharset),
282
                        createErrProcessor(err)));
450
                        createErrProcessor(io)));
283
                    if (descriptor.isInputVisible()) {
451
                    if (in != null) {
284
                        tasks.add(InputReaderTask.newTask(
452
                        tasks.add(InputReaderTask.newTask(
285
                            InputReaders.forReader(in),
453
                            InputReaders.forReader(in),
286
                            createInProcessor(process.getOutputStream())));
454
                            createInProcessor(process.getOutputStream(), inputCharset)));
287
                    }
455
                    }
288
                    for (InputReaderTask task : tasks) {
456
                    for (InputReaderTask task : tasks) {
289
                        executor.submit(task);
457
                        executor.submit(task);
Lines 568-582 Link Here
568
        Mutex.EVENT.readAccess(ui);
736
        Mutex.EVENT.readAccess(ui);
569
    }
737
    }
570
738
571
    private InputProcessor createOutProcessor(OutputWriter writer) {
739
    private InputProcessor createOutProcessor(InputOutput io) {
572
        LineConvertorFactory convertorFactory = descriptor.getOutConvertorFactory();
573
        InputProcessor outProcessor = null;
740
        InputProcessor outProcessor = null;
574
        if (descriptor.isOutLineBased()) {
741
        if (io != InputOutput.NULL) {
575
            outProcessor = InputProcessors.bridge(LineProcessors.printing(writer,
742
            LineConvertorFactory convertorFactory = descriptor.getOutConvertorFactory();
576
                    convertorFactory != null ? convertorFactory.newLineConvertor() : null, true));
743
            OutputWriter writer = io.getOut();
744
            if (descriptor.isOutLineBased()) {
745
                outProcessor = InputProcessors.bridge(LineProcessors.printing(writer,
746
                        convertorFactory != null ? convertorFactory.newLineConvertor() : null, true));
747
            } else {
748
                outProcessor = InputProcessors.printing(writer,
749
                        convertorFactory != null ? convertorFactory.newLineConvertor() : null, true);
750
            }
577
        } else {
751
        } else {
578
            outProcessor = InputProcessors.printing(writer,
752
            outProcessor = NULL_PROCESSOR;
579
                    convertorFactory != null ? convertorFactory.newLineConvertor() : null, true);
580
        }
753
        }
581
754
582
        InputProcessorFactory descriptorOutFactory = descriptor.getOutProcessorFactory();
755
        InputProcessorFactory descriptorOutFactory = descriptor.getOutProcessorFactory();
Lines 587-601 Link Here
587
        return outProcessor;
760
        return outProcessor;
588
    }
761
    }
589
762
590
    private InputProcessor createErrProcessor(OutputWriter writer) {
763
    private InputProcessor createErrProcessor(InputOutput io) {
591
        LineConvertorFactory convertorFactory = descriptor.getErrConvertorFactory();
592
        InputProcessor errProcessor = null;
764
        InputProcessor errProcessor = null;
593
        if (descriptor.isErrLineBased()) {
765
        if (io != InputOutput.NULL) {
594
            errProcessor = InputProcessors.bridge(LineProcessors.printing(writer,
766
            LineConvertorFactory convertorFactory = descriptor.getErrConvertorFactory();
595
                    convertorFactory != null ? convertorFactory.newLineConvertor() : null, false));
767
            OutputWriter writer = io.getErr();
768
            if (descriptor.isErrLineBased()) {
769
                errProcessor = InputProcessors.bridge(LineProcessors.printing(writer,
770
                        convertorFactory != null ? convertorFactory.newLineConvertor() : null, false));
771
            } else {
772
                errProcessor = InputProcessors.printing(writer,
773
                        convertorFactory != null ? convertorFactory.newLineConvertor() : null, false);
774
            }
596
        } else {
775
        } else {
597
            errProcessor = InputProcessors.printing(writer,
776
            errProcessor = NULL_PROCESSOR;
598
                    convertorFactory != null ? convertorFactory.newLineConvertor() : null, false);
599
        }
777
        }
600
778
601
        InputProcessorFactory descriptorErrFactory = descriptor.getErrProcessorFactory();
779
        InputProcessorFactory descriptorErrFactory = descriptor.getErrProcessorFactory();
Lines 606-613 Link Here
606
        return errProcessor;
784
        return errProcessor;
607
    }
785
    }
608
786
609
    private InputProcessor createInProcessor(OutputStream os) {
787
    private InputProcessor createInProcessor(OutputStream os, Charset charset) {
610
        return InputProcessors.copying(new OutputStreamWriter(os));
788
        return InputProcessors.copying(new OutputStreamWriter(os, charset));
611
    }
789
    }
612
790
613
    private static class ProgressCancellable implements Cancellable {
791
    private static class ProgressCancellable implements Cancellable {
(-)a/extexecution/src/org/netbeans/api/extexecution/ExternalProcessBuilder.java (-13 / +63 lines)
Lines 100-105 Link Here
100
100
101
    private final Map<String, String> envVariables = new HashMap<String, String>();
101
    private final Map<String, String> envVariables = new HashMap<String, String>();
102
102
103
    private final boolean emptySystemVariables;
104
103
    /**
105
    /**
104
     * Creates the new builder that will create the process by running
106
     * Creates the new builder that will create the process by running
105
     * given executable. Arguments must not be part of the string.
107
     * given executable. Arguments must not be part of the string.
Lines 117-122 Link Here
117
        this.arguments.addAll(builder.arguments);
119
        this.arguments.addAll(builder.arguments);
118
        this.paths.addAll(builder.paths);
120
        this.paths.addAll(builder.paths);
119
        this.envVariables.putAll(builder.envVariables);
121
        this.envVariables.putAll(builder.envVariables);
122
        this.emptySystemVariables = builder.emptySystemVariables;
120
    }
123
    }
121
124
122
    /**
125
    /**
Lines 286-292 Link Here
286
        }
289
        }
287
290
288
        Map<String, String> pbEnv = pb.environment();
291
        Map<String, String> pbEnv = pb.environment();
289
        Map<String, String> env = buildEnvironment(pbEnv);
292
        Map<String, String> env;
293
        if (emptySystemVariables) {
294
            pbEnv.clear();
295
            env = new HashMap<String, String>();
296
        } else {
297
            env = buildEnvironment(pbEnv);
298
        }
290
        pbEnv.putAll(env);
299
        pbEnv.putAll(env);
291
        String uuid = UUID.randomUUID().toString();
300
        String uuid = UUID.randomUUID().toString();
292
        pbEnv.put(WrapperProcess.KEY_UUID, uuid);
301
        pbEnv.put(WrapperProcess.KEY_UUID, uuid);
Lines 297-302 Link Here
297
        return wp;
306
        return wp;
298
    }
307
    }
299
308
309
    ExternalProcessBuilder emptySystemVariables(boolean emptySystemVariables) {
310
        BuilderData builder = new BuilderData(this);
311
        return new ExternalProcessBuilder(builder.emptySystemVariables(emptySystemVariables));
312
    }
313
300
    /**
314
    /**
301
     * Logs the given <code>pb</code> using the given <code>level</code>.
315
     * Logs the given <code>pb</code> using the given <code>level</code>.
302
     *
316
     *
Lines 331-348 Link Here
331
345
332
        // Find PATH environment variable - on Windows it can be some other
346
        // Find PATH environment variable - on Windows it can be some other
333
        // case and we should use whatever it has.
347
        // case and we should use whatever it has.
334
        String pathName = "PATH"; // NOI18N
348
        String pathName = getPathName(original);
335
336
        if (Utilities.isWindows()) {
337
            pathName = "Path"; // NOI18N
338
339
            for (String key : ret.keySet()) {
340
                if ("PATH".equals(key.toUpperCase(Locale.ENGLISH))) { // NOI18N
341
                    pathName = key;
342
                    break;
343
                }
344
            }
345
        }
346
349
347
        // TODO use StringBuilder
350
        // TODO use StringBuilder
348
        String currentPath = ret.get(pathName);
351
        String currentPath = ret.get(pathName);
Lines 362-367 Link Here
362
        return ret;
365
        return ret;
363
    }
366
    }
364
367
368
365
    // package level for unit testing
369
    // package level for unit testing
366
    List<String> buildArguments() {
370
    List<String> buildArguments() {
367
        if (!Utilities.isWindows()) {
371
        if (!Utilities.isWindows()) {
Lines 378-383 Link Here
378
        return result;
382
        return result;
379
    }
383
    }
380
384
385
    static void putPath(File path, String pathName, boolean prepend, Map<String, String> current) {
386
        String currentPath = current.get(pathName);
387
388
        if (currentPath == null) {
389
            currentPath = "";
390
        }
391
392
        if (prepend) {
393
            currentPath = path.getAbsolutePath().replace(" ", "\\ ") //NOI18N
394
                    + File.pathSeparator + currentPath;
395
        } else {
396
            currentPath = currentPath + File.pathSeparator
397
                    + path.getAbsolutePath().replace(" ", "\\ "); //NOI18N
398
        }
399
400
        if (!"".equals(currentPath.trim())) {
401
            current.put(pathName, currentPath);
402
        }
403
    }
404
405
    static String getPathName(Map<String, String> systemEnv) {
406
        // Find PATH environment variable - on Windows it can be some other
407
        // case and we should use whatever it has.
408
        String pathName = "PATH"; // NOI18N
409
410
        if (Utilities.isWindows()) {
411
            pathName = "Path"; // NOI18N
412
413
            for (String keySystem : systemEnv.keySet()) {
414
                if ("PATH".equals(keySystem.toUpperCase(Locale.ENGLISH))) { // NOI18N
415
                    pathName = keySystem;
416
                    break;
417
                }
418
            }
419
        }
420
        return pathName;
421
    }
422
381
    private static String escapeString(String s) {
423
    private static String escapeString(String s) {
382
        if (s.length() == 0) {
424
        if (s.length() == 0) {
383
            return "\"\""; // NOI18N
425
            return "\"\""; // NOI18N
Lines 475-480 Link Here
475
517
476
        private Map<String, String> envVariables = new HashMap<String, String>();
518
        private Map<String, String> envVariables = new HashMap<String, String>();
477
519
520
        private boolean emptySystemVariables;
521
478
        public BuilderData(String executable) {
522
        public BuilderData(String executable) {
479
            this.executable = executable;
523
            this.executable = executable;
480
        }
524
        }
Lines 486-491 Link Here
486
            this.arguments.addAll(builder.arguments);
530
            this.arguments.addAll(builder.arguments);
487
            this.paths.addAll(builder.paths);
531
            this.paths.addAll(builder.paths);
488
            this.envVariables.putAll(builder.envVariables);
532
            this.envVariables.putAll(builder.envVariables);
533
            this.emptySystemVariables = builder.emptySystemVariables;
489
        }
534
        }
490
535
491
        public BuilderData workingDirectory(File workingDirectory) {
536
        public BuilderData workingDirectory(File workingDirectory) {
Lines 521-526 Link Here
521
            envVariables.put(name, value);
566
            envVariables.put(name, value);
522
            return this;
567
            return this;
523
        }
568
        }
569
570
        public BuilderData emptySystemVariables(boolean emptySystemVariables) {
571
            this.emptySystemVariables = emptySystemVariables;
572
            return this;
573
        }
524
    }
574
    }
525
575
526
576
(-)a/extexecution/src/org/netbeans/api/extexecution/ProcessBuilder.java (-36 / +293 lines)
Lines 46-57 Link Here
46
import java.util.ArrayList;
46
import java.util.ArrayList;
47
import java.util.HashMap;
47
import java.util.HashMap;
48
import java.util.List;
48
import java.util.List;
49
import java.util.Locale;
49
import java.util.Map;
50
import java.util.Map;
50
import java.util.concurrent.Callable;
51
import java.util.concurrent.Callable;
51
import org.netbeans.api.annotations.common.NonNull;
52
import org.netbeans.api.annotations.common.NonNull;
52
import org.netbeans.api.annotations.common.NullAllowed;
53
import org.netbeans.api.annotations.common.NullAllowed;
53
import org.netbeans.modules.extexecution.ProcessBuilderAccessor;
54
import org.netbeans.modules.extexecution.ProcessBuilderAccessor;
55
import org.netbeans.modules.extexecution.ProcessParametersAccessor;
56
import org.netbeans.spi.extexecution.EnvironmentFactory;
57
import org.netbeans.spi.extexecution.EnvironmentImplementation;
54
import org.netbeans.spi.extexecution.ProcessBuilderImplementation;
58
import org.netbeans.spi.extexecution.ProcessBuilderImplementation;
59
import org.netbeans.spi.extexecution.ProcessBuilderImplementation2;
60
import org.netbeans.spi.extexecution.ProcessParameters;
61
import org.openide.util.Lookup;
55
import org.openide.util.NbBundle;
62
import org.openide.util.NbBundle;
56
import org.openide.util.Parameters;
63
import org.openide.util.Parameters;
57
import org.openide.util.UserQuestionException;
64
import org.openide.util.UserQuestionException;
Lines 68-102 Link Here
68
 * for creating the local machine OS processes.
75
 * for creating the local machine OS processes.
69
 * <p>
76
 * <p>
70
 * <i>Thread safety</i> of this class depends on thread safety of
77
 * <i>Thread safety</i> of this class depends on thread safety of
71
 * the {@link ProcessBuilderImplementation} the class is using. If it is thread
78
 * the implementation class.
79
 * <p>
80
 * If the {@link ProcessBuilderImplementation} is used and it is thread
72
 * safe (if possible the implementation should be even stateless) this class
81
 * safe (if possible the implementation should be even stateless) this class
73
 * is thread safe as well.
82
 * is thread safe as well.
83
 * <p>
84
 * If the {@link ProcessBuilderImplementation2} is used and it is (including
85
 * {@link EnvironmentImplementation}) thread safe and does not have any mutable
86
 * configuration accessible via {@link ProcessBuilderImplementation2#getLookup()}
87
 * it is thread safe as well. Otherwise it is not thread safe.
88
 * <p>
89
 * The synchronization mechanism use in this object is the {@link ProcessBuilderImplementation}
90
 * or {@link ProcessBuilderImplementation2} object monitor.
74
 *
91
 *
75
 * @author Petr Hejl
92
 * @author Petr Hejl
76
 * @since 1.28
93
 * @since 1.28
77
 */
94
 */
78
public final class ProcessBuilder implements Callable<Process> {
95
public final class ProcessBuilder implements Callable<Process>, Lookup.Provider {
79
96
80
    private final ProcessBuilderImplementation implementation;
97
    private final ProcessBuilderImplementation implementation;
81
98
99
    private final ProcessBuilderImplementation2 implementation2;
100
101
    private final Object lock;
102
82
    private final String description;
103
    private final String description;
83
104
84
    /**<i>GuardedBy("this")</i>*/
105
    /**<i>GuardedBy("lock")</i>*/
85
    private String executable;
106
    private String executable;
86
107
87
    /**<i>GuardedBy("this")</i>*/
108
    /**<i>GuardedBy("lock")</i>*/
88
    private String workingDirectory;
109
    private String workingDirectory;
89
110
90
    /**<i>GuardedBy("this")</i>*/
111
    /**<i>GuardedBy("lock")</i>*/
91
    private List<String> arguments = new ArrayList<String>();
112
    private List<String> arguments = new ArrayList<String>();
92
113
93
    /**<i>GuardedBy("this")</i>*/
114
    /**<i>GuardedBy("lock")</i>*/
94
    private List<String> paths = new ArrayList<String>();
115
    private List<String> paths = new ArrayList<String>();
95
116
96
    /**<i>GuardedBy("this")</i>*/
117
    /**<i>GuardedBy("lock")</i>*/
97
    private Map<String, String> envVariables = new HashMap<String, String>();
118
    private Map<String, String> envVariables = new HashMap<String, String>();
98
119
99
    /**<i>GuardedBy("this")</i>*/
120
    /**<i>GuardedBy("lock")</i>*/
100
    private boolean redirectErrorStream;
121
    private boolean redirectErrorStream;
101
122
102
    static {
123
    static {
Lines 106-117 Link Here
106
            public ProcessBuilder createProcessBuilder(ProcessBuilderImplementation impl, String description) {
127
            public ProcessBuilder createProcessBuilder(ProcessBuilderImplementation impl, String description) {
107
                return new ProcessBuilder(impl, description);
128
                return new ProcessBuilder(impl, description);
108
            }
129
            }
130
131
            @Override
132
            public ProcessBuilder createProcessBuilder(ProcessBuilderImplementation2 impl, String description) {
133
                return new ProcessBuilder(impl, description);
134
            }
109
        });
135
        });
110
    }
136
    }
111
137
112
    private ProcessBuilder(ProcessBuilderImplementation implementation, String description) {
138
    private ProcessBuilder(ProcessBuilderImplementation implementation, String description) {
139
        this(implementation, null, description);
140
    }
141
142
    private ProcessBuilder(ProcessBuilderImplementation2 implementation2, String description) {
143
        this(null, implementation2, description);
144
    }
145
146
    private ProcessBuilder(ProcessBuilderImplementation implementation, ProcessBuilderImplementation2 implementation2, String description) {
147
        assert implementation == null || implementation2 == null;
113
        this.implementation = implementation;
148
        this.implementation = implementation;
149
        this.implementation2 = implementation2;
114
        this.description = description;
150
        this.description = description;
151
        if (implementation != null) {
152
            lock = implementation;
153
        } else {
154
            lock = implementation2;
155
        }
115
    }
156
    }
116
157
117
    /**
158
    /**
Lines 122-128 Link Here
122
     *             machine
163
     *             machine
123
     */
164
     */
124
    public static ProcessBuilder getLocal() {
165
    public static ProcessBuilder getLocal() {
125
        return new ProcessBuilder(new LocalProcessFactory(),
166
        return new ProcessBuilder(new LocalProcessBuilder(),
126
                NbBundle.getMessage(ProcessBuilder.class, "LocalProcessBuilder"));
167
                NbBundle.getMessage(ProcessBuilder.class, "LocalProcessBuilder"));
127
    }
168
    }
128
169
Lines 146-152 Link Here
146
    public void setExecutable(@NonNull String executable) {
187
    public void setExecutable(@NonNull String executable) {
147
        Parameters.notNull("executable", executable);
188
        Parameters.notNull("executable", executable);
148
189
149
        synchronized (this) {
190
        synchronized (lock) {
150
            this.executable = executable;
191
            this.executable = executable;
151
        }
192
        }
152
    }
193
    }
Lines 158-164 Link Here
158
     * @param workingDirectory the working directory of the process
199
     * @param workingDirectory the working directory of the process
159
     */
200
     */
160
    public void setWorkingDirectory(@NullAllowed String workingDirectory) {
201
    public void setWorkingDirectory(@NullAllowed String workingDirectory) {
161
        synchronized (this) {
202
        synchronized (lock) {
162
            this.workingDirectory = workingDirectory;
203
            this.workingDirectory = workingDirectory;
163
        }
204
        }
164
    }
205
    }
Lines 172-178 Link Here
172
    public void setArguments(@NonNull List<String> arguments) {
213
    public void setArguments(@NonNull List<String> arguments) {
173
        Parameters.notNull("arguments", arguments);
214
        Parameters.notNull("arguments", arguments);
174
215
175
        synchronized (this) {
216
        synchronized (lock) {
176
            this.arguments.clear();
217
            this.arguments.clear();
177
            this.arguments.addAll(arguments);
218
            this.arguments.addAll(arguments);
178
        }
219
        }
Lines 184-194 Link Here
184
     * exception of <code>PATH</code> possibly configured by {@link #setPaths(java.util.List)}.
225
     * exception of <code>PATH</code> possibly configured by {@link #setPaths(java.util.List)}.
185
     *
226
     *
186
     * @param envVariables the environment variables for the process
227
     * @param envVariables the environment variables for the process
228
     * @deprecated use {@link Environment#setVariable(java.lang.String, java.lang.String)}
229
     *             on object received by {@link #getEnvironment()} call
187
     */
230
     */
188
    public void setEnvironmentVariables(@NonNull Map<String, String> envVariables) {
231
    public void setEnvironmentVariables(@NonNull Map<String, String> envVariables) {
189
        Parameters.notNull("envVariables", envVariables);
232
        Parameters.notNull("envVariables", envVariables);
190
233
191
        synchronized (this) {
234
        if (implementation2 != null) {
235
            for (Map.Entry<String, String> entry : envVariables.entrySet()) {
236
                implementation2.getEnvironment().setVariable(entry.getKey(), entry.getValue());
237
            }
238
            return;
239
        }
240
241
        synchronized (lock) {
192
            this.envVariables.clear();
242
            this.envVariables.clear();
193
            this.envVariables.putAll(envVariables);
243
            this.envVariables.putAll(envVariables);
194
        }
244
        }
Lines 196-210 Link Here
196
246
197
    /**
247
    /**
198
     * Sets the additional paths to be included in <code>PATH</code> environment
248
     * Sets the additional paths to be included in <code>PATH</code> environment
199
     * variable for the process.
249
     * variable for the process. The paths are prepended to the PATH variable
250
     * one by one as specified in the list so in fact the last path in
251
     * the list will be the first one in the PATH variable.
252
     * <p>
253
     * This method is <i>semi-deprecated</i>. If {@link #getEnvironment()} is not
254
     * <code>null</code> this call adds paths one by one by call to
255
     * {@link Environment#prependPath(java.lang.String, java.lang.String)}
256
     * on returned object.
200
     *
257
     *
201
     * @param paths the additional paths to be included in <code>PATH</code>
258
     * @param paths the additional paths to be included in <code>PATH</code>
202
     *             environment variable
259
     *             environment variable
260
     * @deprecated use {@link Environment#prependPath(java.lang.String, java.lang.String)}
261
     *             on object received by {@link #getEnvironment()} call, with
262
     *             the first argument being <code>PATH</code>
203
     */
263
     */
204
    public void setPaths(@NonNull List<String> paths) {
264
    public void setPaths(@NonNull List<String> paths) {
205
        Parameters.notNull("paths", paths);
265
        Parameters.notNull("paths", paths);
206
266
207
        synchronized (this) {
267
        if (implementation2 != null) {
268
            for (String path : paths) {
269
                implementation2.getEnvironment().prependPath("PATH", path); // NOI18N
270
            }
271
            return;
272
        }
273
274
        synchronized (lock) {
208
            this.paths.clear();
275
            this.paths.clear();
209
            this.paths.addAll(paths);
276
            this.paths.addAll(paths);
210
        }
277
        }
Lines 218-229 Link Here
218
     * @param redirectErrorStream the error stream redirection
285
     * @param redirectErrorStream the error stream redirection
219
     */
286
     */
220
    public void setRedirectErrorStream(boolean redirectErrorStream) {
287
    public void setRedirectErrorStream(boolean redirectErrorStream) {
221
        synchronized (this) {
288
        synchronized (lock) {
222
            this.redirectErrorStream = redirectErrorStream;
289
            this.redirectErrorStream = redirectErrorStream;
223
        }
290
        }
224
    }
291
    }
225
292
226
    /**
293
    /**
294
     * Returns the object for environment variables manipulation.
295
     *
296
     * @return the object for environment variables manipulation
297
     * @since 1.37
298
     */
299
    @NonNull
300
    public Environment getEnvironment() {
301
        if (implementation2 != null) {
302
            return implementation2.getEnvironment();
303
        }
304
        return EnvironmentFactory.createEnvironment(new EnvironmentImplementation() {
305
306
            @Override
307
            public void prependPath(String name, String value) {
308
                if (!name.equalsIgnoreCase("PATH")) { // NOI18N
309
                    throw new UnsupportedOperationException("The deprecated implementation "
310
                            + implementation.getClass().getName() + "does not support this method for a non PATH variable.");
311
                }
312
                synchronized (lock) {
313
                    paths.add(0, value);
314
                }
315
            }
316
317
            @Override
318
            public void setVariable(String name, String value) {
319
                synchronized (lock) {
320
                    envVariables.put(name, value);
321
                }
322
            }
323
324
            @Override
325
            public String getVariable(String name) {
326
                throw new UnsupportedOperationException("The deprecated implementation "
327
                        + implementation.getClass().getName() + "does not support this method.");
328
            }
329
330
            @Override
331
            public void appendPath(String name, String value) {
332
                throw new UnsupportedOperationException("The deprecated implementation "
333
                        + implementation.getClass().getName() + "does not support this method.");
334
            }
335
336
            @Override
337
            public void removeVariable(String name) {
338
                throw new UnsupportedOperationException("The deprecated implementation "
339
                        + implementation.getClass().getName() + "does not support this method.");
340
            }
341
342
            @Override
343
            public Map<String, String> values() {
344
                throw new UnsupportedOperationException("The deprecated implementation "
345
                        + implementation.getClass().getName() + "does not support this method.");
346
            }
347
        });
348
    }
349
350
    /**
351
     * Returns the associated {@link Lookup}. Extension point provided by
352
     * {@link ProcessBuilderImplementation2}.
353
     *
354
     * @return the associated {@link Lookup}.
355
     * @see ProcessBuilderImplementation2#getLookup()
356
     * @since 1.37
357
     */
358
    @Override
359
    public Lookup getLookup() {
360
        if (implementation2 != null) {
361
            return implementation2.getLookup();
362
        }
363
        return Lookup.EMPTY;
364
    }
365
366
367
    /**
227
     * Creates the new {@link Process} based on the properties configured
368
     * Creates the new {@link Process} based on the properties configured
228
     * in this builder.
369
     * in this builder.
229
     * <p>
370
     * <p>
Lines 232-238 Link Here
232
     * <p>
373
     * <p>
233
     * Since version 1.35 implementors of this method are advised to throw
374
     * Since version 1.35 implementors of this method are advised to throw
234
     * a {@link UserQuestionException} in case the execution cannot be
375
     * a {@link UserQuestionException} in case the execution cannot be
235
     * performed and requires additional user confirmation, or configuration. 
376
     * performed and requires additional user confirmation, or configuration.
236
     * Callers of this method may check for this exception and handle it
377
     * Callers of this method may check for this exception and handle it
237
     * appropriately.
378
     * appropriately.
238
     *
379
     *
Lines 248-299 Link Here
248
    @NonNull
389
    @NonNull
249
    @Override
390
    @Override
250
    public Process call() throws IOException {
391
    public Process call() throws IOException {
251
        String currentExecutable = null;
392
        String currentExecutable;
252
        String currentWorkingDirectory = null;
393
        String currentWorkingDirectory;
253
        List<String> currentArguments = new ArrayList<String>();
394
        List<String> currentArguments = new ArrayList<String>();
254
        List<String> currentPaths = new ArrayList<String>();
395
        List<String> currentPaths = new ArrayList<String>();
255
        Map<String, String> currentEnvVariables = new HashMap<String, String>();
396
        Map<String, String> currentVariables = new HashMap<String, String>();
256
        boolean currentRedirectErrorStream = false;
397
        boolean currentRedirectErrorStream;
257
398
258
        synchronized (this) {
399
        synchronized (lock) {
259
            currentExecutable = executable;
400
            currentExecutable = executable;
260
            currentWorkingDirectory = workingDirectory;
401
            currentWorkingDirectory = workingDirectory;
261
            currentArguments.addAll(arguments);
402
            currentArguments.addAll(arguments);
262
            currentPaths.addAll(paths);
403
            currentPaths.addAll(paths);
263
            currentEnvVariables.putAll(envVariables);
264
            currentRedirectErrorStream = redirectErrorStream;
404
            currentRedirectErrorStream = redirectErrorStream;
405
            if (implementation2 != null) {
406
                currentVariables.putAll(getEnvironment().values());
407
            } else {
408
                currentVariables.putAll(envVariables);
409
            }
265
        }
410
        }
266
411
267
        if (currentExecutable == null) {
412
        if (currentExecutable == null) {
268
            throw new IllegalStateException("The executable has not been configured");
413
            throw new IllegalStateException("The executable has not been configured");
269
        }
414
        }
270
415
416
        if (implementation2 != null) {
417
            ProcessParameters params = ProcessParametersAccessor.getDefault().createProcessParameters(
418
                    currentExecutable, currentWorkingDirectory, currentArguments,
419
                    currentRedirectErrorStream, currentVariables);
420
            return implementation2.createProcess(params);
421
        }
422
271
        return implementation.createProcess(currentExecutable, currentWorkingDirectory, currentArguments,
423
        return implementation.createProcess(currentExecutable, currentWorkingDirectory, currentArguments,
272
                currentPaths, currentEnvVariables, currentRedirectErrorStream);
424
                currentPaths, currentVariables, currentRedirectErrorStream);
273
    }
425
    }
274
426
275
    private static class LocalProcessFactory implements ProcessBuilderImplementation {
427
    /**
428
     * Marks an object from which it is possible to get a {@link ProcessBuilder}.
429
     *
430
     * @since 1.37
431
     */
432
    public static interface Provider {
433
434
        /**
435
         * Returns the {@link ProcessBuilder} for the object.
436
         *
437
         * @return the {@link ProcessBuilder} for the object
438
         * @throws IOException if there was a problem with the provision
439
         */
440
        ProcessBuilder getProcessBuilder() throws IOException;
441
442
    }
443
444
    private static class LocalProcessBuilder implements ProcessBuilderImplementation2 {
445
446
        private final Environment environment = EnvironmentFactory.createEnvironment(
447
                new LocalEnvironment(this, System.getenv()));
276
448
277
        @Override
449
        @Override
278
        public Process createProcess(String executable, String workingDirectory, List<String> arguments,
450
        public Environment getEnvironment() {
279
                List<String> paths, Map<String, String> environment, boolean redirectErrorStream) throws IOException {
451
            return environment;
452
        }
280
453
281
            ExternalProcessBuilder builder = new ExternalProcessBuilder(executable);
454
        @Override
282
            if (workingDirectory != null) {
455
        public Lookup getLookup() {
283
                builder = builder.workingDirectory(new File(workingDirectory));
456
            return Lookup.EMPTY;
457
        }
458
459
        @Override
460
        public Process createProcess(ProcessParameters parameters) throws IOException {
461
            ExternalProcessBuilder builder = new ExternalProcessBuilder(parameters.getExecutable());
462
            String workingDir = parameters.getWorkingDirectory();
463
            if (workingDir != null) {
464
                builder = builder.workingDirectory(new File(workingDir));
284
            }
465
            }
285
            for (String argument : arguments) {
466
            for (String argument : parameters.getArguments()) {
286
                builder = builder.addArgument(argument);
467
                builder = builder.addArgument(argument);
287
            }
468
            }
288
            for (String path : paths) {
469
            builder = builder.redirectErrorStream(parameters.isRedirectErrorStream());
289
                builder = builder.prependPath(new File(path));
470
290
            }
471
            builder = builder.emptySystemVariables(true);
291
            for (Map.Entry<String, String> entry : environment.entrySet()) {
472
            for (Map.Entry<String, String> entry : parameters.getEnvironmentVariables().entrySet()) {
292
                builder = builder.addEnvironmentVariable(entry.getKey(), entry.getValue());
473
                builder = builder.addEnvironmentVariable(entry.getKey(), entry.getValue());
293
            }
474
            }
294
            builder = builder.redirectErrorStream(redirectErrorStream);
295
475
296
            return builder.call();
476
            return builder.call();
297
        }
477
        }
298
    }
478
    }
479
480
    private static class LocalEnvironment implements EnvironmentImplementation {
481
482
        private final LocalProcessBuilder builder;
483
484
        private final Map<String, String> systemEnvironment;
485
486
        private final String pathName;
487
488
        public LocalEnvironment(LocalProcessBuilder builder, Map<String, String> systemEnvironment) {
489
            this.builder = builder;
490
            this.systemEnvironment = new HashMap<String, String>(systemEnvironment);
491
            this.pathName = ExternalProcessBuilder.getPathName(systemEnvironment);
492
        }
493
494
        @Override
495
        public String getVariable(String name) {
496
            synchronized (builder) {
497
                if ("PATH".equals(name.toUpperCase(Locale.ENGLISH))) { // NOI18N
498
                    return systemEnvironment.get(pathName);
499
                } else {
500
                    return systemEnvironment.get(name);
501
                }
502
            }
503
        }
504
505
        @Override
506
        public void appendPath(String name, String value) {
507
            putPath(name, value, false);
508
        }
509
510
        @Override
511
        public void prependPath(String name, String value) {
512
            putPath(name, value, true);
513
        }
514
515
        @Override
516
        public void setVariable(String name, String value) {
517
            synchronized (builder) {
518
                if ("PATH".equals(name.toUpperCase(Locale.ENGLISH))) { // NOI18N
519
                    systemEnvironment.put(pathName, value);
520
                } else {
521
                    systemEnvironment.put(name, value);
522
                }
523
            }
524
        }
525
526
        @Override
527
        public void removeVariable(String name) {
528
            synchronized (builder) {
529
                if ("PATH".equals(name.toUpperCase(Locale.ENGLISH))) { // NOI18N
530
                    systemEnvironment.remove(pathName);
531
                } else {
532
                    systemEnvironment.remove(name);
533
                }
534
            }
535
        }
536
537
        @Override
538
        public Map<String, String> values() {
539
            synchronized (builder) {
540
                return new HashMap<String, String>(systemEnvironment);
541
            }
542
        }
543
544
        private void putPath(String name, String value, boolean prepend) {
545
            synchronized (builder) {
546
                if ("PATH".equals(name.toUpperCase(Locale.ENGLISH))) { // NOI18N
547
                    ExternalProcessBuilder.putPath(new File(value), pathName,
548
                            prepend, systemEnvironment);
549
                } else {
550
                    ExternalProcessBuilder.putPath(new File(value), name,
551
                            prepend, systemEnvironment);
552
                }
553
            }
554
        }
555
    }
299
}
556
}
(-)a/extexecution/src/org/netbeans/api/extexecution/input/InputReaders.java (+7 lines)
Lines 46-51 Link Here
46
import java.io.InputStream;
46
import java.io.InputStream;
47
import java.io.InputStreamReader;
47
import java.io.InputStreamReader;
48
import java.io.Reader;
48
import java.io.Reader;
49
import java.io.StringReader;
49
import java.nio.charset.Charset;
50
import java.nio.charset.Charset;
50
import org.netbeans.api.annotations.common.CheckForNull;
51
import org.netbeans.api.annotations.common.CheckForNull;
51
import org.netbeans.api.annotations.common.NonNull;
52
import org.netbeans.api.annotations.common.NonNull;
Lines 82-87 Link Here
82
     */
83
     */
83
    @NonNull
84
    @NonNull
84
    public static InputReader forReader(@NonNull Reader reader) {
85
    public static InputReader forReader(@NonNull Reader reader) {
86
        if (reader instanceof StringReader) {
87
            // unfortunatelly the string reader is always
88
            // ready (isReady() returns true) which I would consider a bug
89
            // when end of string is reached
90
            return new DefaultInputReader(reader, false);
91
        }
85
        return new DefaultInputReader(reader, true);
92
        return new DefaultInputReader(reader, true);
86
    }
93
    }
87
94
(-)a/extexecution/src/org/netbeans/api/extexecution/process/ProcessCharset.java (+169 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2012 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 2012 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.api.extexecution.process;
43
44
import java.nio.charset.Charset;
45
import org.netbeans.api.annotations.common.CheckForNull;
46
import org.netbeans.api.annotations.common.NonNull;
47
import org.openide.util.Lookup;
48
import org.openide.util.Parameters;
49
50
/**
51
 * This class allows client to get input and output charset of
52
 * the {@link Process}. Though the process charsets might not be always
53
 * supported.
54
 * <p>
55
 * If the {@link Process} implementation wants to support charsets it has to
56
 * implement {@link Lookup.Provider} and there has to be instance of this class
57
 * in the returned {@link Lookup}. The functionality itself is implemented in
58
 * methods {@link #getInputCharset()} and {@link #getOutputCharset()}.
59
 *
60
 * @author Petr Hejl
61
 * @since 1.37
62
 */
63
public abstract class ProcessCharset {
64
65
    private static ProcessCharset find(Process process) {
66
        if (process instanceof Lookup.Provider) {
67
            Lookup.Provider p = (Lookup.Provider) process;
68
            return p.getLookup().lookup(ProcessCharset.class);
69
        }
70
        return null;
71
    }
72
73
    /**
74
     * Checks whether the getting of charsets of the {@link Process} is supported.
75
     * If the return value is <code>false</code> methods
76
     * {@link #getInputCharset(java.lang.Process)} and {@link #getOutputCharset(java.lang.Process)}
77
     * will return <code>null</code> for sure.
78
     *
79
     * @param process the process to check
80
     * @return <code>true</code> if process charsets can be received <code>false</code>
81
     *             otherwise
82
     */
83
    public static boolean isSupported(@NonNull Process process) {
84
        Parameters.notNull("process", process);
85
86
        return find(process) != null;
87
    }
88
89
    /**
90
     * Returns the input charset of the process if supported. In case it is not
91
     * supported or the process can't determine the charset <code>null</code> is
92
     * returned.
93
     *
94
     * @param process the process
95
     * @return the input charset of the process or <code>null</code>
96
     */
97
    @CheckForNull
98
    public static Charset getInputCharset(@NonNull Process process) {
99
        Parameters.notNull("process", process);
100
101
        ProcessCharset processCharset = find(process);
102
        if (processCharset != null) {
103
            return processCharset.getInputCharset();
104
        }
105
        return null;
106
    }
107
108
    /**
109
     * Returns the output charset of the process if supported. In case it is not
110
     * supported or the process can't determine the charset <code>null</code> is
111
     * returned.
112
     *
113
     * @param process the process
114
     * @return the output charset of the process or <code>null</code>
115
     */
116
    @CheckForNull
117
    public static Charset getOutputCharset(@NonNull Process process) {
118
        Parameters.notNull("process", process);
119
120
        ProcessCharset processCharset = find(process);
121
        if (processCharset != null) {
122
            return processCharset.getOutputCharset();
123
        }
124
        return null;
125
    }
126
127
    /**
128
     * Returns the error output charset of the process if supported. In case it
129
     * is not supported or the process can't determine the charset <code>null</code>
130
     * is returned.
131
     *
132
     * @param process the process
133
     * @return the error output charset of the process or <code>null</code>
134
     */
135
    @CheckForNull
136
    public static Charset getErrorCharset(@NonNull Process process) {
137
        Parameters.notNull("process", process);
138
139
        ProcessCharset processCharset = find(process);
140
        if (processCharset != null) {
141
            return processCharset.getErrorCharset();
142
        }
143
        return null;
144
    }
145
146
    /**
147
     * Returns the input charset of a process or <code>null</code>.
148
     *
149
     * @return input charset of a process or <code>null</code>
150
     */
151
    @CheckForNull
152
    protected abstract Charset getInputCharset();
153
154
    /**
155
     * Returns the output charset of a process or <code>null</code>.
156
     *
157
     * @return output charset of a process or <code>null</code>
158
     */
159
    @CheckForNull
160
    protected abstract Charset getOutputCharset();
161
162
    /**
163
     * Returns the error output charset of a process or <code>null</code>.
164
     *
165
     * @return error output charset of a process or <code>null</code>
166
     */
167
    @CheckForNull
168
    protected abstract Charset getErrorCharset();
169
}
(-)a/extexecution/src/org/netbeans/api/extexecution/process/ProcessId.java (+111 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2012 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 2012 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.api.extexecution.process;
43
44
import org.netbeans.api.annotations.common.CheckForNull;
45
import org.netbeans.api.annotations.common.NonNull;
46
import org.openide.util.Lookup;
47
import org.openide.util.Parameters;
48
49
/**
50
 * This class allows client to request ID of the {@link Process}. Though
51
 * the process ID might not be always supported.
52
 * <p>
53
 * If the {@link Process} implementation wants to support the ID it has to
54
 * implement {@link Lookup.Provider} and there has to be instance of this class
55
 * in the returned {@link Lookup}. The functionality itself is implemented in
56
 * method {@link #getId()}.
57
 *
58
 * @author Petr Hejl
59
 * @since 1.37
60
 */
61
public abstract class ProcessId {
62
63
    private static ProcessId find(Process process) {
64
        if (process instanceof Lookup.Provider) {
65
            Lookup.Provider p = (Lookup.Provider) process;
66
            return p.getLookup().lookup(ProcessId.class);
67
        }
68
        return null;
69
    }
70
71
    /**
72
     * Checks whether the getting of the ID of the {@link Process} is supported.
73
     * If the return value is <code>false</code> the {@link #getId(java.lang.Process)}
74
     * will return <code>null</code> for sure.
75
     *
76
     * @param process the process to check
77
     * @return <code>true</code> if the ID can be received <code>false</code>
78
     *             otherwise
79
     */
80
    public static boolean isSupported(@NonNull Process process) {
81
        Parameters.notNull("process", process);
82
        
83
        return find(process) != null;
84
    }
85
86
    /**
87
     * Returns the ID of the process if supported. In case it is not supported
88
     * or the process can't determine its ID <code>null</code> is returned.
89
     *
90
     * @param process the process
91
     * @return the process ID or <code>null</code>
92
     */
93
    @CheckForNull
94
    public static Integer getId(@NonNull Process process) {
95
        Parameters.notNull("process", process);
96
97
        ProcessId processId = find(process);
98
        if (processId != null) {
99
            return processId.getId();
100
        }
101
        return null;
102
    }
103
104
    /**
105
     * Returns the ID of a process or <code>null</code>.
106
     *
107
     * @return ID of a process or <code>null</code>
108
     */
109
    @CheckForNull
110
    protected abstract Integer getId();
111
}
(-)a/extexecution/src/org/netbeans/api/extexecution/process/ProcessSignal.java (+181 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2012 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 2012 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.api.extexecution.process;
43
44
import java.io.IOException;
45
import org.netbeans.api.annotations.common.NonNull;
46
import org.openide.util.Lookup;
47
import org.openide.util.Parameters;
48
49
/**
50
 * This class allows client send a signal to the {@link Process} or to whole
51
 * its group. Though signal sending might not be always supported.
52
 * <p>
53
 * If the {@link Process} implementation wants to support the signal sending
54
 * it has to implement {@link Lookup.Provider} and there has to be instance
55
 * of this class in the returned {@link Lookup}. The functionality itself is
56
 * implemented in methods {@link #signal(org.netbeans.api.extexecution.process.ProcessSignal.Signal)}
57
 * and {@link #signalGroup(org.netbeans.api.extexecution.process.ProcessSignal.Signal)}.
58
 *
59
 * @author Petr Hejl
60
 * @since 1.37
61
 */
62
public abstract class ProcessSignal {
63
64
    private static ProcessSignal find(Process process) {
65
        if (process instanceof Lookup.Provider) {
66
            Lookup.Provider p = (Lookup.Provider) process;
67
            return p.getLookup().lookup(ProcessSignal.class);
68
        }
69
        return null;
70
    }
71
72
    /**
73
     * Checks whether the signal sending is supported for the {@link Process}.
74
     * If the return value is <code>false</code> the signal operations are
75
     * effectively noops.
76
     *
77
     * @param process the process to check
78
     * @return <code>true</code> if the signals can be send <code>false</code>
79
     *             otherwise
80
     */
81
    public static boolean isSupported(@NonNull Process process) {
82
        Parameters.notNull("process", process);
83
84
        return find(process) != null;
85
    }
86
87
    /**
88
     * Sends a signal to the process. If the signal sending is not supported
89
     * this is effectively noop.
90
     *
91
     * @param process the process where to send signal
92
     * @param signal the signal to send
93
     * @throws IOException if problem with signal sending occurs
94
     */
95
    public static void signal(@NonNull Process process, @NonNull Signal signal) throws IOException {
96
        Parameters.notNull("process", process);
97
        Parameters.notNull("signal", signal);
98
99
        ProcessSignal processSignal = find(process);
100
        if (processSignal != null) {
101
            processSignal.signal(signal);
102
        }
103
    }
104
105
    /**
106
     * Sends a signal to the group the process belongs to. If the signal sending
107
     * is not supported this is effectively noop.
108
     *
109
     * @param process the process marking the group where to send signal
110
     * @param signal the signal to send
111
     * @throws IOException if problem with signal sending occurs
112
     */
113
    public static void signalGroup(@NonNull Process process, @NonNull Signal signal) throws IOException {
114
        Parameters.notNull("process", process);
115
        Parameters.notNull("signal", signal);
116
117
        ProcessSignal processSignal = find(process);
118
        if (processSignal != null) {
119
            processSignal.signalGroup(signal);
120
        }
121
    }
122
123
    /**
124
     * Sends a given signal to the process.
125
     *
126
     * @param signal the signal to send
127
     * @throws IOException if problem with signal sending occurs
128
     */
129
    protected abstract void signal(@NonNull Signal signal) throws IOException;
130
131
    /**
132
     * Sends a given signal to the group the process belongs to.
133
     *
134
     * @param signal the signal to send
135
     * @throws IOException if problem with signal sending occurs
136
     */
137
    protected abstract void signalGroup(@NonNull Signal signal) throws IOException;
138
139
    public enum Signal {
140
141
        NULL,
142
        SIGHUP,
143
        SIGINT,
144
        SIGQUIT,
145
        SIGILL,
146
        SIGTRAP,
147
        SIGABRT,
148
        SIGEMT,
149
        SIGFPE,
150
        SIGKILL,
151
        SIGBUS,
152
        SIGSEGV,
153
        SIGSYS,
154
        SIGPIPE,
155
        SIGALRM,
156
        SIGTERM,
157
        SIGUSR1,
158
        SIGUSR2,
159
        SIGCHLD,
160
        SIGPWR,
161
        SIGWINCH,
162
        SIGURG,
163
        SIGPOLL,
164
        SIGSTOP,
165
        SIGTSTP,
166
        SIGCONT,
167
        SIGTTIN,
168
        SIGTTOU,
169
        SIGVTALRM,
170
        SIGPROF,
171
        SIGXCPU,
172
        SIGWAITING,
173
        SIGLWP,
174
        SIGFREEZE,
175
        SIGTHAW,
176
        SIGCANCEL,
177
        SIGLOST,
178
        SIGXRES,
179
        SIGJVM1;
180
    }
181
}
(-)a/extexecution/src/org/netbeans/api/extexecution/process/package-info.java (+50 lines)
Line 0 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 API supporting enhanced functionality for
47
 * a {@link java.lang.Process}.
48
 */
49
package org.netbeans.api.extexecution.process;
50
(-)a/extexecution/src/org/netbeans/modules/extexecution/EnvironmentAccessor.java (+81 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2012 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 2012 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.modules.extexecution;
43
44
import org.netbeans.api.extexecution.Environment;
45
import org.netbeans.spi.extexecution.EnvironmentImplementation;
46
47
/**
48
 *
49
 * @author Petr Hejl
50
 */
51
public abstract class EnvironmentAccessor {
52
53
    private static volatile EnvironmentAccessor DEFAULT;
54
55
    public static EnvironmentAccessor getDefault() {
56
        EnvironmentAccessor a = DEFAULT;
57
        if (a != null) {
58
            return a;
59
        }
60
61
        // invokes static initializer of Environment.class
62
        // that will assign value to the DEFAULT field above
63
        Class c = Environment.class;
64
        try {
65
            Class.forName(c.getName(), true, c.getClassLoader());
66
        } catch (ClassNotFoundException ex) {
67
            assert false : ex;
68
        }
69
        return DEFAULT;
70
    }
71
72
    public static void setDefault(EnvironmentAccessor accessor) {
73
        if (DEFAULT != null) {
74
            throw new IllegalStateException();
75
        }
76
77
        DEFAULT = accessor;
78
    }
79
80
    public abstract Environment createEnvironment(EnvironmentImplementation impl);
81
}
(-)a/extexecution/src/org/netbeans/modules/extexecution/ProcessBuilderAccessor.java (+4 lines)
Lines 42-47 Link Here
42
package org.netbeans.modules.extexecution;
42
package org.netbeans.modules.extexecution;
43
43
44
import org.netbeans.spi.extexecution.ProcessBuilderImplementation;
44
import org.netbeans.spi.extexecution.ProcessBuilderImplementation;
45
import org.netbeans.spi.extexecution.ProcessBuilderImplementation2;
45
46
46
/**
47
/**
47
 *
48
 *
Lines 78-81 Link Here
78
79
79
    public abstract org.netbeans.api.extexecution.ProcessBuilder createProcessBuilder(
80
    public abstract org.netbeans.api.extexecution.ProcessBuilder createProcessBuilder(
80
            ProcessBuilderImplementation impl, String description);
81
            ProcessBuilderImplementation impl, String description);
82
83
    public abstract org.netbeans.api.extexecution.ProcessBuilder createProcessBuilder(
84
            ProcessBuilderImplementation2 impl, String description);
81
}
85
}
(-)a/extexecution/src/org/netbeans/modules/extexecution/ProcessParametersAccessor.java (+84 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2012 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 2012 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.modules.extexecution;
43
44
import java.util.List;
45
import java.util.Map;
46
import org.netbeans.spi.extexecution.ProcessParameters;
47
48
/**
49
 *
50
 * @author Petr Hejl
51
 */
52
public abstract class ProcessParametersAccessor {
53
54
    private static volatile ProcessParametersAccessor DEFAULT;
55
56
    public static ProcessParametersAccessor getDefault() {
57
        ProcessParametersAccessor a = DEFAULT;
58
        if (a != null) {
59
            return a;
60
        }
61
62
        // invokes static initializer of ProcessParameters.class
63
        // that will assign value to the DEFAULT field above
64
        Class c = ProcessParameters.class;
65
        try {
66
            Class.forName(c.getName(), true, c.getClassLoader());
67
        } catch (ClassNotFoundException ex) {
68
            assert false : ex;
69
        }
70
        return DEFAULT;
71
    }
72
73
    public static void setDefault(ProcessParametersAccessor accessor) {
74
        if (DEFAULT != null) {
75
            throw new IllegalStateException();
76
        }
77
78
        DEFAULT = accessor;
79
    }
80
81
    public abstract ProcessParameters createProcessParameters(String executable,
82
            String workingDirectory, List<String> arguments, boolean redirectErrorStream,
83
            Map<String, String> environmentVariables);
84
}
(-)a/extexecution/src/org/netbeans/spi/extexecution/EnvironmentFactory.java (+69 lines)
Line 0 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 org.netbeans.api.extexecution.Environment;
45
import org.netbeans.modules.extexecution.EnvironmentAccessor;
46
47
/**
48
 * The factory allowing SPI implementors of {@link EnvironmentImplementation}
49
 * to create its API instances {@link Environment}.
50
 *
51
 * @author Petr Hejl
52
 * @since 1.37
53
 */
54
public class EnvironmentFactory {
55
56
    private EnvironmentFactory() {
57
        super();
58
    }
59
60
    /**
61
     * Creates the instance of {@link Environment} from its SPI representation.
62
     *
63
     * @param impl SPI representation
64
     * @return the API instance
65
     */
66
    public static Environment createEnvironment(EnvironmentImplementation impl) {
67
        return EnvironmentAccessor.getDefault().createEnvironment(impl);
68
    }
69
}
(-)a/extexecution/src/org/netbeans/spi/extexecution/EnvironmentImplementation.java (+114 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2012 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 2012 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.spi.extexecution;
43
44
import java.util.Map;
45
import org.netbeans.api.annotations.common.CheckForNull;
46
import org.netbeans.api.annotations.common.NonNull;
47
import org.netbeans.api.extexecution.Environment;
48
49
/**
50
 * The interface representing the implementation
51
 * of {@link org.netbeans.api.extexecution.Environment}.
52
 *
53
 * @see Environment
54
 * @author Petr Hejl
55
 * @since 1.37
56
 */
57
public interface EnvironmentImplementation {
58
59
    /**
60
     * Returns the value of the variable or <code>null</code>.
61
     *
62
     * @param name the name of the variable
63
     * @return the value of the variable or <code>null</code>
64
     */
65
    @CheckForNull
66
    String getVariable(@NonNull String name);
67
68
    /**
69
     * Appends a path to a path-like variable. The proper path separator should
70
     * be used to separate the new value.
71
     *
72
     * @param name the name of the variable such as for example
73
     *             <code>PATH</code> or <code>LD_LIBRARY_PATH</code>
74
     * @param value the value (path to append)
75
     */
76
    void appendPath(@NonNull String name, @NonNull String value);
77
78
    /**
79
     * Prepends a path to a path-like variable. The proper path separator should
80
     * be used to separate the new value.
81
     *
82
     * @param name the name of the variable such as for example
83
     *             <code>PATH</code> or <code>LD_LIBRARY_PATH</code>
84
     * @param value the value (path to prepend)
85
     */
86
    void prependPath(@NonNull String name, @NonNull String value);
87
88
    /**
89
     * Sets a value for a variable with the given name.
90
     *
91
     * @param name the name of the variable
92
     * @param value the value
93
     */
94
    void setVariable(@NonNull String name, @NonNull String value);
95
96
    /**
97
     * Removes a variable with the given name. The subsequent call to
98
     * {@link #getVariable(java.lang.String)} with the same argument should
99
     * return <code>null</code>.
100
     *
101
     * @param name the name of the variable
102
     */
103
    void removeVariable(@NonNull String name);
104
105
    /**
106
     * Returns all variable names and associated values as a {@link Map}.
107
     * Changes to the map must not be propagated back to the {@link Environment}.
108
     *
109
     * @return all variable names and associated values
110
     */
111
    @NonNull
112
    Map<String, String> values();
113
114
}
(-)a/extexecution/src/org/netbeans/spi/extexecution/ProcessBuilderFactory.java (+15 lines)
Lines 63-71 Link Here
63
     * @param impl SPI representation
63
     * @param impl SPI representation
64
     * @param description human readable description of the builder
64
     * @param description human readable description of the builder
65
     * @return the API instance
65
     * @return the API instance
66
     * @deprecated use {@link #createProcessBuilder(org.netbeans.spi.extexecution.ProcessBuilderImplementation2, java.lang.String)}
66
     */
67
     */
67
    public static org.netbeans.api.extexecution.ProcessBuilder createProcessBuilder(
68
    public static org.netbeans.api.extexecution.ProcessBuilder createProcessBuilder(
68
            ProcessBuilderImplementation impl, String description) {
69
            ProcessBuilderImplementation impl, String description) {
69
        return ProcessBuilderAccessor.getDefault().createProcessBuilder(impl, description);
70
        return ProcessBuilderAccessor.getDefault().createProcessBuilder(impl, description);
70
    }
71
    }
72
73
    /**
74
     * Creates the instance of {@link org.netbeans.api.extexecution.ProcessBuilder}
75
     * from its SPI representation.
76
     *
77
     * @param impl SPI representation
78
     * @param description human readable description of the builder
79
     * @return the API instance
80
     * @since 1.37
81
     */
82
    public static org.netbeans.api.extexecution.ProcessBuilder createProcessBuilder(
83
            ProcessBuilderImplementation2 impl, String description) {
84
        return ProcessBuilderAccessor.getDefault().createProcessBuilder(impl, description);
85
    }
71
}
86
}
(-)a/extexecution/src/org/netbeans/spi/extexecution/ProcessBuilderImplementation.java (-1 / +2 lines)
Lines 62-67 Link Here
62
 * @see org.netbeans.api.extexecution.ProcessBuilder
62
 * @see org.netbeans.api.extexecution.ProcessBuilder
63
 * @author Petr Hejl
63
 * @author Petr Hejl
64
 * @since 1.28
64
 * @since 1.28
65
 * @deprecated use {@link ProcessBuilderImplementation2}
65
 */
66
 */
66
public interface ProcessBuilderImplementation {
67
public interface ProcessBuilderImplementation {
67
68
Lines 80-86 Link Here
80
     *             the process should be redirected to standard output stream
81
     *             the process should be redirected to standard output stream
81
     * @return a process created with specified parameters and environment
82
     * @return a process created with specified parameters and environment
82
     *             configuration
83
     *             configuration
83
     * @throws IOException IOException if the process could not be created
84
     * @throws IOException if the process could not be created
84
     * @throws UserQuestionException in case there is a need to interact with
85
     * @throws UserQuestionException in case there is a need to interact with
85
     *    user, don't be afraid to throw a subclass of 
86
     *    user, don't be afraid to throw a subclass of 
86
     *    {@link UserQuestionException} with overriden {@link UserQuestionException#confirmed()}
87
     *    {@link UserQuestionException} with overriden {@link UserQuestionException#confirmed()}
(-)a/extexecution/src/org/netbeans/spi/extexecution/ProcessBuilderImplementation2.java (+93 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2012 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 2012 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.spi.extexecution;
43
44
import java.io.IOException;
45
import org.netbeans.api.annotations.common.NonNull;
46
import org.netbeans.api.extexecution.Environment;
47
import org.openide.util.Lookup;
48
49
/**
50
 * The interface representing the implementation
51
 * of {@link org.netbeans.api.extexecution.ProcessBuilder}.
52
 * 
53
 * @see org.netbeans.api.extexecution.ProcessBuilder
54
 * @author Petr Hejl
55
 * @since 1.37
56
 */
57
public interface ProcessBuilderImplementation2 extends Lookup.Provider {
58
59
    /**
60
     * Returns the object for environment variables manipulation.
61
     *
62
     * @return the object for environment variables manipulation
63
     */
64
    @NonNull
65
    Environment getEnvironment();
66
67
    /**
68
     * Provides an extension point to the implementors. One may enhance the
69
     * functionality of {@link org.netbeans.api.extexecution.ProcessBuilder}
70
     * by this as the content of this {@link Lookup} is included in
71
     * {@link org.netbeans.api.extexecution.ProcessBuilder#getLookup()}
72
     *
73
     * @return a lookup providing an extension point
74
     */
75
    @Override
76
    Lookup getLookup();
77
78
    /**
79
     * Creates a process using the specified parameters.
80
     * <p>
81
     * The environment variables stored in parameters are acquired by call to
82
     * {@link Environment#values()}. So if the implementation does not aim to be
83
     * or can't thread safe it may check or use the {@link Environment}
84
     * directly.
85
     *
86
     * @param parameters the instance describing the process parameters
87
     * @return a process created with specified parameters
88
     * @throws IOException if the process could not be created
89
     */
90
    @NonNull
91
    Process createProcess(@NonNull ProcessParameters parameters) throws IOException;
92
93
}
(-)a/extexecution/src/org/netbeans/spi/extexecution/ProcessParameters.java (+142 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2013 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 2013 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.spi.extexecution;
43
44
import java.util.List;
45
import java.util.Map;
46
import org.netbeans.api.annotations.common.CheckForNull;
47
import org.netbeans.api.annotations.common.NonNull;
48
import org.netbeans.modules.extexecution.ProcessParametersAccessor;
49
50
/**
51
 * The parameters configured for process creation.
52
 *
53
 * @see ProcessBuilderImplementation2
54
 * @author Petr Hejl
55
 * @since 1.37
56
 */
57
public final class ProcessParameters {
58
59
    private final String executable;
60
61
    private final String workingDirectory;
62
63
    private final List<String> arguments;
64
65
    private final boolean redirectErrorStream;
66
67
    private final Map<String, String> environmentVariables;
68
69
    static {
70
        ProcessParametersAccessor.setDefault(new ProcessParametersAccessor() {
71
72
            @Override
73
            public ProcessParameters createProcessParameters(String executable, String workingDirectory,
74
                    List<String> arguments, boolean redirectErrorStream, Map<String, String> environmentVariables) {
75
                return new ProcessParameters(executable, workingDirectory, arguments,
76
                        redirectErrorStream, environmentVariables);
77
            }
78
        });
79
    }
80
81
    private ProcessParameters(String executable, String workingDirectory, List<String> arguments,
82
            boolean redirectErrorStream, Map<String, String> environmentVariables) {
83
        this.executable = executable;
84
        this.workingDirectory = workingDirectory;
85
        this.arguments = arguments;
86
        this.redirectErrorStream = redirectErrorStream;
87
        this.environmentVariables = environmentVariables;
88
    }
89
90
    /**
91
     * Returns the configured executable.
92
     *
93
     * @return the configured executable
94
     */
95
    @NonNull
96
    public String getExecutable() {
97
        return executable;
98
    }
99
100
    /**
101
     * Returns the configured working directory or <code>null</code> in case it
102
     * was not configured.
103
     *
104
     * @return the configured working directory or <code>null</code> in case it
105
     *             was not configured
106
     */
107
    @CheckForNull
108
    public String getWorkingDirectory() {
109
        return workingDirectory;
110
    }
111
112
    /**
113
     * Returns the arguments configured for the process.
114
     *
115
     * @return the arguments configured for the process
116
     */
117
    @NonNull
118
    public List<String> getArguments() {
119
        return arguments;
120
    }
121
122
    /**
123
     * Returns <code>true</code> if standard error stream should be redirected
124
     * to standard output stream.
125
     *
126
     * @return <code>true</code> if standard error stream should be redirected
127
     *             to standard output stream
128
     */
129
    public boolean isRedirectErrorStream() {
130
        return redirectErrorStream;
131
    }
132
133
    /**
134
     * Returns the environment variables configured for the process.
135
     *
136
     * @return the environment variables configured for the process
137
     */
138
    @NonNull
139
    public Map<String, String> getEnvironmentVariables() {
140
        return environmentVariables;
141
    }
142
}
(-)a/extexecution/test/unit/src/org/netbeans/api/extexecution/ExecutionServiceTest.java (-3 / +129 lines)
Lines 42-52 Link Here
42
42
43
package org.netbeans.api.extexecution;
43
package org.netbeans.api.extexecution;
44
44
45
import java.io.ByteArrayInputStream;
45
import java.io.FilterInputStream;
46
import java.io.FilterInputStream;
46
import java.io.IOException;
47
import java.io.IOException;
47
import java.io.InputStream;
48
import java.io.InputStream;
48
import java.io.OutputStream;
49
import java.io.OutputStream;
49
import java.io.Reader;
50
import java.io.Reader;
51
import java.io.StringWriter;
52
import java.io.Writer;
50
import java.lang.reflect.InvocationTargetException;
53
import java.lang.reflect.InvocationTargetException;
51
import java.nio.charset.Charset;
54
import java.nio.charset.Charset;
52
import java.util.LinkedList;
55
import java.util.LinkedList;
Lines 358-364 Link Here
358
        final String[] lines = new String[] {"Process line \u1234", "Process line \u1235", "Process line \u1236"};
361
        final String[] lines = new String[] {"Process line \u1234", "Process line \u1235", "Process line \u1236"};
359
362
360
        TestInputStream is = new TestInputStream(TestInputUtils.prepareInputStream(lines, "\n", charset, true));
363
        TestInputStream is = new TestInputStream(TestInputUtils.prepareInputStream(lines, "\n", charset, true));
361
        TestProcess process = new TestProcess(0, is);
364
        TestProcess process = new TestProcess(0, is, null);
362
        is.setProcess(process);
365
        is.setProcess(process);
363
366
364
        TestCallable callable = new TestCallable();
367
        TestCallable callable = new TestCallable();
Lines 536-541 Link Here
536
        assertFalse(val.get());
539
        assertFalse(val.get());
537
    }
540
    }
538
541
542
    public void testWriterService() throws InterruptedException, ExecutionException {
543
        TestProcess process = new TestProcess(0,
544
                new ByteArrayInputStream("testing input".getBytes()),
545
                new ByteArrayInputStream("testing error".getBytes()));
546
        TestCallable callable = new TestCallable();
547
        callable.addProcess(process);
548
549
        StringWriter in = new StringWriter();
550
        StringWriter err = new StringWriter();
551
        ExecutionService service = ExecutionService.newService(callable, in, err);
552
        Future<Integer> task = service.run();
553
        assertNotNull(task);
554
555
        process.waitStarted();
556
557
        process.destroy();
558
        process.waitFor();
559
        assertTrue(process.isFinished());
560
561
        assertEquals(0, task.get().intValue());
562
        assertEquals("testing input", in.toString());
563
        assertEquals("testing error", err.toString());
564
    }
565
566
    public void testWriterServiceOnce() throws InterruptedException, ExecutionException {
567
        TestProcess process = new TestProcess(0,
568
                new ByteArrayInputStream(new byte[0]), null);
569
        TestCallable callable = new TestCallable();
570
        callable.addProcess(process);
571
572
        ExecutionService service = ExecutionService.newService(callable,
573
                (Writer) null, (Writer) null);
574
        Future<Integer> task = service.run();
575
        assertNotNull(task);
576
577
        process.waitStarted();
578
579
        process.destroy();
580
        process.waitFor();
581
        assertTrue(process.isFinished());
582
583
        assertEquals(0, task.get().intValue());
584
585
        try {
586
            service.run();
587
            fail("Multiple run should fail with ISE");
588
        } catch (IllegalStateException ex) {
589
            // expected
590
        }
591
    }
592
593
    public void testLineService() throws InterruptedException, ExecutionException {
594
        final String[] linesIn = new String[] {"Process line 1", "Process line 2", "Process line 3"};
595
        final String[] linesErr = new String[] {"Error line 1", "Error line 2", "Error line 3"};
596
597
        TestInputStream in = new TestInputStream(
598
                TestInputUtils.prepareInputStream(linesIn, "\n", Charset.defaultCharset(), true));
599
        TestInputStream err = new TestInputStream(
600
                TestInputUtils.prepareInputStream(linesErr, "\n", Charset.defaultCharset(), true));
601
        TestProcess process = new TestProcess(0, in, err);
602
        TestCallable callable = new TestCallable();
603
        callable.addProcess(process);
604
605
        TestLineProcessor inProcessor = new TestLineProcessor(false);
606
        TestLineProcessor errProcessor = new TestLineProcessor(false);
607
        ExecutionService service = ExecutionService.newService(callable,
608
                inProcessor, errProcessor, null);
609
        Future<Integer> task = service.run();
610
        assertNotNull(task);
611
612
        process.waitStarted();
613
614
        process.destroy();
615
        process.waitFor();
616
        assertTrue(process.isFinished());
617
618
        assertEquals(0, task.get().intValue());
619
620
        List<String> processed = inProcessor.getLinesProcessed();
621
        assertEquals(linesIn.length, processed.size());
622
        for (int i = 0; i < linesIn.length; i++) {
623
            assertEquals(linesIn[i], processed.get(i));
624
        }
625
        processed = errProcessor.getLinesProcessed();
626
        assertEquals(linesErr.length, processed.size());
627
        for (int i = 0; i < linesErr.length; i++) {
628
            assertEquals(linesErr[i], processed.get(i));
629
        }
630
    }
631
632
    public void testLineServiceOnce() throws InterruptedException, ExecutionException {
633
        TestProcess process = new TestProcess(0,
634
                new ByteArrayInputStream(new byte[0]), null);
635
        TestCallable callable = new TestCallable();
636
        callable.addProcess(process);
637
638
        ExecutionService service = ExecutionService.newService(callable,
639
                null, null, null);
640
        Future<Integer> task = service.run();
641
        assertNotNull(task);
642
643
        process.waitStarted();
644
645
        process.destroy();
646
        process.waitFor();
647
        assertTrue(process.isFinished());
648
649
        assertEquals(0, task.get().intValue());
650
651
        try {
652
            service.run();
653
            fail("Multiple run should fail with ISE");
654
        } catch (IllegalStateException ex) {
655
            // expected
656
        }
657
    }
658
539
    private static InputOutputManager.InputOutputData getInputOutput(String name,
659
    private static InputOutputManager.InputOutputData getInputOutput(String name,
540
            boolean actions, String optionsPath) {
660
            boolean actions, String optionsPath) {
541
661
Lines 579-584 Link Here
579
699
580
        private final InputStream is;
700
        private final InputStream is;
581
701
702
        private final InputStream err;
703
582
        private boolean finished;
704
        private boolean finished;
583
705
584
        private boolean started;
706
        private boolean started;
Lines 586-597 Link Here
586
        public TestProcess(int returnValue) {
708
        public TestProcess(int returnValue) {
587
            this(returnValue, TestInputUtils.prepareInputStream(
709
            this(returnValue, TestInputUtils.prepareInputStream(
588
                    new String[] {"Process line 1", "Process line 2", "Process line 3"}, "\n",
710
                    new String[] {"Process line 1", "Process line 2", "Process line 3"}, "\n",
589
                    Charset.defaultCharset(), true));
711
                    Charset.defaultCharset(), true), null);
590
        }
712
        }
591
713
592
        public TestProcess(int returnValue, InputStream is) {
714
        public TestProcess(int returnValue, InputStream is, InputStream err) {
593
            this.returnValue = returnValue;
715
            this.returnValue = returnValue;
594
            this.is = is;
716
            this.is = is;
717
            this.err = err;
595
        }
718
        }
596
719
597
        public void start() {
720
        public void start() {
Lines 637-642 Link Here
637
760
638
        @Override
761
        @Override
639
        public InputStream getErrorStream() {
762
        public InputStream getErrorStream() {
763
            if (err != null) {
764
                return err;
765
            }
640
            return new InputStream() {
766
            return new InputStream() {
641
                @Override
767
                @Override
642
                public int read() throws IOException {
768
                public int read() throws IOException {
(-)a/extexecution/test/unit/src/org/netbeans/api/extexecution/ProcessBuilderTest.java (-2 / +211 lines)
Lines 48-55 Link Here
48
import java.util.List;
48
import java.util.List;
49
import java.util.Map;
49
import java.util.Map;
50
import org.netbeans.junit.NbTestCase;
50
import org.netbeans.junit.NbTestCase;
51
import org.netbeans.spi.extexecution.EnvironmentFactory;
52
import org.netbeans.spi.extexecution.EnvironmentImplementation;
51
import org.netbeans.spi.extexecution.ProcessBuilderFactory;
53
import org.netbeans.spi.extexecution.ProcessBuilderFactory;
52
import org.netbeans.spi.extexecution.ProcessBuilderImplementation;
54
import org.netbeans.spi.extexecution.ProcessBuilderImplementation;
55
import org.netbeans.spi.extexecution.ProcessBuilderImplementation2;
56
import org.netbeans.spi.extexecution.ProcessParameters;
57
import org.openide.util.Lookup;
53
58
54
/**
59
/**
55
 *
60
 *
Lines 166-172 Link Here
166
        assertEquals("test2", testBuilder.getPaths().get(0));
171
        assertEquals("test2", testBuilder.getPaths().get(0));
167
    }
172
    }
168
173
169
    public void testEnvironment() throws IOException {
174
    public void testEnvironmentVariables() throws IOException {
170
        TestProcessBuilder testBuilder = new TestProcessBuilder();
175
        TestProcessBuilder testBuilder = new TestProcessBuilder();
171
        ProcessBuilder builder = ProcessBuilderFactory.createProcessBuilder(testBuilder, "Test builder");
176
        ProcessBuilder builder = ProcessBuilderFactory.createProcessBuilder(testBuilder, "Test builder");
172
        builder.setExecutable("ls");
177
        builder.setExecutable("ls");
Lines 201-206 Link Here
201
        assertEquals("value2", testBuilder.getEnvironment().get("key2"));
206
        assertEquals("value2", testBuilder.getEnvironment().get("key2"));
202
    }
207
    }
203
208
209
    public void testEnvironment() throws IOException {
210
        TestProcessBuilder2 testBuilder = new TestProcessBuilder2();
211
        ProcessBuilder builder = ProcessBuilderFactory.createProcessBuilder(testBuilder, "Test builder");
212
        builder.setExecutable("ls");
213
214
        builder.getEnvironment().setVariable("key1", "value1");
215
        builder.getEnvironment().setVariable("key2", "value2");
216
217
        assertEquals("value1", testBuilder.getEnvironment().getVariable("key1"));
218
        assertEquals("value2", testBuilder.getEnvironment().getVariable("key2"));
219
220
        builder.call();
221
        assertEquals(2, testBuilder.getParameters().getEnvironmentVariables().size());
222
        assertEquals("value1", testBuilder.getParameters().getEnvironmentVariables().get("key1"));
223
        assertEquals("value2", testBuilder.getParameters().getEnvironmentVariables().get("key2"));
224
225
        builder.getEnvironment().prependPath("PATH", "/test1");
226
        builder.getEnvironment().prependPath("PATH", "/test2");
227
228
        builder.call();
229
        assertEquals(3, testBuilder.getParameters().getEnvironmentVariables().size());
230
        assertEquals("/test2:/test1",
231
                testBuilder.getParameters().getEnvironmentVariables().get("PATH"));
232
233
        builder.getEnvironment().appendPath("PATH", "/test3");
234
235
        builder.call();
236
        assertEquals(3, testBuilder.getParameters().getEnvironmentVariables().size());
237
        assertEquals("/test2:/test1:/test3",
238
                testBuilder.getParameters().getEnvironmentVariables().get("PATH"));
239
240
        builder.getEnvironment().removeVariable("PATH");
241
        assertNull(builder.getEnvironment().getVariable("PATH"));
242
243
        builder.call();
244
        assertEquals(2, testBuilder.getParameters().getEnvironmentVariables().size());
245
        assertNull(testBuilder.getParameters().getEnvironmentVariables().get("PATH"));
246
    }
247
248
    public void testFallbackEnvironment() throws IOException {
249
        TestProcessBuilder testBuilder = new TestProcessBuilder();
250
        ProcessBuilder builder = ProcessBuilderFactory.createProcessBuilder(testBuilder, "Test builder");
251
        builder.setExecutable("ls");
252
253
        builder.getEnvironment().setVariable("key1", "value1");
254
        builder.getEnvironment().setVariable("key2", "value2");
255
256
        builder.call();
257
        assertEquals(2, testBuilder.getEnvironment().size());
258
        assertEquals("value1", testBuilder.getEnvironment().get("key1"));
259
        assertEquals("value2", testBuilder.getEnvironment().get("key2"));
260
261
        builder.getEnvironment().prependPath("PATH", "/test1");
262
        builder.getEnvironment().prependPath("Path", "/test2");
263
264
        builder.call();
265
        assertEquals(2, testBuilder.getPaths().size());
266
        assertEquals("/test2", testBuilder.getPaths().get(0));
267
        assertEquals("/test1", testBuilder.getPaths().get(1));
268
269
        try {
270
            builder.getEnvironment().prependPath("LD_LIBRARY_PATH", "/test");
271
            fail("Prepend of unknown path does not throw exception");
272
        } catch (UnsupportedOperationException ex) {
273
            // expected
274
        }
275
276
        try {
277
            builder.getEnvironment().appendPath("PATH", "/test");
278
            fail("Append of any path does not throw exception");
279
        } catch (UnsupportedOperationException ex) {
280
            // expected
281
        }
282
283
        try {
284
            builder.getEnvironment().getVariable("PATH");
285
            fail("getVariable() does not throw exception");
286
        } catch (UnsupportedOperationException ex) {
287
            // expected
288
        }
289
290
        try {
291
            builder.getEnvironment().removeVariable("PATH");
292
            fail("removeVariable() does not throw exception");
293
        } catch (UnsupportedOperationException ex) {
294
            // expected
295
        }
296
297
        try {
298
            builder.getEnvironment().values();
299
            fail("values() does not throw exception");
300
        } catch (UnsupportedOperationException ex) {
301
            // expected
302
        }
303
    }
304
305
    public void testFallbackEnvironmentCombined() throws IOException {
306
        TestProcessBuilder testBuilder = new TestProcessBuilder();
307
        ProcessBuilder builder = ProcessBuilderFactory.createProcessBuilder(testBuilder, "Test builder");
308
        builder.setExecutable("ls");
309
310
        builder.getEnvironment().setVariable("key1", "value1");
311
        builder.getEnvironment().setVariable("key2", "value2");
312
313
        builder.call();
314
        assertEquals(2, testBuilder.getEnvironment().size());
315
        assertEquals("value1", testBuilder.getEnvironment().get("key1"));
316
        assertEquals("value2", testBuilder.getEnvironment().get("key2"));
317
318
        builder.setEnvironmentVariables(Collections.singletonMap("key3", "value3"));
319
320
        builder.call();
321
        assertEquals(1, testBuilder.getEnvironment().size());
322
        assertEquals("value3", testBuilder.getEnvironment().get("key3"));
323
324
        builder.getEnvironment().prependPath("PATH", "/test1");
325
        builder.getEnvironment().prependPath("Path", "/test2");
326
327
        builder.call();
328
        assertEquals(2, testBuilder.getPaths().size());
329
        assertEquals("/test2", testBuilder.getPaths().get(0));
330
        assertEquals("/test1", testBuilder.getPaths().get(1));
331
332
        builder.setPaths(Collections.singletonList("/test3"));
333
334
        builder.call();
335
        assertEquals(1, testBuilder.getPaths().size());
336
        assertEquals("/test3", testBuilder.getPaths().get(0));
337
    }
338
204
    public void testRedirectErrorStream() throws IOException {
339
    public void testRedirectErrorStream() throws IOException {
205
        TestProcessBuilder testBuilder = new TestProcessBuilder();
340
        TestProcessBuilder testBuilder = new TestProcessBuilder();
206
        ProcessBuilder builder = ProcessBuilderFactory.createProcessBuilder(testBuilder, "Test builder");
341
        ProcessBuilder builder = ProcessBuilderFactory.createProcessBuilder(testBuilder, "Test builder");
Lines 216-222 Link Here
216
        assertTrue(testBuilder.isRedirectErrorStream());
351
        assertTrue(testBuilder.isRedirectErrorStream());
217
    }
352
    }
218
353
219
    private class TestProcessBuilder implements ProcessBuilderImplementation {
354
    private static class TestProcessBuilder implements ProcessBuilderImplementation {
220
355
221
        private String executable;
356
        private String executable;
222
357
Lines 267-272 Link Here
267
        public String getWorkingDirectory() {
402
        public String getWorkingDirectory() {
268
            return workingDirectory;
403
            return workingDirectory;
269
        }
404
        }
405
    }
270
406
407
    private static class TestProcessBuilder2 implements ProcessBuilderImplementation2 {
408
409
        private final Environment environment = EnvironmentFactory.createEnvironment(new TestEnvironment());
410
411
        private ProcessParameters parameters;
412
413
        @Override
414
        public Environment getEnvironment() {
415
            return environment;
416
        }
417
418
        @Override
419
        public Lookup getLookup() {
420
            return Lookup.EMPTY;
421
        }
422
423
        @Override
424
        public Process createProcess(ProcessParameters parameters) throws IOException {
425
            this.parameters = parameters;
426
427
            return null;
428
        }
429
430
        public ProcessParameters getParameters() {
431
            return parameters;
432
        }
433
    }
434
435
    private static class TestEnvironment implements EnvironmentImplementation {
436
437
        private final Map<String, String> values = new HashMap<String, String>();
438
439
        @Override
440
        public String getVariable(String name) {
441
            return values.get(name);
442
        }
443
444
        @Override
445
        public void appendPath(String name, String value) {
446
            String orig = values.get(name);
447
            if (orig == null || orig.isEmpty()) {
448
                values.put(name, value);
449
            } else {
450
                // intentionally hardcoded for tests
451
                values.put(name, orig + ":" + value);
452
            }
453
        }
454
455
        @Override
456
        public void prependPath(String name, String value) {
457
            String orig = values.get(name);
458
            if (orig == null || orig.isEmpty()) {
459
                values.put(name, value);
460
            } else {
461
                // intentionally hardcoded for tests
462
                values.put(name, value + ":" + orig);
463
            }
464
        }
465
466
        @Override
467
        public void setVariable(String name, String value) {
468
            values.put(name, value);
469
        }
470
471
        @Override
472
        public void removeVariable(String name) {
473
            values.remove(name);
474
        }
475
476
        @Override
477
        public Map<String, String> values() {
478
            return new HashMap<String, String>(values);
479
        }
271
    }
480
    }
272
}
481
}
(-)a/extexecution/test/unit/src/org/netbeans/api/extexecution/input/InputReadersReaderTest.java (+19 lines)
Lines 47-52 Link Here
47
import java.io.IOException;
47
import java.io.IOException;
48
import java.io.InputStreamReader;
48
import java.io.InputStreamReader;
49
import java.io.Reader;
49
import java.io.Reader;
50
import java.io.StringReader;
50
import java.nio.charset.Charset;
51
import java.nio.charset.Charset;
51
import java.util.Arrays;
52
import java.util.Arrays;
52
import org.netbeans.junit.NbTestCase;
53
import org.netbeans.junit.NbTestCase;
Lines 85-88 Link Here
85
86
86
        assertTrue(Arrays.equals(TEST_CHARS, processor.getCharsProcessed()));
87
        assertTrue(Arrays.equals(TEST_CHARS, processor.getCharsProcessed()));
87
    }
88
    }
89
90
    public void testReadStringReader() throws IOException {
91
        Reader reader = new StringReader(new String(TEST_CHARS));
92
        InputReader inputReader = InputReaders.forReader(reader);
93
        TestInputProcessor processor = new TestInputProcessor(false);
94
95
        int read = 0;
96
        int retries = 0;
97
        while (read < TEST_CHARS.length && retries < MAX_RETRIES) {
98
            read += inputReader.readInput(processor);
99
            retries++;
100
        }
101
102
        assertEquals(read, TEST_CHARS.length);
103
        assertEquals(0, processor.getResetCount());
104
105
        assertTrue(Arrays.equals(TEST_CHARS, processor.getCharsProcessed()));
106
    }
88
}
107
}
(-)a/extexecution/test/unit/src/org/netbeans/api/extexecution/process/ProcessCharsetTest.java (+91 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2013 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 2013 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.api.extexecution.process;
43
44
import java.nio.charset.Charset;
45
import org.netbeans.junit.NbTestCase;
46
import org.openide.util.Lookup;
47
import org.openide.util.lookup.Lookups;
48
49
/**
50
 *
51
 * @author Petr Hejl
52
 */
53
public class ProcessCharsetTest extends NbTestCase {
54
55
    public ProcessCharsetTest(String name) {
56
        super(name);
57
    }
58
59
    public void testProcessCharset() {
60
        assertFalse(ProcessCharset.isSupported(new TestProcess(Lookup.EMPTY)));
61
62
        assertNull(ProcessCharset.getOutputCharset(new TestProcess(Lookup.EMPTY)));
63
        assertNull(ProcessCharset.getInputCharset(new TestProcess(Lookup.EMPTY)));
64
        assertNull(ProcessCharset.getErrorCharset(new TestProcess(Lookup.EMPTY)));
65
66
        TestProcessCharset charset = new TestProcessCharset();
67
        TestProcess process = new TestProcess(Lookups.fixed(charset));
68
        assertTrue(ProcessCharset.isSupported(process));
69
        assertEquals(charset.getOutputCharset(), ProcessCharset.getOutputCharset(process));
70
        assertEquals(charset.getInputCharset(), ProcessCharset.getInputCharset(process));
71
        assertEquals(charset.getErrorCharset(), ProcessCharset.getErrorCharset(process));
72
    }
73
74
    private static class TestProcessCharset extends ProcessCharset {
75
76
        @Override
77
        protected Charset getInputCharset() {
78
            return Charset.forName("US-ASCII");
79
        }
80
81
        @Override
82
        protected Charset getOutputCharset() {
83
            return Charset.forName("ISO-8859-1");
84
        }
85
86
        @Override
87
        protected Charset getErrorCharset() {
88
            return Charset.forName("UTF-8");
89
        }
90
    }
91
}
(-)a/extexecution/test/unit/src/org/netbeans/api/extexecution/process/ProcessIdTest.java (+76 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2013 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 2013 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.api.extexecution.process;
43
44
import org.netbeans.junit.NbTestCase;
45
import org.openide.util.Lookup;
46
import org.openide.util.lookup.Lookups;
47
48
/**
49
 *
50
 * @author Petr Hejl
51
 */
52
public class ProcessIdTest extends NbTestCase {
53
54
    public ProcessIdTest(String name) {
55
        super(name);
56
    }
57
58
    public void testProcessId() {
59
        assertFalse(ProcessId.isSupported(new TestProcess(Lookup.EMPTY)));
60
61
        assertNull(ProcessId.getId(new TestProcess(Lookup.EMPTY)));
62
        
63
        TestProcessId id = new TestProcessId();
64
        TestProcess process = new TestProcess(Lookups.fixed(id));
65
        assertTrue(ProcessId.isSupported(process));
66
        assertEquals(id.getId(), ProcessId.getId(process));
67
    }
68
69
    private static class TestProcessId extends ProcessId {
70
71
        @Override
72
        protected Integer getId() {
73
            return 1;
74
        }
75
    }
76
}
(-)a/extexecution/test/unit/src/org/netbeans/api/extexecution/process/ProcessSignalTest.java (+116 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2013 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 2013 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.api.extexecution.process;
43
44
import java.io.IOException;
45
import org.netbeans.junit.NbTestCase;
46
import org.openide.util.Lookup;
47
import org.openide.util.lookup.Lookups;
48
49
/**
50
 *
51
 * @author Petr Hejl
52
 */
53
public class ProcessSignalTest extends NbTestCase {
54
55
    public ProcessSignalTest(String name) {
56
        super(name);
57
    }
58
59
    public void testProcessSignal() throws IOException {
60
        assertFalse(ProcessSignal.isSupported(new TestProcess(Lookup.EMPTY)));
61
62
        TestProcessSignal signal = new TestProcessSignal();
63
        TestProcess process = new TestProcess(Lookups.fixed(signal));
64
        assertTrue(ProcessSignal.isSupported(process));
65
66
        ProcessSignal.signal(process, ProcessSignal.Signal.SIGALRM);
67
        ProcessSignal.signalGroup(process, ProcessSignal.Signal.SIGCANCEL);
68
69
        assertEquals(ProcessSignal.Signal.SIGALRM, signal.getSignal());
70
        assertEquals(ProcessSignal.Signal.SIGCANCEL, signal.getGroupSignal());
71
72
        try {
73
            ProcessSignal.signal(process, ProcessSignal.Signal.NULL);
74
            fail("No exception propagated");
75
        } catch (IOException ex) {
76
            // expected
77
        }
78
        try {
79
            ProcessSignal.signalGroup(process, ProcessSignal.Signal.NULL);
80
            fail("No exception propagated");
81
        } catch (IOException ex) {
82
            // expected
83
        }
84
    }
85
86
    private static class TestProcessSignal extends ProcessSignal {
87
88
        private Signal signal;
89
90
        private Signal groupSignal;
91
92
        @Override
93
        protected void signal(Signal signal) throws IOException {
94
            if (this.signal != null) {
95
                throw new IOException("Test");
96
            }
97
            this.signal = signal;
98
        }
99
100
        @Override
101
        protected void signalGroup(Signal signal) throws IOException {
102
            if (this.groupSignal != null) {
103
                throw new IOException("Test");
104
            }
105
            this.groupSignal = signal;
106
        }
107
108
        public Signal getSignal() {
109
            return signal;
110
        }
111
112
        public Signal getGroupSignal() {
113
            return groupSignal;
114
        }
115
    }
116
}
(-)a/extexecution/test/unit/src/org/netbeans/api/extexecution/process/TestProcess.java (+94 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2013 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 2013 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.api.extexecution.process;
43
44
import java.io.InputStream;
45
import java.io.OutputStream;
46
import org.openide.util.Lookup;
47
48
/**
49
 *
50
 * @author Petr Hejl
51
 */
52
public class TestProcess extends Process implements Lookup.Provider {
53
54
    private final Lookup lookup;
55
56
    public TestProcess(Lookup lookup) {
57
        this.lookup = lookup;
58
    }
59
60
    @Override
61
    public Lookup getLookup() {
62
        return lookup;
63
    }
64
65
    @Override
66
    public OutputStream getOutputStream() {
67
        throw new UnsupportedOperationException("Not supported yet.");
68
    }
69
70
    @Override
71
    public InputStream getInputStream() {
72
        throw new UnsupportedOperationException("Not supported yet.");
73
    }
74
75
    @Override
76
    public InputStream getErrorStream() {
77
        throw new UnsupportedOperationException("Not supported yet.");
78
    }
79
80
    @Override
81
    public int waitFor() throws InterruptedException {
82
        throw new UnsupportedOperationException("Not supported yet.");
83
    }
84
85
    @Override
86
    public int exitValue() {
87
        throw new UnsupportedOperationException("Not supported yet.");
88
    }
89
90
    @Override
91
    public void destroy() {
92
        throw new UnsupportedOperationException("Not supported yet.");
93
    }
94
}
(-)a/extexecution/test/unit/src/org/netbeans/spi/extexecution/ProcessParametersTest.java (+79 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2013 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 2013 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.spi.extexecution;
43
44
import java.util.Collections;
45
import java.util.HashMap;
46
import java.util.Map;
47
import org.netbeans.junit.NbTestCase;
48
import org.netbeans.modules.extexecution.ProcessParametersAccessor;
49
50
/**
51
 *
52
 * @author Petr Hejl
53
 */
54
public class ProcessParametersTest extends NbTestCase {
55
56
    public ProcessParametersTest(String name) {
57
        super(name);
58
    }
59
60
    public void testParameters() {
61
        Map<String, String> variables = new HashMap<String, String>();
62
        variables.put("key1", "value1");
63
        variables.put("key2", "value2");
64
65
        ProcessParameters params = ProcessParametersAccessor.getDefault().createProcessParameters(
66
                "ls", "/home", Collections.singletonList("argument"), true, variables);
67
68
        assertEquals("ls", params.getExecutable());
69
        assertEquals("/home", params.getWorkingDirectory());
70
        assertTrue(params.isRedirectErrorStream());
71
72
        assertEquals(1, params.getArguments().size());
73
        assertEquals("argument", params.getArguments().get(0));
74
75
        assertEquals(2, params.getEnvironmentVariables().size());
76
        assertEquals("value1", params.getEnvironmentVariables().get("key1"));
77
        assertEquals("value2", params.getEnvironmentVariables().get("key2"));
78
    }
79
}

Return to bug 232434