View | Details | Raw Unified | Return to bug 244308 | Differences between
and this patch

Collapse All | Expand All

(-)a/extexecution.base/apichanges.xml (+166 lines)
Line 0    Link Here 
1
<?xml version="1.0" encoding="UTF-8"?>
2
<!-- Search for CHANGEME in this document when copying and using it: -->
3
<!--
4
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
5
6
Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
7
8
Oracle and Java are registered trademarks of Oracle and/or its affiliates.
9
Other names may be trademarks of their respective owners.
10
11
12
The contents of this file are subject to the terms of either the GNU
13
General Public License Version 2 only ("GPL") or the Common
14
Development and Distribution License("CDDL") (collectively, the
15
"License"). You may not use this file except in compliance with the
16
License. You can obtain a copy of the License at
17
http://www.netbeans.org/cddl-gplv2.html
18
or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
19
specific language governing permissions and limitations under the
20
License.  When distributing the software, include this License Header
21
Notice in each file and include the License file at
22
nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
23
particular file as subject to the "Classpath" exception as provided
24
by Oracle in the GPL Version 2 section of the License file that
25
accompanied this code. If applicable, add the following below the
26
License Header, with the fields enclosed by brackets [] replaced by
27
your own identifying information:
28
"Portions Copyrighted [year] [name of copyright owner]"
29
30
Contributor(s):
31
32
The Original Software is NetBeans. The Initial Developer of the Original
33
Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
34
Microsystems, Inc. All Rights Reserved.
35
36
If you wish your version of this file to be governed by only the CDDL
37
or only the GPL Version 2, indicate your decision by adding
38
"[Contributor] elects to include this software in this distribution
39
under the [CDDL or GPL Version 2] license." If you do not indicate a
40
single choice of license, a recipient has the option to distribute
41
your version of this file under either the CDDL, the GPL Version 2 or
42
to extend the choice of license to its licensees as provided above.
43
However, if you add GPL Version 2 code and therefore, elected the GPL
44
Version 2 license, then the option applies only if the new code is
45
made subject to such option by the copyright holder.
46
-->
47
<?xml-stylesheet type="text/xml" href="CHANGEME/nbbuild/javadoctools/apichanges.xsl"?>
48
<!DOCTYPE apichanges PUBLIC "-//NetBeans//DTD API changes list 1.0//EN" "../nbbuild/javadoctools/apichanges.dtd">
49
50
<!--
51
52
INFO FOR PEOPLE ADDING CHANGES:
53
54
Check the DTD (apichanges.dtd) for details on the syntax. You do not
55
need to regenerate the HTML, as this is part of Javadoc generation; just
56
change the XML. Rough syntax of a change (several parts optional):
57
58
<change>
59
    <api name="compiler"/>
60
    <summary>Some brief description here, can use <b>XHTML</b></summary>
61
    <version major="1" minor="99"/>
62
    <date day="13" month="6" year="2001"/>
63
    <author login="jrhacker"/>
64
    <compatibility addition="yes"/>
65
    <description>
66
        The main description of the change here.
67
        Again can use full <b>XHTML</b> as needed.
68
    </description>
69
    <class package="org.openide.compiler" name="DoWhatIWantCompiler"/>
70
    <issue number="14309"/>
71
</change>
72
73
Also permitted elements: <package>, <branch>. <version> is API spec
74
version, recommended for all new changes. <compatibility> should say
75
if things were added/modified/deprecated/etc. and give all information
76
related to upgrading old code. List affected top-level classes and
77
link to issue numbers if applicable. See the DTD for more details.
78
79
Changes need not be in any particular order, they are sorted in various
80
ways by the stylesheet anyway.
81
82
Dates are assumed to mean "on the trunk". If you *also* make the same
83
change on a stabilization branch, use the <branch> tag to indicate this
84
and explain why the change was made on a branch in the <description>.
85
86
Please only change this file on the trunk! Rather: you can change it
87
on branches if you want, but these changes will be ignored; only the
88
trunk version of this file is important.
89
90
Deprecations do not count as incompatible, assuming that code using the
91
deprecated calls continues to see their documented behavior. But do
92
specify deprecation="yes" in <compatibility>.
93
94
This file is not a replacement for Javadoc: it is intended to list changes,
95
not describe the complete current behavior, for which ordinary documentation
96
is the proper place.
97
98
-->
99
100
<apichanges>
101
102
    <!-- First, a list of API names you may use: -->
103
    <apidefs>
104
        <apidef name="extexecution_base_api">External Execution Base API</apidef>
105
        <apidef name="extexecution_base_api_input">External Execution Base Input API</apidef>
106
        <apidef name="extexecution_base_spi">External Execution Base SPI</apidef>
107
        <!-- etc. -->
108
    </apidefs>
109
110
    <!-- ACTUAL CHANGES BEGIN HERE: -->
111
112
    <changes>
113
114
        <change>
115
            <api name="extexecution_base_api"/>
116
            <summary>Initial version released</summary>
117
            <version major="1" minor="0"/>
118
            <date day="1" month="6" year="2014"/>
119
            <author login="phejl"/>
120
            <compatibility addition="yes"/>
121
            <description>
122
                First initial release of the External Execution Base API.
123
                Refactored from External Execution API.
124
            </description>
125
            <issue number="244308"/>
126
        </change>
127
    </changes>
128
129
    <!-- Now the surrounding HTML text and document structure: -->
130
131
    <htmlcontents>
132
<!--
133
134
                            NO NO NO NO NO!
135
136
         ==============>    DO NOT EDIT ME!  <==============
137
138
          AUTOMATICALLY GENERATED FROM APICHANGES.XML, DO NOT EDIT
139
140
                SEE CHANGEME/apichanges.xml
141
142
-->
143
    <head>
144
      <title>Change History for the External Execution Base API</title>
145
      <link rel="stylesheet" href="prose.css" type="text/css"/>
146
    </head>
147
    <body>
148
149
<p class="overviewlink"><a href="overview-summary.html">Overview</a></p>
150
151
<h1>Introduction</h1>
152
153
<p>This document lists changes made to the External Execution Base API.</p>
154
155
<!-- The actual lists of changes, as summaries and details: -->
156
157
      <hr/>
158
      
159
      <standard-changelists module-code-name="org.netbeans.modules.extexecution.base"/>
160
161
      <hr/><p>@FOOTER@</p>
162
163
    </body>
164
  </htmlcontents>
165
166
</apichanges>
(-)a/extexecution.base/arch.xml (+1207 lines)
Line 0    Link Here 
1
<?xml version="1.0" encoding="UTF-8"?>
2
<!--
3
The contents of this file are subject to the terms of the Common Development
4
and Distribution License (the License). You may not use this file except in
5
compliance with the License.
6
7
You can obtain a copy of the License at http://www.netbeans.org/cddl.html
8
or http://www.netbeans.org/cddl.txt.
9
10
When distributing Covered Code, include this CDDL Header Notice in each file
11
and include the License file at http://www.netbeans.org/cddl.txt.
12
If applicable, add the following below the CDDL Header, with the fields
13
enclosed by brackets [] replaced by your own identifying information:
14
"Portions Copyrighted [year] [name of copyright owner]"
15
16
The Original Software is NetBeans. The Initial Developer of the Original
17
Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
18
Microsystems, Inc. All Rights Reserved.
19
-->
20
<!DOCTYPE api-answers PUBLIC "-//NetBeans//DTD Arch Answers//EN" "../nbbuild/antsrc/org/netbeans/nbbuild/Arch.dtd" [
21
  <!ENTITY api-questions SYSTEM "../nbbuild/antsrc/org/netbeans/nbbuild/Arch-api-questions.xml">
22
]>
23
24
<api-answers
25
  question-version="1.29"
26
  author="phejl@netbeans.org"
27
>
28
29
  &api-questions;
30
31
32
<!--
33
        <question id="arch-overall" when="init">
34
            Describe the overall architecture. 
35
            <hint>
36
            What will be API for 
37
            <a href="http://openide.netbeans.org/tutorial/api-design.html#design.apiandspi">
38
                clients and what support API</a>? 
39
            What parts will be pluggable?
40
            How will plug-ins be registered? Please use <code>&lt;api type="export"/&gt;</code>
41
            to describe your general APIs and specify their
42
            <a href="http://openide.netbeans.org/tutorial/api-design.html#category-private">
43
            stability categories</a>.
44
            If possible please provide simple diagrams.
45
            </hint>
46
        </question>
47
-->
48
 <answer id="arch-overall">
49
  <p>
50
   <i>This API origins in External Execution API and contains set of basic
51
   features with minimal dependencies.</i> For the better integration with
52
   the IDE check also original External Execution API.
53
  </p>
54
  <p>
55
   The External Execution Base module provides the
56
   <api group="java" name="ExternalExecutionBaseAPI" type="export" category="stable" url="@TOP@org/netbeans/api/extexecution/base/package-summary.html"/>
57
   that contains support for execution of external processes. There is also
58
   abstraction of process builder and support class for extended process handling.
59
  </p>
60
  <p>
61
   Another exported API
62
   <api group="java" name="ExternalExecutionBaseInputAPI" type="export" category="stable" url="@TOP@org/netbeans/api/extexecution/base/input/package-summary.html"/>
63
   define interfaces for input processing (character or line based) and provides
64
   common implementations of these with factory methods.
65
  </p>
66
  <p>
67
   The SPI
68
   <api group="java" name="ExternalExecutionBaseSPI" type="export" category="stable" url="@TOP@org/netbeans/spi/extexecution/base/package-summary.html"/>
69
   allows different implementations of process builder and defined interface
70
   for extended process handling support.
71
  </p>
72
 </answer>
73
74
75
76
<!--
77
        <question id="arch-quality" when="init">
78
            How will the <a href="http://www.netbeans.org/community/guidelines/q-evangelism.html">quality</a>
79
            of your code be tested and 
80
            how are future regressions going to be prevented?
81
            <hint>
82
            What kind of testing do
83
            you want to use? How much functionality, in which areas,
84
            should be covered by the tests? How you find out that your
85
            project was successful?
86
            </hint>
87
        </question>
88
-->
89
 <answer id="arch-quality">
90
  <p>
91
   Most of the API functionality is covered by unit tests. Same applies to
92
   future enhancements.
93
  </p>
94
 </answer>
95
96
97
98
<!--
99
        <question id="arch-time" when="init">
100
            What are the time estimates of the work?
101
            <hint>
102
            Please express your estimates of how long the design, implementation,
103
            stabilization are likely to last. How many people will be needed to
104
            implement this and what is the expected milestone by which the work should be 
105
            ready?
106
            </hint>
107
        </question>
108
-->
109
 <answer id="arch-time">
110
  <p>
111
   Written and functional. Compatible changes can occur in future.
112
  </p>
113
 </answer>
114
115
116
117
<!--
118
        <question id="arch-usecases" when="init">
119
            <hint>
120
                Content of this answer will be displayed as part of page at
121
                http://www.netbeans.org/download/dev/javadoc/usecases.html 
122
                You can use tags &lt;usecase name="name&gt; regular html description &lt;/usecase&gt;
123
                and if you want to use an URL you can prefix if with @TOP@ to begin
124
                at the root of your javadoc
125
            </hint>
126
        
127
            Describe the main <a href="http://openide.netbeans.org/tutorial/api-design.html#usecase">
128
            use cases</a> of the new API. Who will use it under
129
            what circumstances? What kind of code would typically need to be written
130
            to use the module?
131
        </question>
132
-->
133
 <answer id="arch-usecases">
134
  <usecase id="execute-process" name="Execution of an external process">
135
   <p>
136
    Client needs to execute an external process and handle process streams.
137
   </p>
138
   <p>
139
    In order to achieve this client creates the
140
    <a href="@TOP@org/netbeans/api/extexecution/base/BaseExecutionDescriptor.html">BaseExecutionDescriptor</a>.
141
    Via this object client configures all the client integration parameters of
142
    the execution. As a next step client creates the
143
    <a href="@TOP@org/netbeans/api/extexecution/base/BaseExecutionService.html">BaseExecutionService</a>
144
    itself and calls run to execute the job. Run can be called multiple times.
145
    The output and input streams are handled by the service. Additional
146
    processing can be configured in descriptor through interfaces described
147
    in following usecases.
148
   </p>
149
   <p>
150
    The creation of the external process is supported by
151
    <a href="@TOP@org/netbeans/api/extexecution/base/ProcessBuilder.html">ProcessBuilder</a>
152
    to make things easier.
153
   </p>
154
  </usecase>
155
  <usecase id="handle-input" name="Processing the input">
156
   <p>
157
    Client needs to process character data coming from stream, file or other
158
    source.
159
   </p>
160
   <p>
161
    To abstract the source of the data client must implement
162
    <a href="@TOP@org/netbeans/api/extexecution/base/input/InputReader.html">InputReader</a>.
163
    To abstract the data processing client must implement
164
    <a href="@TOP@org/netbeans/api/extexecution/base/input/InputProcessor.html">InputProcessor</a> or
165
    <a href="@TOP@org/netbeans/api/extexecution/base/input/LineProcessor.html">LineProcessor</a>.
166
    For all three interfaces there are prepared common implementations (and bridge
167
    from character based to line based processing) at these three factory classes:
168
   </p>
169
   <ul>
170
    <li><a href="@TOP@org/netbeans/api/extexecution/base/input/InputReaders.html">InputReaders</a></li>
171
    <li><a href="@TOP@org/netbeans/api/extexecution/base/input/InputProcessors.html">InputProcessors</a></li>
172
    <li><a href="@TOP@org/netbeans/api/extexecution/base/input/LineProcessors.html">LineProcessors</a></li>
173
   </ul>
174
   <p>
175
    Once the data source and processing objects are prepared client creates
176
    <a href="@TOP@org/netbeans/api/extexecution/base/input/InputReaderTask.html">InputReaderTask</a>.
177
    Factory methods of the <a href="@TOP@org/netbeans/api/extexecution/base/input/InputReaderTask.html">InputReaderTask</a>
178
    can create either common task exiting on interruption or cancellation
179
    or draining task which is trying to drain out all available data before exiting.
180
   </p>
181
  </usecase>
182
  <usecase id="process-builder" name="Custom process builder">
183
    <p>
184
      Third party wants to implement custom process builder to provide
185
      additional functionality, such as remote execution.
186
    </p>
187
    <p>
188
      In order to do so it will implement
189
      <a href="@TOP@org/netbeans/spi/extexecution/base/ProcessBuilderImplementation.html">
190
      ProcessBuilderImplementation</a> and pass
191
      <a href="@TOP@org/netbeans/api/extexecution/base/ProcessBuilder.html">
192
      ProcessBuilder</a> to its clients. The API instances are created with
193
      help of
194
      <a href="@TOP@org/netbeans/spi/extexecution/base/ProcessBuilderFactory.html">ProcessBuilderFactory</a>.
195
    </p>
196
  </usecase>
197
  <usecase id="destroy-process" name="Destroying a process">
198
    <p>
199
      Client wants to destroy the process, trying to kill whole process tree.
200
      Method
201
      <a href="@TOP@org/netbeans/api/extexecution/base/Processes.html#killTree(java.lang.Process,%20java.util.Map)">
202
      Processes.killTree(java.lang.Process process, Map&lt;String,String&gt; environment)</a>
203
      is designed for that. It will use a
204
      <a href="@TOP@org/netbeans/spi/extexecution/base/ProcessesImplementation.html">ProcessesImplementation</a>
205
      registered in default lookup to do so.
206
    </p>
207
  </usecase>
208
 </answer>
209
210
211
212
<!--
213
        <question id="arch-what" when="init">
214
            What is this project good for?
215
            <hint>
216
            Please provide here a few lines describing the project, 
217
            what problem it should solve, provide links to documentation, 
218
            specifications, etc.
219
            </hint>
220
        </question>
221
-->
222
 <answer id="arch-what">
223
  <p>
224
   Provides common APIs to execute external process and to handle its
225
   streams and process the output. Input/line processing can be used
226
   as separate part.
227
  </p>
228
 </answer>
229
230
231
232
<!--
233
        <question id="arch-where" when="impl">
234
            Where one can find sources for your module?
235
            <hint>
236
                Please provide link to the Hg web client at
237
                http://hg.netbeans.org/
238
                or just use tag defaultanswer generate='here'
239
            </hint>
240
        </question>
241
-->
242
 <answer id="arch-where">
243
  <defaultanswer generate='here' />
244
 </answer>
245
246
247
248
<!--
249
        <question id="compat-deprecation" when="init">
250
            How the introduction of your project influences functionality
251
            provided by previous version of the product?
252
            <hint>
253
            If you are planning to deprecate/remove/change any existing APIs,
254
            list them here accompanied with the reason explaining why you
255
            are doing so.
256
            </hint>
257
        </question>
258
-->
259
 <answer id="compat-deprecation">
260
  <p>
261
   The module languages.execution should be removed as it provides not well
262
   stabilized subset of the same functionality.
263
  </p>
264
 </answer>
265
266
267
268
<!--
269
        <question id="compat-i18n" when="impl">
270
            Is your module correctly internationalized?
271
            <hint>
272
            Correct internationalization means that it obeys instructions 
273
            at <a href="http://www.netbeans.org/download/dev/javadoc/org-openide-modules/org/openide/modules/doc-files/i18n-branding.html">
274
            NetBeans I18N pages</a>.
275
            </hint>
276
        </question>
277
-->
278
 <answer id="compat-i18n">
279
  <p>
280
   Yes.
281
  </p>
282
 </answer>
283
284
285
286
<!--
287
        <question id="compat-standards" when="init">
288
            Does the module implement or define any standards? Is the 
289
            implementation exact or does it deviate somehow?
290
        </question>
291
-->
292
 <answer id="compat-standards">
293
  <p>
294
   No.
295
  </p>
296
 </answer>
297
298
299
300
<!--
301
        <question id="compat-version" when="impl">
302
            Can your module coexist with earlier and future
303
            versions of itself? Can you correctly read all old settings? Will future
304
            versions be able to read your current settings? Can you read
305
            or politely ignore settings stored by a future version?
306
            
307
            <hint>
308
            Very helpful for reading settings is to store version number
309
            there, so future versions can decide whether how to read/convert
310
            the settings and older versions can ignore the new ones.
311
            </hint>
312
        </question>
313
-->
314
 <answer id="compat-version">
315
  <p>
316
   Yes. No settings stored.
317
  </p>
318
 </answer>
319
320
321
322
<!--
323
        <question id="dep-jre" when="final">
324
            Which version of JRE do you need (1.2, 1.3, 1.4, etc.)?
325
            <hint>
326
            It is expected that if your module runs on 1.x that it will run 
327
            on 1.x+1 if no, state that please. Also describe here cases where
328
            you run different code on different versions of JRE and why.
329
            </hint>
330
        </question>
331
-->
332
 <answer id="dep-jre">
333
  <p>
334
   1.5
335
  </p>
336
 </answer>
337
338
339
340
<!--
341
        <question id="dep-jrejdk" when="final">
342
            Do you require the JDK or is the JRE enough?
343
        </question>
344
-->
345
 <answer id="dep-jrejdk">
346
  <p>
347
   JRE is enough.
348
  </p>
349
 </answer>
350
351
352
353
<!--
354
        <question id="dep-nb" when="init">
355
            What other NetBeans projects and modules does this one depend on?
356
            <hint>
357
            Depending on other NetBeans projects influnces the ability of
358
            users of your work to customize their own branded version of
359
            NetBeans by enabling and disabling some modules. Too
360
            much dependencies restrict this kind of customization. If that
361
            is your case, then you may want to split your functionality into
362
            pieces of autoload, eager and regular modules which can be
363
            enabled independently. Usually the answer to this question
364
            is generated from your <code>project.xml</code> file, but
365
            if it is not guessed correctly, you can suppress it by
366
            specifying &lt;defaultanswer generate="none"/&gt; and
367
            write here your own. Please describe such projects as imported APIs using
368
            the <code>&lt;api name="identification" type="import or export" category="stable" url="where is the description" /&gt;</code>.
369
            By doing this information gets listed in the summary page of your
370
            javadoc.
371
            </hint>
372
        </question>
373
-->
374
 <answer id="dep-nb">
375
  <defaultanswer generate='here' />
376
 </answer>
377
378
379
380
<!--
381
        <question id="dep-non-nb" when="init">
382
            What other projects outside NetBeans does this one depend on?
383
            
384
            <hint>
385
            Depending on 3rd party libraries is always problematic,
386
            especially if they are not open source, as that complicates
387
            the licensing scheme of NetBeans. Please enumerate your
388
            external dependencies here, so it is correctly understood since
389
            the begining what are the legal implications of your project.
390
            Also please note that
391
            some non-NetBeans projects are packaged as NetBeans modules
392
            (see <a href="http://libs.netbeans.org/">libraries</a>) and
393
            it is preferred to use this approach when more modules may
394
            depend and share such third-party libraries.
395
            </hint>
396
        </question>
397
-->
398
 <answer id="dep-non-nb">
399
  <p>
400
   None.
401
  </p>
402
 </answer>
403
404
405
406
<!--
407
        <question id="dep-platform" when="init">
408
            On which platforms does your module run? Does it run in the same
409
            way on each?
410
            <hint>
411
            If you plan any dependency on OS or any usage of native code,
412
            please describe why you are doing so and describe how you envision
413
            to enforce the portability of your code.
414
            Please note that there is a support for <a href="http://www.netbeans.org/download/dev/javadoc/org-openide-modules/org/openide/modules/doc-files/api.html#how-os-specific">OS conditionally
415
            enabled modules</a> which together with autoload/eager modules
416
            can allow you to enable to provide the best OS aware support
417
            on certain OSes while providing compatibility bridge on the not
418
            supported ones.
419
            Also please list the supported
420
            OSes/HW platforms and mentioned the lovest version of JDK required
421
            for your project to run on. Also state whether JRE is enough or
422
            you really need JDK.
423
            </hint>
424
        </question>
425
-->
426
 <answer id="dep-platform">
427
  <p>
428
   No known platform dependencies.
429
  </p>
430
 </answer>
431
432
433
434
<!--
435
        <question id="deploy-dependencies" when="final">
436
            What do other modules need to do to declare a dependency on this one,
437
            in addition to or instead of the normal module dependency declaration
438
            (e.g. tokens to require)?
439
            <hint>
440
                Provide a sample of the actual lines you would add to a module manifest
441
                to declare a dependency, for example OpenIDE-Module-Requires: some.token.
442
                If other modules should not depend on this module, or should just use a
443
                simple regular module dependency, you can just answer "nothing". If you
444
                intentionally expose a semistable API to clients using implementation
445
                dependencies, you should mention that here (but there is no need to give
446
                an example of usage).
447
            </hint>
448
        </question>
449
-->
450
 <answer id="deploy-dependencies">
451
  <p>
452
   Nothing.
453
  </p>
454
 </answer>
455
456
457
458
<!--
459
        <question id="deploy-jar" when="impl">
460
            Do you deploy just module JAR file(s) or other files as well?
461
            <hint>
462
            Usually a module consist of one JAR file (perhaps with Class-Path
463
            extensions) and also a configuration file that enables it. If you
464
            have any other files, use
465
            &lt;api group="java.io.File" name="yourname" type="export" category="friend"&gt;...&lt;/api&gt;
466
            to define the location, name and stability of your files (of course
467
            changing "yourname" and "friend" to suit your needs).
468
            
469
            If it uses more than one JAR, describe where they are located, how
470
            they refer to each other. 
471
            If it consist of module JAR(s) and other files, please describe
472
            what is their purpose, why other files are necessary. Please 
473
            make sure that installation/uninstallation leaves the system 
474
            in state as it was before installation.
475
            </hint>
476
        </question>
477
-->
478
 <answer id="deploy-jar">
479
  <p>
480
   Just the single JAR file.
481
  </p>
482
 </answer>
483
484
485
486
<!--
487
        <question id="deploy-nbm" when="impl">
488
            Can you deploy an NBM via the Update Center?
489
            <hint>
490
            If not why?
491
            </hint>
492
        </question>
493
-->
494
 <answer id="deploy-nbm">
495
  <p>
496
   Yes.
497
  </p>
498
 </answer>
499
500
501
502
<!--
503
        <question id="deploy-packages" when="init">
504
            Are packages of your module made inaccessible by not declaring them
505
            public?
506
            
507
            <hint>
508
            By default NetBeans build harness treats all packages are private.
509
            If you export some of them - either as public or friend packages,
510
            you should have a reason. If the reason is described elsewhere
511
            in this document, you can ignore this question.
512
            </hint>
513
        </question>
514
-->
515
 <answer id="deploy-packages">
516
  <p>
517
   Only API packages are exported.
518
  </p>
519
 </answer>
520
521
522
523
<!--
524
        <question id="deploy-shared" when="final">
525
            Do you need to be installed in the shared location only, or in the user directory only,
526
            or can your module be installed anywhere?
527
            <hint>
528
            Installation location shall not matter, if it does explain why.
529
            Consider also whether <code>InstalledFileLocator</code> can help.
530
            </hint>
531
        </question>
532
-->
533
 <answer id="deploy-shared">
534
  <p>
535
   Anywhere.
536
  </p>
537
 </answer>
538
539
540
541
<!--
542
        <question id="exec-ant-tasks" when="impl">
543
            Do you define or register any ant tasks that other can use?
544
            
545
            <hint>
546
            If you provide an ant task that users can use, you need to be very
547
            careful about its syntax and behaviour, as it most likely forms an
548
	          API for end users and as there is a lot of end users, their reaction
549
            when such API gets broken can be pretty strong.
550
            </hint>
551
        </question>
552
-->
553
 <answer id="exec-ant-tasks">
554
  <p>
555
   No.
556
  </p>
557
 </answer>
558
559
560
561
<!--
562
        <question id="exec-classloader" when="impl">
563
            Does your code create its own class loader(s)?
564
            <hint>
565
            A bit unusual. Please explain why and what for.
566
            </hint>
567
        </question>
568
-->
569
 <answer id="exec-classloader">
570
  <p>
571
   No.
572
  </p>
573
 </answer>
574
575
576
577
<!--
578
        <question id="exec-component" when="impl">
579
            Is execution of your code influenced by any (string) property
580
            of any of your components?
581
            
582
            <hint>
583
            Often <code>JComponent.getClientProperty</code>, <code>Action.getValue</code>
584
            or <code>PropertyDescriptor.getValue</code>, etc. are used to influence
585
            a behavior of some code. This of course forms an interface that should
586
            be documented. Also if one depends on some interface that an object
587
            implements (<code>component instanceof Runnable</code>) that forms an
588
            API as well.
589
            </hint>
590
        </question>
591
-->
592
 <answer id="exec-component">
593
  <p>
594
   No.
595
  </p>
596
 </answer>
597
598
599
600
<!--
601
        <question id="exec-introspection" when="impl">
602
            Does your module use any kind of runtime type information (<code>instanceof</code>,
603
            work with <code>java.lang.Class</code>, etc.)?
604
            <hint>
605
            Check for cases when you have an object of type A and you also
606
            expect it to (possibly) be of type B and do some special action. That
607
            should be documented. The same applies on operations in meta-level
608
            (Class.isInstance(...), Class.isAssignableFrom(...), etc.).
609
            </hint>
610
        </question>
611
-->
612
 <answer id="exec-introspection">
613
  <p>
614
   No.
615
  </p>
616
 </answer>
617
618
619
620
<!--
621
        <question id="exec-privateaccess" when="final">
622
            Are you aware of any other parts of the system calling some of 
623
            your methods by reflection?
624
            <hint>
625
            If so, describe the "contract" as an API. Likely private or friend one, but
626
            still API and consider rewrite of it.
627
            </hint>
628
        </question>
629
-->
630
 <answer id="exec-privateaccess">
631
  <p>
632
   No.
633
  </p>
634
 </answer>
635
636
637
638
<!--
639
        <question id="exec-process" when="impl">
640
            Do you execute an external process from your module? How do you ensure
641
            that the result is the same on different platforms? Do you parse output?
642
            Do you depend on result code?
643
            <hint>
644
            If you feed an input, parse the output please declare that as an API.
645
            </hint>
646
        </question>
647
-->
648
 <answer id="exec-process">
649
  <p>
650
   Yes. The API provides support to do so. The result code, input and
651
   output stream content does not define API as this is forwarded to the client
652
   of this module.
653
  </p>
654
 </answer>
655
656
657
658
<!--
659
        <question id="exec-property" when="impl">
660
            Is execution of your code influenced by any environment or
661
            Java system (<code>System.getProperty</code>) property?
662
            On a similar note, is there something interesting that you
663
            pass to <code>java.util.logging.Logger</code>? Or do you observe
664
            what others log?
665
            <hint>
666
            If there is a property that can change the behavior of your 
667
            code, somebody will likely use it. You should describe what it does 
668
            and the <a href="http://openide.netbeans.org/tutorial/api-design.html#life">stability category</a>
669
            of this API. You may use
670
            <pre>
671
                &lt;api type="export" group="property" name="id" category="private" url="http://..."&gt;
672
                    description of the property, where it is used, what it influence, etc.
673
                &lt;/api&gt;            
674
            </pre>
675
            </hint>
676
        </question>
677
-->
678
 <answer id="exec-property">
679
  <p>
680
   No.
681
  </p>
682
 </answer>
683
684
685
686
<!--
687
        <question id="exec-reflection" when="impl">
688
            Does your code use Java Reflection to execute other code?
689
            <hint>
690
            This usually indicates a missing or insufficient API in the other
691
            part of the system. If the other side is not aware of your dependency
692
            this contract can be easily broken.
693
            </hint>
694
        </question>
695
-->
696
 <answer id="exec-reflection">
697
  <p>
698
   No.
699
  </p>
700
 </answer>
701
702
703
704
<!--
705
        <question id="exec-threading" when="init">
706
            What threading models, if any, does your module adhere to? How the
707
            project behaves with respect to threading?
708
            <hint>
709
                Is your API threadsafe? Can it be accessed from any threads or
710
                just from some dedicated ones? Any special relation to AWT and
711
                its Event Dispatch thread? Also
712
                if your module calls foreign APIs which have a specific threading model,
713
                indicate how you comply with the requirements for multithreaded access
714
                (synchronization, mutexes, etc.) applicable to those APIs.
715
                If your module defines any APIs, or has complex internal structures
716
                that might be used from multiple threads, declare how you protect
717
                data against concurrent access, race conditions, deadlocks, etc.,
718
                and whether such rules are enforced by runtime warnings, errors, assertions, etc.
719
                Examples: a class might be non-thread-safe (like Java Collections); might
720
                be fully thread-safe (internal locking); might require access through a mutex
721
                (and may or may not automatically acquire that mutex on behalf of a client method);
722
                might be able to run only in the event queue; etc.
723
                Also describe when any events are fired: synchronously, asynchronously, etc.
724
                Ideas: <a href="http://core.netbeans.org/proposals/threading/index.html#recommendations">Threading Recommendations</a> (in progress)
725
            </hint>
726
        </question>
727
-->
728
 <answer id="exec-threading">
729
  <p>
730
   Each class and factory method defines the thread safety of the class.
731
   If this is missing by accident method can be called from any thread.
732
  </p>
733
 </answer>
734
735
736
737
<!--
738
        <question id="format-clipboard" when="impl">
739
            Which data flavors (if any) does your code read from or insert to
740
            the clipboard (by access to clipboard on means calling methods on <code>java.awt.datatransfer.Transferable</code>?
741
            
742
            <hint>
743
            Often Node's deal with clipboard by usage of <code>Node.clipboardCopy, Node.clipboardCut and Node.pasteTypes</code>.
744
            Check your code for overriding these methods.
745
            </hint>
746
        </question>
747
-->
748
 <answer id="format-clipboard">
749
  <p>
750
   None.
751
  </p>
752
 </answer>
753
754
755
756
<!--
757
        <question id="format-dnd" when="impl">
758
            Which protocols (if any) does your code understand during Drag &amp; Drop?
759
            <hint>
760
            Often Node's deal with clipboard by usage of <code>Node.drag, Node.getDropType</code>. 
761
            Check your code for overriding these methods. Btw. if they are not overridden, they
762
            by default delegate to <code>Node.clipboardCopy, Node.clipboardCut and Node.pasteTypes</code>.
763
            </hint>
764
        </question>
765
-->
766
 <answer id="format-dnd">
767
  <p>
768
   None.
769
  </p>
770
 </answer>
771
772
773
774
<!--
775
        <question id="format-types" when="impl">
776
            Which protocols and file formats (if any) does your module read or write on disk,
777
            or transmit or receive over the network? Do you generate an ant build script?
778
            Can it be edited and modified? 
779
            
780
            <hint>
781
            <p>
782
            Files can be read and written by other programs, modules and users. If they influence
783
            your behaviour, make sure you either document the format or claim that it is a private
784
            api (using the &lt;api&gt; tag). 
785
            </p>
786
            
787
            <p>
788
            If you generate an ant build file, this is very likely going to be seen by end users and
789
            they will be attempted to edit it. You should be ready for that and provide here a link
790
            to documentation that you have for such purposes and also describe how you are going to
791
            understand such files during next release, when you (very likely) slightly change the 
792
            format.
793
            </p>
794
            </hint>
795
        </question>
796
-->
797
 <answer id="format-types">
798
  <p>
799
   None.
800
  </p>
801
 </answer>
802
803
804
805
<!--
806
        <question id="lookup-lookup" when="init">
807
            Does your module use <code>org.openide.util.Lookup</code>
808
            or any similar technology to find any components to communicate with? Which ones?
809
            
810
            <hint>
811
            NetBeans is build around a generic registry of services called
812
            lookup. It is preferable to use it for registration and discovery
813
            if possible. See
814
            <a href="http://www.netbeans.org/download/dev/javadoc/org-openide-util/org/openide/util/lookup/doc-files/index.html">
815
            The Solution to Comunication Between Components
816
            </a>. If you do not plan to use lookup and insist usage
817
            of other solution, then please describe why it is not working for
818
            you.
819
            <br/>
820
            When filling the final version of your arch document, please
821
            describe the interfaces you are searching for, where 
822
            are defined, whether you are searching for just one or more of them,
823
            if the order is important, etc. Also classify the stability of such
824
            API contract. Use &lt;api group=&amp;lookup&amp; /&gt; tag, so
825
            your information gets listed in the summary page of your javadoc.
826
            </hint>
827
        </question>
828
-->
829
 <answer id="lookup-lookup">
830
  <p>
831
   The class for extended process handling
832
   <a href="@TOP@org/netbeans/api/extexecution/base/Processes.html">Processes</a>
833
   is trying to lookup an implementation 
834
   <a href="@TOP@org/netbeans/spi/extexecution/base/ProcessesImplementation.html">ProcessesImplementation</a>
835
   in default lookup.
836
  </p>
837
 </answer>
838
839
840
841
<!--
842
        <question id="lookup-register" when="final">
843
            Do you register anything into lookup for other code to find?
844
            <hint>
845
            Do you register using layer file or using <code>META-INF/services</code>?
846
            Who is supposed to find your component?
847
            </hint>
848
        </question>
849
-->
850
 <answer id="lookup-register">
851
  <p>
852
   No.
853
  </p>
854
 </answer>
855
856
857
858
<!--
859
        <question id="lookup-remove" when="final">
860
            Do you remove entries of other modules from lookup?
861
            <hint>
862
            Why? Of course, that is possible, but it can be dangerous. Is the module
863
            your are masking resource from aware of what you are doing?
864
            </hint>
865
        </question>
866
-->
867
 <answer id="lookup-remove">
868
  <p>
869
   No.
870
  </p>
871
 </answer>
872
873
874
875
<!--
876
        <question id="perf-exit" when="final">
877
            Does your module run any code on exit?
878
        </question>
879
-->
880
 <answer id="perf-exit">
881
  <p>
882
   On JVM shutdown module tries to terminate any running process executed
883
   through the API.
884
  </p>
885
 </answer>
886
887
888
889
<!--
890
        <question id="perf-huge_dialogs" when="final">
891
            Does your module contain any dialogs or wizards with a large number of
892
            GUI controls such as combo boxes, lists, trees, or text areas?
893
        </question>
894
-->
895
 <answer id="perf-huge_dialogs">
896
  <p>
897
   No.
898
  </p>
899
 </answer>
900
901
902
903
<!--
904
        <question id="perf-limit" when="init">
905
            Are there any hard-coded or practical limits in the number or size of
906
            elements your code can handle?
907
            <hint>
908
                Most of algorithms have increasing memory and speed complexity
909
                with respect to size of data they operate on. What is the critical
910
                part of your project that can be seen as a bottleneck with
911
                respect to speed or required memory? What are the practical
912
                sizes of data you tested your project with? What is your estimate
913
                of potential size of data that would cause visible performance
914
                problems? Is there some kind of check to detect such situation
915
                and prevent "hard" crashes - for example the CloneableEditorSupport
916
                checks for size of a file to be opened in editor
917
                and if it is larger than 1Mb it shows a dialog giving the
918
                user the right to decide - e.g. to cancel or commit suicide.
919
            </hint>
920
        </question>
921
-->
922
 <answer id="perf-limit">
923
  <p>
924
   Any spawned process needs 4 threads (the worst case). One as the process
925
   handler, one for the standard input, one for the standard output and one for
926
   the standard error output. The minimal number of threads to handle a process
927
   is 2 (process handler and standard output handler - standard error output
928
   is redirected to the output, no thread for the standard input).
929
  </p>
930
  <p>
931
   Typically the client should not run more than 10 external processes
932
   concurrently.
933
  </p>
934
 </answer>
935
936
937
938
<!--
939
        <question id="perf-mem" when="final">
940
            How much memory does your component consume? Estimate
941
            with a relation to the number of windows, etc.
942
        </question>
943
-->
944
 <answer id="perf-mem">
945
  <p>
946
   The small amount of the memory is consumed by caching data structures like
947
   available output tabs and currently executed processes.
948
  </p>
949
 </answer>
950
951
952
953
<!--
954
        <question id="perf-menus" when="final">
955
            Does your module use dynamically updated context menus, or
956
            context-sensitive actions with complicated and slow enablement logic?
957
            <hint>
958
                If you do a lot of tricks when adding actions to regular or context menus, you can significantly
959
                slow down display of the menu, even when the user is not using your action. Pay attention to
960
                actions you add to the main menu bar, and to context menus of foreign nodes or components. If
961
                the action is conditionally enabled, or changes its display dynamically, you need to check the
962
                impact on performance. In some cases it may be more appropriate to make a simple action that is
963
                always enabled but does more detailed checks in a dialog if it is actually run.
964
            </hint>
965
        </question>
966
-->
967
 <answer id="perf-menus">
968
  <p>
969
   No.
970
  </p>
971
 </answer>
972
973
974
975
<!--
976
        <question id="perf-progress" when="final">
977
            Does your module execute any long-running tasks?
978
            
979
            <hint>Long running tasks should never block 
980
            AWT thread as it badly hurts the UI
981
            <a href="http://performance.netbeans.org/responsiveness/issues.html">
982
            responsiveness</a>.
983
            Tasks like connecting over
984
            network, computing huge amount of data, compilation
985
            be done asynchronously (for example
986
            using <code>RequestProcessor</code>), definitively it should 
987
            not block AWT thread.
988
            </hint>
989
        </question>
990
-->
991
 <answer id="perf-progress">
992
  <p>
993
   Executing external processes. Always scheduled to dedicated thread.
994
  </p>
995
 </answer>
996
997
998
999
<!--
1000
        <question id="perf-scale" when="init">
1001
            Which external criteria influence the performance of your
1002
            program (size of file in editor, number of files in menu, 
1003
            in source directory, etc.) and how well your code scales?
1004
            <hint>
1005
            Please include some estimates, there are other more detailed 
1006
            questions to answer in later phases of implementation. 
1007
            </hint>
1008
        </question>
1009
-->
1010
 <answer id="perf-scale">
1011
  <p>
1012
   Number of threads depending on number of spawned processes (n) increases
1013
   lineary (4n the worst case, 2n the best case).
1014
  </p>
1015
 </answer>
1016
1017
1018
1019
<!--
1020
        <question id="perf-spi" when="init">
1021
            How the performance of the plugged in code will be enforced?
1022
            <hint>
1023
            If you allow foreign code to be plugged into your own module, how
1024
            do you enforce that it will behave correctly and quickly and will not
1025
            negatively influence the performance of your own module?
1026
            </hint>
1027
        </question>
1028
-->
1029
 <answer id="perf-spi">
1030
  <p>
1031
   No enforcement. SPI code may be used to terminate whole process tree.
1032
  </p>
1033
 </answer>
1034
1035
1036
1037
<!--
1038
        <question id="perf-startup" when="final">
1039
            Does your module run any code on startup?
1040
        </question>
1041
-->
1042
 <answer id="perf-startup">
1043
  <p>
1044
   No.
1045
  </p>
1046
 </answer>
1047
1048
1049
1050
<!--
1051
        <question id="perf-wakeup" when="final">
1052
            Does any piece of your code wake up periodically and do something
1053
            even when the system is otherwise idle (no user interaction)?
1054
        </question>
1055
-->
1056
 <answer id="perf-wakeup">
1057
  <p>
1058
   No.
1059
  </p>
1060
 </answer>
1061
1062
1063
1064
<!--
1065
        <question id="resources-file" when="final">
1066
            Does your module use <code>java.io.File</code> directly?
1067
            
1068
            <hint>
1069
            NetBeans provide a logical wrapper over plain files called 
1070
            <code>org.openide.filesystems.FileObject</code> that
1071
            provides uniform access to such resources and is the preferred
1072
            way that should be used. But of course there can be situations when
1073
            this is not suitable.
1074
            </hint>
1075
        </question>
1076
-->
1077
 <answer id="resources-file">
1078
  <p>
1079
   Yes.
1080
  </p>
1081
 </answer>
1082
1083
1084
1085
<!--
1086
        <question id="resources-layer" when="final">
1087
            Does your module provide own layer? Does it create any files or
1088
            folders in it? What it is trying to communicate by that and with which 
1089
            components?
1090
            
1091
            <hint>
1092
            NetBeans allows automatic and declarative installation of resources 
1093
            by module layers. Module register files into appropriate places
1094
            and other components use that information to perform their task
1095
            (build menu, toolbar, window layout, list of templates, set of
1096
            options, etc.). 
1097
            </hint>
1098
        </question>
1099
-->
1100
 <answer id="resources-layer">
1101
  <p>
1102
   No.
1103
  </p>
1104
 </answer>
1105
1106
1107
1108
<!--
1109
        <question id="resources-mask" when="final">
1110
            Does your module mask/hide/override any resources provided by other modules in
1111
            their layers?
1112
            
1113
            <hint>
1114
            If you mask a file provided by another module, you probably depend
1115
            on that and do not want the other module to (for example) change
1116
            the file's name. That module shall thus make that file available as an API
1117
            of some stability category.
1118
            </hint>
1119
        </question>
1120
-->
1121
 <answer id="resources-mask">
1122
  <p>
1123
   No.
1124
  </p>
1125
 </answer>
1126
1127
1128
1129
<!--
1130
        <question id="resources-preferences" when="final">
1131
            Does your module uses preferences via Preferences API? Does your module use NbPreferences or
1132
            or regular JDK Preferences ? Does it read, write or both ? 
1133
            Does it share preferences with other modules ? If so, then why ?
1134
            <hint>
1135
                You may use
1136
                    &lt;api type="export" group="preferences"
1137
                    name="preference node name" category="private"&gt;
1138
                    description of individual keys, where it is used, what it
1139
                    influences, whether the module reads/write it, etc.
1140
                    &lt;/api&gt;
1141
                Due to XML ID restrictions, rather than /org/netbeans/modules/foo give the "name" as org.netbeans.modules.foo.
1142
                Note that if you use NbPreferences this name will then be the same as the code name base of the module.
1143
            </hint>
1144
        </question>
1145
-->
1146
 <answer id="resources-preferences">
1147
  <p>
1148
   No.
1149
  </p>
1150
 </answer>
1151
1152
1153
1154
<!--
1155
        <question id="resources-read" when="final">
1156
            Does your module read any resources from layers? For what purpose?
1157
            
1158
            <hint>
1159
            As this is some kind of intermodule dependency, it is a kind of API.
1160
            Please describe it and classify according to 
1161
            <a href="http://openide.netbeans.org/tutorial/api-design.html#categories">
1162
            common stability categories</a>.
1163
            </hint>
1164
        </question>
1165
-->
1166
 <answer id="resources-read">
1167
  <p>
1168
   No.
1169
  </p>
1170
 </answer>
1171
1172
1173
1174
<!--
1175
        <question id="security-grant" when="final">
1176
            Does your code grant additional rights to some other code?
1177
            <hint>Avoid using a class loader that adds extra
1178
            permissions to loaded code unless really necessary.
1179
            Also note that your API implementation
1180
            can also expose unneeded permissions to enemy code by
1181
            calling AccessController.doPrivileged().</hint>
1182
        </question>
1183
-->
1184
 <answer id="security-grant">
1185
  <p>
1186
   No.
1187
  </p>
1188
 </answer>
1189
1190
1191
1192
<!--
1193
        <question id="security-policy" when="final">
1194
            Does your functionality require modifications to the standard policy file?
1195
            <hint>Your code might pass control to third-party code not
1196
            coming from trusted domains. This could be code downloaded over the
1197
            network or code coming from libraries that are not bundled
1198
            with NetBeans. Which permissions need to be granted to which domains?</hint>
1199
        </question>
1200
-->
1201
 <answer id="security-policy">
1202
  <p>
1203
   No.
1204
  </p>
1205
 </answer>
1206
1207
</api-answers>
(-)a/extexecution.base/build.xml (+5 lines)
Line 0    Link Here 
1
<?xml version="1.0" encoding="UTF-8"?>
2
<project basedir="." default="netbeans" name="extexecution.base">
3
    <description>Builds, tests, and runs the project org.netbeans.modules.extexecution.base</description>
4
    <import file="../nbbuild/templates/projectized.xml"/>
5
</project>
(-)a/extexecution.base/manifest.mf (+6 lines)
Line 0    Link Here 
1
Manifest-Version: 1.0
2
AutoUpdate-Show-In-Client: false
3
OpenIDE-Module: org.netbeans.modules.extexecution.base/2
4
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/extexecution/base/resources/Bundle.properties
5
OpenIDE-Module-Specification-Version: 1.0
6
(-)a/extexecution.base/nbproject/org-netbeans-modules-extexecution.sig (+487 lines)
Line 0    Link Here 
1
#Signature file v4.1
2
#Version 1.41.1
3
4
CLSS public abstract interface java.io.Closeable
5
intf java.lang.AutoCloseable
6
meth public abstract void close() throws java.io.IOException
7
8
CLSS public abstract interface java.io.Serializable
9
10
CLSS public abstract interface java.lang.AutoCloseable
11
meth public abstract void close() throws java.lang.Exception
12
13
CLSS public abstract interface java.lang.Comparable<%0 extends java.lang.Object>
14
meth public abstract int compareTo({java.lang.Comparable%0})
15
16
CLSS public abstract java.lang.Enum<%0 extends java.lang.Enum<{java.lang.Enum%0}>>
17
cons protected init(java.lang.String,int)
18
intf java.io.Serializable
19
intf java.lang.Comparable<{java.lang.Enum%0}>
20
meth protected final java.lang.Object clone() throws java.lang.CloneNotSupportedException
21
meth protected final void finalize()
22
meth public final boolean equals(java.lang.Object)
23
meth public final int compareTo({java.lang.Enum%0})
24
meth public final int hashCode()
25
meth public final int ordinal()
26
meth public final java.lang.Class<{java.lang.Enum%0}> getDeclaringClass()
27
meth public final java.lang.String name()
28
meth public java.lang.String toString()
29
meth public static <%0 extends java.lang.Enum<{%%0}>> {%%0} valueOf(java.lang.Class<{%%0}>,java.lang.String)
30
supr java.lang.Object
31
hfds name,ordinal
32
33
CLSS public java.lang.Object
34
cons public init()
35
meth protected java.lang.Object clone() throws java.lang.CloneNotSupportedException
36
meth protected void finalize() throws java.lang.Throwable
37
meth public boolean equals(java.lang.Object)
38
meth public final java.lang.Class<?> getClass()
39
meth public final void notify()
40
meth public final void notifyAll()
41
meth public final void wait() throws java.lang.InterruptedException
42
meth public final void wait(long) throws java.lang.InterruptedException
43
meth public final void wait(long,int) throws java.lang.InterruptedException
44
meth public int hashCode()
45
meth public java.lang.String toString()
46
47
CLSS public abstract interface java.lang.Runnable
48
meth public abstract void run()
49
50
CLSS public abstract interface java.lang.annotation.Annotation
51
meth public abstract boolean equals(java.lang.Object)
52
meth public abstract int hashCode()
53
meth public abstract java.lang.Class<? extends java.lang.annotation.Annotation> annotationType()
54
meth public abstract java.lang.String toString()
55
56
CLSS public abstract interface !annotation java.lang.annotation.Documented
57
 anno 0 java.lang.annotation.Documented()
58
 anno 0 java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy value=RUNTIME)
59
 anno 0 java.lang.annotation.Target(java.lang.annotation.ElementType[] value=[ANNOTATION_TYPE])
60
intf java.lang.annotation.Annotation
61
62
CLSS public abstract interface !annotation java.lang.annotation.Retention
63
 anno 0 java.lang.annotation.Documented()
64
 anno 0 java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy value=RUNTIME)
65
 anno 0 java.lang.annotation.Target(java.lang.annotation.ElementType[] value=[ANNOTATION_TYPE])
66
intf java.lang.annotation.Annotation
67
meth public abstract java.lang.annotation.RetentionPolicy value()
68
69
CLSS public abstract interface !annotation java.lang.annotation.Target
70
 anno 0 java.lang.annotation.Documented()
71
 anno 0 java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy value=RUNTIME)
72
 anno 0 java.lang.annotation.Target(java.lang.annotation.ElementType[] value=[ANNOTATION_TYPE])
73
intf java.lang.annotation.Annotation
74
meth public abstract java.lang.annotation.ElementType[] value()
75
76
CLSS public abstract interface java.util.concurrent.Callable<%0 extends java.lang.Object>
77
meth public abstract {java.util.concurrent.Callable%0} call() throws java.lang.Exception
78
79
CLSS public final org.netbeans.api.extexecution.ExecutionDescriptor
80
cons public init()
81
innr public abstract interface static InputProcessorFactory
82
innr public abstract interface static LineConvertorFactory
83
innr public abstract interface static RerunCondition
84
meth public org.netbeans.api.extexecution.ExecutionDescriptor charset(java.nio.charset.Charset)
85
 anno 0 org.netbeans.api.annotations.common.CheckReturnValue()
86
 anno 0 org.netbeans.api.annotations.common.NonNull()
87
 anno 1 org.netbeans.api.annotations.common.NullAllowed()
88
meth public org.netbeans.api.extexecution.ExecutionDescriptor controllable(boolean)
89
 anno 0 org.netbeans.api.annotations.common.CheckReturnValue()
90
 anno 0 org.netbeans.api.annotations.common.NonNull()
91
meth public org.netbeans.api.extexecution.ExecutionDescriptor errConvertorFactory(org.netbeans.api.extexecution.ExecutionDescriptor$LineConvertorFactory)
92
 anno 0 org.netbeans.api.annotations.common.CheckReturnValue()
93
 anno 0 org.netbeans.api.annotations.common.NonNull()
94
 anno 1 org.netbeans.api.annotations.common.NullAllowed()
95
meth public org.netbeans.api.extexecution.ExecutionDescriptor errLineBased(boolean)
96
 anno 0 org.netbeans.api.annotations.common.CheckReturnValue()
97
 anno 0 org.netbeans.api.annotations.common.NonNull()
98
meth public org.netbeans.api.extexecution.ExecutionDescriptor errProcessorFactory(org.netbeans.api.extexecution.ExecutionDescriptor$InputProcessorFactory)
99
 anno 0 org.netbeans.api.annotations.common.CheckReturnValue()
100
 anno 0 org.netbeans.api.annotations.common.NonNull()
101
 anno 1 org.netbeans.api.annotations.common.NullAllowed()
102
meth public org.netbeans.api.extexecution.ExecutionDescriptor frontWindow(boolean)
103
 anno 0 org.netbeans.api.annotations.common.CheckReturnValue()
104
 anno 0 org.netbeans.api.annotations.common.NonNull()
105
meth public org.netbeans.api.extexecution.ExecutionDescriptor frontWindowOnError(boolean)
106
 anno 0 org.netbeans.api.annotations.common.CheckReturnValue()
107
 anno 0 org.netbeans.api.annotations.common.NonNull()
108
meth public org.netbeans.api.extexecution.ExecutionDescriptor inputOutput(org.openide.windows.InputOutput)
109
 anno 0 org.netbeans.api.annotations.common.CheckReturnValue()
110
 anno 0 org.netbeans.api.annotations.common.NonNull()
111
 anno 1 org.netbeans.api.annotations.common.NullAllowed()
112
meth public org.netbeans.api.extexecution.ExecutionDescriptor inputVisible(boolean)
113
 anno 0 org.netbeans.api.annotations.common.CheckReturnValue()
114
 anno 0 org.netbeans.api.annotations.common.NonNull()
115
meth public org.netbeans.api.extexecution.ExecutionDescriptor noReset(boolean)
116
 anno 0 org.netbeans.api.annotations.common.CheckReturnValue()
117
 anno 0 org.netbeans.api.annotations.common.NonNull()
118
meth public org.netbeans.api.extexecution.ExecutionDescriptor optionsPath(java.lang.String)
119
 anno 0 org.netbeans.api.annotations.common.CheckReturnValue()
120
 anno 0 org.netbeans.api.annotations.common.NonNull()
121
 anno 1 org.netbeans.api.annotations.common.NullAllowed()
122
meth public org.netbeans.api.extexecution.ExecutionDescriptor outConvertorFactory(org.netbeans.api.extexecution.ExecutionDescriptor$LineConvertorFactory)
123
 anno 0 org.netbeans.api.annotations.common.CheckReturnValue()
124
 anno 0 org.netbeans.api.annotations.common.NonNull()
125
 anno 1 org.netbeans.api.annotations.common.NullAllowed()
126
meth public org.netbeans.api.extexecution.ExecutionDescriptor outLineBased(boolean)
127
 anno 0 org.netbeans.api.annotations.common.CheckReturnValue()
128
 anno 0 org.netbeans.api.annotations.common.NonNull()
129
meth public org.netbeans.api.extexecution.ExecutionDescriptor outProcessorFactory(org.netbeans.api.extexecution.ExecutionDescriptor$InputProcessorFactory)
130
 anno 0 org.netbeans.api.annotations.common.CheckReturnValue()
131
 anno 0 org.netbeans.api.annotations.common.NonNull()
132
 anno 1 org.netbeans.api.annotations.common.NullAllowed()
133
meth public org.netbeans.api.extexecution.ExecutionDescriptor postExecution(java.lang.Runnable)
134
 anno 0 org.netbeans.api.annotations.common.CheckReturnValue()
135
 anno 0 org.netbeans.api.annotations.common.NonNull()
136
 anno 1 org.netbeans.api.annotations.common.NullAllowed()
137
meth public org.netbeans.api.extexecution.ExecutionDescriptor preExecution(java.lang.Runnable)
138
 anno 0 org.netbeans.api.annotations.common.CheckReturnValue()
139
 anno 0 org.netbeans.api.annotations.common.NonNull()
140
 anno 1 org.netbeans.api.annotations.common.NullAllowed()
141
meth public org.netbeans.api.extexecution.ExecutionDescriptor rerunCondition(org.netbeans.api.extexecution.ExecutionDescriptor$RerunCondition)
142
 anno 0 org.netbeans.api.annotations.common.CheckReturnValue()
143
 anno 0 org.netbeans.api.annotations.common.NonNull()
144
 anno 1 org.netbeans.api.annotations.common.NullAllowed()
145
meth public org.netbeans.api.extexecution.ExecutionDescriptor showProgress(boolean)
146
 anno 0 org.netbeans.api.annotations.common.CheckReturnValue()
147
 anno 0 org.netbeans.api.annotations.common.NonNull()
148
meth public org.netbeans.api.extexecution.ExecutionDescriptor showSuspended(boolean)
149
 anno 0 org.netbeans.api.annotations.common.CheckReturnValue()
150
 anno 0 org.netbeans.api.annotations.common.NonNull()
151
supr java.lang.Object
152
hfds charset,controllable,errConvertorFactory,errLineBased,errProcessorFactory,front,frontWindowOnError,input,inputOutput,noReset,optionsPath,outConvertorFactory,outLineBased,outProcessorFactory,postExecution,preExecution,progress,rerunCondition,suspend
153
hcls DescriptorData
154
155
CLSS public abstract interface static org.netbeans.api.extexecution.ExecutionDescriptor$InputProcessorFactory
156
 outer org.netbeans.api.extexecution.ExecutionDescriptor
157
meth public abstract org.netbeans.api.extexecution.input.InputProcessor newInputProcessor(org.netbeans.api.extexecution.input.InputProcessor)
158
 anno 0 org.netbeans.api.annotations.common.NonNull()
159
 anno 1 org.netbeans.api.annotations.common.NonNull()
160
161
CLSS public abstract interface static org.netbeans.api.extexecution.ExecutionDescriptor$LineConvertorFactory
162
 outer org.netbeans.api.extexecution.ExecutionDescriptor
163
meth public abstract org.netbeans.api.extexecution.print.LineConvertor newLineConvertor()
164
 anno 0 org.netbeans.api.annotations.common.NonNull()
165
166
CLSS public abstract interface static org.netbeans.api.extexecution.ExecutionDescriptor$RerunCondition
167
 outer org.netbeans.api.extexecution.ExecutionDescriptor
168
meth public abstract boolean isRerunPossible()
169
meth public abstract void addChangeListener(javax.swing.event.ChangeListener)
170
 anno 1 org.netbeans.api.annotations.common.NonNull()
171
meth public abstract void removeChangeListener(javax.swing.event.ChangeListener)
172
 anno 1 org.netbeans.api.annotations.common.NonNull()
173
174
CLSS public final org.netbeans.api.extexecution.ExecutionService
175
meth public java.util.concurrent.Future<java.lang.Integer> run()
176
 anno 0 org.netbeans.api.annotations.common.NonNull()
177
meth public static org.netbeans.api.extexecution.ExecutionService newService(java.util.concurrent.Callable<java.lang.Process>,org.netbeans.api.extexecution.ExecutionDescriptor,java.lang.String)
178
 anno 0 org.netbeans.api.annotations.common.NonNull()
179
 anno 1 org.netbeans.api.annotations.common.NonNull()
180
 anno 2 org.netbeans.api.annotations.common.NonNull()
181
 anno 3 org.netbeans.api.annotations.common.NonNull()
182
supr java.lang.Object
183
hfds EXECUTOR_SERVICE,EXECUTOR_SHUTDOWN_SLICE,LOGGER,RUNNING_PROCESSES,descriptor,originalDisplayName,processCreator
184
hcls ProgressAction,ProgressCancellable,WrappedException
185
186
CLSS public final org.netbeans.api.extexecution.ExternalProcessBuilder
187
cons public init(java.lang.String)
188
 anno 1 org.netbeans.api.annotations.common.NonNull()
189
intf java.util.concurrent.Callable<java.lang.Process>
190
meth public java.lang.Process call() throws java.io.IOException
191
 anno 0 org.netbeans.api.annotations.common.NonNull()
192
meth public org.netbeans.api.extexecution.ExternalProcessBuilder addArgument(java.lang.String)
193
 anno 0 org.netbeans.api.annotations.common.CheckReturnValue()
194
 anno 0 org.netbeans.api.annotations.common.NonNull()
195
 anno 1 org.netbeans.api.annotations.common.NonNull()
196
meth public org.netbeans.api.extexecution.ExternalProcessBuilder addEnvironmentVariable(java.lang.String,java.lang.String)
197
 anno 0 org.netbeans.api.annotations.common.CheckReturnValue()
198
 anno 0 org.netbeans.api.annotations.common.NonNull()
199
 anno 1 org.netbeans.api.annotations.common.NonNull()
200
 anno 2 org.netbeans.api.annotations.common.NonNull()
201
meth public org.netbeans.api.extexecution.ExternalProcessBuilder prependPath(java.io.File)
202
 anno 0 org.netbeans.api.annotations.common.CheckReturnValue()
203
 anno 0 org.netbeans.api.annotations.common.NonNull()
204
 anno 1 org.netbeans.api.annotations.common.NonNull()
205
meth public org.netbeans.api.extexecution.ExternalProcessBuilder redirectErrorStream(boolean)
206
 anno 0 org.netbeans.api.annotations.common.CheckReturnValue()
207
 anno 0 org.netbeans.api.annotations.common.NonNull()
208
meth public org.netbeans.api.extexecution.ExternalProcessBuilder workingDirectory(java.io.File)
209
 anno 0 org.netbeans.api.annotations.common.CheckReturnValue()
210
 anno 0 org.netbeans.api.annotations.common.NonNull()
211
 anno 1 org.netbeans.api.annotations.common.NonNull()
212
supr java.lang.Object
213
hfds ESCAPED_PATTERN,LOGGER,PROXY_AUTHENTICATION_PASSWORD,PROXY_AUTHENTICATION_USERNAME,USE_PROXY_AUTHENTICATION,arguments,envVariables,executable,paths,redirectErrorStream,workingDirectory
214
hcls BuilderData
215
216
CLSS public final org.netbeans.api.extexecution.ExternalProcessSupport
217
meth public static void destroy(java.lang.Process,java.util.Map<java.lang.String,java.lang.String>)
218
 anno 1 org.netbeans.api.annotations.common.NonNull()
219
 anno 2 org.netbeans.api.annotations.common.NonNull()
220
supr java.lang.Object
221
222
CLSS public final org.netbeans.api.extexecution.ProcessBuilder
223
intf java.util.concurrent.Callable<java.lang.Process>
224
meth public java.lang.Process call() throws java.io.IOException
225
 anno 0 org.netbeans.api.annotations.common.NonNull()
226
meth public java.lang.String getDescription()
227
 anno 0 org.netbeans.api.annotations.common.NonNull()
228
meth public static org.netbeans.api.extexecution.ProcessBuilder getLocal()
229
meth public void setArguments(java.util.List<java.lang.String>)
230
 anno 1 org.netbeans.api.annotations.common.NonNull()
231
meth public void setEnvironmentVariables(java.util.Map<java.lang.String,java.lang.String>)
232
 anno 1 org.netbeans.api.annotations.common.NonNull()
233
meth public void setExecutable(java.lang.String)
234
 anno 1 org.netbeans.api.annotations.common.NonNull()
235
meth public void setPaths(java.util.List<java.lang.String>)
236
 anno 1 org.netbeans.api.annotations.common.NonNull()
237
meth public void setRedirectErrorStream(boolean)
238
meth public void setWorkingDirectory(java.lang.String)
239
 anno 1 org.netbeans.api.annotations.common.NullAllowed()
240
supr java.lang.Object
241
hfds arguments,description,envVariables,executable,implementation,paths,redirectErrorStream,workingDirectory
242
hcls LocalProcessFactory
243
244
CLSS public abstract interface org.netbeans.api.extexecution.input.InputProcessor
245
intf java.io.Closeable
246
meth public abstract void close() throws java.io.IOException
247
meth public abstract void processInput(char[]) throws java.io.IOException
248
 anno 1 org.netbeans.api.annotations.common.NonNull()
249
meth public abstract void reset() throws java.io.IOException
250
251
CLSS public final org.netbeans.api.extexecution.input.InputProcessors
252
meth public !varargs static org.netbeans.api.extexecution.input.InputProcessor proxy(org.netbeans.api.extexecution.input.InputProcessor[])
253
 anno 0 org.netbeans.api.annotations.common.NonNull()
254
 anno 1 org.netbeans.api.annotations.common.NonNull()
255
meth public static org.netbeans.api.extexecution.input.InputProcessor ansiStripping(org.netbeans.api.extexecution.input.InputProcessor)
256
 anno 0 org.netbeans.api.annotations.common.NonNull()
257
 anno 1 org.netbeans.api.annotations.common.NonNull()
258
meth public static org.netbeans.api.extexecution.input.InputProcessor bridge(org.netbeans.api.extexecution.input.LineProcessor)
259
 anno 0 org.netbeans.api.annotations.common.NonNull()
260
 anno 1 org.netbeans.api.annotations.common.NonNull()
261
meth public static org.netbeans.api.extexecution.input.InputProcessor copying(java.io.Writer)
262
 anno 0 org.netbeans.api.annotations.common.NonNull()
263
 anno 1 org.netbeans.api.annotations.common.NonNull()
264
meth public static org.netbeans.api.extexecution.input.InputProcessor printing(org.openide.windows.OutputWriter,boolean)
265
 anno 0 org.netbeans.api.annotations.common.NonNull()
266
 anno 1 org.netbeans.api.annotations.common.NonNull()
267
meth public static org.netbeans.api.extexecution.input.InputProcessor printing(org.openide.windows.OutputWriter,org.netbeans.api.extexecution.print.LineConvertor,boolean)
268
 anno 0 org.netbeans.api.annotations.common.NonNull()
269
 anno 1 org.netbeans.api.annotations.common.NonNull()
270
 anno 2 org.netbeans.api.annotations.common.NullAllowed()
271
supr java.lang.Object
272
hfds LOGGER
273
hcls AnsiStrippingInputProcessor,Bridge,CopyingInputProcessor,PrintingInputProcessor,ProxyInputProcessor
274
275
CLSS public abstract interface org.netbeans.api.extexecution.input.InputReader
276
intf java.io.Closeable
277
meth public abstract int readInput(org.netbeans.api.extexecution.input.InputProcessor) throws java.io.IOException
278
 anno 1 org.netbeans.api.annotations.common.NullAllowed()
279
meth public abstract void close() throws java.io.IOException
280
281
CLSS public final org.netbeans.api.extexecution.input.InputReaderTask
282
intf java.lang.Runnable
283
intf org.openide.util.Cancellable
284
meth public boolean cancel()
285
meth public static org.netbeans.api.extexecution.input.InputReaderTask newDrainingTask(org.netbeans.api.extexecution.input.InputReader,org.netbeans.api.extexecution.input.InputProcessor)
286
 anno 0 org.netbeans.api.annotations.common.NonNull()
287
 anno 1 org.netbeans.api.annotations.common.NonNull()
288
 anno 2 org.netbeans.api.annotations.common.NullAllowed()
289
meth public static org.netbeans.api.extexecution.input.InputReaderTask newTask(org.netbeans.api.extexecution.input.InputReader,org.netbeans.api.extexecution.input.InputProcessor)
290
 anno 0 org.netbeans.api.annotations.common.NonNull()
291
 anno 1 org.netbeans.api.annotations.common.NonNull()
292
 anno 2 org.netbeans.api.annotations.common.NullAllowed()
293
meth public void run()
294
supr java.lang.Object
295
hfds DELAY_INCREMENT,LOGGER,MAX_DELAY,MIN_DELAY,cancelled,draining,inputProcessor,inputReader,running
296
297
CLSS public final org.netbeans.api.extexecution.input.InputReaders
298
innr public final static FileInput
299
meth public static org.netbeans.api.extexecution.input.InputReader forFile(java.io.File,java.nio.charset.Charset)
300
 anno 0 org.netbeans.api.annotations.common.NonNull()
301
 anno 1 org.netbeans.api.annotations.common.NonNull()
302
 anno 2 org.netbeans.api.annotations.common.NonNull()
303
meth public static org.netbeans.api.extexecution.input.InputReader forFileInputProvider(org.netbeans.api.extexecution.input.InputReaders$FileInput$Provider)
304
 anno 0 org.netbeans.api.annotations.common.NonNull()
305
 anno 1 org.netbeans.api.annotations.common.NonNull()
306
meth public static org.netbeans.api.extexecution.input.InputReader forReader(java.io.Reader)
307
 anno 0 org.netbeans.api.annotations.common.NonNull()
308
 anno 1 org.netbeans.api.annotations.common.NonNull()
309
meth public static org.netbeans.api.extexecution.input.InputReader forStream(java.io.InputStream,java.nio.charset.Charset)
310
 anno 0 org.netbeans.api.annotations.common.NonNull()
311
 anno 1 org.netbeans.api.annotations.common.NonNull()
312
 anno 2 org.netbeans.api.annotations.common.NonNull()
313
supr java.lang.Object
314
315
CLSS public final static org.netbeans.api.extexecution.input.InputReaders$FileInput
316
 outer org.netbeans.api.extexecution.input.InputReaders
317
cons public init(java.io.File,java.nio.charset.Charset)
318
 anno 1 org.netbeans.api.annotations.common.NonNull()
319
 anno 2 org.netbeans.api.annotations.common.NonNull()
320
innr public abstract interface static Provider
321
meth public java.io.File getFile()
322
 anno 0 org.netbeans.api.annotations.common.NonNull()
323
meth public java.nio.charset.Charset getCharset()
324
 anno 0 org.netbeans.api.annotations.common.NonNull()
325
supr java.lang.Object
326
hfds charset,file
327
328
CLSS public abstract interface static org.netbeans.api.extexecution.input.InputReaders$FileInput$Provider
329
 outer org.netbeans.api.extexecution.input.InputReaders$FileInput
330
meth public abstract org.netbeans.api.extexecution.input.InputReaders$FileInput getFileInput()
331
 anno 0 org.netbeans.api.annotations.common.CheckForNull()
332
333
CLSS public abstract interface org.netbeans.api.extexecution.input.LineProcessor
334
intf java.io.Closeable
335
meth public abstract void close()
336
meth public abstract void processLine(java.lang.String)
337
 anno 1 org.netbeans.api.annotations.common.NonNull()
338
meth public abstract void reset()
339
340
CLSS public final org.netbeans.api.extexecution.input.LineProcessors
341
meth public !varargs static org.netbeans.api.extexecution.input.LineProcessor proxy(org.netbeans.api.extexecution.input.LineProcessor[])
342
 anno 0 org.netbeans.api.annotations.common.NonNull()
343
 anno 1 org.netbeans.api.annotations.common.NonNull()
344
meth public static org.netbeans.api.extexecution.input.LineProcessor patternWaiting(java.util.regex.Pattern,java.util.concurrent.CountDownLatch)
345
 anno 0 org.netbeans.api.annotations.common.NonNull()
346
 anno 1 org.netbeans.api.annotations.common.NonNull()
347
 anno 2 org.netbeans.api.annotations.common.NonNull()
348
meth public static org.netbeans.api.extexecution.input.LineProcessor printing(org.openide.windows.OutputWriter,boolean)
349
 anno 0 org.netbeans.api.annotations.common.NonNull()
350
 anno 1 org.netbeans.api.annotations.common.NonNull()
351
meth public static org.netbeans.api.extexecution.input.LineProcessor printing(org.openide.windows.OutputWriter,org.netbeans.api.extexecution.print.LineConvertor,boolean)
352
 anno 0 org.netbeans.api.annotations.common.NonNull()
353
 anno 1 org.netbeans.api.annotations.common.NonNull()
354
 anno 2 org.netbeans.api.annotations.common.NullAllowed()
355
supr java.lang.Object
356
hfds LOGGER
357
hcls PrintingLineProcessor,ProxyLineProcessor,WaitingLineProcessor
358
359
CLSS abstract interface org.netbeans.api.extexecution.input.package-info
360
361
CLSS abstract interface org.netbeans.api.extexecution.package-info
362
363
CLSS public final org.netbeans.api.extexecution.print.ConvertedLine
364
meth public java.lang.String getText()
365
 anno 0 org.netbeans.api.annotations.common.NonNull()
366
meth public org.openide.windows.OutputListener getListener()
367
 anno 0 org.netbeans.api.annotations.common.CheckForNull()
368
meth public static org.netbeans.api.extexecution.print.ConvertedLine forText(java.lang.String,org.openide.windows.OutputListener)
369
 anno 0 org.netbeans.api.annotations.common.NonNull()
370
 anno 1 org.netbeans.api.annotations.common.NonNull()
371
 anno 2 org.netbeans.api.annotations.common.NullAllowed()
372
supr java.lang.Object
373
hfds listener,text
374
375
CLSS public abstract interface org.netbeans.api.extexecution.print.LineConvertor
376
meth public abstract java.util.List<org.netbeans.api.extexecution.print.ConvertedLine> convert(java.lang.String)
377
 anno 0 org.netbeans.api.annotations.common.CheckForNull()
378
 anno 1 org.netbeans.api.annotations.common.NonNull()
379
380
CLSS public final org.netbeans.api.extexecution.print.LineConvertors
381
innr public abstract interface static FileLocator
382
meth public !varargs static org.netbeans.api.extexecution.print.LineConvertor proxy(org.netbeans.api.extexecution.print.LineConvertor[])
383
 anno 0 org.netbeans.api.annotations.common.NonNull()
384
 anno 1 org.netbeans.api.annotations.common.NonNull()
385
meth public static org.netbeans.api.extexecution.print.LineConvertor filePattern(org.netbeans.api.extexecution.print.LineConvertors$FileLocator,java.util.regex.Pattern,java.util.regex.Pattern,int,int)
386
 anno 0 org.netbeans.api.annotations.common.NonNull()
387
 anno 1 org.netbeans.api.annotations.common.NullAllowed()
388
 anno 2 org.netbeans.api.annotations.common.NonNull()
389
 anno 3 org.netbeans.api.annotations.common.NullAllowed()
390
meth public static org.netbeans.api.extexecution.print.LineConvertor httpUrl()
391
 anno 0 org.netbeans.api.annotations.common.NonNull()
392
supr java.lang.Object
393
hfds DEFAULT_FILE_HANDLER,DEFAULT_HTTP_HANDLER,LOGGER
394
hcls FilePatternConvertor,HttpUrlConvertor,ProxyLineConvertor
395
396
CLSS public abstract interface static org.netbeans.api.extexecution.print.LineConvertors$FileLocator
397
 outer org.netbeans.api.extexecution.print.LineConvertors
398
meth public abstract org.openide.filesystems.FileObject find(java.lang.String)
399
 anno 0 org.netbeans.api.annotations.common.CheckForNull()
400
 anno 1 org.netbeans.api.annotations.common.NonNull()
401
402
CLSS abstract interface org.netbeans.api.extexecution.print.package-info
403
404
CLSS public final org.netbeans.api.extexecution.startup.StartupExtender
405
innr public final static !enum StartMode
406
meth public java.lang.String getDescription()
407
 anno 0 org.netbeans.api.annotations.common.NonNull()
408
meth public java.util.List<java.lang.String> getArguments()
409
 anno 0 org.netbeans.api.annotations.common.NonNull()
410
meth public static java.util.List<org.netbeans.api.extexecution.startup.StartupExtender> getExtenders(org.openide.util.Lookup,org.netbeans.api.extexecution.startup.StartupExtender$StartMode)
411
 anno 0 org.netbeans.api.annotations.common.NonNull()
412
 anno 1 org.netbeans.api.annotations.common.NonNull()
413
 anno 2 org.netbeans.api.annotations.common.NonNull()
414
supr java.lang.Object
415
hfds LOG,arguments,description
416
417
CLSS public final static !enum org.netbeans.api.extexecution.startup.StartupExtender$StartMode
418
 outer org.netbeans.api.extexecution.startup.StartupExtender
419
fld public final static org.netbeans.api.extexecution.startup.StartupExtender$StartMode DEBUG
420
fld public final static org.netbeans.api.extexecution.startup.StartupExtender$StartMode NORMAL
421
fld public final static org.netbeans.api.extexecution.startup.StartupExtender$StartMode PROFILE
422
fld public final static org.netbeans.api.extexecution.startup.StartupExtender$StartMode TEST_DEBUG
423
fld public final static org.netbeans.api.extexecution.startup.StartupExtender$StartMode TEST_NORMAL
424
fld public final static org.netbeans.api.extexecution.startup.StartupExtender$StartMode TEST_PROFILE
425
meth public java.lang.String toString()
426
meth public static org.netbeans.api.extexecution.startup.StartupExtender$StartMode valueOf(java.lang.String)
427
meth public static org.netbeans.api.extexecution.startup.StartupExtender$StartMode[] values()
428
supr java.lang.Enum<org.netbeans.api.extexecution.startup.StartupExtender$StartMode>
429
hfds mode
430
431
CLSS abstract interface org.netbeans.api.extexecution.startup.package-info
432
433
CLSS public org.netbeans.spi.extexecution.ProcessBuilderFactory
434
meth public static org.netbeans.api.extexecution.ProcessBuilder createProcessBuilder(org.netbeans.spi.extexecution.ProcessBuilderImplementation,java.lang.String)
435
supr java.lang.Object
436
437
CLSS public abstract interface org.netbeans.spi.extexecution.ProcessBuilderImplementation
438
meth public abstract java.lang.Process createProcess(java.lang.String,java.lang.String,java.util.List<java.lang.String>,java.util.List<java.lang.String>,java.util.Map<java.lang.String,java.lang.String>,boolean) throws java.io.IOException
439
 anno 0 org.netbeans.api.annotations.common.NonNull()
440
 anno 1 org.netbeans.api.annotations.common.NonNull()
441
 anno 2 org.netbeans.api.annotations.common.NullAllowed()
442
 anno 3 org.netbeans.api.annotations.common.NonNull()
443
 anno 4 org.netbeans.api.annotations.common.NonNull()
444
 anno 5 org.netbeans.api.annotations.common.NonNull()
445
446
CLSS public abstract interface org.netbeans.spi.extexecution.destroy.ProcessDestroyPerformer
447
meth public abstract void destroy(java.lang.Process,java.util.Map<java.lang.String,java.lang.String>)
448
449
CLSS abstract interface org.netbeans.spi.extexecution.destroy.package-info
450
451
CLSS public abstract interface org.netbeans.spi.extexecution.open.FileOpenHandler
452
meth public abstract void open(org.openide.filesystems.FileObject,int)
453
 anno 1 org.netbeans.api.annotations.common.NonNull()
454
455
CLSS public abstract interface org.netbeans.spi.extexecution.open.HttpOpenHandler
456
meth public abstract void open(java.net.URL)
457
 anno 1 org.netbeans.api.annotations.common.NonNull()
458
459
CLSS public abstract interface org.netbeans.spi.extexecution.open.OptionOpenHandler
460
meth public abstract void open(java.lang.String)
461
 anno 1 org.netbeans.api.annotations.common.NonNull()
462
463
CLSS abstract interface org.netbeans.spi.extexecution.open.package-info
464
465
CLSS abstract interface org.netbeans.spi.extexecution.package-info
466
467
CLSS public abstract interface org.netbeans.spi.extexecution.startup.StartupExtenderImplementation
468
innr public abstract interface static !annotation Registration
469
meth public abstract java.util.List<java.lang.String> getArguments(org.openide.util.Lookup,org.netbeans.api.extexecution.startup.StartupExtender$StartMode)
470
 anno 0 org.netbeans.api.annotations.common.NonNull()
471
 anno 1 org.netbeans.api.annotations.common.NonNull()
472
 anno 2 org.netbeans.api.annotations.common.NonNull()
473
474
CLSS public abstract interface static !annotation org.netbeans.spi.extexecution.startup.StartupExtenderImplementation$Registration
475
 outer org.netbeans.spi.extexecution.startup.StartupExtenderImplementation
476
 anno 0 java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy value=SOURCE)
477
 anno 0 java.lang.annotation.Target(java.lang.annotation.ElementType[] value=[TYPE, METHOD])
478
intf java.lang.annotation.Annotation
479
meth public abstract !hasdefault int position()
480
meth public abstract java.lang.String displayName()
481
meth public abstract org.netbeans.api.extexecution.startup.StartupExtender$StartMode[] startMode()
482
483
CLSS abstract interface org.netbeans.spi.extexecution.startup.package-info
484
485
CLSS public abstract interface org.openide.util.Cancellable
486
meth public abstract boolean cancel()
487
(-)a/extexecution.base/nbproject/project.properties (+53 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-2006 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
is.autoload=true
45
javac.source=1.6
46
47
javadoc.arch=${basedir}/arch.xml
48
javadoc.apichanges=${basedir}/apichanges.xml
49
nbm.module.author=Petr Hejl
50
51
test.config.stableBTD.includes=**/*Test.class
52
test.config.stableBTD.excludes=\
53
    **/ExecutionServiceTest.class
(-)a/extexecution.base/nbproject/project.xml (+70 lines)
Line 0    Link Here 
1
<?xml version="1.0" encoding="UTF-8"?>
2
<project xmlns="http://www.netbeans.org/ns/project/1">
3
    <type>org.netbeans.modules.apisupport.project</type>
4
    <configuration>
5
        <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
6
            <code-name-base>org.netbeans.modules.extexecution.base</code-name-base>
7
            <module-dependencies>
8
                <dependency>
9
                    <code-name-base>org.netbeans.api.annotations.common</code-name-base>
10
                    <build-prerequisite/>
11
                    <compile-dependency/>
12
                    <run-dependency>
13
                        <release-version>1</release-version>
14
                        <specification-version>1.0</specification-version>
15
                    </run-dependency>
16
                </dependency>
17
                <dependency>
18
                    <code-name-base>org.openide.util.base</code-name-base>
19
                    <build-prerequisite/>
20
                    <compile-dependency/>
21
                    <run-dependency>
22
                        <specification-version>9.1</specification-version>
23
                    </run-dependency>
24
                </dependency>
25
                <dependency>
26
                    <code-name-base>org.openide.util.lookup</code-name-base>
27
                    <build-prerequisite/>
28
                    <compile-dependency/>
29
                    <run-dependency>
30
                        <specification-version>8.0</specification-version>
31
                    </run-dependency>
32
                </dependency>
33
            </module-dependencies>
34
            <test-dependencies>
35
                <test-type>
36
                    <name>unit</name>
37
                    <test-dependency>
38
                        <code-name-base>org.netbeans.modules.extexecution.base</code-name-base>
39
                        <recursive/>
40
                        <compile-dependency/>
41
                    </test-dependency>
42
                    <test-dependency>
43
                        <code-name-base>org.netbeans.modules.nbjunit</code-name-base>
44
                        <recursive/>
45
                        <compile-dependency/>
46
                    </test-dependency>
47
                    <test-dependency>
48
                        <code-name-base>org.netbeans.libs.junit4</code-name-base>
49
                        <compile-dependency/>
50
                    </test-dependency>
51
                    <test-dependency>
52
                        <code-name-base>org.openide.util.base</code-name-base>
53
                        <compile-dependency/>
54
                        <test/>
55
                    </test-dependency>
56
                    <test-dependency>
57
                        <code-name-base>org.openide.util.lookup</code-name-base>
58
                        <compile-dependency/>
59
                        <test/>
60
                    </test-dependency>
61
                </test-type>
62
            </test-dependencies>
63
            <public-packages>
64
                <package>org.netbeans.api.extexecution.base</package>
65
                <package>org.netbeans.api.extexecution.base.input</package>
66
                <package>org.netbeans.spi.extexecution.base</package>
67
            </public-packages>
68
        </data>
69
    </configuration>
70
</project>
(-)a/extexecution.base/src/org/netbeans/api/extexecution/base/BaseExecutionDescriptor.java (+283 lines)
Line 0    Link Here 
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2014 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 2014 Sun Microsystems, Inc.
41
 */
42
43
package org.netbeans.api.extexecution.base;
44
45
import java.io.Reader;
46
import java.nio.charset.Charset;
47
import org.netbeans.api.annotations.common.CheckReturnValue;
48
import org.netbeans.api.annotations.common.NonNull;
49
import org.netbeans.api.annotations.common.NullAllowed;
50
import org.netbeans.api.extexecution.base.input.InputProcessor;
51
52
/**
53
 * Descriptor for the execution service. Describes the runtime attributes
54
 * of the {@link BaseExecutionService}.
55
 * <p>
56
 * <i>Thread safety</i> of this class depends on type of objects passed to its
57
 * configuration methods. If these objects are immutable, resulting descriptor
58
 * is immutable as well. It these objects are thread safe, resulting descriptor
59
 * is thread safe as well.
60
 *
61
 * @author Petr Hejl
62
 * @see BaseExecutionService
63
 */
64
public final class BaseExecutionDescriptor {
65
66
    private final Charset charset;
67
68
    private final Runnable preExecution;
69
70
    private final ParametrizedRunnable<Integer> postExecution;
71
72
    private final InputProcessorFactory outProcessorFactory;
73
74
    private final InputProcessorFactory errProcessorFactory;
75
76
    private final ReaderFactory inReaderFactory;
77
78
    /**
79
     * Creates the new descriptor. All properties are initialized to
80
     * <code>null</code>.
81
     */
82
    public BaseExecutionDescriptor() {
83
        this(null, null, null, null, null, null);
84
    }
85
86
    private BaseExecutionDescriptor(Charset charset, Runnable preExecution,
87
            ParametrizedRunnable<Integer> postExecution,
88
            InputProcessorFactory outProcessorFactory,
89
            InputProcessorFactory errProcessorFactory,
90
            ReaderFactory inReaderFactory) {
91
92
        this.charset = charset;
93
        this.preExecution = preExecution;
94
        this.postExecution = postExecution;
95
        this.outProcessorFactory = outProcessorFactory;
96
        this.errProcessorFactory = errProcessorFactory;
97
        this.inReaderFactory = inReaderFactory;
98
    }
99
100
    /**
101
     * Returns a descriptor with configured charset. If configured
102
     * value is not <code>null</code> the {@link BaseExecutionService} will
103
     * use the given charset to decode the process streams. When
104
     * <code>null</code> the platform default will be used.
105
     * <p>
106
     * Note that in the most common scenario of execution of OS native
107
     * process you shouldn't need to set the charset. The platform default
108
     * (which is the default used) is just the right choice.
109
     * <p>
110
     * The default (not configured) value is <code>null</code>.
111
     * <p>
112
     * All other properties of the returned descriptor are inherited from
113
     * <code>this</code>.
114
     *
115
     * @param charset charset, <code>null</code> allowed
116
     * @return this descriptor with configured charset
117
     */
118
    @NonNull
119
    @CheckReturnValue
120
    public BaseExecutionDescriptor charset(@NullAllowed Charset charset) {
121
        return new BaseExecutionDescriptor(charset, preExecution, postExecution,
122
                outProcessorFactory, errProcessorFactory, inReaderFactory);
123
    }
124
125
    Charset getCharset() {
126
        return charset;
127
    }
128
129
    /**
130
     * Returns a descriptor with configured pre execution runnable. This
131
     * runnable is executed <i>before</i> the external execution itself
132
     * (when invoked by {@link BaseExecutionService#run()}).
133
     * <p>
134
     * The default (not configured) value is <code>null</code>.
135
     * <p>
136
     * All other properties of the returned descriptor are inherited from
137
     * <code>this</code>.
138
     *
139
     * @param preExecution pre execution runnable, <code>null</code> allowed
140
     * @return new descriptor with configured pre execution runnable
141
     */
142
    @NonNull
143
    @CheckReturnValue
144
    public BaseExecutionDescriptor preExecution(@NullAllowed Runnable preExecution) {
145
        return new BaseExecutionDescriptor(charset, preExecution, postExecution,
146
                outProcessorFactory, errProcessorFactory, inReaderFactory);
147
    }
148
149
    Runnable getPreExecution() {
150
        return preExecution;
151
    }
152
153
    /**
154
     * Returns a descriptor with configured post execution runnable. This
155
     * runnable is executed <i>after</i> the external execution itself
156
     * (when invoked by {@link BaseExecutionService#run()}).
157
     * <p>
158
     * The default (not configured) value is <code>null</code>.
159
     * <p>
160
     * All other properties of the returned descriptor are inherited from
161
     * <code>this</code>.
162
     *
163
     * @param postExecution post execution runnable, <code>null</code> allowed
164
     * @return new descriptor with configured post execution runnable
165
     */
166
    @NonNull
167
    @CheckReturnValue
168
    public BaseExecutionDescriptor postExecution(@NullAllowed ParametrizedRunnable<Integer> postExecution) {
169
        return new BaseExecutionDescriptor(charset, preExecution, postExecution,
170
                outProcessorFactory, errProcessorFactory, inReaderFactory);
171
    }
172
173
    ParametrizedRunnable<Integer> getPostExecution() {
174
        return postExecution;
175
    }
176
177
    /**
178
     * Returns a descriptor with configured factory for standard output
179
     * processor. The factory is used by {@link BaseExecutionService} to create
180
     * processor for standard output.
181
     * <p>
182
     * The default (not configured) value is <code>null</code>.
183
     * <p>
184
     * All other properties of the returned descriptor are inherited from
185
     * <code>this</code>.
186
     *
187
     * @param outProcessorFactory factory for standard output processor,
188
     *             <code>null</code> allowed
189
     * @return new descriptor with configured factory for additional
190
     *             processor to use for standard output
191
     */
192
    @NonNull
193
    @CheckReturnValue
194
    public BaseExecutionDescriptor outProcessorFactory(@NullAllowed InputProcessorFactory outProcessorFactory) {
195
        return new BaseExecutionDescriptor(charset, preExecution, postExecution,
196
                outProcessorFactory, errProcessorFactory, inReaderFactory);
197
    }
198
199
    InputProcessorFactory getOutProcessorFactory() {
200
        return outProcessorFactory;
201
    }
202
203
    /**
204
     * Returns a descriptor with configured factory for standard error output
205
     * processor. The factory is used by {@link BaseExecutionService} to create
206
     * processor for standard error output.
207
     * <p>
208
     * The default (not configured) value is <code>null</code>.
209
     * <p>
210
     * All other properties of the returned descriptor are inherited from
211
     * <code>this</code>.
212
     *
213
     * @param errProcessorFactory factory for standard error output processor,
214
     *             <code>null</code> allowed
215
     * @return new descriptor with configured factory for additional
216
     *             processor to use for standard error output
217
     */
218
    @NonNull
219
    @CheckReturnValue
220
    public BaseExecutionDescriptor errProcessorFactory(@NullAllowed InputProcessorFactory errProcessorFactory) {
221
        return new BaseExecutionDescriptor(charset, preExecution, postExecution,
222
                outProcessorFactory, errProcessorFactory, inReaderFactory);
223
    }
224
225
    InputProcessorFactory getErrProcessorFactory() {
226
        return errProcessorFactory;
227
    }
228
229
    /**
230
     * Returns a descriptor with configured factory for standard input reader.
231
     * The factory is used by {@link BaseExecutionService} to create
232
     * a reader providing input to the process.
233
     * <p>
234
     * The default (not configured) value is <code>null</code>.
235
     * <p>
236
     * All other properties of the returned descriptor are inherited from
237
     * <code>this</code>.
238
     *
239
     * @param inReaderFactory  factory for standard input reader,
240
     *             <code>null</code> allowed
241
     * @return new descriptor with configured factory for reader to use
242
     *             for standard input
243
     */
244
    @NonNull
245
    @CheckReturnValue
246
    public BaseExecutionDescriptor inReaderFactory(@NullAllowed ReaderFactory inReaderFactory) {
247
        return new BaseExecutionDescriptor(charset, preExecution, postExecution,
248
                outProcessorFactory, errProcessorFactory, inReaderFactory);
249
    }
250
251
    ReaderFactory getInReaderFactory() {
252
        return inReaderFactory;
253
    }
254
255
    /**
256
     * Factory creating the input processor.
257
     */
258
    public interface InputProcessorFactory {
259
260
        /**
261
         * Creates and returns new input processor.
262
         *
263
         * @return new input processor
264
         */
265
        @NonNull
266
        InputProcessor newInputProcessor();
267
268
    }
269
270
    /**
271
     * Factory creating the reader.
272
     */
273
    public interface ReaderFactory {
274
275
        /**
276
         * Creates and returns new reader.
277
         *
278
         * @return new reader
279
         */
280
        Reader newReader();
281
    }
282
283
}
(-)a/extexecution.base/src/org/netbeans/api/extexecution/base/BaseExecutionService.java (+389 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-2008 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
package org.netbeans.api.extexecution.base;
45
46
import java.io.BufferedInputStream;
47
import java.io.OutputStream;
48
import java.io.OutputStreamWriter;
49
import java.io.Reader;
50
import java.nio.charset.Charset;
51
import java.security.AccessController;
52
import java.security.PrivilegedAction;
53
import java.util.ArrayList;
54
import java.util.HashSet;
55
import java.util.List;
56
import java.util.Set;
57
import java.util.concurrent.Callable;
58
import java.util.concurrent.CountDownLatch;
59
import java.util.concurrent.ExecutorService;
60
import java.util.concurrent.Executors;
61
import java.util.concurrent.Future;
62
import java.util.concurrent.FutureTask;
63
import java.util.concurrent.TimeUnit;
64
import java.util.logging.Level;
65
import java.util.logging.Logger;
66
import org.netbeans.api.annotations.common.NonNull;
67
import org.netbeans.api.extexecution.base.BaseExecutionDescriptor.InputProcessorFactory;
68
import org.netbeans.api.extexecution.base.input.InputProcessor;
69
import org.netbeans.api.extexecution.base.input.InputProcessors;
70
import org.netbeans.api.extexecution.base.input.InputReaderTask;
71
import org.netbeans.api.extexecution.base.input.InputReaders;
72
import org.netbeans.modules.extexecution.base.ProcessInputStream;
73
import org.openide.util.Cancellable;
74
import org.openide.util.RequestProcessor;
75
76
/**
77
 * Base Execution service provides the facility to execute a process.
78
 * <p>
79
 * All processes launched by this class are terminated on VM exit (if
80
 * these are not finished or terminated earlier).
81
 *
82
 * <div class="nonnormative">
83
 * <p>
84
 * Sample usage (ls command):
85
 * <pre>
86
 *     BaseExecutionDescriptor descriptor = new BaseExecutionDescriptor()
87
 *             .outProcessorFactory(new BaseExecutionDescriptor.InputProcessorFactory() {
88
 *
89
 *         &#64;Override
90
 *         public InputProcessor newInputProcessor() {
91
 *             return InputProcessors.copying(new BufferedWriter(new OutputStreamWriter(System.out)));
92
 *         }
93
 *     });
94
 *
95
 *     ProcessBuilder processBuilder = ProcessBuilder.getLocal();
96
 *     processBuilder.setExecutable(ls);
97
 *
98
 *     BaseExecutionService service = BaseExecutionService.newService(processBuilder, descriptor);
99
 *     Future&lt;Integer&gt task = service.run();
100
 * </pre>
101
 * <p>
102
 * Even simpler usage but without displaying output (ls command):
103
 * <pre>
104
 *     ProcessBuilder processBuilder = ProcessBuilder.getLocal();
105
 *     processBuilder.setExecutable(ls);
106
 *
107
 *     ExecutionService service = ExecutionService.newService(processBuilder, new BaseExecutionDescriptor());
108
 *     Future&lt;Integer&gt task = service.run();
109
 * </pre>
110
 * </div>
111
 *
112
 * @author Petr Hejl
113
 * @see #newService(java.util.concurrent.Callable, org.netbeans.api.extexecution.base.BaseExecutionDescriptor)
114
 * @see BaseExecutionDescriptor
115
 */
116
public final class BaseExecutionService {
117
118
    private static final Logger LOGGER = Logger.getLogger(BaseExecutionService.class.getName());
119
120
    private static final Set<Process> RUNNING_PROCESSES = new HashSet<Process>();
121
122
    private static final int EXECUTOR_SHUTDOWN_SLICE = 1000;
123
124
    private static final ExecutorService EXECUTOR_SERVICE = new RequestProcessor(BaseExecutionService.class.getName(), Integer.MAX_VALUE);
125
126
    static {
127
128
        // shutdown hook
129
        Runtime.getRuntime().addShutdownHook(new Thread() {
130
131
            @Override
132
            public void run() {
133
                EXECUTOR_SERVICE.shutdown();
134
135
                synchronized (RUNNING_PROCESSES) {
136
                    for (Process process : RUNNING_PROCESSES) {
137
                        process.destroy();
138
                    }
139
                }
140
            }
141
        });
142
    }
143
144
    private final Callable<? extends Process> processCreator;
145
146
    private final BaseExecutionDescriptor descriptor;
147
148
    private BaseExecutionService(Callable<? extends Process> processCreator,
149
            BaseExecutionDescriptor descriptor) {
150
        this.processCreator = processCreator;
151
        this.descriptor = descriptor;
152
    }
153
154
    /**
155
     * Creates new execution service. Service will wrap up the processes
156
     * created by <code>processCreator</code> and will manage them.
157
     *
158
     * @param processCreator callable returning the process to wrap up
159
     * @param descriptor descriptor describing the configuration of service
160
     * @return new execution service
161
     */
162
    @NonNull
163
    public static BaseExecutionService newService(@NonNull Callable<? extends Process> processCreator,
164
            @NonNull BaseExecutionDescriptor descriptor) {
165
        return new BaseExecutionService(processCreator, descriptor);
166
    }
167
168
    /**
169
     * Runs the process described by this service. The call does not block
170
     * and the task is represented by the returned value. Integer returned
171
     * as a result of the {@link Future} is exit code of the process.
172
     * <p>
173
     * This method can be invoked multiple times returning the different and
174
     * unrelated {@link Future}s. On each call <code>Callable&lt;Process&gt;</code>
175
     * passed to {@link #newService(java.util.concurrent.Callable, org.netbeans.api.extexecution.base.BaseExecutionDescriptor)}
176
     * is invoked in order to create the process. If the process creation fails
177
     * (throwing an exception) returned <code>Future</code> will throw
178
     * {@link java.util.concurrent.ExecutionException} on {@link Future#get()}
179
     * request.
180
     * <p>
181
     * For details on execution control see {@link BaseExecutionDescriptor}.
182
     *
183
     * @return task representing the actual run, value representing result
184
     *             of the {@link Future} is exit code of the process
185
     */
186
    @NonNull
187
    public Future<Integer> run() {
188
        final Reader in;
189
        BaseExecutionDescriptor.ReaderFactory factory = descriptor.getInReaderFactory();
190
        if (factory != null) {
191
            in = factory.newReader();
192
        } else {
193
            in = null;
194
        }
195
196
        final CountDownLatch finishedLatch = new CountDownLatch(1);
197
198
        Callable<Integer> callable = new Callable<Integer>() {
199
            @Override
200
            public Integer call() throws Exception {
201
202
                boolean interrupted = false;
203
                Process process = null;
204
                Integer ret = null;
205
                ExecutorService executor = null;
206
207
                ProcessInputStream outStream = null;
208
                ProcessInputStream errStream = null;
209
210
                List<InputReaderTask> tasks = new ArrayList<InputReaderTask>();
211
212
                try {
213
                    final Runnable pre = descriptor.getPreExecution();
214
                    if (pre != null) {
215
                        pre.run();
216
                    }
217
218
                    if (Thread.currentThread().isInterrupted()) {
219
                        return null;
220
                    }
221
222
                    process = processCreator.call();
223
                    synchronized (RUNNING_PROCESSES) {
224
                        RUNNING_PROCESSES.add(process);
225
                    }
226
227
                    if (Thread.currentThread().isInterrupted()) {
228
                        return null;
229
                    }
230
231
                    outStream = new ProcessInputStream(process, process.getInputStream());
232
                    errStream = new ProcessInputStream(process, process.getErrorStream());
233
234
                    executor = Executors.newFixedThreadPool(in != null ? 3 : 2);
235
236
                    Charset charset = descriptor.getCharset();
237
                    if (charset == null) {
238
                        charset = Charset.defaultCharset();
239
                    }
240
241
                    tasks.add(InputReaderTask.newDrainingTask(
242
                        InputReaders.forStream(new BufferedInputStream(outStream), charset),
243
                        createOutProcessor()));
244
                    tasks.add(InputReaderTask.newDrainingTask(
245
                        InputReaders.forStream(new BufferedInputStream(errStream), charset),
246
                        createErrProcessor()));
247
                    if (in != null) {
248
                        tasks.add(InputReaderTask.newTask(
249
                            InputReaders.forReader(in),
250
                            createInProcessor(process.getOutputStream(), charset)));
251
                    }
252
                    for (InputReaderTask task : tasks) {
253
                        executor.submit(task);
254
                    }
255
256
                    process.waitFor();
257
                } catch (InterruptedException ex) {
258
                    LOGGER.log(Level.FINE, null, ex);
259
                    interrupted = true;
260
                } catch (Throwable t) {
261
                    LOGGER.log(Level.INFO, null, t);
262
                    throw new WrappedException(t);
263
                } finally {
264
                    try {
265
                        // fully evaluated - we want to clear interrupted status in any case
266
                        interrupted |= Thread.interrupted();
267
268
                        if (!interrupted) {
269
                            if (outStream != null) {
270
                                outStream.close(true);
271
                            }
272
                            if (errStream != null) {
273
                                errStream.close(true);
274
                            }
275
                        }
276
277
                        if (process != null) {
278
                            process.destroy();
279
                            synchronized (RUNNING_PROCESSES) {
280
                                RUNNING_PROCESSES.remove(process);
281
                            }
282
283
                            try {
284
                                ret = process.exitValue();
285
                            } catch (IllegalThreadStateException ex) {
286
                                LOGGER.log(Level.FINE, "Process not yet exited", ex);
287
                            }
288
                        }
289
                    } catch (Throwable t) {
290
                        LOGGER.log(Level.INFO, null, t);
291
                        throw new WrappedException(t);
292
                    } finally {
293
                        try {
294
                            cleanup(tasks, executor);
295
296
                            final ParametrizedRunnable<Integer> post
297
                                    = descriptor.getPostExecution();
298
                            if (post != null) {
299
                                post.run(ret);
300
                            }
301
                        } finally {
302
                            finishedLatch.countDown();
303
                            if (interrupted) {
304
                                Thread.currentThread().interrupt();
305
                            }
306
                        }
307
                    }
308
                }
309
310
                return ret;
311
            }
312
        };
313
314
        final FutureTask<Integer> current = new FutureTask<Integer>(callable) {
315
316
            @Override
317
            protected void setException(Throwable t) {
318
                if (t instanceof WrappedException) {
319
                    super.setException(((WrappedException) t).getCause());
320
                } else {
321
                    super.setException(t);
322
                }
323
            }
324
325
        };
326
327
        EXECUTOR_SERVICE.execute(current);
328
        return current;
329
    }
330
331
    private void cleanup(final List<InputReaderTask> tasks, final ExecutorService processingExecutor) {
332
        boolean interrupted = false;
333
        if (processingExecutor != null) {
334
            try {
335
                AccessController.doPrivileged(new PrivilegedAction<Void>() {
336
                    @Override
337
                    public Void run() {
338
                        processingExecutor.shutdown();
339
                        return null;
340
                    }
341
                });
342
                for (Cancellable cancellable : tasks) {
343
                    cancellable.cancel();
344
                }
345
                while (!processingExecutor.awaitTermination(EXECUTOR_SHUTDOWN_SLICE, TimeUnit.MILLISECONDS)) {
346
                    LOGGER.log(Level.INFO, "Awaiting processing finish");
347
                }
348
            } catch (InterruptedException ex) {
349
                interrupted = true;
350
            }
351
        }
352
353
        if (interrupted) {
354
            Thread.currentThread().interrupt();
355
        }
356
    }
357
358
    private InputProcessor createOutProcessor() {
359
        InputProcessor outProcessor = null;
360
        InputProcessorFactory descriptorOutFactory = descriptor.getOutProcessorFactory();
361
        if (descriptorOutFactory != null) {
362
            outProcessor = descriptorOutFactory.newInputProcessor();
363
        }
364
365
        return outProcessor;
366
    }
367
368
    private InputProcessor createErrProcessor() {
369
        InputProcessor errProcessor = null;
370
        InputProcessorFactory descriptorErrFactory = descriptor.getErrProcessorFactory();
371
        if (descriptorErrFactory != null) {
372
            errProcessor = descriptorErrFactory.newInputProcessor();
373
        }
374
375
        return errProcessor;
376
    }
377
378
    private InputProcessor createInProcessor(OutputStream os, Charset charset) {
379
        return InputProcessors.copying(new OutputStreamWriter(os, charset));
380
    }
381
382
    private static class WrappedException extends Exception {
383
384
        public WrappedException(Throwable cause) {
385
            super(cause);
386
        }
387
388
    }
389
}
(-)a/extexecution.base/src/org/netbeans/api/extexecution/base/Bundle.properties (+43 lines)
Line 0    Link Here 
1
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
2
#
3
# Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
4
#
5
# Oracle and Java are registered trademarks of Oracle and/or its affiliates.
6
# Other names may be trademarks of their respective owners.
7
#
8
# The contents of this file are subject to the terms of either the GNU
9
# General Public License Version 2 only ("GPL") or the Common
10
# Development and Distribution License("CDDL") (collectively, the
11
# "License"). You may not use this file except in compliance with the
12
# License. You can obtain a copy of the License at
13
# http://www.netbeans.org/cddl-gplv2.html
14
# or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
15
# specific language governing permissions and limitations under the
16
# License.  When distributing the software, include this License Header
17
# Notice in each file and include the License file at
18
# nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
19
# particular file as subject to the "Classpath" exception as provided
20
# by Oracle in the GPL Version 2 section of the License file that
21
# accompanied this code. If applicable, add the following below the
22
# License Header, with the fields enclosed by brackets [] replaced by
23
# your own identifying information:
24
# "Portions Copyrighted [year] [name of copyright owner]"
25
#
26
# Contributor(s):
27
#
28
# The Original Software is NetBeans. The Initial Developer of the Original
29
# Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
30
# Microsystems, Inc. All Rights Reserved.
31
#
32
# If you wish your version of this file to be governed by only the CDDL
33
# or only the GPL Version 2, indicate your decision by adding
34
# "[Contributor] elects to include this software in this distribution
35
# under the [CDDL or GPL Version 2] license." If you do not indicate a
36
# single choice of license, a recipient has the option to distribute
37
# your version of this file under either the CDDL, the GPL Version 2 or
38
# to extend the choice of license to its licensees as provided above.
39
# However, if you add GPL Version 2 code and therefore, elected the GPL
40
# Version 2 license, then the option applies only if the new code is
41
# made subject to such option by the copyright holder.
42
43
LocalProcessBuilder=Builder creating local processes
(-)a/extexecution.base/src/org/netbeans/api/extexecution/base/Environment.java (+155 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.base;
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.base.EnvironmentAccessor;
48
import org.netbeans.spi.extexecution.base.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
 */
58
public final class Environment {
59
60
    private final EnvironmentImplementation implementation;
61
62
    static {
63
        EnvironmentAccessor.setDefault(new EnvironmentAccessor() {
64
65
            @Override
66
            public Environment createEnvironment(EnvironmentImplementation impl) {
67
                return new Environment(impl);
68
            }
69
        });
70
    }
71
72
    private Environment(EnvironmentImplementation implementation) {
73
        this.implementation = implementation;
74
    }
75
76
    /**
77
     * Returns the value of the variable or <code>null</code>.
78
     *
79
     * @param name the name of the variable
80
     * @return the value of the variable or <code>null</code>
81
     */
82
    @CheckForNull
83
    public String getVariable(@NonNull String name) {
84
        Parameters.notNull("name", name);
85
86
        return implementation.getVariable(name);
87
    }
88
89
    /**
90
     * Appends a path to a path-like variable. The proper path separator is used
91
     * to separate the new value.
92
     *
93
     * @param name the name of the variable such as for example
94
     *             <code>PATH</code> or <code>LD_LIBRARY_PATH</code>
95
     * @param value the value (path to append)
96
     */
97
    public void appendPath(@NonNull String name, @NonNull String value) {
98
        Parameters.notNull("name", name);
99
        Parameters.notNull("value", value);
100
101
        implementation.appendPath(name, value);
102
    }
103
104
    /**
105
     * Prepends a path to a path-like variable. The proper path separator is used
106
     * to separate the new value.
107
     *
108
     * @param name the name of the variable such as for example
109
     *             <code>PATH</code> or <code>LD_LIBRARY_PATH</code>
110
     * @param value the value (path to prepend)
111
     */
112
    public void prependPath(@NonNull String name, @NonNull String value) {
113
        Parameters.notNull("name", name);
114
        Parameters.notNull("value", value);
115
116
        implementation.prependPath(name, value);
117
    }
118
119
    /**
120
     * Sets a value for a variable with the given name.
121
     *
122
     * @param name the name of the variable
123
     * @param value the value
124
     */
125
    public void setVariable(@NonNull String name, @NonNull String value) {
126
        Parameters.notNull("name", name);
127
        Parameters.notNull("value", value);
128
129
        implementation.setVariable(name, value);
130
    }
131
132
    /**
133
     * Removes a variable with the given name. The subsequent call to
134
     * {@link #getVariable(java.lang.String)} with the same argument will return
135
     * <code>null</code>.
136
     *
137
     * @param name the name of the variable
138
     */
139
    public void removeVariable(@NonNull String name) {
140
        Parameters.notNull("name", name);
141
142
        implementation.removeVariable(name);
143
    }
144
145
    /**
146
     * Returns all variable names and associated values as a {@link Map}.
147
     * Changes to the map are not propagated back to the {@link Environment}.
148
     *
149
     * @return all variable names and associated values
150
     */
151
    @NonNull
152
    public Map<String, String> values() {
153
        return implementation.values();
154
    }
155
}
(-)a/extexecution.base/src/org/netbeans/api/extexecution/base/ParametrizedRunnable.java (+59 lines)
Line 0    Link Here 
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2014 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 2014 Sun Microsystems, Inc.
41
 */
42
43
package org.netbeans.api.extexecution.base;
44
45
/**
46
 * The interface representing a runnable code accepting a parameter.
47
 *
48
 * @author Petr Hejl
49
 * @param <T> the type of required parameter
50
 */
51
public interface ParametrizedRunnable<T> {
52
53
    /**
54
     * The runnable code itself.
55
     *
56
     * @param parameter the parameter
57
     */
58
    void run(T parameter);
59
}
(-)a/extexecution.base/src/org/netbeans/api/extexecution/base/ProcessBuilder.java (+405 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.api.extexecution.base;
43
44
import java.io.File;
45
import java.io.IOException;
46
import java.util.ArrayList;
47
import java.util.HashMap;
48
import java.util.List;
49
import java.util.Locale;
50
import java.util.Map;
51
import java.util.concurrent.Callable;
52
import org.netbeans.api.annotations.common.NonNull;
53
import org.netbeans.api.annotations.common.NullAllowed;
54
import org.netbeans.modules.extexecution.base.ExternalProcessBuilder;
55
import org.netbeans.modules.extexecution.base.ProcessBuilderAccessor;
56
import org.netbeans.modules.extexecution.base.ProcessParametersAccessor;
57
import org.netbeans.spi.extexecution.base.EnvironmentFactory;
58
import org.netbeans.spi.extexecution.base.EnvironmentImplementation;
59
import org.netbeans.spi.extexecution.base.ProcessBuilderImplementation;
60
import org.netbeans.spi.extexecution.base.ProcessParameters;
61
import org.openide.util.Lookup;
62
import org.openide.util.NbBundle;
63
import org.openide.util.Parameters;
64
65
/**
66
 * Abstraction of process builders. You can freely configure the parameters
67
 * and then create a process by calling the {@link #call()} method. You can
68
 * also (re)configure the builder and spawn a different process.
69
 * <p>
70
 * Note the API does not prescribe the actual meaning of {@link Process}.
71
 * It may be local process, remote process or some other implementation.
72
 * <p>
73
 * You can use the default implementation returned by {@link #getLocal()}
74
 * for creating the local machine OS processes.
75
 * <p>
76
 * <i>Thread safety</i> of this class depends on thread safety of
77
 * the implementation class.
78
 * <p>
79
 * If the {@link ProcessBuilderImplementation} is used and it is thread
80
 * safe (if possible the implementation should be even stateless) this class
81
 * is thread safe as well.
82
 * <p>
83
 * If the {@link ProcessBuilderImplementation} is used and it is (including
84
 * {@link EnvironmentImplementation}) thread safe and does not have any mutable
85
 * configuration accessible via {@link ProcessBuilderImplementation#getLookup()}
86
 * it is thread safe as well. Otherwise it is not thread safe.
87
 * <p>
88
 * The synchronization mechanism used in this object is the {@link ProcessBuilderImplementation}
89
 * object monitor.
90
 *
91
 * @author Petr Hejl
92
 */
93
// TODO proxy autoconfiguration optional via lookup
94
public final class ProcessBuilder implements Callable<Process>, Lookup.Provider {
95
96
    private final ProcessBuilderImplementation implementation;
97
98
    private final Object lock;
99
100
    private final String description;
101
102
    /**<i>GuardedBy("lock")</i>*/
103
    private String executable;
104
105
    /**<i>GuardedBy("lock")</i>*/
106
    private String workingDirectory;
107
108
    /**<i>GuardedBy("lock")</i>*/
109
    private final List<String> arguments = new ArrayList<String>();
110
111
    /**<i>GuardedBy("lock")</i>*/
112
    private boolean redirectErrorStream;
113
114
    static {
115
        ProcessBuilderAccessor.setDefault(new ProcessBuilderAccessor() {
116
117
            @Override
118
            public ProcessBuilder createProcessBuilder(ProcessBuilderImplementation impl, String description) {
119
                return new ProcessBuilder(impl, description);
120
            }
121
        });
122
    }
123
124
    private ProcessBuilder(ProcessBuilderImplementation implementation2, String description) {
125
        assert implementation2 != null;
126
        this.implementation = implementation2;
127
        this.description = description;
128
129
        this.lock = implementation2;
130
    }
131
132
    /**
133
     * Returns the {@link ProcessBuilder} creating the OS process on local
134
     * machine. Returned implementation is <code>thread safe</code>.
135
     * The returned builder also attempts to properly configure HTTP proxy
136
     * for the process.
137
     *
138
     * @return the {@link ProcessBuilder} creating the OS process on local
139
     *             machine
140
     */
141
    public static ProcessBuilder getLocal() {
142
        return new ProcessBuilder(new LocalProcessBuilder(),
143
                NbBundle.getMessage(ProcessBuilder.class, "LocalProcessBuilder"));
144
    }
145
146
    /**
147
     * Returns the human readable description of this builder.
148
     *
149
     * @return the human readable description of this builder
150
     */
151
    @NonNull
152
    public String getDescription() {
153
        return description;
154
    }
155
156
    /**
157
     * Sets the executable to run. There is no default value. The {@link #call()}
158
     * methods throws {@link IllegalStateException} when there is no executable
159
     * configured.
160
     *
161
     * @param executable the executable to run
162
     */
163
    public void setExecutable(@NonNull String executable) {
164
        Parameters.notNull("executable", executable);
165
166
        synchronized (lock) {
167
            this.executable = executable;
168
        }
169
    }
170
171
    /**
172
     * Sets the working directory for the process created by subsequent call
173
     * of {@link #call()}. The default value is implementation specific.
174
     *
175
     * @param workingDirectory the working directory of the process
176
     */
177
    public void setWorkingDirectory(@NullAllowed String workingDirectory) {
178
        synchronized (lock) {
179
            this.workingDirectory = workingDirectory;
180
        }
181
    }
182
183
    /**
184
     * Sets the arguments passed to the process created by subsequent call
185
     * of {@link #call()}. By default there are no arguments.
186
     *
187
     * @param arguments the arguments passed to the process
188
     */
189
    public void setArguments(@NonNull List<String> arguments) {
190
        Parameters.notNull("arguments", arguments);
191
192
        synchronized (lock) {
193
            this.arguments.clear();
194
            this.arguments.addAll(arguments);
195
        }
196
    }
197
198
    /**
199
     * Configures the error stream redirection. If <code>true</code> the error
200
     * stream of process created by subsequent call of {@link #call()} method
201
     * will be redirected to standard output stream.
202
     *
203
     * @param redirectErrorStream the error stream redirection
204
     */
205
    public void setRedirectErrorStream(boolean redirectErrorStream) {
206
        synchronized (lock) {
207
            this.redirectErrorStream = redirectErrorStream;
208
        }
209
    }
210
211
    /**
212
     * Returns the object for environment variables manipulation.
213
     *
214
     * @return the object for environment variables manipulation
215
     */
216
    @NonNull
217
    public Environment getEnvironment() {
218
        return implementation.getEnvironment();
219
    }
220
221
    /**
222
     * Returns the associated {@link Lookup}. Extension point provided by
223
     * {@link ProcessBuilderImplementation}.
224
     *
225
     * @return the associated {@link Lookup}.
226
     * @see ProcessBuilderImplementation#getLookup()
227
     */
228
    @Override
229
    public Lookup getLookup() {
230
        if (implementation != null) {
231
            return implementation.getLookup();
232
        }
233
        return Lookup.EMPTY;
234
    }
235
236
237
    /**
238
     * Creates the new {@link Process} based on the properties configured
239
     * in this builder.
240
     * <p>
241
     * Actual behavior depends on the builder implementation, but it should
242
     * respect all the properties configured on this builder.
243
     *
244
     * @see ProcessBuilderImplementation
245
     * @return the new {@link Process} based on the properties configured
246
     *             in this builder
247
     * @throws IOException if the process could not be created
248
     * @throws IllegalStateException if there is no executable configured
249
     *             by {@link #setExecutable(java.lang.String)}
250
     */
251
    @NonNull
252
    @Override
253
    public Process call() throws IOException {
254
        String currentExecutable;
255
        String currentWorkingDirectory;
256
        List<String> currentArguments = new ArrayList<String>();
257
        Map<String, String> currentVariables = new HashMap<String, String>();
258
        boolean currentRedirectErrorStream;
259
260
        synchronized (lock) {
261
            currentExecutable = executable;
262
            currentWorkingDirectory = workingDirectory;
263
            currentArguments.addAll(arguments);
264
            currentRedirectErrorStream = redirectErrorStream;
265
            currentVariables.putAll(getEnvironment().values());
266
        }
267
268
        if (currentExecutable == null) {
269
            throw new IllegalStateException("The executable has not been configured");
270
        }
271
272
        ProcessParameters params = ProcessParametersAccessor.getDefault().createProcessParameters(
273
                currentExecutable, currentWorkingDirectory, currentArguments,
274
                currentRedirectErrorStream, currentVariables);
275
        return implementation.createProcess(params);
276
    }
277
278
//    /**
279
//     * Marks an object from which it is possible to get a {@link ProcessBuilder}.
280
//     */
281
//    public static interface Provider {
282
//
283
//        /**
284
//         * Returns the {@link ProcessBuilder} for the object.
285
//         *
286
//         * @return the {@link ProcessBuilder} for the object
287
//         * @throws IOException if there was a problem with the provision
288
//         */
289
//        ProcessBuilder getProcessBuilder() throws IOException;
290
//
291
//    }
292
293
    private static class LocalProcessBuilder implements ProcessBuilderImplementation {
294
295
        private final Environment environment = EnvironmentFactory.createEnvironment(
296
                new LocalEnvironment(this, System.getenv()));
297
298
        @Override
299
        public Environment getEnvironment() {
300
            return environment;
301
        }
302
303
        @Override
304
        public Lookup getLookup() {
305
            return Lookup.EMPTY;
306
        }
307
308
        @Override
309
        public Process createProcess(ProcessParameters parameters) throws IOException {
310
            ExternalProcessBuilder builder = new ExternalProcessBuilder(parameters.getExecutable());
311
            String workingDir = parameters.getWorkingDirectory();
312
            if (workingDir != null) {
313
                builder = builder.workingDirectory(new File(workingDir));
314
            }
315
            for (String argument : parameters.getArguments()) {
316
                builder = builder.addArgument(argument);
317
            }
318
            builder = builder.redirectErrorStream(parameters.isRedirectErrorStream());
319
320
            builder = builder.emptySystemVariables(true);
321
            for (Map.Entry<String, String> entry : parameters.getEnvironmentVariables().entrySet()) {
322
                builder = builder.addEnvironmentVariable(entry.getKey(), entry.getValue());
323
            }
324
325
            return builder.call();
326
        }
327
    }
328
329
    private static class LocalEnvironment implements EnvironmentImplementation {
330
331
        private final LocalProcessBuilder builder;
332
333
        private final Map<String, String> systemEnvironment;
334
335
        private final String pathName;
336
337
        public LocalEnvironment(LocalProcessBuilder builder, Map<String, String> systemEnvironment) {
338
            this.builder = builder;
339
            this.systemEnvironment = new HashMap<String, String>(systemEnvironment);
340
            this.pathName = ExternalProcessBuilder.getPathName(systemEnvironment);
341
        }
342
343
        @Override
344
        public String getVariable(String name) {
345
            synchronized (builder) {
346
                if ("PATH".equals(name.toUpperCase(Locale.ENGLISH))) { // NOI18N
347
                    return systemEnvironment.get(pathName);
348
                } else {
349
                    return systemEnvironment.get(name);
350
                }
351
            }
352
        }
353
354
        @Override
355
        public void appendPath(String name, String value) {
356
            putPath(name, value, false);
357
        }
358
359
        @Override
360
        public void prependPath(String name, String value) {
361
            putPath(name, value, true);
362
        }
363
364
        @Override
365
        public void setVariable(String name, String value) {
366
            synchronized (builder) {
367
                if ("PATH".equals(name.toUpperCase(Locale.ENGLISH))) { // NOI18N
368
                    systemEnvironment.put(pathName, value);
369
                } else {
370
                    systemEnvironment.put(name, value);
371
                }
372
            }
373
        }
374
375
        @Override
376
        public void removeVariable(String name) {
377
            synchronized (builder) {
378
                if ("PATH".equals(name.toUpperCase(Locale.ENGLISH))) { // NOI18N
379
                    systemEnvironment.remove(pathName);
380
                } else {
381
                    systemEnvironment.remove(name);
382
                }
383
            }
384
        }
385
386
        @Override
387
        public Map<String, String> values() {
388
            synchronized (builder) {
389
                return new HashMap<String, String>(systemEnvironment);
390
            }
391
        }
392
393
        private void putPath(String name, String value, boolean prepend) {
394
            synchronized (builder) {
395
                if ("PATH".equals(name.toUpperCase(Locale.ENGLISH))) { // NOI18N
396
                    ExternalProcessBuilder.putPath(new File(value), pathName,
397
                            prepend, systemEnvironment);
398
                } else {
399
                    ExternalProcessBuilder.putPath(new File(value), name,
400
                            prepend, systemEnvironment);
401
                }
402
            }
403
        }
404
    }
405
}
(-)a/extexecution.base/src/org/netbeans/api/extexecution/base/Processes.java (+82 lines)
Line 0    Link Here 
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2014 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 2014 Sun Microsystems, Inc.
41
 */
42
43
package org.netbeans.api.extexecution.base;
44
45
import java.util.Map;
46
import org.netbeans.spi.extexecution.base.ProcessesImplementation;
47
import org.openide.util.Lookup;
48
49
/**
50
 * The utility class for better processes handling.
51
 *
52
 * @author Petr Hejl
53
 * @see ProcessesImplementation
54
 */
55
public final class Processes {
56
57
    private Processes() {
58
        super();
59
    }
60
61
    /**
62
     * Kills the process passed as parameter and <i>attempts</i> to terminate
63
     * all child processes in process tree.
64
     * <p>
65
     * Any process running in environment containing the same variables
66
     * with the same values as those passed in <code>env</code> (all of them)
67
     * is supposed to be part of the process tree and may be killed.
68
     *
69
     * @param process process to kill
70
     * @param environment map containing the variables and their values which the
71
     *             process must have to be considered being part of
72
     *             the tree to kill
73
     */
74
    public static void killTree(Process process, Map<String, String> environment) {
75
        ProcessesImplementation impl = Lookup.getDefault().lookup(ProcessesImplementation.class);
76
        if (impl != null) {
77
            impl.killTree(process, environment);
78
        }
79
80
        process.destroy();
81
    }
82
}
(-)a/extexecution.base/src/org/netbeans/api/extexecution/base/input/InputProcessor.java (+92 lines)
Line 0    Link Here 
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 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
 * 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 2008 Sun Microsystems, Inc.
41
 */
42
43
package org.netbeans.api.extexecution.base.input;
44
45
import java.io.Closeable;
46
import java.io.IOException;
47
import org.netbeans.api.annotations.common.NonNull;
48
49
/**
50
 * Processes chars read by {@link InputReader}.
51
 * <p>
52
 * When the implementation is used just by single InputReader it
53
 * does not have to be thread safe.
54
 *
55
 * @author Petr Hejl
56
 * @see InputReader
57
 */
58
public interface InputProcessor extends Closeable, AutoCloseable {
59
60
    /**
61
     * Processes the characters.
62
     *
63
     * @param chars characters to process
64
     * @throws IOException if any processing error occurs
65
     */
66
    void processInput(@NonNull char[] chars) throws IOException;
67
68
    /**
69
     * Notifies the processor that it should reset its state.
70
     * <p>
71
     * The circumstances when this method is called must be defined
72
     * by the particular {@link InputReader}.
73
     * <p>
74
     * <div class="nonnormative">
75
     * For example reset is called by reader returned from
76
     * {@link InputReaders#forFileInputProvider(org.netbeans.api.extexecution.base.input.InputReaders.FileInput.Provider) }
77
     * when the provided file is changed.
78
     * </div>
79
     *
80
     * @throws IOException if error occurs while reseting
81
     */
82
    void reset() throws IOException;
83
84
    /**
85
     * Closes the processor releasing the resources held by it.
86
     *
87
     * @throws IOException if error occurs while closing
88
     */
89
    @Override
90
    void close() throws IOException;
91
92
}
(-)a/extexecution.base/src/org/netbeans/api/extexecution/base/input/InputProcessors.java (+416 lines)
Line 0    Link Here 
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 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
 * 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 2008 Sun Microsystems, Inc.
41
 */
42
43
package org.netbeans.api.extexecution.base.input;
44
45
import java.io.IOException;
46
import java.io.PrintWriter;
47
import java.io.Writer;
48
import java.util.ArrayList;
49
import java.util.Arrays;
50
import java.util.List;
51
import java.util.logging.Level;
52
import java.util.logging.Logger;
53
import org.netbeans.api.annotations.common.NonNull;
54
import org.netbeans.modules.extexecution.base.input.LineParsingHelper;
55
import org.openide.util.Parameters;
56
57
/**
58
 * Factory methods for {@link InputProcessor} classes.
59
 *
60
 * @author Petr Hejl
61
 */
62
public final class InputProcessors {
63
64
    private static final Logger LOGGER = Logger.getLogger(InputProcessors.class.getName());
65
66
    private InputProcessors() {
67
        super();
68
    }
69
70
    /**
71
     * Returns the processor converting characters to the whole lines passing
72
     * them to the given line processor.
73
     * <p>
74
     * Any reset or close is delegated to the corresponding method
75
     * of line processor.
76
     * <p>
77
     * Returned processor is <i>not thread safe</i>.
78
     *
79
     * @param lineProcessor processor consuming parsed lines
80
     * @return the processor converting characters to the whole lines
81
     */
82
    @NonNull
83
    public static InputProcessor bridge(@NonNull LineProcessor lineProcessor) {
84
        return new Bridge(lineProcessor);
85
    }
86
87
    /**
88
     * Returns the processor acting as a proxy.
89
     * <p>
90
     * Any action taken on this processor is distributed to all processors
91
     * passed as arguments in the same order as they were passed to this method.
92
     * <p>
93
     * Returned processor is <i>not thread safe</i>.
94
     *
95
     * @param processors processor to which the actions will be distributed
96
     * @return the processor acting as a proxy
97
     */
98
    @NonNull
99
    public static InputProcessor proxy(@NonNull InputProcessor... processors) {
100
        return new ProxyInputProcessor(processors);
101
    }
102
103
    /**
104
     * Returns the processor that writes every character passed for processing
105
     * to the given writer.
106
     * <p>
107
     * Reset action on the returned processor is noop. Processor closes the
108
     * writer on {@link InputProcessor#close()}.
109
     * <p>
110
     * Returned processor is <i>not thread safe</i>.
111
     *
112
     * @param writer processed characters will be written to this writer
113
     * @return the processor that writes every character passed for processing
114
     *             to the given writer
115
     */
116
    @NonNull
117
    public static InputProcessor copying(@NonNull Writer writer) {
118
        return new CopyingInputProcessor(writer);
119
    }
120
121
    /**
122
     * Returns the processor printing all characters passed for processing to
123
     * the given writer.
124
     * <p>
125
     * Reset action on the returned processor is noop. Processor closes the
126
     * writer on {@link InputProcessor#close()}.
127
     * <p>
128
     * Returned processor is <i>not thread safe</i>.
129
     *
130
     * @param out where to print received characters
131
     * @return the processor printing all characters passed for processing to
132
     *             the given writer
133
     */
134
    @NonNull
135
    public static InputProcessor printing(@NonNull PrintWriter out) {
136
        return new PrintingInputProcessor(out);
137
    }
138
139
    /**
140
     * Returns the processor that strips any
141
     * <a href="http://en.wikipedia.org/wiki/ANSI_escape_code">ANSI escape sequences</a>
142
     * and passes the result to the delegate.
143
     * <p>
144
     * Reset and close methods on the returned processor invokes
145
     * the corresponding actions on delegate.
146
     * <p>
147
     * Returned processor is <i>not thread safe</i>.
148
     *
149
     * @param delegate processor that will receive characters without control
150
     *             sequences
151
     * @return the processor that strips any ANSI escape sequences and passes
152
     *             the result to the delegate
153
     */
154
    @NonNull
155
    public static InputProcessor ansiStripping(@NonNull InputProcessor delegate) {
156
        return new AnsiStrippingInputProcessor(delegate);
157
    }
158
159
    private static class Bridge implements InputProcessor {
160
161
        private final LineProcessor lineProcessor;
162
163
        private final LineParsingHelper helper = new LineParsingHelper();
164
165
        private boolean closed;
166
167
        public Bridge(LineProcessor lineProcessor) {
168
            Parameters.notNull("lineProcessor", lineProcessor);
169
170
            this.lineProcessor = lineProcessor;
171
        }
172
173
        @Override
174
        public final void processInput(char[] chars) {
175
            if (closed) {
176
                throw new IllegalStateException("Already closed processor");
177
            }
178
179
            String[] lines = helper.parse(chars);
180
            for (String line : lines) {
181
                lineProcessor.processLine(line);
182
            }
183
        }
184
185
        @Override
186
        public final void reset() {
187
            if (closed) {
188
                throw new IllegalStateException("Already closed processor");
189
            }
190
191
            flush();
192
            lineProcessor.reset();
193
        }
194
195
        @Override
196
        public final void close() {
197
            closed = true;
198
199
            flush();
200
            lineProcessor.close();
201
        }
202
203
        private void flush() {
204
            String line = helper.getTrailingLine(true);
205
            if (line != null) {
206
                lineProcessor.processLine(line);
207
            }
208
        }
209
    }
210
211
    private static class ProxyInputProcessor implements InputProcessor {
212
213
        private final List<InputProcessor> processors = new ArrayList<InputProcessor>();
214
215
        private boolean closed;
216
217
        public ProxyInputProcessor(InputProcessor... processors) {
218
            for (InputProcessor processor : processors) {
219
                if (processor != null) {
220
                    this.processors.add(processor);
221
                }
222
            }
223
        }
224
225
        @Override
226
        public void processInput(char[] chars) throws IOException {
227
            if (closed) {
228
                throw new IllegalStateException("Already closed processor");
229
            }
230
231
            for (InputProcessor processor : processors) {
232
                processor.processInput(chars);
233
            }
234
        }
235
236
        @Override
237
        public void reset() throws IOException {
238
            if (closed) {
239
                throw new IllegalStateException("Already closed processor");
240
            }
241
242
            for (InputProcessor processor : processors) {
243
                processor.reset();
244
            }
245
        }
246
247
        @Override
248
        public void close() throws IOException {
249
            closed = true;
250
251
            for (InputProcessor processor : processors) {
252
                processor.close();
253
            }
254
        }
255
    }
256
257
    private static class PrintingInputProcessor implements InputProcessor {
258
259
        private final PrintWriter out;
260
261
        private final LineParsingHelper helper = new LineParsingHelper();
262
263
        private boolean closed;
264
265
        public PrintingInputProcessor(PrintWriter out) {
266
            assert out != null;
267
268
            this.out = out;
269
        }
270
271
        @Override
272
        public void processInput(char[] chars) {
273
            assert chars != null;
274
275
            if (closed) {
276
                throw new IllegalStateException("Already closed processor");
277
            }
278
279
            String[] lines = helper.parse(chars);
280
            for (String line : lines) {
281
                LOGGER.log(Level.FINEST, "{0}\\n", line);
282
283
                out.println(line);
284
                out.flush();
285
            }
286
287
            String line = helper.getTrailingLine(true);
288
            if (line != null) {
289
                LOGGER.log(Level.FINEST, line);
290
291
                out.print(line);
292
                out.flush();
293
            }
294
        }
295
296
        @Override
297
        public void reset() throws IOException {
298
            // noop
299
        }
300
301
        @Override
302
        public void close() throws IOException {
303
            closed = true;
304
305
            out.close();
306
        }
307
    }
308
309
    private static class CopyingInputProcessor implements InputProcessor {
310
311
        private final Writer writer;
312
313
        private boolean closed;
314
315
        public CopyingInputProcessor(Writer writer) {
316
            this.writer = writer;
317
        }
318
319
        @Override
320
        public void processInput(char[] chars) throws IOException {
321
            if (closed) {
322
                throw new IllegalStateException("Already closed processor");
323
            }
324
325
            LOGGER.log(Level.FINEST, Arrays.toString(chars));
326
            writer.write(chars);
327
            writer.flush();
328
        }
329
330
        @Override
331
        public void reset() {
332
            // noop
333
        }
334
335
        @Override
336
        public void close() throws IOException {
337
            closed = true;
338
339
            writer.close();
340
        }
341
    }
342
343
    private static class AnsiStrippingInputProcessor implements InputProcessor {
344
345
        private final InputProcessor delegate;
346
347
        private boolean closed;
348
349
        public AnsiStrippingInputProcessor(InputProcessor delegate) {
350
            this.delegate = delegate;
351
        }
352
353
        @Override
354
        public void processInput(char[] chars) throws IOException {
355
            if (closed) {
356
                throw new IllegalStateException("Already closed processor");
357
            }
358
359
            // FIXME optimize me
360
            String sequence = new String(chars);
361
            if (containsAnsiColors(sequence)) {
362
                sequence = stripAnsiColors(sequence);
363
            }
364
            delegate.processInput(sequence.toCharArray());
365
        }
366
367
        @Override
368
        public void reset() throws IOException {
369
            if (closed) {
370
                throw new IllegalStateException("Already closed processor");
371
            }
372
373
            delegate.reset();
374
        }
375
376
        @Override
377
        public void close() throws IOException {
378
            closed = true;
379
380
            delegate.close();
381
        }
382
383
        private static boolean containsAnsiColors(String sequence) {
384
            // RSpec will color output with ANSI color sequence terminal escapes
385
            return sequence.indexOf("\033[") != -1; // NOI18N
386
        }
387
388
        private static String stripAnsiColors(String sequence) {
389
            StringBuilder sb = new StringBuilder(sequence.length());
390
            int index = 0;
391
            int max = sequence.length();
392
            while (index < max) {
393
                int nextEscape = sequence.indexOf("\033[", index); // NOI18N
394
                if (nextEscape == -1) {
395
                    nextEscape = sequence.length();
396
                }
397
398
                for (int n = (nextEscape == -1) ? max : nextEscape; index < n; index++) {
399
                    sb.append(sequence.charAt(index));
400
                }
401
402
                if (nextEscape != -1) {
403
                    for (; index < max; index++) {
404
                        char c = sequence.charAt(index);
405
                        if (c == 'm') {
406
                            index++;
407
                            break;
408
                        }
409
                    }
410
                }
411
            }
412
413
            return sb.toString();
414
        }
415
    }
416
}
(-)a/extexecution.base/src/org/netbeans/api/extexecution/base/input/InputReader.java (+80 lines)
Line 0    Link Here 
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 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
 * 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 2008 Sun Microsystems, Inc.
41
 */
42
43
package org.netbeans.api.extexecution.base.input;
44
45
import java.io.Closeable;
46
import java.io.IOException;
47
import org.netbeans.api.annotations.common.NullAllowed;
48
49
/**
50
 * This interface represents abstraction for reading characters. It allows
51
 * custom processing of such characters through the given processor.
52
 * <p>
53
 * For safe usage in {@link InputReaderTask} implementation of this
54
 * interface has to be responsive to interruption.
55
 *
56
 * @author Petr Hejl
57
 */
58
public interface InputReader extends Closeable, AutoCloseable {
59
60
    /**
61
     * Reads some input and process it through the processor (if any).
62
     * <p>
63
     * Implementation of this method has to be non blocking
64
     * for safe usage in {@link InputReaderTask}.
65
     *
66
     * @param processor consumer of read characters, may be <code>null</code>
67
     * @return number of characters read
68
     * @throws IOException if any read or process error occurs
69
     */
70
    int readInput(@NullAllowed InputProcessor processor) throws IOException;
71
72
    /**
73
     * Closes the reader releasing the resources held by it.
74
     *
75
     * @throws IOException if error occurs while closing
76
     */
77
    @Override
78
    void close() throws IOException;
79
80
}
(-)a/extexecution.base/src/org/netbeans/api/extexecution/base/input/InputReaderTask.java (+271 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
package org.netbeans.api.extexecution.base.input;
46
47
import java.io.IOException;
48
import java.util.logging.Level;
49
import java.util.logging.Logger;
50
import org.netbeans.api.annotations.common.NonNull;
51
import org.netbeans.api.annotations.common.NullAllowed;
52
import org.openide.util.Cancellable;
53
import org.openide.util.Parameters;
54
55
/**
56
 * Task consuming data from the certain reader, processing them with the given
57
 * processor.
58
 * <p>
59
 * When exception occurs while the task is running the task is terminated.
60
 * Task is responsive to interruption. InputReader is closed on finish (includes
61
 * both cases throwing an exception and interruption).
62
 * <p>
63
 * The {@link #run()} method can be executed just once.
64
 * <p>
65
 * Task is <i>not finished</i> implicitly by reaching the end of the reader.
66
 * The caller has to finish it either by interruption or explicit cancellation.
67
 * Cancellation is preferred in situations where the interruption could make
68
 * cleanup operations on {@link InputProcessor} impossible to happen.
69
 *
70
 * <div class="nonnormative">
71
 * <p>
72
 * Sample usage - reading standard output of the process (throwing the data away):
73
 * <pre>
74
 *     java.lang.Process process = ...
75
 *     java.util.concurrent.ExecutorService executorService = ...
76
 *     Runnable runnable = InputReaderTask.newTask(
77
 *         InputReaders.forStream(process.getInputStream(), Charset.defaultCharset()));
78
 *     executorService.submit(runnable);
79
 *
80
 *     ...
81
 *
82
 *     executorService.shutdownNow();
83
 * </pre>
84
 * Sample usage - forwarding data to standard input of the process:
85
 * <pre>
86
 *     java.lang.Process process = ...
87
 *     java.util.concurrent.ExecutorService executorService = ...
88
 *     Runnable runnable = InputReaderTask.newTask(
89
 *         InputReaders.forStream(System.in, Charset.defaultCharset()),
90
 *         InputProcessors.copying(new OutputStreamWriter(process.getOutputStream())));
91
 *     executorService.submit(runnable);
92
 *
93
 *     ...
94
 *
95
 *     executorService.shutdownNow();
96
 * </pre>
97
 * </div>
98
 *
99
 * @author Petr Hejl
100
 */
101
public final class InputReaderTask implements Runnable, Cancellable {
102
103
    private static final Logger LOGGER = Logger.getLogger(InputReaderTask.class.getName());
104
105
    private static final int MIN_DELAY = 50;
106
107
    private static final int MAX_DELAY = 300;
108
109
    private static final int DELAY_INCREMENT = 50;
110
111
    private final InputReader inputReader;
112
113
    private final InputProcessor inputProcessor;
114
115
    private final boolean draining;
116
117
    private boolean cancelled;
118
119
    private boolean running;
120
121
    private InputReaderTask(InputReader inputReader, InputProcessor inputProcessor, boolean draining) {
122
        this.inputReader = inputReader;
123
        this.inputProcessor = inputProcessor;
124
        this.draining = draining;
125
    }
126
127
    /**
128
     * Creates a new task. The task will read the data from reader processing
129
     * them through processor (if any) until interrupted or canceled.
130
     * <p>
131
     * <i>{@link InputReader} must be non blocking.</i>
132
     *
133
     * @param reader data producer
134
     * @param processor processor consuming the data, may be <code>null</code>
135
     * @return task handling the read process
136
     */
137
    @NonNull
138
    public static InputReaderTask newTask(@NonNull InputReader reader, @NullAllowed InputProcessor processor) {
139
        Parameters.notNull("reader", reader);
140
141
        return new InputReaderTask(reader, processor, false);
142
    }
143
144
    /**
145
     * Creates the new task. The task will read the data from reader processing
146
     * them through processor (if any). When interrupted or canceled task will
147
     * try to read all the remaining <i>available</i> data before exiting.
148
     * <p>
149
     * <i>{@link InputReader} must be non blocking.</i>
150
     *
151
     * @param reader data producer
152
     * @param processor processor consuming the data, may be <code>null</code>
153
     * @return task handling the read process
154
     */
155
    @NonNull
156
    public static InputReaderTask newDrainingTask(@NonNull InputReader reader, @NullAllowed InputProcessor processor) {
157
        Parameters.notNull("reader", reader);
158
159
        return new InputReaderTask(reader, processor, true);
160
    }
161
162
    /**
163
     * Task repeatedly reads the data from the InputReader, passing the content
164
     * to InputProcessor (if any).
165
     * <p>
166
     * It is not allowed to invoke run multiple times.
167
     */
168
    @Override
169
    public void run() {
170
        synchronized (this) {
171
            if (running) {
172
                throw new IllegalStateException("Already running task");
173
            }
174
            running = true;
175
        }
176
177
        boolean interrupted = false;
178
        try {
179
            long delay = MIN_DELAY;
180
            int emptyReads = 0;
181
182
            while (true) {
183
                synchronized (this) {
184
                    if (Thread.currentThread().isInterrupted() || cancelled) {
185
                        interrupted = Thread.interrupted();
186
                        break;
187
                    }
188
                }
189
190
                int count = inputReader.readInput(inputProcessor);
191
192
                // compute the delay based on how often we really get the data
193
                if (count > 0) {
194
                    delay = MIN_DELAY;
195
                    emptyReads = 0;
196
                } else {
197
                    // increase the delay only slowly - once for
198
                    // MAX_DELAY / DELAY_INCREMENT unsuccesfull read attempts
199
                    if (emptyReads > (MAX_DELAY / DELAY_INCREMENT)) {
200
                        emptyReads = 0;
201
                        delay = Math.min(delay + DELAY_INCREMENT, MAX_DELAY);
202
                    } else {
203
                        emptyReads++;
204
                    }
205
                }
206
207
                if (LOGGER.isLoggable(Level.FINEST)) {
208
                    LOGGER.log(Level.FINEST, "Task {0} sleeping for {1} ms",
209
                            new Object[] {Thread.currentThread().getName(), delay});
210
                }
211
                try {
212
                    // give the producer some time to write the output
213
                    Thread.sleep(delay);
214
                } catch (InterruptedException e) {
215
                    interrupted = true;
216
                    break;
217
                }
218
            }
219
220
            synchronized (this) {
221
                if (Thread.currentThread().isInterrupted() || cancelled) {
222
                    interrupted = Thread.interrupted();
223
                }
224
            }
225
        } catch (Exception ex) {
226
            LOGGER.log(Level.FINE, null, ex);
227
        } finally {
228
            // drain the rest
229
            if (draining) {
230
                try {
231
                    while (inputReader.readInput(inputProcessor) > 0) {
232
                        LOGGER.log(Level.FINE, "Draining the rest of the reader");
233
                    }
234
                } catch (IOException ex) {
235
                    LOGGER.log(Level.FINE, null, ex);
236
                }
237
            }
238
239
            // perform cleanup
240
            try {
241
                if (inputProcessor != null) {
242
                    inputProcessor.close();
243
                }
244
                inputReader.close();
245
            } catch (IOException ex) {
246
                LOGGER.log(Level.INFO, null, ex);
247
            } finally {
248
                if (interrupted) {
249
                    Thread.currentThread().interrupt();
250
                }
251
            }
252
        }
253
    }
254
255
    /**
256
     * Cancels the task. If the task is not running or task is already canceled
257
     * this is noop.
258
     *
259
     * @return <code>true</code> if the task was successfully canceled
260
     */
261
    @Override
262
    public boolean cancel() {
263
        synchronized (this) {
264
            if (cancelled) {
265
                return false;
266
            }
267
            cancelled = true;
268
            return true;
269
        }
270
    }
271
}
(-)a/extexecution.base/src/org/netbeans/api/extexecution/base/input/InputReaders.java (+238 lines)
Line 0    Link Here 
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 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
 * 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 2008 Sun Microsystems, Inc.
41
 */
42
43
package org.netbeans.api.extexecution.base.input;
44
45
import java.io.File;
46
import java.io.InputStream;
47
import java.io.InputStreamReader;
48
import java.io.Reader;
49
import java.io.StringReader;
50
import java.nio.charset.Charset;
51
import org.netbeans.api.annotations.common.CheckForNull;
52
import org.netbeans.api.annotations.common.NonNull;
53
import org.netbeans.modules.extexecution.base.input.FileInputReader;
54
import org.netbeans.modules.extexecution.base.input.DefaultInputReader;
55
import org.openide.util.Parameters;
56
57
/**
58
 * Factory methods for {@link InputReader} classes.
59
 *
60
 * @author Petr Hejl
61
 */
62
public final class InputReaders {
63
64
    private InputReaders() {
65
        super();
66
    }
67
68
    /**
69
     * Returns the input reader backed by the given reader.
70
     * <p>
71
     * The client should not use the reader passed as argument anymore. When
72
     * the returned input reader is closed reader passed as argument is closed
73
     * respectively.
74
     * <p>
75
     * Returned reader will never call reset on {@link InputProcessor} while
76
     * reading.
77
     * <p>
78
     * Returned reader is <i>not thread safe</i> so it can't be used in
79
     * multiple instances of {@link InputReaderTask}.
80
     *
81
     * @param reader real source of the data
82
     * @return input reader backed by the given reader
83
     */
84
    @NonNull
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
        }
92
        return new DefaultInputReader(reader, true);
93
    }
94
95
    /**
96
     * Returns the input reader backed by the given stream. To convert read
97
     * bytes to characters specified charset is used.
98
     * <p>
99
     * The client should not use the stream passed as argument anymore. When
100
     * the returned input reader is closed stream is closed respectively.
101
     * <p>
102
     * Returned reader will never call reset on {@link InputProcessor} while
103
     * reading.
104
     * <p>
105
     * Returned reader is <i>not thread safe</i> so it can't be used in
106
     * multiple instances of {@link InputReaderTask}.
107
     *
108
     * @param stream real source of the data
109
     * @param charset bytes to characters conversion charset
110
     * @return input reader backed by the given stream
111
     */
112
    @NonNull
113
    public static InputReader forStream(@NonNull InputStream stream, @NonNull Charset charset) {
114
        Parameters.notNull("stream", stream);
115
116
        return forReader(new InputStreamReader(stream, charset));
117
    }
118
119
    /**
120
     * Returns the input reader for the given file. To convert read bytes
121
     * to characters specified charset is used.
122
     * <p>
123
     * Returned reader will never call reset on {@link InputProcessor} while
124
     * reading.
125
     * <p>
126
     * Returned reader is <i>not thread safe</i> so it can't be used in
127
     * multiple instances of {@link InputReaderTask}.
128
     *
129
     * @param file file to read from
130
     * @param charset bytes to characters conversion charset
131
     * @return input reader for the given file
132
     */
133
    @NonNull
134
    public static InputReader forFile(@NonNull File file, @NonNull Charset charset) {
135
        Parameters.notNull("file", file);
136
        Parameters.notNull("charset", charset);
137
138
        final FileInput fileInput = new FileInput(file, charset);
139
        return forFileInputProvider(new FileInput.Provider() {
140
141
            @Override
142
            public FileInput getFileInput() {
143
                return fileInput;
144
            }
145
        });
146
    }
147
148
    /**
149
     * Returns the input reader reading data from the given provider.
150
     * <p>
151
     * This means that the actual file (and the corresponding charset) used
152
     * can change during the processing. This is specifically useful for
153
     * rotating log files.
154
     * <p>
155
     * Before each read cycle reader invokes {@link FileInput.Provider#getFileInput()}
156
     * to determine the actual file to read.
157
     * <p>
158
     * When processing the input {@link InputProcessor#reset()} is called on
159
     * each file change (when provided file input differs from the previous one).
160
     * <p>
161
     * Returned reader is <i>not thread safe</i> so it can't be used in
162
     * multiple instances of {@link InputReaderTask}.
163
     *
164
     * @param fileProvider provider used to get the file to process
165
     * @return input reader for the given provider
166
     */
167
    @NonNull
168
    public static InputReader forFileInputProvider(@NonNull FileInput.Provider fileProvider) {
169
        Parameters.notNull("fileProvider", fileProvider);
170
171
        return new FileInputReader(fileProvider);
172
    }
173
174
    /**
175
     * Represents the file with associated charset for reading from it.
176
     *
177
     * This class is <i>immutable</i>.
178
     */
179
    public static final class FileInput {
180
181
        private final File file;
182
183
        private final Charset charset;
184
185
        /**
186
         * Creates the new input representing the given file.
187
         *
188
         * @param file file to represent
189
         * @param charset associated charset
190
         */
191
        public FileInput(@NonNull File file, @NonNull Charset charset) {
192
            Parameters.notNull("file", file);
193
            Parameters.notNull("charset", charset);
194
195
            this.file = file;
196
            this.charset = charset;
197
        }
198
199
        /**
200
         * Returns the charset for reading the file.
201
         *
202
         * @return the charset for reading the file
203
         */
204
        @NonNull
205
        public Charset getCharset() {
206
            return charset;
207
        }
208
209
        /**
210
         * Returns the file represented by this input.
211
         *
212
         * @return the file represented by this input
213
         */
214
        @NonNull
215
        public File getFile() {
216
            return file;
217
        }
218
219
        /**
220
         * Provides the file input.
221
         *
222
         * @see InputReaders#forFileInputProvider(org.netbeans.api.extexecution.base.input.InputReaders.FileInput.Provider)
223
         */
224
        public interface Provider {
225
226
            /**
227
             * Returns the file input to use or <code>null</code> if there is
228
             * no file to read currently.
229
             *
230
             * @return the file input to use or <code>null</code> if there is
231
             * no file to read currently
232
             */
233
            @CheckForNull
234
            FileInput getFileInput();
235
236
        }
237
    }
238
}
(-)a/extexecution.base/src/org/netbeans/api/extexecution/base/input/LineProcessor.java (+89 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
package org.netbeans.api.extexecution.base.input;
46
47
import java.io.Closeable;
48
import org.netbeans.api.annotations.common.NonNull;
49
50
/**
51
 * Processes the lines fetched by {@link InputReader} usually with help
52
 * of the {@link InputProcessors#bridge(LineProcessor)}.
53
 * <p>
54
 * When the implementation is used just by single bridge it
55
 * does not have to be thread safe.
56
 *
57
 * @author Petr Hejl
58
 * @see InputProcessors#bridge(LineProcessor)
59
 * @see InputReader
60
 */
61
public interface LineProcessor extends Closeable, AutoCloseable {
62
63
    /**
64
     * Processes the line.
65
     *
66
     * @param line the line to process
67
     */
68
    void processLine(@NonNull String line);
69
70
    /**
71
     * Notifies the processor that it should reset its state.
72
     * <p>
73
     * The circumstances when this method is called must be defined by
74
     * the code using this class.
75
     * <div class="nonnormative">
76
     * For example processor created with
77
     * {@link InputProcessors#bridge(LineProcessor)} delegates any call
78
     * to {@link InputProcessor#reset()} to this method.
79
     * </div>
80
     */
81
    void reset();
82
83
    /**
84
     * Closes the processor releasing the resources held by it.
85
     */
86
    @Override
87
    void close();
88
89
}
(-)a/extexecution.base/src/org/netbeans/api/extexecution/base/input/LineProcessors.java (+257 lines)
Line 0    Link Here 
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 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
 * 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 2008 Sun Microsystems, Inc.
41
 */
42
43
package org.netbeans.api.extexecution.base.input;
44
45
import java.io.PrintWriter;
46
import java.util.ArrayList;
47
import java.util.List;
48
import java.util.concurrent.CountDownLatch;
49
import java.util.logging.Level;
50
import java.util.logging.Logger;
51
import java.util.regex.Pattern;
52
import org.netbeans.api.annotations.common.NonNull;
53
54
/**
55
 * Factory methods for {@link LineProcessor} classes.
56
 * <p>
57
 * Note that main difference between {@link InputProcessor} and
58
 * {@link LineProcessor} is that LineProcessor always process whole lines.
59
 *
60
 * @author Petr Hejl
61
 * @see InputProcessors#bridge(org.netbeans.api.extexecution.base.input.LineProcessor)
62
 */
63
public final class LineProcessors {
64
65
    private static final Logger LOGGER = Logger.getLogger(LineProcessors.class.getName());
66
67
    private LineProcessors() {
68
        super();
69
    }
70
71
    /**
72
     * Returns the processor acting as a proxy.
73
     * <p>
74
     * Any action taken on this processor is distributed to all processors
75
     * passed as arguments in the same order as they were passed to this method.
76
     * <p>
77
     * Returned processor is <i>not thread safe</i>.
78
     *
79
     * @param processors processor to which the actions will be distributed
80
     * @return the processor acting as a proxy
81
     */
82
    @NonNull
83
    public static LineProcessor proxy(@NonNull LineProcessor... processors) {
84
        return new ProxyLineProcessor(processors);
85
    }
86
87
    /**
88
     * Returns the processor printing all lines passed for processing to
89
     * the given output writer.
90
     * <p>
91
     * Processor closes the output writer on {@link InputProcessor#close()}.
92
     * <p>
93
     * Returned processor is <i>not thread safe</i>.
94
     *
95
     * @param out where to print received lines
96
     * @return the processor printing all lines passed for processing to
97
     *             the given output writer
98
     */
99
    @NonNull
100
    public static LineProcessor printing(@NonNull PrintWriter out) {
101
        return new PrintingLineProcessor(out);
102
    }
103
104
    /**
105
     * Returns the processor that will wait for the line matching the pattern,
106
     * decreasing the latch when such line appears for the first time.
107
     * <p>
108
     * Reset action on the returned processor is noop.
109
     * <p>
110
     * Returned processor is <i>thread safe</i>.
111
     *
112
     * @param pattern pattern that line must match in order decrease the latch
113
     * @param latch latch to decrease when the line matching the pattern appears
114
     *             for the first time
115
     * @return the processor that will wait for the line matching the pattern,
116
     *             decreasing the latch when such line appears for the first time
117
     */
118
    @NonNull
119
    public static LineProcessor patternWaiting(@NonNull Pattern pattern, @NonNull CountDownLatch latch) {
120
        return new WaitingLineProcessor(pattern, latch);
121
    }
122
123
    private static class ProxyLineProcessor implements LineProcessor {
124
125
        private final List<LineProcessor> processors = new ArrayList<LineProcessor>();
126
127
        private boolean closed;
128
129
        public ProxyLineProcessor(LineProcessor... processors) {
130
            for (LineProcessor processor : processors) {
131
                if (processor != null) {
132
                    this.processors.add(processor);
133
                }
134
            }
135
        }
136
137
        @Override
138
        public void processLine(String line) {
139
            if (closed) {
140
                throw new IllegalStateException("Already closed processor");
141
            }
142
143
            for (LineProcessor processor : processors) {
144
                processor.processLine(line);
145
            }
146
        }
147
148
        @Override
149
        public void reset() {
150
            if (closed) {
151
                throw new IllegalStateException("Already closed processor");
152
            }
153
154
            for (LineProcessor processor : processors) {
155
                processor.reset();
156
            }
157
        }
158
159
        @Override
160
        public void close() {
161
            closed = true;
162
163
            for (LineProcessor processor : processors) {
164
                processor.close();
165
            }
166
        }
167
    }
168
169
    private static class PrintingLineProcessor implements LineProcessor {
170
171
        private final PrintWriter out;
172
173
        private boolean closed;
174
175
        public PrintingLineProcessor(PrintWriter out) {
176
            assert out != null;
177
178
            this.out = out;
179
        }
180
181
        @Override
182
        public void processLine(String line) {
183
            assert line != null;
184
185
            if (closed) {
186
                throw new IllegalStateException("Already closed processor");
187
            }
188
189
            LOGGER.log(Level.FINEST, line);
190
191
            out.println(line);
192
            out.flush();
193
        }
194
195
        @Override
196
        public void reset() {
197
            if (closed) {
198
                throw new IllegalStateException("Already closed processor");
199
            }
200
        }
201
202
        @Override
203
        public void close() {
204
            closed = true;
205
206
            out.flush();
207
            out.close();
208
        }
209
    }
210
211
    private static class WaitingLineProcessor implements LineProcessor {
212
213
        private final Pattern pattern;
214
215
        private final CountDownLatch latch;
216
217
        /**<i>GuardedBy("this")</i>*/
218
        private boolean processed;
219
220
        /**<i>GuardedBy("this")</i>*/
221
        private boolean closed;
222
223
        public WaitingLineProcessor(Pattern pattern, CountDownLatch latch) {
224
            assert pattern != null;
225
            assert latch != null;
226
227
            this.pattern = pattern;
228
            this.latch = latch;
229
        }
230
231
        @Override
232
        public synchronized void processLine(String line) {
233
            assert line != null;
234
235
            if (closed) {
236
                throw new IllegalStateException("Already closed processor");
237
            }
238
239
            if (!processed && pattern.matcher(line).matches()) {
240
                latch.countDown();
241
                processed = true;
242
            }
243
        }
244
245
        @Override
246
        public synchronized void reset() {
247
            if (closed) {
248
                throw new IllegalStateException("Already closed processor");
249
            }
250
        }
251
252
        @Override
253
        public synchronized void close() {
254
            closed = true;
255
        }
256
    }
257
}
(-)a/extexecution.base/src/org/netbeans/api/extexecution/base/input/package-info.java (+53 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 support API for processing the growing streams or files. The API
47
 * provides classes for automated processing of such inputs. The processing
48
 * is character or line based.
49
 *
50
 * @see org.netbeans.api.extexecution.base.input.InputReaderTask
51
 */
52
package org.netbeans.api.extexecution.base.input;
53
(-)a/extexecution.base/src/org/netbeans/api/extexecution/base/package-info.java (+51 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 execution of an external process.
47
 *
48
 * @see org.netbeans.api.extexecution.base.BaseExecutionService
49
 */
50
package org.netbeans.api.extexecution.base;
51
(-)a/extexecution.base/src/org/netbeans/modules/extexecution/base/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.base;
43
44
import org.netbeans.api.extexecution.base.Environment;
45
import org.netbeans.spi.extexecution.base.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.base/src/org/netbeans/modules/extexecution/base/ExternalProcessBuilder.java (+576 lines)
Line 0    Link Here 
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 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
 * 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 2008 Sun Microsystems, Inc.
41
 */
42
43
package org.netbeans.modules.extexecution.base;
44
45
import java.io.File;
46
import java.io.IOException;
47
import java.util.ArrayList;
48
import java.util.HashMap;
49
import java.util.Iterator;
50
import java.util.List;
51
import java.util.Locale;
52
import java.util.Map;
53
import java.util.UUID;
54
import java.util.concurrent.Callable;
55
import java.util.logging.Level;
56
import java.util.logging.Logger;
57
import java.util.prefs.Preferences;
58
import java.util.regex.Pattern;
59
import org.netbeans.api.annotations.common.CheckReturnValue;
60
import org.netbeans.api.annotations.common.NonNull;
61
import org.openide.util.NbPreferences;
62
import org.openide.util.Parameters;
63
import org.openide.util.BaseUtilities;
64
65
/**
66
 * Utility class to make the local external process creation easier.
67
 * <p>
68
 * Builder handle command, working directory, <code>PATH</code> variable and HTTP proxy.
69
 * <p>
70
 * This class is <i>immutable</i>.
71
 * <p>
72
 * Also see {@link ProcessBuilder#getLocal()}.
73
 *
74
 * @author Petr Hejl
75
 * @see #call()
76
 */
77
public final class ExternalProcessBuilder implements Callable<Process> {
78
79
    private static final Logger LOGGER = Logger.getLogger(ExternalProcessBuilder.class.getName());
80
81
    private static final Pattern ESCAPED_PATTERN = Pattern.compile("\".*\""); // NOI18N
82
83
    // FIXME: get rid of those proxy constants as soon as some NB Proxy API is available
84
    private static final String USE_PROXY_AUTHENTICATION = "useProxyAuthentication"; // NOI18N
85
86
    private static final String PROXY_AUTHENTICATION_USERNAME = "proxyAuthenticationUsername"; // NOI18N
87
88
    private static final String PROXY_AUTHENTICATION_PASSWORD = "proxyAuthenticationPassword"; // NOI18N
89
90
    private final String executable;
91
92
    private final File workingDirectory;
93
94
    private final boolean redirectErrorStream;
95
96
    private final List<String> arguments = new ArrayList<String>();
97
98
    private final List<File> paths = new ArrayList<File>();
99
100
    private final Map<String, String> envVariables = new HashMap<String, String>();
101
102
    private final boolean emptySystemVariables;
103
104
    /**
105
     * Creates the new builder that will create the process by running
106
     * given executable. Arguments must not be part of the string.
107
     *
108
     * @param executable executable to run
109
     */
110
    public ExternalProcessBuilder(@NonNull String executable) {
111
        this(new BuilderData(executable));
112
    }
113
114
    private ExternalProcessBuilder(BuilderData builder) {
115
        this.executable = builder.executable;
116
        this.workingDirectory = builder.workingDirectory;
117
        this.redirectErrorStream = builder.redirectErrorStream;
118
        this.arguments.addAll(builder.arguments);
119
        this.paths.addAll(builder.paths);
120
        this.envVariables.putAll(builder.envVariables);
121
        this.emptySystemVariables = builder.emptySystemVariables;
122
    }
123
124
    /**
125
     * Returns a builder with configured working directory. Process
126
     * subsequently created by the {@link #call()} method on returned builder
127
     * will be executed with this directory as current working dir.
128
     * <p>
129
     * The default value is undefined. Note that in such case each process has
130
     * working directory corresponding to the value of <code>user.dir</code>
131
     * system property.
132
     * <p>
133
     * All other properties of the returned builder are inherited from
134
     * <code>this</code>.
135
     *
136
     * @param workingDirectory working directory
137
     * @return new builder with configured working directory
138
     */
139
    @NonNull
140
    @CheckReturnValue
141
    public ExternalProcessBuilder workingDirectory(@NonNull File workingDirectory) {
142
        Parameters.notNull("workingDirectory", workingDirectory);
143
144
        BuilderData builder = new BuilderData(this);
145
        return new ExternalProcessBuilder(builder.workingDirectory(workingDirectory));
146
    }
147
148
    /**
149
     * Returns a builder with configured error stream redirection. If configured
150
     * value is <code>true</code> process subsequently created by
151
     * the {@link #call()} method on returned builder will redirect the error
152
     * stream to the standard output stream.
153
     * <p>
154
     * The default value is <code>false</code>.
155
     * <p>
156
     * All other properties of the returned builder are inherited from
157
     * <code>this</code>.
158
     *
159
     * @param redirectErrorStream if <code>true</code> error stream will be
160
     *             redirected to standard output
161
     * @return new builder with configured error stream redirection
162
     */
163
    @NonNull
164
    @CheckReturnValue
165
    public ExternalProcessBuilder redirectErrorStream(boolean redirectErrorStream) {
166
        BuilderData builder = new BuilderData(this);
167
        return new ExternalProcessBuilder(builder.redirectErrorStream(redirectErrorStream));
168
    }
169
170
    /**
171
     * Returns a builder with additional path in <code>PATH</code> variable.
172
     * <p>
173
     * In the group of paths added by this call the last added path will
174
     * be the first one in the <code>PATH</code> variable.
175
     * <p>
176
     * By default no additional paths are added to <code>PATH</code> variable.
177
     * <p>
178
     * All other properties of the returned builder are inherited from
179
     * <code>this</code>.
180
     *
181
     * @param path path to add to <code>PATH</code> variable
182
     * @return new builder with additional path in <code>PATH</code> variable
183
     */
184
    @NonNull
185
    @CheckReturnValue
186
    public ExternalProcessBuilder prependPath(@NonNull File path) {
187
        Parameters.notNull("path", path);
188
189
        BuilderData builder = new BuilderData(this);
190
        return new ExternalProcessBuilder(builder.prependPath(path));
191
    }
192
193
    /**
194
     * Returns a builder with additional argument for the command. Arguments
195
     * are passed to executable in the same order in which they are added.
196
     * <p>
197
     * By default no additional arguments are passed to executable.
198
     * <p>
199
     * All other properties of the returned builder are inherited from
200
     * <code>this</code>.
201
     * <p>
202
     * If there is a need to parse arguments already provided as one big
203
     * string the method that can help is
204
     * {@link Utilities#parseParameters(java.lang.String)}.
205
     *
206
     *
207
     * @param argument command argument to add
208
     * @return new builder with additional argument for the command
209
     */
210
    @NonNull
211
    @CheckReturnValue
212
    public ExternalProcessBuilder addArgument(@NonNull String argument) {
213
        Parameters.notNull("argument", argument);
214
215
        BuilderData builder = new BuilderData(this);
216
        return new ExternalProcessBuilder(builder.addArgument(argument));
217
    }
218
219
    /**
220
     * Returns a builder with additional environment variable for the command.
221
     * <p>
222
     * By default no additional environment variables are configured.
223
     * <p>
224
     * All other properties of the returned builder are inherited from
225
     * <code>this</code>.
226
     *
227
     * @param name name of the variable
228
     * @param value value of the variable
229
     * @return new builder with additional environment variable for the command
230
     * @see #call()
231
     */
232
    @NonNull
233
    @CheckReturnValue
234
    public ExternalProcessBuilder addEnvironmentVariable(@NonNull String name, @NonNull String value) {
235
        Parameters.notNull("name", name);
236
        Parameters.notNull("value", value);
237
238
        BuilderData builder = new BuilderData(this);
239
        return new ExternalProcessBuilder(builder.addEnvironmentVariable(name, value));
240
    }
241
242
    /**
243
     * Creates the new {@link Process} based on the properties configured
244
     * in this builder. Created process will try to kill all its children on
245
     * call to {@link Process#destroy()}.
246
     * <p>
247
     * Process is created by executing the executable with configured arguments.
248
     * If custom working directory is specified it is used otherwise value
249
     * of system property <code>user.dir</code> is used as working dir.
250
     * <p>
251
     * Environment variables are prepared in following way:
252
     * <ol>
253
     *   <li>Get table of system environment variables.
254
     *   <li>Put all environment variables configured by
255
     * {@link #addEnvironmentVariable(java.lang.String, java.lang.String)}.
256
     * This rewrites system variables if conflict occurs.
257
     *   <li>Get <code>PATH</code> variable and append all paths added
258
     * by {@link #prependPath(java.io.File)}. The order of paths in <code>PATH</code>
259
     * variable is reversed to order of addition (the last added is the first
260
     * one in <code>PATH</code>). Original content of <code>PATH</code> follows
261
     * the added content.
262
     *   <li>If neither <code>http_proxy</code> nor <code>HTTP_PROXY</code>
263
     * environment variable is set then HTTP proxy settings configured in the
264
     * IDE are stored as <code>http_proxy</code> environment variable
265
     * (the format of the value is <code>http://username:password@host:port</code>).
266
     * </ol>
267
     * @return the new {@link Process} based on the properties configured
268
     *             in this builder
269
     * @throws IOException if the process could not be created
270
     */
271
    @NonNull
272
    @Override
273
    public Process call() throws IOException {
274
        List<String> commandList = new ArrayList<String>();
275
276
        if (BaseUtilities.isWindows() && !ESCAPED_PATTERN.matcher(executable).matches()) {
277
            commandList.add(escapeString(executable));
278
        } else {
279
            commandList.add(executable);
280
        }
281
282
        List<String> args = buildArguments();
283
        commandList.addAll(args);
284
285
        java.lang.ProcessBuilder pb = new java.lang.ProcessBuilder(commandList.toArray(new String[commandList.size()]));
286
        if (workingDirectory != null) {
287
            pb.directory(workingDirectory);
288
        }
289
290
        Map<String, String> pbEnv = pb.environment();
291
        Map<String, String> env;
292
        if (emptySystemVariables) {
293
            pbEnv.clear();
294
            env = new HashMap<String, String>();
295
        } else {
296
            env = buildEnvironment(pbEnv);
297
        }
298
        pbEnv.putAll(env);
299
        String uuid = UUID.randomUUID().toString();
300
        pbEnv.put(WrapperProcess.KEY_UUID, uuid);
301
        adjustProxy(pb);
302
        pb.redirectErrorStream(redirectErrorStream);
303
        logProcess(Level.FINE, pb);
304
        WrapperProcess wp = new WrapperProcess(pb.start(), uuid);
305
        return wp;
306
    }
307
308
    public ExternalProcessBuilder emptySystemVariables(boolean emptySystemVariables) {
309
        BuilderData builder = new BuilderData(this);
310
        return new ExternalProcessBuilder(builder.emptySystemVariables(emptySystemVariables));
311
    }
312
313
    /**
314
     * Logs the given <code>pb</code> using the given <code>level</code>.
315
     *
316
     * @param pb the ProcessBuilder to log.
317
     * @param level the level for logging.
318
     */
319
    private void logProcess(final Level level, final java.lang.ProcessBuilder pb) {
320
321
        if (!LOGGER.isLoggable(level)) {
322
            return;
323
        }
324
325
        File dir = pb.directory();
326
        String basedir = dir == null ? "" : "(basedir: " + dir.getAbsolutePath() + ") "; //NOI18N
327
328
        StringBuilder command = new StringBuilder();
329
        for (Iterator<String> it = pb.command().iterator(); it.hasNext();) {
330
            command.append(it.next());
331
            if (it.hasNext()) {
332
                command.append(' '); //NOI18N
333
            }
334
        }
335
336
        LOGGER.log(level, "Running: " + basedir + '"' + command.toString() + '"'); //NOI18N
337
        LOGGER.log(level, "Environment: " + pb.environment()); //NOI18N
338
    }
339
340
    // package level for unit testing
341
    Map<String, String> buildEnvironment(Map<String, String> original) {
342
        Map<String, String> ret = new HashMap<String, String>(original);
343
        ret.putAll(envVariables);
344
345
        // Find PATH environment variable - on Windows it can be some other
346
        // case and we should use whatever it has.
347
        String pathName = getPathName(original);
348
349
        // TODO use StringBuilder
350
        String currentPath = ret.get(pathName);
351
352
        if (currentPath == null) {
353
            currentPath = "";
354
        }
355
356
        for (File path : paths) {
357
            currentPath = path.getAbsolutePath().replace(" ", "\\ ") //NOI18N
358
                    + File.pathSeparator + currentPath;
359
        }
360
361
        if (!"".equals(currentPath.trim())) {
362
            ret.put(pathName, currentPath);
363
        }
364
        return ret;
365
    }
366
367
368
    // package level for unit testing
369
    List<String> buildArguments() {
370
        if (!BaseUtilities.isWindows()) {
371
            return new ArrayList<String>(arguments);
372
        }
373
        List<String> result = new ArrayList<String>(arguments.size());
374
        for (String arg : arguments) {
375
            if (arg != null && !ESCAPED_PATTERN.matcher(arg).matches()) {
376
                result.add(escapeString(arg));
377
            } else {
378
                result.add(arg);
379
            }
380
        }
381
        return result;
382
    }
383
384
    public static void putPath(File path, String pathName, boolean prepend, Map<String, String> current) {
385
        String currentPath = current.get(pathName);
386
387
        if (currentPath == null) {
388
            currentPath = "";
389
        }
390
391
        if (prepend) {
392
            currentPath = path.getAbsolutePath().replace(" ", "\\ ") //NOI18N
393
                    + File.pathSeparator + currentPath;
394
        } else {
395
            currentPath = currentPath + File.pathSeparator
396
                    + path.getAbsolutePath().replace(" ", "\\ "); //NOI18N
397
        }
398
399
        if (!"".equals(currentPath.trim())) {
400
            current.put(pathName, currentPath);
401
        }
402
    }
403
404
    public static String getPathName(Map<String, String> systemEnv) {
405
        // Find PATH environment variable - on Windows it can be some other
406
        // case and we should use whatever it has.
407
        String pathName = "PATH"; // NOI18N
408
409
        if (BaseUtilities.isWindows()) {
410
            pathName = "Path"; // NOI18N
411
412
            for (String keySystem : systemEnv.keySet()) {
413
                if ("PATH".equals(keySystem.toUpperCase(Locale.ENGLISH))) { // NOI18N
414
                    pathName = keySystem;
415
                    break;
416
                }
417
            }
418
        }
419
        return pathName;
420
    }
421
422
    private static String escapeString(String s) {
423
        if (s.length() == 0) {
424
            return "\"\""; // NOI18N
425
        }
426
427
        StringBuilder sb = new StringBuilder();
428
429
        boolean hasSpace = false;
430
        final int slen = s.length();
431
        char c;
432
433
        for (int i = 0; i < slen; i++) {
434
            c = s.charAt(i);
435
436
            if (Character.isWhitespace(c)) {
437
                hasSpace = true;
438
                sb.append(c);
439
440
                continue;
441
            }
442
            sb.append(c);
443
        }
444
445
        if (hasSpace) {
446
            sb.insert(0, '"'); // NOI18N
447
            sb.append('"'); // NOI18N
448
        }
449
        return sb.toString();
450
    }
451
452
    private void adjustProxy(java.lang.ProcessBuilder pb) {
453
        String proxy = getNetBeansHttpProxy();
454
        if (proxy != null) {
455
            Map<String, String> env = pb.environment();
456
            if ((env.get("HTTP_PROXY") == null) && (env.get("http_proxy") == null)) { // NOI18N
457
                env.put("HTTP_PROXY", proxy); // NOI18N
458
                env.put("http_proxy", proxy); // NOI18N
459
            }
460
            // PENDING - what if proxy was null so the user has TURNED off
461
            // proxies while there is still an environment variable set - should
462
            // we honor their environment, or honor their NetBeans proxy
463
            // settings (e.g. unset HTTP_PROXY in the environment before
464
            // launching plugin?
465
        }
466
    }
467
468
    /**
469
     * FIXME: get rid of the whole method as soon as some NB Proxy API is
470
     * available.
471
     */
472
    private static String getNetBeansHttpProxy() {
473
        // FIXME use ProxySelector
474
475
        String host = System.getProperty("http.proxyHost"); // NOI18N
476
477
        if (host == null) {
478
            return null;
479
        }
480
481
        String portHttp = System.getProperty("http.proxyPort"); // NOI18N
482
        int port;
483
484
        try {
485
            port = Integer.parseInt(portHttp);
486
        } catch (NumberFormatException e) {
487
            port = 8080;
488
        }
489
490
        Preferences prefs = NbPreferences.root().node("org/netbeans/core"); // NOI18N
491
        boolean useAuth = prefs.getBoolean(USE_PROXY_AUTHENTICATION, false);
492
        String auth = "";
493
        if (useAuth) {
494
            auth = prefs.get(PROXY_AUTHENTICATION_USERNAME, "") + ":" + prefs.get(PROXY_AUTHENTICATION_PASSWORD, "") + '@'; // NOI18N
495
        }
496
497
        // Gem requires "http://" in front of the port name if it's not already there
498
        if (host.indexOf(':') == -1) {
499
            host = "http://" + auth + host; // NOI18N
500
        }
501
502
        return host + ":" + port; // NOI18N
503
    }
504
505
    private static class BuilderData {
506
507
        private final String executable;
508
509
        private File workingDirectory;
510
511
        private boolean redirectErrorStream;
512
513
        private List<String> arguments = new ArrayList<String>();
514
515
        private List<File> paths = new ArrayList<File>();
516
517
        private Map<String, String> envVariables = new HashMap<String, String>();
518
519
        private boolean emptySystemVariables;
520
521
        public BuilderData(String executable) {
522
            this.executable = executable;
523
        }
524
525
        public BuilderData(ExternalProcessBuilder builder) {
526
            this.executable = builder.executable;
527
            this.workingDirectory = builder.workingDirectory;
528
            this.redirectErrorStream = builder.redirectErrorStream;
529
            this.arguments.addAll(builder.arguments);
530
            this.paths.addAll(builder.paths);
531
            this.envVariables.putAll(builder.envVariables);
532
            this.emptySystemVariables = builder.emptySystemVariables;
533
        }
534
535
        public BuilderData workingDirectory(File workingDirectory) {
536
            assert workingDirectory != null;
537
538
            this.workingDirectory = workingDirectory;
539
            return this;
540
        }
541
542
        public BuilderData redirectErrorStream(boolean redirectErrorStream) {
543
            this.redirectErrorStream = redirectErrorStream;
544
            return this;
545
        }
546
547
        public BuilderData prependPath(File path) {
548
            assert path != null;
549
550
            paths.add(path);
551
            return this;
552
        }
553
554
        public BuilderData addArgument(String argument) {
555
            assert argument != null;
556
557
            arguments.add(argument);
558
            return this;
559
        }
560
561
        public BuilderData addEnvironmentVariable(String name, String value) {
562
            assert name != null;
563
            assert value != null;
564
565
            envVariables.put(name, value);
566
            return this;
567
        }
568
569
        public BuilderData emptySystemVariables(boolean emptySystemVariables) {
570
            this.emptySystemVariables = emptySystemVariables;
571
            return this;
572
        }
573
    }
574
575
576
}
(-)a/extexecution.base/src/org/netbeans/modules/extexecution/base/ProcessBuilderAccessor.java (+81 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.modules.extexecution.base;
43
44
import org.netbeans.spi.extexecution.base.ProcessBuilderImplementation;
45
46
/**
47
 *
48
 * @author Petr Hejl
49
 */
50
public abstract class ProcessBuilderAccessor {
51
52
    private static volatile ProcessBuilderAccessor DEFAULT;
53
54
    public static ProcessBuilderAccessor getDefault() {
55
        ProcessBuilderAccessor a = DEFAULT;
56
        if (a != null) {
57
            return a;
58
        }
59
60
        // invokes static initializer of ProcessBuilder.class
61
        // that will assign value to the DEFAULT field above
62
        Class c = org.netbeans.api.extexecution.base.ProcessBuilder.class;
63
        try {
64
            Class.forName(c.getName(), true, c.getClassLoader());
65
        } catch (ClassNotFoundException ex) {
66
            assert false : ex;
67
        }
68
        return DEFAULT;
69
    }
70
71
    public static void setDefault(ProcessBuilderAccessor accessor) {
72
        if (DEFAULT != null) {
73
            throw new IllegalStateException();
74
        }
75
76
        DEFAULT = accessor;
77
    }
78
79
    public abstract org.netbeans.api.extexecution.base.ProcessBuilder createProcessBuilder(
80
            ProcessBuilderImplementation impl, String description);
81
}
(-)a/extexecution.base/src/org/netbeans/modules/extexecution/base/ProcessInputStream.java (+196 lines)
Line 0    Link Here 
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 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
 * 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 2008 Sun Microsystems, Inc.
41
 */
42
43
package org.netbeans.modules.extexecution.base;
44
45
import java.io.ByteArrayOutputStream;
46
import java.io.FilterInputStream;
47
import java.io.IOException;
48
import java.io.InputStream;
49
import java.util.logging.Level;
50
import java.util.logging.Logger;
51
52
/**
53
 *
54
 * @author Petr Hejl
55
 */
56
public final class ProcessInputStream extends FilterInputStream {
57
58
    private static final Logger LOGGER = Logger.getLogger(ProcessInputStream.class.getName());
59
60
    private final Process process;
61
62
    private byte[] buffer;
63
64
    private int position;
65
66
    private boolean closed;
67
68
    private boolean exhausted;
69
70
    public ProcessInputStream(Process process, InputStream in) {
71
        super(in);
72
        this.process = process;
73
    }
74
75
    @Override
76
    public synchronized int available() throws IOException {
77
        if (buffer != null && position < buffer.length) {
78
            return buffer.length - position;
79
        } else if (closed) {
80
            if (!exhausted) {
81
                exhausted = true;
82
                return 0;
83
            } else {
84
                throw new IOException("Already closed stream");
85
            }
86
        }
87
        return super.available();
88
    }
89
90
    @Override
91
    public synchronized void close() throws IOException {
92
        if (!closed) {
93
            close(false);
94
        }
95
    }
96
97
    @Override
98
    public void mark(int readlimit) {
99
        // noop
100
    }
101
102
    @Override
103
    public boolean markSupported() {
104
        return false;
105
    }
106
107
    @Override
108
    public synchronized int read() throws IOException {
109
        if (buffer != null && position < buffer.length) {
110
            return buffer[position++];
111
        } else if (closed) {
112
            if (!exhausted) {
113
                exhausted = true;
114
                return -1;
115
            } else {
116
                throw new IOException("Already closed stream");
117
            }
118
        }
119
        return super.read();
120
    }
121
122
    @Override
123
    public int read(byte[] b) throws IOException {
124
        return read(b, 0, b.length);
125
    }
126
127
    @Override
128
    public synchronized int read(byte[] b, int off, int len) throws IOException {
129
        if (buffer != null) {
130
            int available = buffer.length - position;
131
            int size = Math.min(len, available);
132
            System.arraycopy(buffer, position, b, off, size);
133
            position += size;
134
            return size;
135
        } else if (closed) {
136
            if (!exhausted) {
137
                exhausted = true;
138
                return -1;
139
            } else {
140
                throw new IOException("Already closed stream");
141
            }
142
        }
143
        return super.read(b, off, len);
144
    }
145
146
    @Override
147
    public void reset() throws IOException {
148
        // noop
149
    }
150
151
    @Override
152
    public long skip(long n) throws IOException {
153
        return 0;
154
    }
155
156
    public synchronized void close(boolean drain) throws IOException {
157
        closed = true;
158
159
        if (drain) {
160
            LOGGER.log(Level.FINE, "Draining process stream");
161
162
            boolean running = false;
163
            try {
164
                process.exitValue();
165
            } catch (IllegalThreadStateException ex) {
166
                running = true;
167
            }
168
169
            if (running) {
170
                LOGGER.log(Level.FINE, "Process is still running");
171
            }
172
173
            ByteArrayOutputStream os = new ByteArrayOutputStream();
174
            try {
175
                if (running) {
176
                    while (super.available() > 0) {
177
                        os.write(super.read());
178
                    }
179
                } else {
180
                    int read;
181
                    // FIXME this occasionaly block forever on Vista :(
182
                    while ((read = super.read()) >= 0) {
183
                        os.write(read);
184
                    }
185
                }
186
            } catch (IOException ex) {
187
                LOGGER.log(Level.FINE, null, ex);
188
            }
189
190
            buffer = os.toByteArray();
191
            LOGGER.log(Level.FINE, "Read {0} bytes from stream", buffer.length);
192
        }
193
194
        super.close();
195
    }
196
}
(-)a/extexecution.base/src/org/netbeans/modules/extexecution/base/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.base;
43
44
import java.util.List;
45
import java.util.Map;
46
import org.netbeans.spi.extexecution.base.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.base/src/org/netbeans/modules/extexecution/base/WrapperProcess.java (+96 lines)
Line 0    Link Here 
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 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
 * 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 2009 Sun Microsystems, Inc.
41
 */
42
43
package org.netbeans.modules.extexecution.base;
44
45
import java.io.InputStream;
46
import java.io.OutputStream;
47
import java.util.Collections;
48
import org.netbeans.api.extexecution.base.Processes;
49
50
/**
51
 *
52
 * @author mkleint
53
 */
54
public class WrapperProcess extends Process {
55
56
    public static final String KEY_UUID = "NB_EXEC_EXTEXECUTION_PROCESS_UUID"; //NOI18N
57
    private final String uuid;
58
59
    private final Process del;
60
61
    public WrapperProcess(Process delegate, String uuid) {
62
        this.del = delegate;
63
        this.uuid = uuid;
64
    }
65
66
    @Override
67
    public OutputStream getOutputStream() {
68
        return del.getOutputStream();
69
    }
70
71
    @Override
72
    public InputStream getInputStream() {
73
        return del.getInputStream();
74
    }
75
76
    @Override
77
    public InputStream getErrorStream() {
78
        return del.getErrorStream();
79
    }
80
81
    @Override
82
    public int waitFor() throws InterruptedException {
83
        return del.waitFor();
84
    }
85
86
    @Override
87
    public int exitValue() {
88
        return del.exitValue();
89
    }
90
91
    @Override
92
    public void destroy() {
93
        Processes.killTree(del, Collections.singletonMap(KEY_UUID, uuid));
94
    }
95
96
}
(-)a/extexecution.base/src/org/netbeans/modules/extexecution/base/input/DefaultInputReader.java (+117 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
package org.netbeans.modules.extexecution.base.input;
46
47
import java.io.BufferedReader;
48
import java.io.IOException;
49
import java.io.Reader;
50
import java.util.logging.Level;
51
import java.util.logging.Logger;
52
import org.netbeans.api.extexecution.base.input.InputProcessor;
53
import org.netbeans.api.extexecution.base.input.InputReader;
54
55
/**
56
 * This class is <i>NotThreadSafe</i>.
57
 *
58
 * @author Petr.Hejl
59
 */
60
public class DefaultInputReader implements InputReader {
61
62
    private static final Logger LOGGER = Logger.getLogger(DefaultInputReader.class.getName());
63
64
    private static final int BUFFER_SIZE = 512;
65
66
    private final Reader reader;
67
68
    private final char[] buffer;
69
70
    private final boolean greedy;
71
72
    private boolean closed;
73
74
    public DefaultInputReader(Reader reader, boolean greedy) {
75
        assert reader != null;
76
77
        this.reader = new BufferedReader(reader);
78
        this.greedy = greedy;
79
        this.buffer = new char[greedy ? BUFFER_SIZE * 2 : BUFFER_SIZE];
80
    }
81
82
    @Override
83
    public int readInput(InputProcessor inputProcessor) throws IOException {
84
        if (closed) {
85
            throw new IllegalStateException("Already closed reader");
86
        }
87
88
        if (!reader.ready()) {
89
            return 0;
90
        }
91
92
        int fetched = 0;
93
        // TODO optimization possible
94
        StringBuilder builder = new StringBuilder();
95
        do {
96
            int size = reader.read(buffer);
97
            if (size > 0) {
98
                builder.append(buffer, 0, size);
99
                fetched += size;
100
            }
101
        } while (reader.ready() && greedy);
102
103
        if (inputProcessor != null && fetched > 0) {
104
            inputProcessor.processInput(builder.toString().toCharArray());
105
        }
106
107
        return fetched;
108
    }
109
110
    @Override
111
    public void close() throws IOException {
112
        closed = true;
113
        reader.close();
114
        LOGGER.log(Level.FINEST, "Reader closed");
115
    }
116
117
}
(-)a/extexecution.base/src/org/netbeans/modules/extexecution/base/input/FileInputReader.java (+157 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