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

View | Details | Raw Unified | Return to bug 244308
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
 *
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.FileInputStream;
49
import java.io.IOException;
50
import java.io.InputStreamReader;
51
import java.io.Reader;
52
import java.util.logging.Level;
53
import java.util.logging.Logger;
54
import org.netbeans.api.extexecution.base.input.InputProcessor;
55
import org.netbeans.api.extexecution.base.input.InputReader;
56
import org.netbeans.api.extexecution.base.input.InputReaders;
57
58
/**
59
 * This class is <i>NotThreadSafe</i>.
60
 *
61
 * @author Petr Hejl
62
 */
63
public class FileInputReader implements InputReader {
64
65
    private static final Logger LOGGER = Logger.getLogger(FileInputReader.class.getName());
66
67
    private static final int BUFFER_SIZE = 512;
68
69
    private final InputReaders.FileInput.Provider fileProvider;
70
71
    private final char[] buffer = new char[BUFFER_SIZE];
72
73
    private InputReaders.FileInput currentFile;
74
75
    private Reader reader;
76
77
    private long fileLength;
78
79
    private boolean closed;
80
81
    public FileInputReader(InputReaders.FileInput.Provider fileProvider) {
82
        assert fileProvider != null;
83
84
        this.fileProvider = fileProvider;
85
    }
86
87
    @Override
88
    public int readInput(InputProcessor inputProcessor) {
89
        if (closed) {
90
            throw new IllegalStateException("Already closed reader");
91
        }
92
93
        int fetched = 0;
94
        try {
95
            InputReaders.FileInput file = fileProvider.getFileInput();
96
97
            if ((currentFile != file && (currentFile == null || !currentFile.equals(file)))
98
                    || fileLength > currentFile.getFile().length() || reader == null) {
99
100
                if (reader != null) {
101
                    reader.close();
102
                }
103
104
                currentFile = file;
105
106
                if (currentFile != null && currentFile.getFile().exists()
107
                        && currentFile.getFile().canRead()) {
108
109
                    reader = new BufferedReader(new InputStreamReader(
110
                            new FileInputStream(currentFile.getFile()), currentFile.getCharset()));
111
                }
112
                if (fileLength > 0) {
113
                    inputProcessor.reset();
114
                }
115
                fileLength = 0;
116
            }
117
118
            if (reader == null) {
119
                return fetched;
120
            }
121
122
            int size = reader.read(buffer);
123
            if (size > 0) {
124
                fileLength += size;
125
                fetched += size;
126
127
                if (inputProcessor != null) {
128
                    char[] toProcess = new char[size];
129
                    System.arraycopy(buffer, 0, toProcess, 0, size);
130
                    inputProcessor.processInput(toProcess);
131
                }
132
            }
133
        } catch (Exception ex) {
134
            LOGGER.log(Level.INFO, null, ex);
135
            // we will try the next loop (if any)
136
            if (reader != null) {
137
                try {
138
                    reader.close();
139
                } catch (IOException iex) {
140
                    LOGGER.log(Level.FINE, null, ex);
141
                }
142
            }
143
        }
144
145
        return fetched;
146
    }
147
148
    @Override
149
    public void close() throws IOException {
150
        closed = true;
151
        if (reader != null) {
152
            reader.close();
153
            reader = null;
154
        }
155
    }
156
157
}
(-)a/extexecution.base/src/org/netbeans/modules/extexecution/base/input/LineParsingHelper.java (+119 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.nio.CharBuffer;
48
import java.util.ArrayList;
49
import java.util.List;
50
51
/**
52
 * This class is <i>NotThreadSafe</i>.
53
 * 
54
 * @author Petr Hejl
55
 */
56
public final class LineParsingHelper {
57
58
    private String trailingLine;
59
60
    public LineParsingHelper() {
61
        super();
62
    }
63
    
64
    public String[] parse(char[] buffer) {
65
        return parse(buffer, 0, buffer.length);
66
    }
67
68
    public String[] parse(char[] buffer, int offset, int limit) {
69
        return parse(CharBuffer.wrap(buffer, offset, limit));
70
    }
71
72
    public String[] parse(CharSequence input) {
73
        //prepend the text from the last reading to the text actually read
74
        String lines = (trailingLine != null ? trailingLine : "");
75
        lines += input.toString();
76
        int tlLength = (trailingLine != null ? trailingLine.length() : 0);
77
        int start = 0;
78
        List<String> ret = new ArrayList<String>();
79
        int length = input.length();
80
        for (int i = 0; i < length; i++) { // going through the text read and searching for the new line
81
            //we see '\n' or '\r', *not* '\r\n'
82
            char c = input.charAt(i);
83
            if (c == '\r'
84
                    && (i + 1 == length || input.charAt(i + 1) != '\n')
85
                    || c == '\n') {
86
                String line = lines.substring(start, tlLength + i);
87
                //move start to the character right after the new line
88
                start = tlLength + (i + 1);
89
                ret.add(line);
90
            } else if (c == '\r'
91
                    && (i + 1 < length) && input.charAt(i + 1) == '\n') {//we see '\r\n'
92
                String line = lines.substring(start, tlLength + i);
93
                //skip the '\n' character
94
                i += 1;
95
                //move start to the character right after the new line
96
                start = tlLength + (i + 1);
97
                ret.add(line);
98
            }
99
        }
100
        if (start < lines.length()) {
101
            //new line was not found at the end of the input, the remaing text is stored for the next reading
102
            trailingLine = lines.substring(start);
103
        } else {
104
            //null and not empty string to indicate that there is no valid input to write out;
105
            //an empty string means that a new line character may be written out according
106
            //to the LineProcessor implementation
107
            trailingLine = null;
108
        }
109
        return ret.toArray(new String[ret.size()]);
110
    }
111
112
    public String getTrailingLine(boolean flush) {
113
        String line = trailingLine;
114
        if (flush) {
115
            trailingLine = null;
116
        }
117
        return "".equals(line) ? null : line;
118
    }
119
}
(-)a/extexecution.base/src/org/netbeans/modules/extexecution/base/input/package-info.java (+49 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
 * Implementation classes for stream processing API.
47
 */
48
package org.netbeans.modules.extexecution.base.input;
49
(-)a/extexecution.base/src/org/netbeans/modules/extexecution/base/resources/Bundle.properties (+46 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
OpenIDE-Module-Name=External Execution Base API
44
OpenIDE-Module-Display-Category=Base IDE
45
OpenIDE-Module-Short-Description=Supports execution of external processes
46
OpenIDE-Module-Long-Description=Supports execution of external processes.
(-)a/extexecution.base/src/org/netbeans/spi/extexecution/base/EnvironmentFactory.java (+68 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2011 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.spi.extexecution.base;
43
44
import org.netbeans.api.extexecution.base.Environment;
45
import org.netbeans.modules.extexecution.base.EnvironmentAccessor;
46
47
/**
48
 * The factory allowing SPI implementors of {@link EnvironmentImplementation}
49
 * to create its API instances {@link Environment}.
50
 *
51
 * @author Petr Hejl
52
 */
53
public final class EnvironmentFactory {
54
55
    private EnvironmentFactory() {
56
        super();
57
    }
58
59
    /**
60
     * Creates the instance of {@link Environment} from its SPI representation.
61
     *
62
     * @param impl SPI representation
63
     * @return the API instance
64
     */
65
    public static Environment createEnvironment(EnvironmentImplementation impl) {
66
        return EnvironmentAccessor.getDefault().createEnvironment(impl);
67
    }
68
}
(-)a/extexecution.base/src/org/netbeans/spi/extexecution/base/EnvironmentImplementation.java (+114 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2012 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2012 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.spi.extexecution.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.api.extexecution.base.Environment;
48
49
/**
50
 * The interface representing the implementation
51
 * of {@link Environment}.
52
 *
53
 * @see Environment
54
 * @author Petr Hejl
55
 */
56
public interface EnvironmentImplementation {
57
58
    /**
59
     * Returns the value of the variable or <code>null</code>.
60
     *
61
     * @param name the name of the variable
62
     * @return the value of the variable or <code>null</code>
63
     */
64
    @CheckForNull
65
    String getVariable(@NonNull String name);
66
67
    /**
68
     * Appends a path to a path-like variable. The proper path separator should
69
     * be used to separate the new value.
70
     *
71
     * @param name the name of the variable such as for example
72
     *             <code>PATH</code> or <code>LD_LIBRARY_PATH</code>
73
     * @param value the value (path to append)
74
     */
75
    void appendPath(@NonNull String name, @NonNull String value);
76
77
    /**
78
     * Prepends a path to a path-like variable. The proper path separator should
79
     * be used to separate the new value.
80
     *
81
     * @param name the name of the variable such as for example
82
     *             <code>PATH</code> or <code>LD_LIBRARY_PATH</code>
83
     * @param value the value (path to prepend)
84
     */
85
    void prependPath(@NonNull String name, @NonNull String value);
86
87
    /**
88
     * Sets a value for a variable with the given name.
89
     *
90
     * @param name the name of the variable
91
     * @param value the value
92
     */
93
    void setVariable(@NonNull String name, @NonNull String value);
94
95
    /**
96
     * Removes a variable with the given name. The subsequent call to
97
     * {@link #getVariable(java.lang.String)} with the same argument should
98
     * return <code>null</code>.
99
     *
100
     * @param name the name of the variable
101
     */
102
    void removeVariable(@NonNull String name);
103
104
    /**
105
     * Returns all variable names and associated values as a {@link Map}.
106
     * Changes to the map <i>must not</i> be propagated back to the
107
     * {@link Environment}.
108
     *
109
     * @return all variable names and associated values
110
     */
111
    @NonNull
112
    Map<String, String> values();
113
114
}
(-)a/extexecution.base/src/org/netbeans/spi/extexecution/base/ProcessBuilderFactory.java (+70 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2011 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.spi.extexecution.base;
43
44
import org.netbeans.modules.extexecution.base.ProcessBuilderAccessor;
45
46
/**
47
 * The factory allowing SPI implementors of {@link ProcessBuilderImplementation}
48
 * to create its API instances {@link org.netbeans.api.extexecution.base.ProcessBuilder}.
49
 *
50
 * @author Petr Hejl
51
 */
52
public final class ProcessBuilderFactory {
53
54
    private ProcessBuilderFactory() {
55
        super();
56
    }
57
58
    /**
59
     * Creates the instance of {@link org.netbeans.api.extexecution.base.ProcessBuilder}
60
     * from its SPI representation.
61
     *
62
     * @param impl SPI representation
63
     * @param description human readable description of the builder
64
     * @return the API instance
65
     */
66
    public static org.netbeans.api.extexecution.base.ProcessBuilder createProcessBuilder(
67
            ProcessBuilderImplementation impl, String description) {
68
        return ProcessBuilderAccessor.getDefault().createProcessBuilder(impl, description);
69
    }
70
}
(-)a/extexecution.base/src/org/netbeans/spi/extexecution/base/ProcessBuilderImplementation.java (+92 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2012 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2012 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.spi.extexecution.base;
43
44
import java.io.IOException;
45
import org.netbeans.api.annotations.common.NonNull;
46
import org.netbeans.api.extexecution.base.Environment;
47
import org.openide.util.Lookup;
48
49
/**
50
 * The interface representing the implementation
51
 * of {@link org.netbeans.api.extexecution.base.ProcessBuilder}.
52
 *
53
 * @see org.netbeans.api.extexecution.base.ProcessBuilder
54
 * @author Petr Hejl
55
 */
56
public interface ProcessBuilderImplementation extends Lookup.Provider {
57
58
    /**
59
     * Returns the object for environment variables manipulation.
60
     *
61
     * @return the object for environment variables manipulation
62
     */
63
    @NonNull
64
    Environment getEnvironment();
65
66
    /**
67
     * Provides an extension point to the implementors. One may enhance the
68
     * functionality of {@link org.netbeans.api.extexecution.base.ProcessBuilder}
69
     * by this as the content of the {@link Lookup} is included in
70
     * {@link org.netbeans.api.extexecution.base.ProcessBuilder#getLookup()}
71
     *
72
     * @return a lookup providing an extension point
73
     */
74
    @Override
75
    Lookup getLookup();
76
77
    /**
78
     * Creates a process using the specified parameters.
79
     * <p>
80
     * The environment variables stored in parameters are acquired by call to
81
     * {@link Environment#values()}. So if the implementation does not aim to be
82
     * or can't be thread safe it may check or use the {@link Environment}
83
     * directly.
84
     *
85
     * @param parameters the instance describing the process parameters
86
     * @return a process created with specified parameters
87
     * @throws IOException if the process could not be created
88
     */
89
    @NonNull
90
    Process createProcess(@NonNull ProcessParameters parameters) throws IOException;
91
92
}
(-)a/extexecution.base/src/org/netbeans/spi/extexecution/base/ProcessParameters.java (+141 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2013 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2013 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.spi.extexecution.base;
43
44
import java.util.List;
45
import java.util.Map;
46
import org.netbeans.api.annotations.common.CheckForNull;
47
import org.netbeans.api.annotations.common.NonNull;
48
import org.netbeans.modules.extexecution.base.ProcessParametersAccessor;
49
50
/**
51
 * The parameters configured for process creation.
52
 *
53
 * @see ProcessBuilderImplementation
54
 * @author Petr Hejl
55
 */
56
public final class ProcessParameters {
57
58
    private final String executable;
59
60
    private final String workingDirectory;
61
62
    private final List<String> arguments;
63
64
    private final boolean redirectErrorStream;
65
66
    private final Map<String, String> environmentVariables;
67
68
    static {
69
        ProcessParametersAccessor.setDefault(new ProcessParametersAccessor() {
70
71
            @Override
72
            public ProcessParameters createProcessParameters(String executable, String workingDirectory,
73
                    List<String> arguments, boolean redirectErrorStream, Map<String, String> environmentVariables) {
74
                return new ProcessParameters(executable, workingDirectory, arguments,
75
                        redirectErrorStream, environmentVariables);
76
            }
77
        });
78
    }
79
80
    private ProcessParameters(String executable, String workingDirectory, List<String> arguments,
81
            boolean redirectErrorStream, Map<String, String> environmentVariables) {
82
        this.executable = executable;
83
        this.workingDirectory = workingDirectory;
84
        this.arguments = arguments;
85
        this.redirectErrorStream = redirectErrorStream;
86
        this.environmentVariables = environmentVariables;
87
    }
88
89
    /**
90
     * Returns the configured executable.
91
     *
92
     * @return the configured executable
93
     */
94
    @NonNull
95
    public String getExecutable() {
96
        return executable;
97
    }
98
99
    /**
100
     * Returns the configured working directory or <code>null</code> in case it
101
     * was not configured.
102
     *
103
     * @return the configured working directory or <code>null</code> in case it
104
     *             was not configured
105
     */
106
    @CheckForNull
107
    public String getWorkingDirectory() {
108
        return workingDirectory;
109
    }
110
111
    /**
112
     * Returns the arguments configured for the process.
113
     *
114
     * @return the arguments configured for the process
115
     */
116
    @NonNull
117
    public List<String> getArguments() {
118
        return arguments;
119
    }
120
121
    /**
122
     * Returns <code>true</code> if standard error stream should be redirected
123
     * to standard output stream.
124
     *
125
     * @return <code>true</code> if standard error stream should be redirected
126
     *             to standard output stream
127
     */
128
    public boolean isRedirectErrorStream() {
129
        return redirectErrorStream;
130
    }
131
132
    /**
133
     * Returns the environment variables configured for the process.
134
     *
135
     * @return the environment variables configured for the process
136
     */
137
    @NonNull
138
    public Map<String, String> getEnvironmentVariables() {
139
        return environmentVariables;
140
    }
141
}
(-)a/extexecution.base/src/org/netbeans/spi/extexecution/base/ProcessesImplementation.java (+74 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.spi.extexecution.base;
44
45
import java.util.Map;
46
47
/**
48
 * The interface representing the implementation
49
 * of {@link org.netbeans.api.extexecution.base.Processes}.
50
 * <p>
51
 * Implementation of this interface should be published in default lookup
52
 * in order to be used by
53
 * {@link org.netbeans.api.extexecution.base.Processes}
54
 *
55
 * @see org.netbeans.api.extexecution.base.Processes
56
 * @author Petr Hejl
57
 */
58
public interface ProcessesImplementation {
59
60
    /**
61
     * Kills the process passed as parameter and <i>attempts</i> to terminate
62
     * all child processes in process tree.
63
     * <p>
64
     * Any process running in environment containing the same variables
65
     * with the same values as those passed in <code>env</code> (all of them)
66
     * is supposed to be part of the process tree and may be killed.
67
     *
68
     * @param process process to kill
69
     * @param environment map containing the variables and their values which the
70
     *             process must have to be considered being part of
71
     *             the tree to kill
72
     */
73
    void killTree(Process process, Map<String, String> environment);
74
}
(-)a/extexecution.base/src/org/netbeans/spi/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 support SPI for creation of external processes.
47
 *
48
 * @see org.netbeans.spi.extexecution.base.ProcessBuilderImplementation
49
 */
50
package org.netbeans.spi.extexecution.base;
51
(-)a/extexecution.base/test/unit/src/org/netbeans/api/extexecution/base/BaseExecutionServiceTest.java (+513 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;
44
45
import java.io.FilterInputStream;
46
import java.io.IOException;
47
import java.io.InputStream;
48
import java.io.OutputStream;
49
import java.lang.reflect.InvocationTargetException;
50
import java.nio.charset.Charset;
51
import java.util.LinkedList;
52
import java.util.List;
53
import java.util.concurrent.BrokenBarrierException;
54
import java.util.concurrent.Callable;
55
import java.util.concurrent.CountDownLatch;
56
import java.util.concurrent.CyclicBarrier;
57
import java.util.concurrent.ExecutionException;
58
import java.util.concurrent.Future;
59
import java.util.concurrent.TimeUnit;
60
import java.util.concurrent.TimeoutException;
61
import org.netbeans.api.extexecution.base.input.InputProcessor;
62
import org.netbeans.api.extexecution.base.input.InputProcessors;
63
import org.netbeans.api.extexecution.base.input.TestInputUtils;
64
import org.netbeans.api.extexecution.base.input.TestLineProcessor;
65
import org.netbeans.junit.NbTestCase;
66
67
/**
68
 *
69
 * @author Petr Hejl
70
 */
71
public class BaseExecutionServiceTest extends NbTestCase {
72
73
    private static final int PROCESS_TIMEOUT = 30000;
74
75
    public BaseExecutionServiceTest(String name) {
76
        super(name);
77
    }
78
79
    public void testSimpleRun() throws InterruptedException {
80
        TestProcess process = new TestProcess(0);
81
        TestCallable callable = new TestCallable();
82
        callable.addProcess(process);
83
84
        BaseExecutionDescriptor descriptor = new BaseExecutionDescriptor();
85
        BaseExecutionService service = BaseExecutionService.newService(
86
                callable, descriptor);
87
88
        Future<Integer> task = service.run();
89
        assertNotNull(task);
90
91
        process.waitStarted();
92
93
        process.destroy();
94
        process.waitFor();
95
        assertTrue(process.isFinished());
96
        assertEquals(0, process.exitValue());
97
    }
98
99
    public void testReRun() throws InvocationTargetException, InterruptedException {
100
        TestProcess process = new TestProcess(0);
101
        TestCallable callable = new TestCallable();
102
        callable.addProcess(process);
103
104
        BaseExecutionDescriptor descriptor = new BaseExecutionDescriptor();
105
        BaseExecutionService service = BaseExecutionService.newService(
106
                callable, descriptor);
107
108
        // first run
109
        Future<Integer> task = service.run();
110
        assertNotNull(task);
111
        assertFalse(process.isFinished());
112
113
        process.waitStarted();
114
        task.cancel(true);
115
        assertTrue(task.isCancelled());
116
117
        process.waitFor();
118
        assertTrue(process.isFinished());
119
        assertEquals(0, process.exitValue());
120
121
        // second run
122
        process = new TestProcess(1);
123
        callable.addProcess(process);
124
125
        task = service.run();
126
        assertNotNull(task);
127
        assertFalse(process.isFinished());
128
129
        // we want to test real started process
130
        process.waitStarted();
131
        task.cancel(true);
132
        assertTrue(task.isCancelled());
133
134
        process.waitFor();
135
        assertTrue(process.isFinished());
136
        assertEquals(1, process.exitValue());
137
    }
138
139
    public void testCancelRerun() throws InterruptedException {
140
        TestProcess process = new TestProcess(0);
141
        TestCallable callable = new TestCallable();
142
        callable.addProcess(process);
143
144
        BaseExecutionDescriptor descriptor = new BaseExecutionDescriptor();
145
        final CountDownLatch latch = new CountDownLatch(1);
146
        descriptor = descriptor.preExecution(new Runnable() {
147
            public void run() {
148
                try {
149
                    latch.await();
150
                } catch (InterruptedException ex) {
151
                    Thread.currentThread().interrupt();
152
                }
153
            }
154
        });
155
156
        BaseExecutionService service = BaseExecutionService.newService(
157
                callable, descriptor);
158
159
        // first run
160
        Future<Integer> task = service.run();
161
        assertNotNull(task);
162
        assertFalse(process.isFinished());
163
164
        task.cancel(true);
165
        // guaranteed process was not executed
166
        latch.countDown();
167
168
        assertTrue(task.isCancelled());
169
        assertFalse(process.isStarted());
170
        assertFalse(process.isFinished());
171
172
        // second run
173
        task = service.run();
174
        assertNotNull(task);
175
        assertFalse(process.isFinished());
176
177
        // we want to test real started process
178
        process.waitStarted();
179
        task.cancel(true);
180
        assertTrue(task.isCancelled());
181
182
        process.waitFor();
183
        assertTrue(process.isFinished());
184
        assertEquals(0, process.exitValue());
185
    }
186
187
    public void testConcurrentRun() throws InterruptedException, ExecutionException, BrokenBarrierException {
188
        TestProcess process1 = new TestProcess(0);
189
        TestProcess process2 = new TestProcess(1);
190
        TestCallable callable = new TestCallable();
191
        callable.addProcess(process1);
192
        callable.addProcess(process2);
193
194
        BaseExecutionDescriptor descriptor = new BaseExecutionDescriptor();
195
        final CyclicBarrier barrier = new CyclicBarrier(3);
196
        descriptor = descriptor.preExecution(new Runnable() {
197
            public void run() {
198
                try {
199
                    barrier.await();
200
                } catch (InterruptedException ex) {
201
                    Thread.currentThread().interrupt();
202
                } catch (BrokenBarrierException ex) {
203
                    throw new RuntimeException(ex);
204
                }
205
            }
206
        });
207
208
        BaseExecutionService service = BaseExecutionService.newService(
209
                callable, descriptor);
210
211
        Future<Integer> task1 = service.run();
212
        Future<Integer> task2 = service.run();
213
214
        // wait for both tasks
215
        barrier.await();
216
217
        process1.destroy();
218
        process2.destroy();
219
220
        // TODO can we check returns values somehow ?
221
        // task - process assignment is determined by the winner of the race :(
222
        task1.get().intValue();
223
        task2.get().intValue();
224
225
        assertTrue(task1.isDone());
226
        assertTrue(task2.isDone());
227
228
        assertFalse(task1.isCancelled());
229
        assertFalse(task2.isCancelled());
230
    }
231
232
    public void testHooks() throws InterruptedException, ExecutionException {
233
        TestProcess process = new TestProcess(0);
234
        TestCallable callable = new TestCallable();
235
        callable.addProcess(process);
236
237
        class TestRunnable implements Runnable {
238
239
            public volatile boolean executed;
240
241
            public void run() {
242
                executed = true;
243
            }
244
        }
245
        
246
        class TestParametrizedRunnable implements ParametrizedRunnable<Integer> {
247
248
            public volatile boolean executed;
249
250
            public void run(Integer parameter) {
251
                executed = true;
252
            }
253
        }
254
255
        TestRunnable preRunnable = new TestRunnable();
256
        TestParametrizedRunnable postRunnable = new TestParametrizedRunnable();
257
258
        BaseExecutionDescriptor descriptor = new BaseExecutionDescriptor();
259
        descriptor = descriptor.preExecution(preRunnable).postExecution(postRunnable);
260
261
        BaseExecutionService service = BaseExecutionService.newService(
262
                callable, descriptor);
263
264
        Future<Integer> task = service.run();
265
        assertNotNull(task);
266
267
        process.waitStarted();
268
        assertTrue(preRunnable.executed);
269
270
        process.destroy();
271
        assertEquals(0, task.get().intValue());
272
        assertTrue(postRunnable.executed);
273
    }
274
275
    public void testCharset() throws InterruptedException, ExecutionException, TimeoutException {
276
        Charset charset = Charset.forName("UTF-16LE");
277
        final String[] lines = new String[] {"Process line \u1234", "Process line \u1235", "Process line \u1236"};
278
279
        TestInputStream is = new TestInputStream(TestInputUtils.prepareInputStream(lines, "\n", charset, true));
280
        TestProcess process = new TestProcess(0, is, null);
281
        is.setProcess(process);
282
283
        TestCallable callable = new TestCallable();
284
        callable.addProcess(process);
285
286
        final TestLineProcessor processor = new TestLineProcessor(false);
287
        BaseExecutionDescriptor descriptor = new BaseExecutionDescriptor().charset(charset).outProcessorFactory(
288
                new BaseExecutionDescriptor.InputProcessorFactory() {
289
290
            public InputProcessor newInputProcessor() {
291
                return InputProcessors.bridge(processor);
292
            }
293
        });
294
295
        BaseExecutionService service = BaseExecutionService.newService(
296
                callable, descriptor);
297
298
        Future<Integer> task = service.run();
299
        assertNotNull(task);
300
301
        assertEquals(0, task.get(PROCESS_TIMEOUT, TimeUnit.MILLISECONDS).intValue());
302
        assertTrue(process.isFinished());
303
        assertEquals(0, process.exitValue());
304
305
        List<String> processed = processor.getLinesProcessed();
306
        assertEquals(lines.length, processed.size());
307
        for (int i = 0; i < lines.length; i++) {
308
            assertEquals(lines[i], processed.get(i));
309
        }
310
    }
311
312
    private static class TestCallable implements Callable<Process> {
313
314
        private final LinkedList<TestProcess> processes = new LinkedList<TestProcess>();
315
316
        public TestCallable() {
317
            super();
318
        }
319
320
        public synchronized void addProcess(TestProcess process) {
321
            processes.add(process);
322
        }
323
324
        public synchronized Process call() throws Exception {
325
            if (processes.isEmpty()) {
326
                throw new IllegalStateException("No process configured");
327
            }
328
329
            TestProcess ret = processes.removeFirst();
330
            ret.start();
331
332
            return ret;
333
        }
334
    }
335
336
    private static class TestProcess extends Process {
337
338
        private final int returnValue;
339
340
        private final InputStream is;
341
342
        private final InputStream err;
343
344
        private boolean finished;
345
346
        private boolean started;
347
348
        public TestProcess(int returnValue) {
349
            this(returnValue, TestInputUtils.prepareInputStream(
350
                    new String[] {"Process line 1", "Process line 2", "Process line 3"}, "\n",
351
                    Charset.defaultCharset(), true), null);
352
        }
353
354
        public TestProcess(int returnValue, InputStream is, InputStream err) {
355
            this.returnValue = returnValue;
356
            this.is = is;
357
            this.err = err;
358
        }
359
360
        public void start() {
361
            synchronized (this) {
362
                started = true;
363
                notifyAll();
364
            }
365
        }
366
367
        public boolean isStarted() {
368
            synchronized (this) {
369
                return started;
370
            }
371
        }
372
373
        public boolean isFinished() {
374
            synchronized (this) {
375
                return finished;
376
            }
377
        }
378
379
        @Override
380
        public void destroy() {
381
            synchronized (this) {
382
                if (finished) {
383
                    return;
384
                }
385
386
                finished = true;
387
                notifyAll();
388
            }
389
        }
390
391
        @Override
392
        public int exitValue() {
393
            synchronized (this) {
394
                if (!finished) {
395
                    throw new IllegalStateException("Not finished yet");
396
                }
397
            }
398
            return returnValue;
399
        }
400
401
        @Override
402
        public InputStream getErrorStream() {
403
            if (err != null) {
404
                return err;
405
            }
406
            return new InputStream() {
407
                @Override
408
                public int read() throws IOException {
409
                    return -1;
410
                }
411
            };
412
        }
413
414
        @Override
415
        public InputStream getInputStream() {
416
            return is;
417
        }
418
419
        @Override
420
        public OutputStream getOutputStream() {
421
            return new OutputStream() {
422
                @Override
423
                public void write(int b) throws IOException {
424
                    // throw it away
425
                }
426
            };
427
        }
428
429
        @Override
430
        public int waitFor() throws InterruptedException {
431
            synchronized (this) {
432
                while (!finished) {
433
                    wait();
434
                }
435
            }
436
            return returnValue;
437
        }
438
439
        public void waitStarted() throws InterruptedException {
440
            synchronized (this) {
441
                while (!started) {
442
                    wait();
443
                }
444
            }
445
        }
446
    }
447
448
    private static class TestInputStream extends FilterInputStream {
449
450
        private Process process;
451
452
        public TestInputStream(InputStream is) {
453
            super(is);
454
        }
455
456
        public synchronized Process getProcess() {
457
            return process;
458
        }
459
460
        public synchronized void setProcess(Process process) {
461
            this.process = process;
462
        }
463
464
        @Override
465
        public int available() throws IOException {
466
            int available = super.available();
467
            if (available <= 0) {
468
                Process toDestroy = getProcess();
469
                if (toDestroy != null) {
470
                    toDestroy.destroy();
471
                }
472
            }
473
            return available;
474
        }
475
476
477
        @Override
478
        public int read() throws IOException {
479
            int val = super.read();
480
            if (val < 0) {
481
                Process toDestroy = getProcess();
482
                if (toDestroy != null) {
483
                    toDestroy.destroy();
484
                }
485
            }
486
            return val;
487
        }
488
489
        @Override
490
        public int read(byte[] b) throws IOException {
491
            int val = super.read(b);
492
            if (val < 0) {
493
                Process toDestroy = getProcess();
494
                if (toDestroy != null) {
495
                    toDestroy.destroy();
496
                }
497
            }
498
            return val;
499
        }
500
501
        @Override
502
        public int read(byte[] b, int off, int len) throws IOException {
503
            int val = super.read(b, off, len);
504
            if (val < 0) {
505
                Process toDestroy = getProcess();
506
                if (toDestroy != null) {
507
                    toDestroy.destroy();
508
                }
509
            }
510
            return val;
511
        }
512
    }
513
}
(-)a/extexecution.base/test/unit/src/org/netbeans/api/extexecution/base/ProcessBuilderTest.java (+303 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.IOException;
45
import java.util.ArrayList;
46
import java.util.Collections;
47
import java.util.HashMap;
48
import java.util.List;
49
import java.util.Map;
50
import org.netbeans.junit.NbTestCase;
51
import org.netbeans.spi.extexecution.base.EnvironmentFactory;
52
import org.netbeans.spi.extexecution.base.EnvironmentImplementation;
53
import org.netbeans.spi.extexecution.base.ProcessBuilderFactory;
54
import org.netbeans.spi.extexecution.base.ProcessBuilderImplementation;
55
import org.netbeans.spi.extexecution.base.ProcessParameters;
56
import org.openide.util.Lookup;
57
58
/**
59
 *
60
 * @author Petr Hejl
61
 */
62
public class ProcessBuilderTest extends NbTestCase {
63
64
    public ProcessBuilderTest(String name) {
65
        super(name);
66
    }
67
68
    public void testExecutable() throws IOException {
69
        TestProcessBuilder testBuilder = new TestProcessBuilder();
70
        ProcessBuilder builder = ProcessBuilderFactory.createProcessBuilder(testBuilder, "Test builder");
71
72
        try {
73
            builder.call();
74
            fail("Empty executable does not throw exception");
75
        } catch (IllegalStateException ex) {
76
            // expected
77
        }
78
79
        builder.setExecutable("ls");
80
        builder.call();
81
        assertEquals("ls", testBuilder.getParameters().getExecutable());
82
83
        builder.setExecutable("cd");
84
        assertEquals("ls", testBuilder.getParameters().getExecutable());
85
86
        builder.call();
87
        assertEquals("cd", testBuilder.getParameters().getExecutable());
88
    }
89
90
    public void testWorkingDirectory() throws IOException {
91
        TestProcessBuilder testBuilder = new TestProcessBuilder();
92
        ProcessBuilder builder = ProcessBuilderFactory.createProcessBuilder(testBuilder, "Test builder");
93
        builder.setExecutable("ls");
94
95
        builder.call();
96
        assertNull(testBuilder.getParameters().getWorkingDirectory());
97
98
        builder.setWorkingDirectory("test");
99
        assertNull(testBuilder.getParameters().getWorkingDirectory());
100
101
        builder.call();
102
        assertEquals("test", testBuilder.getParameters().getWorkingDirectory());
103
    }
104
105
    public void testArguments() throws IOException {
106
        TestProcessBuilder testBuilder = new TestProcessBuilder();
107
        ProcessBuilder builder = ProcessBuilderFactory.createProcessBuilder(testBuilder, "Test builder");
108
        builder.setExecutable("ls");
109
110
        builder.call();
111
        assertTrue(testBuilder.getParameters().getArguments().isEmpty());
112
113
        List<String> arguments = new ArrayList<String>();
114
        Collections.addAll(arguments, "test1", "test2");
115
        builder.setArguments(arguments);
116
        assertTrue(testBuilder.getParameters().getArguments().isEmpty());
117
118
        builder.call();
119
        assertEquals(2, testBuilder.getParameters().getArguments().size());
120
        assertEquals("test1", testBuilder.getParameters().getArguments().get(0));
121
        assertEquals("test2", testBuilder.getParameters().getArguments().get(1));
122
123
        arguments.remove(0);
124
        assertEquals(2, testBuilder.getParameters().getArguments().size());
125
        assertEquals("test1", testBuilder.getParameters().getArguments().get(0));
126
        assertEquals("test2", testBuilder.getParameters().getArguments().get(1));
127
128
        builder.call();
129
        assertEquals(2, testBuilder.getParameters().getArguments().size());
130
        assertEquals("test1", testBuilder.getParameters().getArguments().get(0));
131
        assertEquals("test2", testBuilder.getParameters().getArguments().get(1));
132
133
        builder.setArguments(arguments);
134
        builder.call();
135
        assertEquals(1, testBuilder.getParameters().getArguments().size());
136
        assertEquals("test2", testBuilder.getParameters().getArguments().get(0));
137
    }
138
139
    public void testEnvironmentVariables() throws IOException {
140
        TestProcessBuilder testBuilder = new TestProcessBuilder();
141
        ProcessBuilder builder = ProcessBuilderFactory.createProcessBuilder(testBuilder, "Test builder");
142
        builder.setExecutable("ls");
143
144
        builder.call();
145
        assertTrue(testBuilder.getParameters().getEnvironmentVariables().isEmpty());
146
147
        Environment environment = builder.getEnvironment();
148
        environment.setVariable("key1", "value1");
149
        environment.setVariable("key2", "value2");
150
        assertTrue(testBuilder.getParameters().getEnvironmentVariables().isEmpty());
151
152
        builder.call();
153
        assertEquals(2, testBuilder.getParameters().getEnvironmentVariables().size());
154
        assertEquals("value1", testBuilder.getParameters()
155
                .getEnvironmentVariables().get("key1"));
156
        assertEquals("value2", testBuilder.getParameters()
157
                .getEnvironmentVariables().get("key2"));
158
159
        environment.removeVariable("key1");
160
        assertEquals(2, testBuilder.getParameters().getEnvironmentVariables().size());
161
        assertEquals("value1", testBuilder.getParameters()
162
                .getEnvironmentVariables().get("key1"));
163
        assertEquals("value2", testBuilder.getParameters()
164
                .getEnvironmentVariables().get("key2"));
165
166
        builder.call();
167
        assertEquals(1, testBuilder.getParameters()
168
                .getEnvironmentVariables().size());
169
        assertEquals("value2", testBuilder.getParameters()
170
                .getEnvironmentVariables().get("key2"));
171
    }
172
173
    public void testEnvironment() throws IOException {
174
        TestProcessBuilder testBuilder = new TestProcessBuilder();
175
        ProcessBuilder builder = ProcessBuilderFactory.createProcessBuilder(testBuilder, "Test builder");
176
        builder.setExecutable("ls");
177
178
        builder.getEnvironment().setVariable("key1", "value1");
179
        builder.getEnvironment().setVariable("key2", "value2");
180
181
        assertEquals("value1", testBuilder.getEnvironment().getVariable("key1"));
182
        assertEquals("value2", testBuilder.getEnvironment().getVariable("key2"));
183
184
        builder.call();
185
        assertEquals(2, testBuilder.getParameters().getEnvironmentVariables().size());
186
        assertEquals("value1", testBuilder.getParameters()
187
                .getEnvironmentVariables().get("key1"));
188
        assertEquals("value2", testBuilder.getParameters()
189
                .getEnvironmentVariables().get("key2"));
190
191
        builder.getEnvironment().prependPath("PATH", "/test1");
192
        builder.getEnvironment().prependPath("PATH", "/test2");
193
194
        builder.call();
195
        assertEquals(3, testBuilder.getParameters().getEnvironmentVariables().size());
196
        assertEquals("/test2:/test1",
197
                testBuilder.getParameters().getEnvironmentVariables().get("PATH"));
198
199
        builder.getEnvironment().appendPath("PATH", "/test3");
200
201
        builder.call();
202
        assertEquals(3, testBuilder.getParameters().getEnvironmentVariables().size());
203
        assertEquals("/test2:/test1:/test3",
204
                testBuilder.getParameters().getEnvironmentVariables().get("PATH"));
205
206
        builder.getEnvironment().removeVariable("PATH");
207
        assertNull(builder.getEnvironment().getVariable("PATH"));
208
209
        builder.call();
210
        assertEquals(2, testBuilder.getParameters().getEnvironmentVariables().size());
211
        assertNull(testBuilder.getParameters().getEnvironmentVariables().get("PATH"));
212
    }
213
214
    public void testRedirectErrorStream() throws IOException {
215
        TestProcessBuilder testBuilder = new TestProcessBuilder();
216
        ProcessBuilder builder = ProcessBuilderFactory.createProcessBuilder(testBuilder, "Test builder");
217
        builder.setExecutable("ls");
218
219
        builder.call();
220
        assertFalse(testBuilder.getParameters().isRedirectErrorStream());
221
222
        builder.setRedirectErrorStream(true);
223
        assertFalse(testBuilder.getParameters().isRedirectErrorStream());
224
225
        builder.call();
226
        assertTrue(testBuilder.getParameters().isRedirectErrorStream());
227
    }
228
229
    private static class TestProcessBuilder implements ProcessBuilderImplementation {
230
231
        private final Environment environment = EnvironmentFactory.createEnvironment(new TestEnvironment());
232
233
        private ProcessParameters parameters;
234
235
        @Override
236
        public Environment getEnvironment() {
237
            return environment;
238
        }
239
240
        @Override
241
        public Lookup getLookup() {
242
            return Lookup.EMPTY;
243
        }
244
245
        @Override
246
        public Process createProcess(ProcessParameters parameters) throws IOException {
247
            this.parameters = parameters;
248
249
            return null;
250
        }
251
252
        public ProcessParameters getParameters() {
253
            return parameters;
254
        }
255
    }
256
257
    private static class TestEnvironment implements EnvironmentImplementation {
258
259
        private final Map<String, String> values = new HashMap<String, String>();
260
261
        @Override
262
        public String getVariable(String name) {
263
            return values.get(name);
264
        }
265
266
        @Override
267
        public void appendPath(String name, String value) {
268
            String orig = values.get(name);
269
            if (orig == null || orig.isEmpty()) {
270
                values.put(name, value);
271
            } else {
272
                // intentionally hardcoded for tests
273
                values.put(name, orig + ":" + value);
274
            }
275
        }
276
277
        @Override
278
        public void prependPath(String name, String value) {
279
            String orig = values.get(name);
280
            if (orig == null || orig.isEmpty()) {
281
                values.put(name, value);
282
            } else {
283
                // intentionally hardcoded for tests
284
                values.put(name, value + ":" + orig);
285
            }
286
        }
287
288
        @Override
289
        public void setVariable(String name, String value) {
290
            values.put(name, value);
291
        }
292
293
        @Override
294
        public void removeVariable(String name) {
295
            values.remove(name);
296
        }
297
298
        @Override
299
        public Map<String, String> values() {
300
            return new HashMap<String, String>(values);
301
        }
302
    }
303
}
(-)a/extexecution.base/test/unit/src/org/netbeans/api/extexecution/base/ProcessesTest.java (+152 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.api.extexecution.base;
44
45
import java.io.InputStream;
46
import java.io.OutputStream;
47
import java.util.HashMap;
48
import java.util.Map;
49
import org.netbeans.junit.NbTestCase;
50
import org.netbeans.spi.extexecution.base.ProcessesImplementation;
51
import org.openide.util.Lookup;
52
import org.openide.util.test.MockLookup;
53
54
/**
55
 *
56
 * @author Petr Hejl
57
 */
58
public class ProcessesTest extends NbTestCase {
59
60
    public ProcessesTest(String name) {
61
        super(name);
62
    }
63
64
    @Override
65
    protected void setUp() throws Exception {
66
        super.setUp();
67
68
        MockLookup.setInstances(new TestProcessesImplementation());
69
    }
70
71
    public void testKillTree() {
72
        TestProcess process = new TestProcess();
73
        Map<String, String> env = new HashMap<String, String>();
74
        env.put("test1", "value1");
75
        env.put("test2", "value2");
76
77
        Processes.killTree(process, env);
78
79
        ProcessesImplementation impl = Lookup.getDefault().lookup(ProcessesImplementation.class);
80
        assertNotNull(impl);
81
82
        TestProcessesImplementation testPerformer = (TestProcessesImplementation) impl;
83
        assertEquals(process, testPerformer.getProcess());
84
85
        Map<String, String> perfEnv = testPerformer.getEnv();
86
        assertEquals(2, perfEnv.size());
87
88
        assertEquals(env.get("test1"), perfEnv.get("test1"));
89
        assertEquals(env.get("test2"), perfEnv.get("test2"));
90
    }
91
92
    private static class TestProcess extends Process {
93
94
        private boolean destroyed;
95
96
        public boolean destroyCalled() {
97
            return destroyed;
98
        }
99
100
        @Override
101
        public void destroy() {
102
            this.destroyed = true;
103
        }
104
105
        @Override
106
        public int exitValue() {
107
            return 0;
108
        }
109
110
        @Override
111
        public InputStream getErrorStream() {
112
            throw new UnsupportedOperationException("Not supported yet.");
113
        }
114
115
        @Override
116
        public InputStream getInputStream() {
117
            throw new UnsupportedOperationException("Not supported yet.");
118
        }
119
120
        @Override
121
        public OutputStream getOutputStream() {
122
            throw new UnsupportedOperationException("Not supported yet.");
123
        }
124
125
        @Override
126
        public int waitFor() throws InterruptedException {
127
            return 0;
128
        }
129
130
    }
131
132
    private static class TestProcessesImplementation implements ProcessesImplementation {
133
134
        private Process process;
135
136
        private Map<String, String> env;
137
138
        @Override
139
        public void killTree(Process process, Map<String, String> environment) {
140
            this.process = process;
141
            this.env = environment;
142
        }
143
144
        public Process getProcess() {
145
            return process;
146
        }
147
148
        public Map<String, String> getEnv() {
149
            return env;
150
        }
151
    }
152
}
(-)a/extexecution.base/test/unit/src/org/netbeans/api/extexecution/base/input/InputProcessorsTest.java (+216 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.ByteArrayOutputStream;
46
import java.io.IOException;
47
import java.io.PrintWriter;
48
import java.util.ArrayList;
49
import java.util.Arrays;
50
import java.util.Collections;
51
import java.util.List;
52
import org.netbeans.junit.NbTestCase;
53
54
/**
55
 *
56
 * @author Petr Hejl
57
 */
58
public class InputProcessorsTest extends NbTestCase {
59
60
    private static final char[] PROXY_CHARS_CHUNK1 = "abcdefghij".toCharArray();
61
62
    private static final char[] PROXY_CHARS_CHUNK2 = "jihgfedcba".toCharArray();
63
64
    private static final char[][] PROXY_TEST_CHARS = new char[][] {
65
        PROXY_CHARS_CHUNK1, PROXY_CHARS_CHUNK2
66
    };
67
68
    private static final List<String> BRIDGE_TEST_LINES = new ArrayList<String>();
69
70
    private static final char[][] BRIDGE_TEST_CHARS;
71
72
    static {
73
        Collections.addAll(BRIDGE_TEST_LINES, "test1", "test2");
74
75
        BRIDGE_TEST_CHARS = new char[BRIDGE_TEST_LINES.size()][];
76
        for (int i = 0; i < BRIDGE_TEST_LINES.size(); i++) {
77
            BRIDGE_TEST_CHARS[i] = (BRIDGE_TEST_LINES.get(i) + "\n").toCharArray();
78
        }
79
    }
80
81
    public InputProcessorsTest(String name) {
82
        super(name);
83
    }
84
85
    public void testBridge() throws IOException {
86
        TestLineProcessor processor = new TestLineProcessor(false);
87
        InputProcessor bridge = InputProcessors.bridge(processor);
88
89
        for (char[] chunk : BRIDGE_TEST_CHARS) {
90
            bridge.processInput(chunk);
91
        }
92
93
        assertEquals(0, processor.getResetCount());
94
        assertEquals(BRIDGE_TEST_LINES, processor.getLinesProcessed());
95
96
        bridge.reset();
97
        assertEquals(1, processor.getResetCount());
98
99
        bridge.close();
100
        assertClosedConditions(bridge, true);
101
        assertTrue(processor.isClosed());
102
    }
103
104
    public void testProxy() throws IOException {
105
        TestInputProcessor processor1 = new TestInputProcessor(false);
106
        TestInputProcessor processor2 = new TestInputProcessor(false);
107
108
        InputProcessor proxy = InputProcessors.proxy(processor1, processor2);
109
        int size = 0;
110
        for (char[] chunk : PROXY_TEST_CHARS) {
111
            proxy.processInput(chunk);
112
            size += chunk.length;
113
        }
114
115
        char[] expected = new char[size];
116
        int position = 0;
117
        for (char[] chunk : PROXY_TEST_CHARS) {
118
            System.arraycopy(chunk, 0, expected, position, chunk.length);
119
            position += chunk.length;
120
        }
121
122
        assertEquals(0, processor1.getResetCount());
123
        assertEquals(0, processor2.getResetCount());
124
125
        assertTrue(Arrays.equals(expected, processor1.getCharsProcessed()));
126
        assertTrue(Arrays.equals(expected, processor2.getCharsProcessed()));
127
128
        proxy.reset();
129
130
        assertEquals(1, processor1.getResetCount());
131
        assertEquals(1, processor2.getResetCount());
132
133
        proxy.close();
134
        assertClosedConditions(proxy, true);
135
136
        assertTrue(processor1.isClosed());
137
        assertTrue(processor2.isClosed());
138
    }
139
140
    public void testPrinting() throws IOException {
141
        TestInputWriter writer = new TestInputWriter(new PrintWriter(new ByteArrayOutputStream()));
142
        InputProcessor processor = InputProcessors.printing(writer);
143
144
        processor.processInput("pre".toCharArray());
145
        assertEquals("pre", writer.getPrintedRaw());
146
        processor.processInput("test1\n".toCharArray());
147
        assertEquals("pretest1\n", writer.getPrintedRaw());
148
        processor.processInput("test2\n".toCharArray());
149
        assertEquals("pretest1\ntest2\n", writer.getPrintedRaw());
150
        processor.processInput("test3".toCharArray());
151
        assertEquals("pretest1\ntest2\ntest3", writer.getPrintedRaw());
152
153
        processor.processInput("\n".toCharArray());
154
155
        processor.close();
156
        assertClosedConditions(processor, false);
157
    }
158
159
    public void testPrintingCloseOrdering() throws IOException {
160
        final TestInputWriter writer = new TestInputWriter(new PrintWriter(new ByteArrayOutputStream()));
161
        final InputProcessor delegate = InputProcessors.printing(writer);
162
163
        InputProcessor processor = new InputProcessor() {
164
165
            public void processInput(char[] chars) throws IOException {
166
                delegate.processInput(chars);
167
            }
168
169
            public void reset() throws IOException {
170
                delegate.reset();
171
            }
172
173
            public void close() throws IOException {
174
                delegate.processInput("closing mark".toCharArray());
175
                delegate.close();
176
            }
177
        };
178
179
180
        processor.processInput("first".toCharArray());
181
        assertEquals("first", writer.getPrintedRaw());
182
        processor.processInput("second\n".toCharArray());
183
        assertEquals("firstsecond\n", writer.getPrintedRaw());
184
185
        processor.close();
186
        assertEquals("firstsecond\nclosing mark", writer.getPrintedRaw());
187
        assertClosedConditions(processor, false);
188
    }
189
190
    private static <T> void assertEquals(List<T> expected, List<T> value) {
191
        assertEquals(expected.size(), value.size());
192
        for (int i = 0; i < expected.size(); i++) {
193
            assertEquals(expected.get(i), value.get(i));
194
        }
195
    }
196
197
    private static void assertClosedConditions(InputProcessor inputProcessor,
198
            boolean reset) throws IOException {
199
200
        try {
201
            inputProcessor.processInput(new char[] {'0'});
202
            fail("Does not throw IllegalStateException after close");
203
        } catch (IllegalStateException ex) {
204
            // expected
205
        }
206
207
        if (reset) {
208
            try {
209
                inputProcessor.reset();
210
                fail("Does not throw IllegalStateException after close");
211
            } catch (IllegalStateException ex) {
212
                // expected
213
            }
214
        }
215
    }
216
}
(-)a/extexecution.base/test/unit/src/org/netbeans/api/extexecution/base/input/InputReadersFileTest.java (+188 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
 * 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 2007 Sun Microsystems, Inc.
41
 */
42
43
package org.netbeans.api.extexecution.base.input;
44
45
import java.io.File;
46
import java.io.IOException;
47
import java.nio.charset.Charset;
48
import java.util.Arrays;
49
import org.netbeans.api.extexecution.base.input.InputReaders.FileInput;
50
import org.netbeans.junit.NbTestCase;
51
52
/**
53
 *
54
 * @author Petr Hejl
55
 */
56
public class InputReadersFileTest extends NbTestCase {
57
58
    private static final char[] TEST_CHARS = "abcdefghij".toCharArray();
59
60
    private static final char[] TEST_CHARS_ROTATE = "jihgfedcba".toCharArray();
61
62
    private static final Charset TEST_CHARSET = Charset.forName("UTF-8");
63
64
    private static final int MAX_RETRIES = TEST_CHARS.length * 2;
65
66
    private File byteFile;
67
68
    private File byteFileRotate;
69
70
    public InputReadersFileTest(String name) {
71
        super(name);
72
    }
73
74
    @Override
75
    protected void setUp() throws Exception {
76
        super.setUp();
77
78
        byteFile = TestInputUtils.prepareFile(
79
                "testFile.txt", getWorkDir(), TEST_CHARS, TEST_CHARSET);
80
        byteFileRotate = TestInputUtils.prepareFile(
81
                "testFileRotate.txt", getWorkDir(), TEST_CHARS_ROTATE, TEST_CHARSET);
82
    }
83
84
    public void testReadInput() throws IOException {
85
        final FileInput fileInput = new FileInput(byteFile, TEST_CHARSET);
86
        InputReader reader = InputReaders.forFileInputProvider(new InputReaders.FileInput.Provider() {
87
88
            public FileInput getFileInput() {
89
                return fileInput;
90
            }
91
        });
92
        TestInputProcessor processor = new TestInputProcessor(false);
93
94
        int read = 0;
95
        int retries = 0;
96
        while (read < TEST_CHARS.length && retries < MAX_RETRIES) {
97
            read += reader.readInput(processor);
98
            retries++;
99
        }
100
101
        assertEquals(read, TEST_CHARS.length);
102
        assertEquals(0, processor.getResetCount());
103
104
        assertTrue(Arrays.equals(TEST_CHARS, processor.getCharsProcessed()));
105
    }
106
107
    public void testRotation() throws IOException {
108
        TestProvider provider = new TestProvider(byteFile, TEST_CHARSET);
109
110
        InputReader outputReader = InputReaders.forFileInputProvider(provider);
111
        TestInputProcessor processor = new TestInputProcessor(true);
112
113
        int read = 0;
114
        int retries = 0;
115
        while (read < TEST_CHARS.length && retries < MAX_RETRIES) {
116
            read += outputReader.readInput(processor);
117
            retries++;
118
        }
119
120
        assertEquals(read, TEST_CHARS.length);
121
        assertEquals(0, processor.getResetCount());
122
123
        assertTrue(Arrays.equals(TEST_CHARS, processor.getCharsProcessed()));
124
125
        // file rotation
126
        provider.setFile(byteFileRotate);
127
128
        read = 0;
129
        retries = 0;
130
        while (read < TEST_CHARS_ROTATE.length && retries < MAX_RETRIES) {
131
            read += outputReader.readInput(processor);
132
            retries++;
133
        }
134
135
        assertEquals(read, TEST_CHARS_ROTATE.length);
136
        assertEquals(1, processor.getResetCount());
137
138
        assertTrue(Arrays.equals(TEST_CHARS_ROTATE, processor.getCharsProcessed()));
139
    }
140
141
    public void testFactory() {
142
        try {
143
            InputReaders.forFile(null, null);
144
            fail("Accepts null file generator"); // NOI18N
145
        } catch (NullPointerException ex) {
146
            // expected
147
        }
148
    }
149
150
    public void testClose() throws IOException {
151
        final FileInput fileInput = new FileInput(byteFile, TEST_CHARSET);
152
        InputReader reader = InputReaders.forFileInputProvider(new InputReaders.FileInput.Provider() {
153
154
            public FileInput getFileInput() {
155
                return fileInput;
156
            }
157
        });
158
        reader.close();
159
160
        try {
161
            reader.readInput(null);
162
            fail("Reader not throw exception on read after closing it"); // NOI18N
163
        } catch (IllegalStateException ex) {
164
            // expected
165
        }
166
    }
167
168
    private static class TestProvider implements InputReaders.FileInput.Provider {
169
170
        private final Charset charset;
171
172
        private FileInput fileInput;
173
174
        public TestProvider(File file, Charset charset) {
175
            this.charset = charset;
176
            setFile(file);
177
        }
178
179
        public final FileInput getFileInput() {
180
            return fileInput;
181
        }
182
183
        public final void setFile(File file) {
184
            this.fileInput = new FileInput(file, charset);
185
        }
186
187
    }
188
}
(-)a/extexecution.base/test/unit/src/org/netbeans/api/extexecution/base/input/InputReadersReaderTest.java (+105 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
 * 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 2007 Sun Microsystems, Inc.
41
 */
42
43
package org.netbeans.api.extexecution.base.input;
44
45
import java.io.IOException;
46
import java.io.InputStreamReader;
47
import java.io.Reader;
48
import java.io.StringReader;
49
import java.nio.charset.Charset;
50
import java.util.Arrays;
51
import org.netbeans.junit.NbTestCase;
52
53
/**
54
 *
55
 * @author Petr Hejl
56
 */
57
public class InputReadersReaderTest extends NbTestCase {
58
59
    private static final char[] TEST_CHARS = "abcdefghij".toCharArray();
60
61
    private static final int MAX_RETRIES = TEST_CHARS.length * 2;
62
63
    private static final Charset TEST_CHARSET = Charset.forName("UTF-8");
64
65
    public InputReadersReaderTest(String name) {
66
        super(name);
67
    }
68
69
    public void testReadInput() throws IOException {
70
        Reader reader = new InputStreamReader(TestInputUtils.prepareInputStream(
71
                TEST_CHARS, TEST_CHARSET), TEST_CHARSET);
72
        InputReader inputReader = InputReaders.forReader(reader);
73
        TestInputProcessor processor = new TestInputProcessor(false);
74
75
        int read = 0;
76
        int retries = 0;
77
        while (read < TEST_CHARS.length && retries < MAX_RETRIES) {
78
            read += inputReader.readInput(processor);
79
            retries++;
80
        }
81
82
        assertEquals(read, TEST_CHARS.length);
83
        assertEquals(0, processor.getResetCount());
84
85
        assertTrue(Arrays.equals(TEST_CHARS, processor.getCharsProcessed()));
86
    }
87
88
    public void testReadStringReader() throws IOException {
89
        Reader reader = new StringReader(new String(TEST_CHARS));
90
        InputReader inputReader = InputReaders.forReader(reader);
91
        TestInputProcessor processor = new TestInputProcessor(false);
92
93
        int read = 0;
94
        int retries = 0;
95
        while (read < TEST_CHARS.length && retries < MAX_RETRIES) {
96
            read += inputReader.readInput(processor);
97
            retries++;
98
        }
99
100
        assertEquals(read, TEST_CHARS.length);
101
        assertEquals(0, processor.getResetCount());
102
103
        assertTrue(Arrays.equals(TEST_CHARS, processor.getCharsProcessed()));
104
    }
105
}
(-)a/extexecution.base/test/unit/src/org/netbeans/api/extexecution/base/input/InputReadersStreamTest.java (+105 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
 * 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 2007 Sun Microsystems, Inc.
41
 */
42
43
package org.netbeans.api.extexecution.base.input;
44
45
import java.io.IOException;
46
import java.nio.charset.Charset;
47
import java.util.Arrays;
48
import org.netbeans.junit.NbTestCase;
49
50
/**
51
 *
52
 * @author Petr Hejl
53
 */
54
public class InputReadersStreamTest extends NbTestCase {
55
56
    private static final char[] TEST_CHARS = "abcdefghij".toCharArray();
57
58
    private static final int MAX_RETRIES = TEST_CHARS.length * 2;
59
60
    private static final Charset TEST_CHARSET = Charset.forName("UTF-8");
61
62
    public InputReadersStreamTest(String name) {
63
        super(name);
64
    }
65
66
    public void testReadInput() throws IOException {
67
        InputReader reader = InputReaders.forStream(TestInputUtils.prepareInputStream(
68
                TEST_CHARS, TEST_CHARSET), TEST_CHARSET);
69
        TestInputProcessor processor = new TestInputProcessor(false);
70
71
        int read = 0;
72
        int retries = 0;
73
        while (read < TEST_CHARS.length && retries < MAX_RETRIES) {
74
            read += reader.readInput(processor);
75
            retries++;
76
        }
77
78
        assertEquals(read, TEST_CHARS.length);
79
        assertEquals(0, processor.getResetCount());
80
81
        assertTrue(Arrays.equals(TEST_CHARS, processor.getCharsProcessed()));
82
    }
83
84
    public void testFactory() {
85
        try {
86
            InputReaders.forStream(null, TEST_CHARSET);
87
            fail("Accepts null stream"); // NOI18N
88
        } catch (NullPointerException ex) {
89
            // expected
90
        }
91
    }
92
93
    public void testClose() throws IOException {
94
        InputReader reader = InputReaders.forStream(TestInputUtils.prepareInputStream(
95
                TEST_CHARS, TEST_CHARSET), TEST_CHARSET);
96
        reader.close();
97
98
        try {
99
            reader.readInput(null);
100
            fail("Reader not throw exception on read after closing it"); // NOI18N
101
        } catch (IllegalStateException ex) {
102
            // expected
103
        }
104
    }
105
}
(-)a/extexecution.base/test/unit/src/org/netbeans/api/extexecution/base/input/LineProcessorsTest.java (+335 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.ByteArrayOutputStream;
46
import java.io.PrintWriter;
47
import java.util.ArrayList;
48
import java.util.Collections;
49
import java.util.List;
50
import java.util.Random;
51
import java.util.concurrent.BrokenBarrierException;
52
import java.util.concurrent.CountDownLatch;
53
import java.util.concurrent.CyclicBarrier;
54
import java.util.concurrent.ExecutorService;
55
import java.util.concurrent.Executors;
56
import java.util.concurrent.TimeUnit;
57
import java.util.concurrent.TimeoutException;
58
import java.util.regex.Pattern;
59
import org.netbeans.junit.NbTestCase;
60
import org.netbeans.junit.RandomlyFails;
61
62
/**
63
 *
64
 * @author Petr Hejl
65
 */
66
public class LineProcessorsTest extends NbTestCase {
67
68
    private static final String WAIT_RELEASE_STRING = "test"; // NOI18N
69
70
    private static final long DEADLOCK_TIMEOUT = 1000;
71
72
    private static final int WAIT_THREAD_COUNT = 5;
73
74
    private static final int PRODUCER_THREAD_COUNT = 5;
75
76
    private static final long TEST_TIMEOUT = 5000;
77
78
    private static final List<String> PROXY_TEST_LINES = new ArrayList<String>();
79
80
    private static final List<String> PRINTING_TEST_LINES = new ArrayList<String>(5);
81
82
    static {
83
        Collections.addAll(PROXY_TEST_LINES, "test1", "test2");
84
85
        Collections.addAll(PRINTING_TEST_LINES,
86
                "the first test line",
87
                "the second test line",
88
                "the third test line",
89
                "the fourth test line",
90
                "the fifth test line");
91
    }
92
93
    private ExecutorService executor;
94
95
    public LineProcessorsTest(String name) {
96
        super(name);
97
    }
98
99
    @Override
100
    protected void setUp() throws Exception {
101
        super.setUp();
102
        executor = Executors.newCachedThreadPool();
103
    }
104
105
    @Override
106
    protected void tearDown() throws Exception {
107
        super.tearDown();
108
        executor.shutdownNow();
109
    }
110
111
    public void testProxy() {
112
        TestLineProcessor processor1 = new TestLineProcessor(false);
113
        TestLineProcessor processor2 = new TestLineProcessor(false);
114
115
        LineProcessor proxy = LineProcessors.proxy(processor1, processor2);
116
        for (String line : PROXY_TEST_LINES) {
117
            proxy.processLine(line);
118
        }
119
120
        assertEquals(0, processor1.getResetCount());
121
        assertEquals(0, processor2.getResetCount());
122
123
        assertEquals(PROXY_TEST_LINES, processor1.getLinesProcessed());
124
        assertEquals(PROXY_TEST_LINES, processor2.getLinesProcessed());
125
126
        proxy.reset();
127
128
        assertEquals(1, processor1.getResetCount());
129
        assertEquals(1, processor2.getResetCount());
130
131
        proxy.close();
132
        assertClosedConditions(proxy);
133
134
        assertTrue(processor1.isClosed());
135
        assertTrue(processor2.isClosed());
136
    }
137
138
    public void testPrinting() {
139
        TestInputWriter writer = new TestInputWriter(new PrintWriter(new ByteArrayOutputStream()));
140
        LineProcessor lineProcessor = LineProcessors.printing(writer);
141
        for (String line : PRINTING_TEST_LINES) {
142
            lineProcessor.processLine(line);
143
        }
144
        assertEquals(PRINTING_TEST_LINES, writer.getPrinted());
145
146
        lineProcessor.close();
147
        assertClosedConditions(lineProcessor);
148
    }
149
150
    public void testPrintingCloseOrdering() {
151
        final TestInputWriter writer = new TestInputWriter(new PrintWriter(new ByteArrayOutputStream()));
152
        final LineProcessor delegate = LineProcessors.printing(writer);
153
154
        LineProcessor lineProcessor = new LineProcessor() {
155
156
            public void processLine(String line) {
157
                delegate.processLine(line);
158
            }
159
160
            public void reset() {
161
                delegate.reset();
162
            }
163
164
            public void close() {
165
                delegate.processLine("closing mark");
166
                delegate.close();
167
            }
168
        };
169
170
        for (String line : PRINTING_TEST_LINES) {
171
            lineProcessor.processLine(line);
172
        }
173
        assertEquals(PRINTING_TEST_LINES, writer.getPrinted());
174
175
        lineProcessor.close();
176
        List<String> printed = new ArrayList<String>(PRINTING_TEST_LINES);
177
        printed.add("closing mark");
178
        assertEquals(printed, writer.getPrinted());
179
        assertClosedConditions(lineProcessor);
180
    }
181
182
    public void testWaiting() throws InterruptedException, BrokenBarrierException {
183
        final CountDownLatch latch = new CountDownLatch(1);
184
        final LineProcessor lineProcessor = LineProcessors.patternWaiting(
185
                Pattern.compile(WAIT_RELEASE_STRING), latch);
186
        CyclicBarrier barrier = new CyclicBarrier(2);
187
188
        executor.execute(new WaitRunnable(latch, barrier));
189
        barrier.await();
190
        lineProcessor.processLine(WAIT_RELEASE_STRING);
191
192
        try {
193
            barrier.await(DEADLOCK_TIMEOUT, TimeUnit.MILLISECONDS);
194
        } catch (TimeoutException ex) {
195
            fail("Deadlock occurs");
196
        }
197
198
        executor.execute(new WaitRunnable(latch, barrier));
199
        barrier.await();
200
        try {
201
            barrier.await(DEADLOCK_TIMEOUT, TimeUnit.MILLISECONDS);
202
        } catch (TimeoutException ex) {
203
            fail("Deadlock occurs");
204
        }
205
206
        lineProcessor.close();
207
        assertClosedConditions(lineProcessor);
208
    }
209
210
    @RandomlyFails // NB-Core-Build #8029
211
    public void testWaitingThreadSafety() throws InterruptedException, BrokenBarrierException {
212
        final CountDownLatch latch = new CountDownLatch(1);
213
        final LineProcessor lineProcessor = LineProcessors.patternWaiting(
214
                Pattern.compile(WAIT_RELEASE_STRING), latch);
215
        CyclicBarrier barrier = new CyclicBarrier(WAIT_THREAD_COUNT + 1);
216
217
        for (int i = 0; i < WAIT_THREAD_COUNT; i++) {
218
            executor.execute(new WaitRunnable(latch, barrier));
219
        }
220
221
        barrier.await();
222
223
        Random random = new Random();
224
        for (int i = 0; i < PRODUCER_THREAD_COUNT; i++) {
225
            executor.execute(new ProducerRunnable(lineProcessor, WAIT_RELEASE_STRING, random.nextInt(5)));
226
        }
227
228
        // guarantee finish
229
        executor.execute(new Runnable() {
230
            public void run() {
231
                try {
232
                    Thread.sleep(TEST_TIMEOUT);
233
                    lineProcessor.processLine(WAIT_RELEASE_STRING);
234
                } catch (InterruptedException ex) {
235
                    //throw new RuntimeException(ex);
236
                }
237
            }
238
        });
239
240
        try {
241
            barrier.await(TEST_TIMEOUT + DEADLOCK_TIMEOUT, TimeUnit.MILLISECONDS);
242
        } catch (TimeoutException ex) {
243
            fail("Deadlock occurs");
244
        }
245
    }
246
247
    private static <T> void assertEquals(List<T> expected, List<T> value) {
248
        assertEquals(expected.size(), value.size());
249
        for (int i = 0; i < expected.size(); i++) {
250
            assertEquals(expected.get(i), value.get(i));
251
        }
252
    }
253
254
    private static void assertClosedConditions(LineProcessor lineProcessor) {
255
        try {
256
            lineProcessor.processLine("something");
257
            fail("Does not throw IllegalStateException after close");
258
        } catch (IllegalStateException ex) {
259
            // expected
260
        }
261
262
        try {
263
            lineProcessor.reset();
264
            fail("Does not throw IllegalStateException after close");
265
        } catch (IllegalStateException ex) {
266
            // expected
267
        }
268
    }
269
270
    private static class WaitRunnable implements Runnable {
271
272
        private final CountDownLatch latch;
273
274
        private final CyclicBarrier barrier;
275
276
        public WaitRunnable(CountDownLatch latch, CyclicBarrier barrier) {
277
            this.latch = latch;
278
            this.barrier = barrier;
279
        }
280
281
        public void run() {
282
            try {
283
                barrier.await();
284
                latch.await();
285
                barrier.await();
286
            } catch (InterruptedException ex) {
287
                // timeouted test
288
                Thread.currentThread().interrupt();
289
            } catch (BrokenBarrierException ex) {
290
                // timeouted test
291
            }
292
        }
293
294
    }
295
296
    private static class ProducerRunnable implements Runnable {
297
298
        private final LineProcessor lineProcessor;
299
300
        private final String releaseString;
301
302
        private final Random random = new Random();
303
304
        private final int iterations;
305
306
        public ProducerRunnable(LineProcessor lineProcessor, String releaseString, int iterations) {
307
            this.lineProcessor = lineProcessor;
308
            this.releaseString = releaseString;
309
            this.iterations = iterations;
310
        }
311
312
        public void run() {
313
            for (int i = 0; i < iterations; i++) {
314
                if (Thread.interrupted()) {
315
                    return;
316
                }
317
318
                int val = random.nextInt(10);
319
                if (val == 0) {
320
                    lineProcessor.processLine(releaseString);
321
                    return;
322
                } else {
323
                    lineProcessor.processLine("generated " + val);
324
                }
325
326
                try {
327
                    Thread.sleep(random.nextInt(300));
328
                } catch (InterruptedException ex) {
329
                    Thread.currentThread().interrupt();
330
                    return;
331
                }
332
            }
333
        }
334
    }
335
}
(-)a/extexecution.base/test/unit/src/org/netbeans/api/extexecution/base/input/TestInputProcessor.java (+91 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
 * 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 2007 Sun Microsystems, Inc.
41
 */
42
43
package org.netbeans.api.extexecution.base.input;
44
45
/**
46
 *
47
 * This class is <i>NotThreadSafe</i>.
48
 * @author Petr Hejl
49
 */
50
public class TestInputProcessor implements InputProcessor {
51
52
    private final boolean cleanBytesOnReset;
53
54
    private StringBuilder charsProcessed = new StringBuilder();
55
56
    private int resetCount = 0;
57
58
    private boolean closed;
59
60
    public TestInputProcessor(boolean cleanBytesOnReset) {
61
        this.cleanBytesOnReset = cleanBytesOnReset;
62
    }
63
64
    public void processInput(char[] chars) {
65
        charsProcessed.append(chars);
66
    }
67
68
    public void reset() {
69
        resetCount++;
70
        if (cleanBytesOnReset) {
71
            charsProcessed.setLength(0);
72
        }
73
    }
74
75
    public void close() {
76
        closed = true;
77
    }
78
79
    public char[] getCharsProcessed() {
80
        return charsProcessed.toString().toCharArray();
81
    }
82
83
    public int getResetCount() {
84
        return resetCount;
85
    }
86
87
    public boolean isClosed() {
88
        return closed;
89
    }
90
91
}
(-)a/extexecution.base/test/unit/src/org/netbeans/api/extexecution/base/input/TestInputUtils.java (+148 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
 * 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 2007 Sun Microsystems, Inc.
41
 */
42
43
package org.netbeans.api.extexecution.base.input;
44
45
import java.io.BufferedOutputStream;
46
import java.io.BufferedWriter;
47
import java.io.ByteArrayInputStream;
48
import java.io.File;
49
import java.io.FileOutputStream;
50
import java.io.IOException;
51
import java.io.InputStream;
52
import java.io.OutputStreamWriter;
53
import java.io.Writer;
54
import java.nio.ByteBuffer;
55
import java.nio.CharBuffer;
56
import java.nio.charset.Charset;
57
import java.util.Random;
58
59
/**
60
 *
61
 * @author Petr Hejl
62
 */
63
public final class TestInputUtils {
64
65
    private TestInputUtils() {
66
        super();
67
    }
68
69
    public static InputStream prepareInputStream(String[] lines, String separator,
70
            Charset charset, boolean terminate) {
71
72
        StringBuffer buffer = new StringBuffer();
73
        for (int i = 0; i < lines.length; i++) {
74
            buffer.append(lines[i]);
75
            if (terminate || i < (lines.length - 1)) {
76
                buffer.append(separator);
77
            }
78
        }
79
80
        ByteBuffer byteBuffer = charset.encode(buffer.toString());
81
        int length = byteBuffer.limit();
82
        byte[] byteArray = new byte[length];
83
        byteBuffer.position(0);
84
        byteBuffer.get(byteArray);
85
86
        return prepareInputStream(byteArray);
87
    }
88
89
    public static InputStream prepareInputStream(char[] chars, Charset charset) {
90
        CharBuffer wrapped = CharBuffer.wrap(chars);
91
        ByteBuffer buffer = charset.encode(wrapped);
92
        byte[] bytes = new byte[buffer.limit()];
93
        buffer.get(bytes);
94
        return prepareInputStream(bytes);
95
    }
96
    
97
    private static InputStream prepareInputStream(byte[] bytes) {
98
        return new ByteArrayInputStream(bytes.clone());
99
    }
100
101
    public static File prepareFile(String name, File workDir,
102
            String[] lines, String separator, Charset charset, boolean terminate) throws IOException {
103
104
        File file = new File(workDir, name);
105
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), charset));
106
        try {
107
            for (int i = 0; i < lines.length; i++) {
108
            writer.write(lines[i]);
109
            if (terminate || i < (lines.length - 1)) {
110
                writer.write(separator);
111
            }
112
            }
113
        } finally {
114
            writer.close();
115
        }
116
        return file;
117
    }
118
119
    public static File prepareFile(String name, File workDir, char[] chars,
120
            Charset charset) throws IOException {
121
        
122
        File file = new File(workDir, name);
123
        Writer writer = new OutputStreamWriter(new BufferedOutputStream(new FileOutputStream(file)), charset);
124
        try {
125
            writer.write(chars);
126
        } finally {
127
            writer.close();
128
        }
129
        return file;
130
    }
131
132
    public static class EndlessAsciiInputStream extends InputStream {
133
134
        private final Random random = new Random();
135
136
        @Override
137
        public int read() throws IOException {
138
            return random.nextInt(256);
139
        }
140
141
        @Override
142
        public int available() throws IOException {
143
            return 1;
144
        }
145
146
    }
147
148
}
(-)a/extexecution.base/test/unit/src/org/netbeans/api/extexecution/base/input/TestInputWriter.java (+95 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.io.Writer;
47
import java.util.ArrayList;
48
import java.util.Collections;
49
import java.util.List;
50
51
/**
52
 *
53
 * @author Petr Hejl
54
 */
55
public class TestInputWriter extends PrintWriter {
56
57
    private List<String> printed = new ArrayList<String>();
58
59
    private StringBuilder builder = new StringBuilder();
60
61
    private int resetsProcessed;
62
63
    private String cache = "";
64
65
    public TestInputWriter(Writer w) {
66
        super(w);
67
    }
68
69
    @Override
70
    public void print(String s) {
71
        cache = s;
72
        builder.append(s);
73
        super.print(s);
74
    }
75
76
    @Override
77
    public void println() {
78
        printed.add(cache);
79
        builder.append("\n");
80
        cache = "";
81
        super.println();
82
    }
83
84
    public List<String> getPrinted() {
85
        return Collections.unmodifiableList(printed);
86
    }
87
88
    public String getPrintedRaw() {
89
        return builder.toString();
90
    }
91
92
    public int getResetsProcessed() {
93
        return resetsProcessed;
94
    }
95
}
(-)a/extexecution.base/test/unit/src/org/netbeans/api/extexecution/base/input/TestLineProcessor.java (+94 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
 * 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 2007 Sun Microsystems, Inc.
41
 */
42
43
package org.netbeans.api.extexecution.base.input;
44
45
import java.util.ArrayList;
46
import java.util.Collections;
47
import java.util.List;
48
49
/**
50
 *
51
 * This class is <i>NotThreadSafe</i>.
52
 * @author Petr Hejl
53
 */
54
public class TestLineProcessor implements LineProcessor {
55
56
    private final boolean clearLinesOnReset;
57
58
    private List<String> linesProcessed = new ArrayList<String>();
59
60
    private int resetCount = 0;
61
62
    private boolean closed;
63
64
    public TestLineProcessor(boolean clearLinesOnReset) {
65
        this.clearLinesOnReset = clearLinesOnReset;
66
    }
67
68
    public void processLine(String line) {
69
        linesProcessed.add(line);
70
    }
71
72
    public void reset() {
73
        resetCount++;
74
        if (clearLinesOnReset) {
75
            linesProcessed.clear();
76
        }
77
    }
78
79
    public void close() {
80
        closed = true;
81
    }
82
83
    public List<String> getLinesProcessed() {
84
        return Collections.unmodifiableList(linesProcessed);
85
    }
86
87
    public int getResetCount() {
88
        return resetCount;
89
    }
90
91
    public boolean isClosed() {
92
        return closed;
93
    }
94
}
(-)a/extexecution.base/test/unit/src/org/netbeans/modules/extexecution/base/ExternalProcessBuilderTest.java (+112 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.Collections;
48
import java.util.HashMap;
49
import java.util.Map;
50
import org.netbeans.junit.NbTestCase;
51
52
/**
53
 *
54
 * @author Petr Hejl
55
 */
56
public class ExternalProcessBuilderTest extends NbTestCase {
57
58
    public ExternalProcessBuilderTest(String name) {
59
        super(name);
60
    }
61
62
    public void testEnvironment() {
63
        ExternalProcessBuilder creator = new ExternalProcessBuilder("command");
64
        creator = creator.addEnvironmentVariable("test1", "value1");
65
        creator = creator.addEnvironmentVariable("test2", "value2");
66
67
        Map<String, String> env = new HashMap<String, String>(
68
                creator.buildEnvironment(Collections.<String, String>emptyMap()));
69
        assertEquals("value1", env.remove("test1"));
70
        assertEquals("value2", env.remove("test2"));
71
        assertTrue(env.isEmpty());
72
    }
73
74
    public void testPath() {
75
        ExternalProcessBuilder creator = new ExternalProcessBuilder("command");
76
        Map<String, String> original = new HashMap<String, String>();
77
        original.put("PATH", "original");
78
79
        // original path
80
        Map<String, String> env = new HashMap<String, String>(
81
                creator.buildEnvironment(original));
82
        assertEquals("original", env.remove("PATH"));
83
        assertTrue(env.isEmpty());
84
85
        // some added path
86
        File addedPath = new File("addedPath");
87
        creator = creator.prependPath(addedPath);
88
        env = new HashMap<String, String>(creator.buildEnvironment(original));
89
        assertEquals(addedPath.getAbsolutePath().replace(" ", "\\ ") + File.pathSeparator + "original", env.remove("PATH"));
90
        assertTrue(env.isEmpty());
91
92
        // yet another path
93
        File nextPath = new File("nextPath");
94
        creator = creator.prependPath(nextPath);
95
        env = new HashMap<String, String>(creator.buildEnvironment(original));
96
        assertEquals(
97
                nextPath.getAbsolutePath().replace(" ", "\\ ") + File.pathSeparator
98
                + addedPath.getAbsolutePath().replace(" ", "\\ ") + File.pathSeparator
99
                + "original", env.remove("PATH"));
100
        assertTrue(env.isEmpty());
101
    }
102
103
    public void testImmutability() throws IOException {
104
        ExternalProcessBuilder builder = new ExternalProcessBuilder("ls");
105
106
        assertNotSame(builder, builder.addArgument("test"));
107
        assertNotSame(builder, builder.addEnvironmentVariable("test", "test"));
108
        assertNotSame(builder, builder.prependPath(getWorkDir()));
109
        assertNotSame(builder, builder.redirectErrorStream(true));
110
        assertNotSame(builder, builder.workingDirectory(getWorkDir()));
111
    }
112
}
(-)a/extexecution.base/test/unit/src/org/netbeans/modules/extexecution/base/input/LineParsingHelperTest.java (+126 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
 * 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 2007 Sun Microsystems, Inc.
41
 */
42
43
package org.netbeans.modules.extexecution.base.input;
44
45
import java.nio.ByteBuffer;
46
import java.nio.charset.Charset;
47
import org.netbeans.junit.NbTestCase;
48
49
/**
50
 *
51
 * @author Petr Hejl
52
 */
53
public class LineParsingHelperTest extends NbTestCase {
54
55
    private static final String[] TEST_LINES = new String[] {"line1", "line2", "line3"}; // NOI18N
56
57
    private static final String[] TEST_SEPARATORS = new String[] {"\n", "\r", "\r\n"}; // NOI18N
58
59
    private static final int EXTENDED_LENGTH = 10;
60
61
    public LineParsingHelperTest(String name) {
62
        super(name);
63
    }
64
65
    public void testParsingCharacterIterator() {
66
        for (String separator : TEST_SEPARATORS) {
67
            StringBuffer testInput = new StringBuffer();
68
            for (String line : TEST_LINES) {
69
                testInput.append(line).append(separator);
70
            }
71
72
            LineParsingHelper helper = new LineParsingHelper();
73
            String[] lines = helper.parse(testInput);
74
            checkParsingResults(lines, helper);
75
        }
76
    }
77
78
    public void testParsingCharacterArray() {
79
        for (String separator : TEST_SEPARATORS) {
80
            StringBuffer testInput = new StringBuffer();
81
            for (String line : TEST_LINES) {
82
                testInput.append(line).append(separator);
83
            }
84
85
            LineParsingHelper helper = new LineParsingHelper();
86
            char[] characterTestInput = new char[testInput.length()];
87
            testInput.getChars(0, testInput.length(), characterTestInput, 0);
88
            String[] lines = helper.parse(characterTestInput);
89
            checkParsingResults(lines, helper);
90
91
            characterTestInput = new char[testInput.length() + EXTENDED_LENGTH];
92
            testInput.getChars(0, testInput.length(), characterTestInput, 0);
93
            lines = helper.parse(characterTestInput, 0, testInput.length());
94
            checkParsingResults(lines, helper);
95
        }
96
    }
97
98
    public void testTrailingLine() {
99
        String testLine = "line1\nline2\nline3"; // NOI18N
100
        LineParsingHelper helper = new LineParsingHelper();
101
        String[] lines = helper.parse(testLine);
102
103
        assertEquals(2, lines.length);
104
        assertEquals("line1", lines[0]); // NOI18N
105
        assertEquals("line2", lines[1]); // NOI18N
106
107
        assertEquals("line3", helper.getTrailingLine(false));
108
        assertEquals("line3", helper.getTrailingLine(true));
109
        assertEquals(null, helper.getTrailingLine(true));
110
111
        testLine = "line1\nline2\nline3\n";
112
        helper.parse(testLine);
113
        assertEquals(null, helper.getTrailingLine(true));
114
    }
115
116
    private void checkParsingResults(String[] lines, LineParsingHelper helper) {
117
        assertEquals(TEST_LINES.length, lines.length);
118
119
        for (int i = 0; i < TEST_LINES.length; i++) {
120
            assertEquals(TEST_LINES[i], lines[i]);
121
        }
122
123
        assertEquals(null, helper.getTrailingLine(false));
124
        assertEquals(null, helper.getTrailingLine(true));
125
    }
126
}
(-)a/extexecution.base/test/unit/src/org/netbeans/spi/extexecution/base/ProcessParametersTest.java (+79 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2013 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2013 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.spi.extexecution.base;
43
44
import java.util.Collections;
45
import java.util.HashMap;
46
import java.util.Map;
47
import org.netbeans.junit.NbTestCase;
48
import org.netbeans.modules.extexecution.base.ProcessParametersAccessor;
49
50
/**
51
 *
52
 * @author Petr Hejl
53
 */
54
public class ProcessParametersTest extends NbTestCase {
55
56
    public ProcessParametersTest(String name) {
57
        super(name);
58
    }
59
60
    public void testParameters() {
61
        Map<String, String> variables = new HashMap<String, String>();
62
        variables.put("key1", "value1");
63
        variables.put("key2", "value2");
64
65
        ProcessParameters params = ProcessParametersAccessor.getDefault().createProcessParameters(
66
                "ls", "/home", Collections.singletonList("argument"), true, variables);
67
68
        assertEquals("ls", params.getExecutable());
69
        assertEquals("/home", params.getWorkingDirectory());
70
        assertTrue(params.isRedirectErrorStream());
71
72
        assertEquals(1, params.getArguments().size());
73
        assertEquals("argument", params.getArguments().get(0));
74
75
        assertEquals(2, params.getEnvironmentVariables().size());
76
        assertEquals("value1", params.getEnvironmentVariables().get("key1"));
77
        assertEquals("value2", params.getEnvironmentVariables().get("key2"));
78
    }
79
}
(-)a/extexecution.impl/nbproject/project.xml (+9 lines)
Lines 30-35 Link Here
30
                    </run-dependency>
30
                    </run-dependency>
31
                </dependency>
31
                </dependency>
32
                <dependency>
32
                <dependency>
33
                    <code-name-base>org.netbeans.modules.extexecution.base</code-name-base>
34
                    <build-prerequisite/>
35
                    <compile-dependency/>
36
                    <run-dependency>
37
                        <release-version>2</release-version>
38
                        <specification-version>1.0</specification-version>
39
                    </run-dependency>
40
                </dependency>
41
                <dependency>
33
                    <code-name-base>org.netbeans.modules.options.api</code-name-base>
42
                    <code-name-base>org.netbeans.modules.options.api</code-name-base>
34
                    <build-prerequisite/>
43
                    <build-prerequisite/>
35
                    <compile-dependency/>
44
                    <compile-dependency/>
(-)a/extexecution.impl/src/org/netbeans/modules/extexecution/destroy/ProcessTreeDestroyPerformer.java (-62 lines)
Lines 1-62 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.destroy;
44
45
import java.util.Map;
46
import org.netbeans.processtreekiller.ProcessTreeKiller;
47
import org.netbeans.spi.extexecution.destroy.ProcessDestroyPerformer;
48
import org.openide.util.lookup.ServiceProvider;
49
50
/**
51
 *
52
 * @author mkleint
53
 */
54
@ServiceProvider(service=ProcessDestroyPerformer.class)
55
public class ProcessTreeDestroyPerformer implements ProcessDestroyPerformer {
56
57
    @Override
58
    public void destroy(Process process, Map<String, String> env) {
59
        ProcessTreeKiller.get().kill(process, env);
60
    }
61
62
}
(-)a/extexecution.impl/src/org/netbeans/modules/extexecution/destroy/ProcessesImpl.java (+72 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.destroy;
44
45
import java.util.Map;
46
import org.netbeans.processtreekiller.ProcessTreeKiller;
47
import org.netbeans.spi.extexecution.base.ProcessesImplementation;
48
import org.netbeans.spi.extexecution.destroy.ProcessDestroyPerformer;
49
import org.openide.util.lookup.ServiceProvider;
50
import org.openide.util.lookup.ServiceProviders;
51
52
/**
53
 *
54
 * @author mkleint
55
 */
56
@ServiceProviders({
57
    @ServiceProvider(service=ProcessDestroyPerformer.class),
58
    @ServiceProvider(service=ProcessesImplementation.class)
59
})
60
public class ProcessesImpl implements ProcessDestroyPerformer, ProcessesImplementation {
61
62
    @Override
63
    public void destroy(Process process, Map<String, String> env) {
64
        ProcessTreeKiller.get().kill(process, env);
65
    }
66
67
    @Override
68
    public void killTree(Process process, Map<String, String> environment) {
69
        ProcessTreeKiller.get().kill(process, environment);
70
    }
71
72
}
(-)a/extexecution/apichanges.xml (+19 lines)
Lines 117-122 Link Here
117
    <changes>
117
    <changes>
118
118
119
        <change>
119
        <change>
120
            <summary>API split and deprecation</summary>
121
            <version major="1" minor="43"/>
122
            <date day="1" month="6" year="2014"/>
123
            <author login="phejl"/>
124
            <compatibility addition="yes"/>
125
            <description>
126
                Splitting the API deprecating major parts.
127
            </description>
128
            <class package="org.netbeans.api.extexecution" name="ExternalProcessSupport"/>
129
            <class package="org.netbeans.api.extexecution" name="ProcessBuilder"/>
130
            <class package="org.netbeans.api.extexecution.print" name="InputProcessors"/>
131
            <class package="org.netbeans.api.extexecution.print" name="LineProcessors"/>
132
            <class package="org.netbeans.spi.extexecution" name="ProcessBuilderImplementation"/>
133
            <package name="org.netbeans.api.extexecution.input"/>
134
            <package name="org.netbeans.spi.extexecution"/>
135
            <package name="org.netbeans.spi.extexecution.destroy"/>
136
            <issue number="244308"/>
137
        </change>
138
        <change>
120
            <api name="extexecution_spi"/>
139
            <api name="extexecution_spi"/>
121
            <summary>Advice to throw UserQuestionException</summary>
140
            <summary>Advice to throw UserQuestionException</summary>
122
            <version major="1" minor="35"/>
141
            <version major="1" minor="35"/>
(-)a/extexecution/arch.xml (-19 / +51 lines)
Lines 47-79 Link Here
47
-->
47
-->
48
 <answer id="arch-overall">
48
 <answer id="arch-overall">
49
  <p>
49
  <p>
50
   <i>The major parts of this API has been refactored to External Execution Base API
51
   in version 1.43.</i> This API is now to be used in situations where the base
52
   support is not sufficient such as when you need progress and output window
53
   integration.
54
  </p>
55
  <p>
50
   The External Execution module provides the
56
   The External Execution module provides the
51
   <api group="java" name="ExternalExecutionAPI" type="export" category="stable" url="@TOP@org/netbeans/api/extexecution/package-summary.html"/>
57
   <api group="java" name="ExternalExecutionAPI" type="export" category="stable" url="@TOP@org/netbeans/api/extexecution/package-summary.html"/>
52
   that contains support for execution of external processes in the IDE. It also
58
   that contains support for execution of external processes in the IDE. It also
53
   provide support class for the actual creation of the external process
59
   provide support class for the actual creation of the external process
54
   and support for destroying the process tree. There is also abstraction of
60
   and support for destroying the process tree.
55
   process builder.
61
   <span style="text-decoration:line-through;">There is also abstraction of
62
   process builder.</span> The builder is now deprecated and replaced by one in
63
   External Execution Base API.
56
  </p>
64
  </p>
57
  <p>
65
  <p>
58
   Another exported API
66
   <span style="text-decoration:line-through;">Another exported API
59
   <api group="java" name="ExternalExecutionInputAPI" type="export" category="stable" url="@TOP@org/netbeans/api/extexecution/input/package-summary.html"/>
67
   <api group="java" name="ExternalExecutionInputAPI" type="export" category="stable" url="@TOP@org/netbeans/api/extexecution/input/package-summary.html"/>
60
   define interfaces for input processing (character or line based)
68
   define interfaces for input processing (character or line based)
61
   and provides common implementations of these with factory methods.
69
   and provides common implementations of these with factory methods.</span>
70
   This API is now deprecated in favor of External Execution Base API.
62
  </p>
71
  </p>
63
  <p>
72
  <p>
64
   Natural extension to input processing API is printing API
73
   Natural extension to input processing API is printing API
65
   <api group="java" name="ExternalExecutionInputPrintingAPI" type="export" category="stable" url="@TOP@org/netbeans/api/extexecution/print/package-summary.html"/>
74
   <api group="java" name="ExternalExecutionInputPrintingAPI" type="export" category="stable" url="@TOP@org/netbeans/api/extexecution/print/package-summary.html"/>
66
   that defines interfaces transforming lines to lines printed to
75
   that defines interfaces transforming lines to lines printed to
67
   <code>org.openide.windows.OutputWriter</code>. API provides common implementations too.
76
   <code>org.openide.windows.OutputWriter</code>. API provides common implementations too
77
   and provides processor for <code>org.openide.windows.OutputWriter</code> printing.
68
  </p>
78
  </p>
69
  <p>
79
  <p>
70
   The SPI
80
   <span style="text-decoration:line-through;">The SPI
71
   <api group="java" name="ExternalExecutionSPI" type="export" category="stable" url="@TOP@org/netbeans/spi/extexecution/package-summary.html"/>
81
   <api group="java" name="ExternalExecutionSPI" type="export" category="stable" url="@TOP@org/netbeans/spi/extexecution/package-summary.html"/>
72
   allows different implementations of process builder.
82
   allows different implementations of process builder.</span>
83
   This API is now deprecated in favor of External Execution Base API.
73
  </p>
84
  </p>
74
  <p>
85
  <p>
75
   There is also SPI allowing to register support for destroying the process tree
86
   <span style="text-decoration:line-through;">There is also SPI allowing to 
76
   <api group="java" name="ExternalExecutionDestroySPI" type="export" category="stable" url="@TOP@org/netbeans/spi/extexecution/destroy/package-summary.html"/>.
87
   register support for destroying the process tree
88
   <api group="java" name="ExternalExecutionDestroySPI" type="export" category="stable" url="@TOP@org/netbeans/spi/extexecution/destroy/package-summary.html"/>.</span>
89
   This API is now deprecated in favor of <code>org.netbeans.spi.extexecution.base.ProcessesImplementation</code>
90
   from External Execution Base API.
77
  </p>
91
  </p>
78
  <p>
92
  <p>
79
   The <api group="java" name="ExternalExecutionOpenSPI" type="export" category="stable" url="@TOP@org/netbeans/spi/extexecution/open/package-summary.html"/>
93
   The <api group="java" name="ExternalExecutionOpenSPI" type="export" category="stable" url="@TOP@org/netbeans/spi/extexecution/open/package-summary.html"/>
Lines 175-182 Link Here
175
  </usecase>
189
  </usecase>
176
  <usecase id="handle-input" name="Processing the input">
190
  <usecase id="handle-input" name="Processing the input">
177
   <p>
191
   <p>
178
    Client needs to process character data coming from stream, file or other
192
    <span style="text-decoration:line-through;">Client needs to process character
179
    source.
193
    data coming from stream, file or other source.</span> This usecase should 
194
    be solved by External Execution Base API.
180
   </p>
195
   </p>
181
   <p>
196
   <p>
182
    To abstract the source of the data client must implement
197
    To abstract the source of the data client must implement
Lines 214-223 Link Here
214
    The both default printing processors provide factory method accepting
229
    The both default printing processors provide factory method accepting
215
    <a href="@TOP@org/netbeans/api/extexecution/print/LineConvertor.html">LineConvertor</a>.
230
    <a href="@TOP@org/netbeans/api/extexecution/print/LineConvertor.html">LineConvertor</a>.
216
    Namely
231
    Namely
217
    <a href="@TOP@org/netbeans/api/extexecution/input/InputProcessors.html#printing(org.openide.windows.OutputWriter,%20org.netbeans.api.extexecution.print.LineConvertor,%20boolean)">
232
    <a href="@TOP@org/netbeans/api/extexecution/print/InputProcessors.html#printing(org.openide.windows.OutputWriter,%20org.netbeans.api.extexecution.print.LineConvertor,%20boolean)">
218
     InputProcessors.printing(org.openide.windows.OutputWriter out, LineConvertor convertor, boolean resetEnabled)</a>
233
     InputProcessors.printing(org.openide.windows.OutputWriter out, LineConvertor convertor, boolean resetEnabled)</a>
219
    and
234
    and
220
    <a href="@TOP@org/netbeans/api/extexecution/input/LineProcessors.html#printing(org.openide.windows.OutputWriter,%20org.netbeans.api.extexecution.print.LineConvertor,%20boolean)">
235
    <a href="@TOP@org/netbeans/api/extexecution/print/LineProcessors.html#printing(org.openide.windows.OutputWriter,%20org.netbeans.api.extexecution.print.LineConvertor,%20boolean)">
221
     LineProcessors.printing(org.openide.windows.OutputWriter out, LineConvertor convertor, boolean resetEnabled)</a>.
236
     LineProcessors.printing(org.openide.windows.OutputWriter out, LineConvertor convertor, boolean resetEnabled)</a>.
222
237
223
    Convertor is then used to convert received lines to printed ones.
238
    Convertor is then used to convert received lines to printed ones.
Lines 227-234 Link Here
227
  </usecase>
242
  </usecase>
228
  <usecase id="process-builder" name="Custom process builder">
243
  <usecase id="process-builder" name="Custom process builder">
229
    <p>
244
    <p>
230
      Third party wants to implement custom process builder to provide
245
      <span style="text-decoration:line-through;">Third party wants to implement custom process builder to provide
231
      additional functionality, such as remote execution.
246
      additional functionality, such as remote execution.</span>
247
      This usecase should be solved by External Execution Base API.
232
    </p>
248
    </p>
233
    <p>
249
    <p>
234
      In order to do so it will implement
250
      In order to do so it will implement
Lines 242-248 Link Here
242
  </usecase>
258
  </usecase>
243
  <usecase id="destroy-process" name="Destroying a process">
259
  <usecase id="destroy-process" name="Destroying a process">
244
    <p>
260
    <p>
245
      Client wants to destroy the process, trying to kill whole process tree.
261
      <span style="text-decoration:line-through;">Client wants to destroy the process, trying to kill whole process tree.</span>
262
      This usecase should be solved by External Execution Base API.
246
      Method
263
      Method
247
      <a href="@TOP@org/netbeans/api/extexecution/ExternalProcessSupport.html#destroy(java.lang.Process,%20java.util.Map)">
264
      <a href="@TOP@org/netbeans/api/extexecution/ExternalProcessSupport.html#destroy(java.lang.Process,%20java.util.Map)">
248
       ExternalProcessSupport.destroy(java.lang.Process process, Map&lt;String,String&gt; env)</a>
265
       ExternalProcessSupport.destroy(java.lang.Process process, Map&lt;String,String&gt; env)</a>
Lines 510-518 Link Here
510
-->
527
-->
511
 <answer id="dep-platform">
528
 <answer id="dep-platform">
512
  <p>
529
  <p>
513
   No known platform dependencies. In future there could be need for native code
530
   No known platform dependencies.
514
   in order to terminate the whole process tree created by execution of external
515
   process.
516
  </p>
531
  </p>
517
 </answer>
532
 </answer>
518
533
Lines 922-927 Link Here
922
   <a href="@TOP@org/netbeans/spi/extexecution/destroy/ProcessDestroyPerformer.html">ProcessDestroyPerformer</a>
937
   <a href="@TOP@org/netbeans/spi/extexecution/destroy/ProcessDestroyPerformer.html">ProcessDestroyPerformer</a>
923
   as a tool for killing the whole process tree.
938
   as a tool for killing the whole process tree.
924
  </p>
939
  </p>
940
  <p>
941
      Implementations of <a href="@TOP@org/netbeans/spi/extexecution/open/FileOpenHandler.html">FileOpenHandler</a>
942
      and <a href="@TOP@org/netbeans/spi/extexecution/open/HttpOpenHandler.html">HttpOpenHandler</a>
943
      are looked up to provide support for file and url opening by default line
944
      convertors created by <a href="@TOP@org/netbeans/api/extexecution/print/LineConvertors.html">LineConvertors</a>.
945
  </p>
946
  <p>
947
      Implementation of <a href="@TOP@org/netbeans/spi/extexecution/open/OptionOpenHandler.html">OptionOpenHandler</a>
948
      is looked up to provide support for options opening from output window
949
      when configured by <a href="@TOP@org/netbeans/api/extexecution/ExecutionDescriptor.html">ExecutionDescriptor</a>.
950
  </p>
951
  <p>
952
      The <a href="@TOP@org/netbeans/spi/extexecution/startup/StartupExtenderImplementation.html">StartupExtenderImplementation</a>s
953
      at path <code>StartupExtender</code> are looked up when the API
954
      <a href="@TOP@org/netbeans/api/extexecution/startup/StartupExtender.html">StartupExtender</a>
955
      needs to know all such extenders.
956
  </p>
925
 </answer>
957
 </answer>
926
958
927
959
(-)a/extexecution/manifest.mf (-1 / +1 lines)
Lines 2-7 Link Here
2
AutoUpdate-Show-In-Client: false
2
AutoUpdate-Show-In-Client: false
3
OpenIDE-Module: org.netbeans.modules.extexecution/2
3
OpenIDE-Module: org.netbeans.modules.extexecution/2
4
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/extexecution/resources/Bundle.properties
4
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/extexecution/resources/Bundle.properties
5
OpenIDE-Module-Specification-Version: 1.42
5
OpenIDE-Module-Specification-Version: 1.43
6
OpenIDE-Module-Recommends: org.netbeans.spi.extexecution.open.OptionOpenHandler, org.netbeans.spi.extexecution.open.FileOpenHandler, org.netbeans.spi.extexecution.open.HttpOpenHandler
6
OpenIDE-Module-Recommends: org.netbeans.spi.extexecution.open.OptionOpenHandler, org.netbeans.spi.extexecution.open.FileOpenHandler, org.netbeans.spi.extexecution.open.HttpOpenHandler
7
7
(-)a/extexecution/nbproject/project.xml (+9 lines)
Lines 24-29 Link Here
24
                    </run-dependency>
24
                    </run-dependency>
25
                </dependency>
25
                </dependency>
26
                <dependency>
26
                <dependency>
27
                    <code-name-base>org.netbeans.modules.extexecution.base</code-name-base>
28
                    <build-prerequisite/>
29
                    <compile-dependency/>
30
                    <run-dependency>
31
                        <release-version>2</release-version>
32
                        <specification-version>1.0</specification-version>
33
                    </run-dependency>
34
                </dependency>
35
                <dependency>
27
                    <code-name-base>org.openide.filesystems</code-name-base>
36
                    <code-name-base>org.openide.filesystems</code-name-base>
28
                    <build-prerequisite/>
37
                    <build-prerequisite/>
29
                    <compile-dependency/>
38
                    <compile-dependency/>
(-)a/extexecution/src/org/netbeans/api/extexecution/ExecutionDescriptor.java (-14 / +136 lines)
Lines 43-48 Link Here
43
package org.netbeans.api.extexecution;
43
package org.netbeans.api.extexecution;
44
44
45
import java.nio.charset.Charset;
45
import java.nio.charset.Charset;
46
import java.util.logging.Level;
47
import java.util.logging.Logger;
46
import javax.swing.event.ChangeListener;
48
import javax.swing.event.ChangeListener;
47
import org.netbeans.api.annotations.common.CheckReturnValue;
49
import org.netbeans.api.annotations.common.CheckReturnValue;
48
import org.netbeans.api.annotations.common.NonNull;
50
import org.netbeans.api.annotations.common.NonNull;
Lines 53-59 Link Here
53
import org.openide.windows.InputOutput;
55
import org.openide.windows.InputOutput;
54
56
55
/**
57
/**
56
 * Descriptor for the execution environment. Describes the runtime attributes
58
 * Descriptor for the execution service. Describes the runtime attributes
57
 * of the {@link ExecutionService}.
59
 * of the {@link ExecutionService}.
58
 * <p>
60
 * <p>
59
 * <i>Thread safety</i> of this class depends on type of objects passed to its
61
 * <i>Thread safety</i> of this class depends on type of objects passed to its
Lines 66-71 Link Here
66
 */
68
 */
67
public final class ExecutionDescriptor {
69
public final class ExecutionDescriptor {
68
70
71
    private static final Logger LOGGER = Logger.getLogger(ExecutionDescriptor.class.getName());
72
69
    // TODO provide constants for common descriptors (are there any?)
73
    // TODO provide constants for common descriptors (are there any?)
70
74
71
    private final Runnable preExecution;
75
    private final Runnable preExecution;
Lines 95-102 Link Here
95
    private final LineConvertorFactory errConvertorFactory;
99
    private final LineConvertorFactory errConvertorFactory;
96
100
97
    private final InputProcessorFactory outProcessorFactory;
101
    private final InputProcessorFactory outProcessorFactory;
102
    
103
    private final InputProcessorFactory2 outProcessorFactory2;
98
104
99
    private final InputProcessorFactory errProcessorFactory;
105
    private final InputProcessorFactory errProcessorFactory;
106
    
107
    private final InputProcessorFactory2 errProcessorFactory2;
100
108
101
    private final InputOutput inputOutput;
109
    private final InputOutput inputOutput;
102
110
Lines 128-134 Link Here
128
        this.outConvertorFactory = data.outConvertorFactory;
136
        this.outConvertorFactory = data.outConvertorFactory;
129
        this.errConvertorFactory = data.errConvertorFactory;
137
        this.errConvertorFactory = data.errConvertorFactory;
130
        this.outProcessorFactory = data.outProcessorFactory;
138
        this.outProcessorFactory = data.outProcessorFactory;
139
        this.outProcessorFactory2 = data.outProcessorFactory2;
131
        this.errProcessorFactory = data.errProcessorFactory;
140
        this.errProcessorFactory = data.errProcessorFactory;
141
        this.errProcessorFactory2 = data.errProcessorFactory2;
132
        this.inputOutput = data.inputOutput;
142
        this.inputOutput = data.inputOutput;
133
        this.rerunCondition = data.rerunCondition;
143
        this.rerunCondition = data.rerunCondition;
134
        this.optionsPath = data.optionsPath;
144
        this.optionsPath = data.optionsPath;
Lines 388-396 Link Here
388
     * <p>
398
     * <p>
389
     * Note that {@link ExecutionService} automatically uses
399
     * Note that {@link ExecutionService} automatically uses
390
     * the printing processor created by
400
     * the printing processor created by
391
     * {@link org.netbeans.api.extexecution.input.InputProcessors#printing(org.openide.windows.OutputWriter, org.netbeans.api.extexecution.print.LineConvertor, boolean)}
401
     * {@link org.netbeans.api.extexecution.print.InputProcessors#printing(org.openide.windows.OutputWriter, org.netbeans.api.extexecution.print.LineConvertor, boolean)}
392
     * or
402
     * or
393
     * {@link org.netbeans.api.extexecution.input.LineProcessors#printing(org.openide.windows.OutputWriter, org.netbeans.api.extexecution.print.LineConvertor, boolean)}
403
     * {@link org.netbeans.api.extexecution.print.LineProcessors#printing(org.openide.windows.OutputWriter, org.netbeans.api.extexecution.print.LineConvertor, boolean)}
404
     * (in case {@link #outLineBased(boolean)} is configured to <code>true</code>)
405
     * if there is no configured factory.
406
     * <p>
407
     * The default (not configured) value is <code>null</code>.
408
     * <p>
409
     * All other properties of the returned descriptor are inherited from
410
     * <code>this</code>.
411
     *
412
     * @param outProcessorFactory factory for standard output processor,
413
     *             <code>null</code> allowed
414
     * @return new descriptor with configured factory for additional
415
     *             processor to use for standard output
416
     * @deprecated use {@link #outProcessorFactory(org.netbeans.api.extexecution.ExecutionDescriptor.InputProcessorFactory2)}
417
     */
418
    @NonNull
419
    @CheckReturnValue
420
    public ExecutionDescriptor outProcessorFactory(@NullAllowed InputProcessorFactory outProcessorFactory) {
421
        DescriptorData data = new DescriptorData(this);
422
        return new ExecutionDescriptor(data.outProcessorFactory(outProcessorFactory));
423
    }
424
425
    InputProcessorFactory getOutProcessorFactory() {
426
        return outProcessorFactory;
427
    }
428
    
429
    /**
430
     * Returns a descriptor with configured factory for standard output
431
     * processor. The factory is used by {@link ExecutionService} to create
432
     * additional processor for standard output. <i>The configured value will
433
     * be ignored if you previously configured processor via deprecated
434
     * {@link #outProcessorFactory(org.netbeans.api.extexecution.ExecutionDescriptor.InputProcessorFactory)}.</i>
435
     * <p>
436
     * Note that {@link ExecutionService} automatically uses
437
     * the printing processor created by
438
     * {@link org.netbeans.api.extexecution.print.InputProcessors#printing(org.openide.windows.OutputWriter, org.netbeans.api.extexecution.print.LineConvertor, boolean)}
439
     * or
440
     * {@link org.netbeans.api.extexecution.print.LineProcessors#printing(org.openide.windows.OutputWriter, org.netbeans.api.extexecution.print.LineConvertor, boolean)}
394
     * (in case {@link #outLineBased(boolean)} is configured to <code>true</code>)
441
     * (in case {@link #outLineBased(boolean)} is configured to <code>true</code>)
395
     * if there is no configured factory.
442
     * if there is no configured factory.
396
     * <p>
443
     * <p>
Lines 406-418 Link Here
406
     */
453
     */
407
    @NonNull
454
    @NonNull
408
    @CheckReturnValue
455
    @CheckReturnValue
409
    public ExecutionDescriptor outProcessorFactory(@NullAllowed InputProcessorFactory outProcessorFactory) {
456
    public ExecutionDescriptor outProcessorFactory(@NullAllowed InputProcessorFactory2 outProcessorFactory) {
457
        if (errProcessorFactory != null) {
458
            LOGGER.log(Level.WARNING, "The factory will be ignored as legacy InputProcessorFactory is already defined");
459
        }
410
        DescriptorData data = new DescriptorData(this);
460
        DescriptorData data = new DescriptorData(this);
411
        return new ExecutionDescriptor(data.outProcessorFactory(outProcessorFactory));
461
        return new ExecutionDescriptor(data.outProcessorFactory(outProcessorFactory2));
412
    }
462
    }
413
463
414
    InputProcessorFactory getOutProcessorFactory() {
464
    InputProcessorFactory2 getOutProcessorFactory2() {
415
        return outProcessorFactory;
465
        return outProcessorFactory2;
416
    }
466
    }
417
467
418
    /**
468
    /**
Lines 422-430 Link Here
422
     * <p>
472
     * <p>
423
     * Note that {@link ExecutionService} automatically uses
473
     * Note that {@link ExecutionService} automatically uses
424
     * the printing processor created by
474
     * the printing processor created by
425
     * {@link org.netbeans.api.extexecution.input.InputProcessors#printing(org.openide.windows.OutputWriter, org.netbeans.api.extexecution.print.LineConvertor, boolean)}
475
     * {@link org.netbeans.api.extexecution.print.InputProcessors#printing(org.openide.windows.OutputWriter, org.netbeans.api.extexecution.print.LineConvertor, boolean)}
426
     * or
476
     * or
427
     * {@link org.netbeans.api.extexecution.input.LineProcessors#printing(org.openide.windows.OutputWriter, org.netbeans.api.extexecution.print.LineConvertor, boolean)}
477
     * {@link org.netbeans.api.extexecution.print.LineProcessors#printing(org.openide.windows.OutputWriter, org.netbeans.api.extexecution.print.LineConvertor, boolean)}
478
     * (in case {@link #errLineBased(boolean)} is configured to <code>true</code>)
479
     * if there is no configured factory.
480
     * <p>
481
     * The default (not configured) value is <code>null</code>.
482
     * <p>
483
     * All other properties of the returned descriptor are inherited from
484
     * <code>this</code>.
485
     *
486
     * @param errProcessorFactory factory for standard error output processor,
487
     *             <code>null</code> allowed
488
     * @return new descriptor with configured factory for additional
489
     *             processor to use for standard error output
490
     * @deprecated use {@link #errProcessorFactory(org.netbeans.api.extexecution.ExecutionDescriptor.InputProcessorFactory2)}
491
     */
492
    @NonNull
493
    @CheckReturnValue
494
    public ExecutionDescriptor errProcessorFactory(@NullAllowed InputProcessorFactory errProcessorFactory) {
495
        DescriptorData data = new DescriptorData(this);
496
        return new ExecutionDescriptor(data.errProcessorFactory(errProcessorFactory));
497
    }
498
499
    InputProcessorFactory getErrProcessorFactory() {
500
        return errProcessorFactory;
501
    }
502
    
503
    /**
504
     * Returns a descriptor with configured factory for standard error output
505
     * processor. The factory is used by {@link ExecutionService} to create
506
     * additional processor for standard error output. <i>The configured value will
507
     * be ignored if you previously configured processor via deprecated
508
     * {@link #errProcessorFactory(org.netbeans.api.extexecution.ExecutionDescriptor.InputProcessorFactory)}.</i>
509
     * <p>
510
     * Note that {@link ExecutionService} automatically uses
511
     * the printing processor created by
512
     * {@link org.netbeans.api.extexecution.print.InputProcessors#printing(org.openide.windows.OutputWriter, org.netbeans.api.extexecution.print.LineConvertor, boolean)}
513
     * or
514
     * {@link org.netbeans.api.extexecution.print.LineProcessors#printing(org.openide.windows.OutputWriter, org.netbeans.api.extexecution.print.LineConvertor, boolean)}
428
     * (in case {@link #errLineBased(boolean)} is configured to <code>true</code>)
515
     * (in case {@link #errLineBased(boolean)} is configured to <code>true</code>)
429
     * if there is no configured factory.
516
     * if there is no configured factory.
430
     * <p>
517
     * <p>
Lines 440-452 Link Here
440
     */
527
     */
441
    @NonNull
528
    @NonNull
442
    @CheckReturnValue
529
    @CheckReturnValue
443
    public ExecutionDescriptor errProcessorFactory(@NullAllowed InputProcessorFactory errProcessorFactory) {
530
    public ExecutionDescriptor errProcessorFactory(@NullAllowed InputProcessorFactory2 errProcessorFactory) {
531
        if (errProcessorFactory != null) {
532
            LOGGER.log(Level.WARNING, "The factory will be ignored as legacy InputProcessorFactory is already defined");
533
        }
444
        DescriptorData data = new DescriptorData(this);
534
        DescriptorData data = new DescriptorData(this);
445
        return new ExecutionDescriptor(data.errProcessorFactory(errProcessorFactory));
535
        return new ExecutionDescriptor(data.errProcessorFactory(errProcessorFactory2));
446
    }
536
    }
447
537
448
    InputProcessorFactory getErrProcessorFactory() {
538
    InputProcessorFactory2 getErrProcessorFactory2() {
449
        return errProcessorFactory;
539
        return errProcessorFactory2;
450
    }
540
    }
451
541
452
    /**
542
    /**
Lines 673-678 Link Here
673
763
674
    /**
764
    /**
675
     * Factory creating the input processor.
765
     * Factory creating the input processor.
766
     * @deprecated use {@link InputProcessorFactory2}
676
     */
767
     */
677
    public interface InputProcessorFactory {
768
    public interface InputProcessorFactory {
678
769
Lines 687-695 Link Here
687
        InputProcessor newInputProcessor(@NonNull InputProcessor defaultProcessor);
778
        InputProcessor newInputProcessor(@NonNull InputProcessor defaultProcessor);
688
779
689
    }
780
    }
781
    
782
    /**
783
     * Factory creating the input processor.
784
     */
785
    public interface InputProcessorFactory2 {
786
787
        /**
788
         * Creates and returns new input processor.
789
         *
790
         * @param defaultProcessor default processor created by
791
         *             infrastructure that is printing chars to the output window
792
         * @return new input processor
793
         */
794
        @NonNull
795
        org.netbeans.api.extexecution.base.input.InputProcessor newInputProcessor(@NonNull org.netbeans.api.extexecution.base.input.InputProcessor defaultProcessor);
796
797
    }
690
798
691
    /**
799
    /**
692
     * Factory creating the line covertor.
800
     * Factory creating the line convertor.
693
     */
801
     */
694
    public interface LineConvertorFactory {
802
    public interface LineConvertorFactory {
695
803
Lines 732-739 Link Here
732
        private LineConvertorFactory errConvertorFactory;
840
        private LineConvertorFactory errConvertorFactory;
733
841
734
        private InputProcessorFactory outProcessorFactory;
842
        private InputProcessorFactory outProcessorFactory;
843
        
844
        private InputProcessorFactory2 outProcessorFactory2;
735
845
736
        private InputProcessorFactory errProcessorFactory;
846
        private InputProcessorFactory errProcessorFactory;
847
        
848
        private InputProcessorFactory2 errProcessorFactory2;
737
849
738
        private InputOutput inputOutput;
850
        private InputOutput inputOutput;
739
851
Lines 823-833 Link Here
823
            this.outProcessorFactory = outProcessorFactory;
935
            this.outProcessorFactory = outProcessorFactory;
824
            return this;
936
            return this;
825
        }
937
        }
938
        
939
        public DescriptorData outProcessorFactory(InputProcessorFactory2 outProcessorFactory) {
940
            this.outProcessorFactory2 = outProcessorFactory2;
941
            return this;
942
        }
826
943
827
        public DescriptorData errProcessorFactory(InputProcessorFactory errProcessorFactory) {
944
        public DescriptorData errProcessorFactory(InputProcessorFactory errProcessorFactory) {
828
            this.errProcessorFactory = errProcessorFactory;
945
            this.errProcessorFactory = errProcessorFactory;
829
            return this;
946
            return this;
830
        }
947
        }
948
        
949
        public DescriptorData errProcessorFactory(InputProcessorFactory2 errProcessorFactory) {
950
            this.errProcessorFactory2 = errProcessorFactory2;
951
            return this;
952
        }
831
953
832
        public DescriptorData outConvertorFactory(LineConvertorFactory convertorFactory) {
954
        public DescriptorData outConvertorFactory(LineConvertorFactory convertorFactory) {
833
            this.outConvertorFactory = convertorFactory;
955
            this.outConvertorFactory = convertorFactory;
(-)a/extexecution/src/org/netbeans/api/extexecution/ExecutionService.java (-207 / +95 lines)
Lines 47-94 Link Here
47
import org.netbeans.modules.extexecution.StopAction;
47
import org.netbeans.modules.extexecution.StopAction;
48
import org.netbeans.modules.extexecution.RerunAction;
48
import org.netbeans.modules.extexecution.RerunAction;
49
import java.awt.event.ActionEvent;
49
import java.awt.event.ActionEvent;
50
import java.io.BufferedInputStream;
51
import java.io.IOException;
50
import java.io.IOException;
52
import java.io.OutputStream;
53
import java.io.OutputStreamWriter;
54
import java.io.Reader;
51
import java.io.Reader;
55
import java.nio.charset.Charset;
56
import java.security.AccessController;
57
import java.security.PrivilegedAction;
58
import java.util.ArrayList;
59
import java.util.HashSet;
60
import java.util.List;
61
import java.util.Set;
62
import java.util.concurrent.Callable;
52
import java.util.concurrent.Callable;
63
import java.util.concurrent.CountDownLatch;
53
import java.util.concurrent.ExecutionException;
64
import java.util.concurrent.ExecutorService;
65
import java.util.concurrent.Executors;
66
import java.util.concurrent.Future;
54
import java.util.concurrent.Future;
67
import java.util.concurrent.FutureTask;
68
import java.util.concurrent.TimeUnit;
55
import java.util.concurrent.TimeUnit;
56
import java.util.concurrent.TimeoutException;
69
import java.util.logging.Level;
57
import java.util.logging.Level;
70
import java.util.logging.Logger;
58
import java.util.logging.Logger;
71
import javax.swing.AbstractAction;
59
import javax.swing.AbstractAction;
72
import org.netbeans.api.annotations.common.NonNull;
60
import org.netbeans.api.annotations.common.NonNull;
73
import org.netbeans.api.progress.ProgressHandle;
61
import org.netbeans.api.progress.ProgressHandle;
74
import org.netbeans.api.progress.ProgressHandleFactory;
62
import org.netbeans.api.progress.ProgressHandleFactory;
75
import org.netbeans.modules.extexecution.ProcessInputStream;
76
import org.netbeans.api.extexecution.ExecutionDescriptor.InputProcessorFactory;
63
import org.netbeans.api.extexecution.ExecutionDescriptor.InputProcessorFactory;
64
import org.netbeans.api.extexecution.ExecutionDescriptor.InputProcessorFactory2;
77
import org.netbeans.api.extexecution.ExecutionDescriptor.LineConvertorFactory;
65
import org.netbeans.api.extexecution.ExecutionDescriptor.LineConvertorFactory;
78
import org.netbeans.api.extexecution.input.InputProcessor;
66
import org.netbeans.api.extexecution.base.BaseExecutionDescriptor;
79
import org.netbeans.api.extexecution.input.InputProcessors;
67
import org.netbeans.api.extexecution.base.BaseExecutionService;
80
import org.netbeans.api.extexecution.input.InputReaderTask;
68
import org.netbeans.api.extexecution.base.ParametrizedRunnable;
81
import org.netbeans.api.extexecution.input.InputReaders;
69
import org.netbeans.api.extexecution.base.input.InputProcessor;
82
import org.netbeans.api.extexecution.input.LineProcessors;
70
import org.netbeans.api.extexecution.base.input.InputProcessors;
71
import org.netbeans.api.extexecution.print.LineProcessors;
72
import org.netbeans.modules.extexecution.input.BaseInputProcessor;
73
import org.netbeans.modules.extexecution.input.DelegatingInputProcessor;
83
import org.openide.util.Cancellable;
74
import org.openide.util.Cancellable;
84
import org.openide.util.Mutex;
75
import org.openide.util.Mutex;
85
import org.openide.util.NbBundle;
76
import org.openide.util.NbBundle;
86
import org.openide.util.RequestProcessor;
87
import org.openide.windows.InputOutput;
77
import org.openide.windows.InputOutput;
88
import org.openide.windows.OutputWriter;
78
import org.openide.windows.OutputWriter;
89
79
90
/**
80
/**
91
 * Execution service provides the facility to execute the process while
81
 * Execution service provides the facility to execute a process while
92
 * displaying the output and handling the input.
82
 * displaying the output and handling the input.
93
 * <p>
83
 * <p>
94
 * It will execute the program with an associated I/O window, with stop and
84
 * It will execute the program with an associated I/O window, with stop and
Lines 124-135 Link Here
124
114
125
    private static final Logger LOGGER = Logger.getLogger(ExecutionService.class.getName());
115
    private static final Logger LOGGER = Logger.getLogger(ExecutionService.class.getName());
126
116
127
    private static final Set<Process> RUNNING_PROCESSES = new HashSet<Process>();
128
129
    private static final int EXECUTOR_SHUTDOWN_SLICE = 1000;
130
131
    private static final ExecutorService EXECUTOR_SERVICE = new RequestProcessor(ExecutionService.class.getName(), Integer.MAX_VALUE);
132
133
    static {
117
    static {
134
        // rerun accessor
118
        // rerun accessor
135
        RerunAction.Accessor.setDefault(new RerunAction.Accessor() {
119
        RerunAction.Accessor.setDefault(new RerunAction.Accessor() {
Lines 139-159 Link Here
139
                return service.run(required);
123
                return service.run(required);
140
            }
124
            }
141
        });
125
        });
142
143
        // shutdown hook
144
        Runtime.getRuntime().addShutdownHook(new Thread() {
145
146
            @Override
147
            public void run() {
148
                EXECUTOR_SERVICE.shutdown();
149
150
                synchronized (RUNNING_PROCESSES) {
151
                    for (Process process : RUNNING_PROCESSES) {
152
                        process.destroy();
153
                    }
154
                }
155
            }
156
        });
157
    }
126
    }
158
127
159
    private final Callable<Process> processCreator;
128
    private final Callable<Process> processCreator;
Lines 224-358 Link Here
224
        final OutputWriter err = io.getErr();
193
        final OutputWriter err = io.getErr();
225
        final Reader in = io.getIn();
194
        final Reader in = io.getIn();
226
195
227
        final CountDownLatch finishedLatch = new CountDownLatch(1);
228
229
        class ExecutedHolder {
196
        class ExecutedHolder {
230
            private boolean executed = false;
197
            private boolean executed = false;
231
        }
198
        }
232
        final ExecutedHolder executed = new ExecutedHolder();
199
        final ExecutedHolder executed = new ExecutedHolder();
233
200
234
        Callable<Integer> callable = new Callable<Integer>() {
201
        BaseExecutionDescriptor realDescriptor = new BaseExecutionDescriptor();
235
            public Integer call() throws Exception {
202
        realDescriptor = realDescriptor.charset(descriptor.getCharset());
203
        realDescriptor = realDescriptor.inReaderFactory(new BaseExecutionDescriptor.ReaderFactory() {
236
204
237
                boolean interrupted = false;
205
            @Override
238
                Process process = null;
206
            public Reader newReader() {
239
                Integer ret = null;
207
                return in;
240
                ExecutorService executor = null;
208
            }
209
        });
210
        realDescriptor = realDescriptor.preExecution(new Runnable() {
241
211
242
                ProcessInputStream outStream = null;
212
            @Override
243
                ProcessInputStream errStream = null;
213
            public void run() {
214
                executed.executed = true;
215
                Runnable orig = descriptor.getPreExecution();
216
                if (orig != null) {
217
                    orig.run();
218
                }
219
            }
220
        });
221
        realDescriptor = realDescriptor.postExecution(new ParametrizedRunnable<Integer>() {
244
222
245
                List<InputReaderTask> tasks = new ArrayList<InputReaderTask>();
223
            @Override
224
            public void run(Integer parameter) {
225
                cleanup(handle, ioData, ioData.getInputOutput() != descriptor.getInputOutput(),
226
                        descriptor.isFrontWindowOnError() && parameter != null && parameter != 0);
227
                Runnable orig = descriptor.getPostExecution();
228
                if (orig != null) {
229
                    orig.run();
230
                }
231
            }
232
        });
233
        realDescriptor = realDescriptor.outProcessorFactory(new BaseExecutionDescriptor.InputProcessorFactory() {
246
234
247
                try {
235
            @Override
248
                    executed.executed = true;
236
            public InputProcessor newInputProcessor() {
249
                    final Runnable pre = descriptor.getPreExecution();
237
                return createOutProcessor(out);
250
                    if (pre != null) {
238
            }
251
                        pre.run();
239
        });
252
                    }
240
        realDescriptor = realDescriptor.errProcessorFactory(new BaseExecutionDescriptor.InputProcessorFactory() {
253
241
254
                    if (Thread.currentThread().isInterrupted()) {
242
            @Override
255
                        return null;
243
            public InputProcessor newInputProcessor() {
256
                    }
244
                return createErrProcessor(err);
257
258
                    process = processCreator.call();
259
                    synchronized (RUNNING_PROCESSES) {
260
                        RUNNING_PROCESSES.add(process);
261
                    }
262
263
                    if (Thread.currentThread().isInterrupted()) {
264
                        return null;
265
                    }
266
267
                    outStream = new ProcessInputStream(process, process.getInputStream());
268
                    errStream = new ProcessInputStream(process, process.getErrorStream());
269
270
                    executor = Executors.newFixedThreadPool(descriptor.isInputVisible() ? 3 : 2);
271
272
                    Charset charset = descriptor.getCharset();
273
                    if (charset == null) {
274
                        charset = Charset.defaultCharset();
275
                    }
276
277
                    tasks.add(InputReaderTask.newDrainingTask(
278
                        InputReaders.forStream(new BufferedInputStream(outStream), charset),
279
                        createOutProcessor(out)));
280
                    tasks.add(InputReaderTask.newDrainingTask(
281
                        InputReaders.forStream(new BufferedInputStream(errStream), charset),
282
                        createErrProcessor(err)));
283
                    if (descriptor.isInputVisible()) {
284
                        tasks.add(InputReaderTask.newTask(
285
                            InputReaders.forReader(in),
286
                            createInProcessor(process.getOutputStream())));
287
                    }
288
                    for (InputReaderTask task : tasks) {
289
                        executor.submit(task);
290
                    }
291
292
                    process.waitFor();
293
                } catch (InterruptedException ex) {
294
                    LOGGER.log(Level.FINE, null, ex);
295
                    interrupted = true;
296
                } catch (Throwable t) {
297
                    LOGGER.log(Level.INFO, null, t);
298
                    throw new WrappedException(t);
299
                } finally {
300
                    try {
301
                        // fully evaluated - we want to clear interrupted status in any case
302
                        interrupted = interrupted | Thread.interrupted();
303
304
                        if (!interrupted) {
305
                            if (outStream != null) {
306
                                outStream.close(true);
307
                            }
308
                            if (errStream != null) {
309
                                errStream.close(true);
310
                            }
311
                        }
312
313
                        if (process != null) {
314
                            process.destroy();
315
                            synchronized (RUNNING_PROCESSES) {
316
                                RUNNING_PROCESSES.remove(process);
317
                            }
318
319
                            try {
320
                                ret = process.exitValue();
321
                            } catch (IllegalThreadStateException ex) {
322
                                LOGGER.log(Level.FINE, "Process not yet exited", ex);
323
                            }
324
                        }
325
                    } catch (Throwable t) {
326
                        LOGGER.log(Level.INFO, null, t);
327
                        throw new WrappedException(t);
328
                    } finally {
329
                        try {
330
                            cleanup(tasks, executor, handle, ioData,
331
                                    ioData.getInputOutput() != descriptor.getInputOutput(),
332
                                    descriptor.isFrontWindowOnError() && ret != null && ret.intValue() != 0);
333
334
                            final Runnable post = descriptor.getPostExecution();
335
                            if (post != null) {
336
                                post.run();
337
                            }
338
                        } finally {
339
                            finishedLatch.countDown();
340
                            if (interrupted) {
341
                                Thread.currentThread().interrupt();
342
                            }
343
                        }
344
                    }
345
                }
346
347
                return ret;
348
            }
245
            }
349
        };
246
        });
350
247
        
351
        final FutureTask<Integer> current = new FutureTask<Integer>(callable) {
248
        BaseExecutionService service = BaseExecutionService.newService(processCreator, realDescriptor);
249
        final Future<Integer> delegate = service.run();
250
        
251
        final Future<Integer> current = new Future<Integer>() {
352
252
353
            @Override
253
            @Override
354
            public boolean cancel(boolean mayInterruptIfRunning) {
254
            public boolean cancel(boolean mayInterruptIfRunning) {
355
                boolean ret = super.cancel(mayInterruptIfRunning);
255
                boolean ret = delegate.cancel(mayInterruptIfRunning);
356
                if (!executed.executed) {
256
                if (!executed.executed) {
357
                    // not executed at all - passing false to show
257
                    // not executed at all - passing false to show
358
                    cleanup(handle, ioData, false);
258
                    cleanup(handle, ioData, false);
Lines 376-389 Link Here
376
            }
276
            }
377
277
378
            @Override
278
            @Override
379
            protected void setException(Throwable t) {
279
            public boolean isCancelled() {
380
                if (t instanceof WrappedException) {
280
                return delegate.isCancelled();
381
                    super.setException(((WrappedException) t).getCause());
382
                } else {
383
                    super.setException(t);
384
                }
385
            }
281
            }
386
282
283
            @Override
284
            public boolean isDone() {
285
                return delegate.isDone();
286
            }
287
288
            @Override
289
            public Integer get() throws InterruptedException, ExecutionException {
290
                return delegate.get();
291
            }
292
293
            @Override
294
            public Integer get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
295
                return delegate.get(timeout, unit);
296
            }
387
        };
297
        };
388
298
389
        // TODO cleanup
299
        // TODO cleanup
Lines 391-396 Link Here
391
        final RerunAction workingRerunAction = ioData.getRerunAction();
301
        final RerunAction workingRerunAction = ioData.getRerunAction();
392
302
393
        Mutex.EVENT.readAccess(new Runnable() {
303
        Mutex.EVENT.readAccess(new Runnable() {
304
            @Override
394
            public void run() {
305
            public void run() {
395
                if (workingStopAction != null) {
306
                if (workingStopAction != null) {
396
                    synchronized (workingStopAction) {
307
                    synchronized (workingStopAction) {
Lines 413-419 Link Here
413
            cancellable.setTask(current);
324
            cancellable.setTask(current);
414
        }
325
        }
415
326
416
        EXECUTOR_SERVICE.execute(current);
417
        return current;
327
        return current;
418
    }
328
    }
419
329
Lines 507-536 Link Here
507
        return handle;
417
        return handle;
508
    }
418
    }
509
419
510
    private void cleanup(final List<InputReaderTask> tasks, final ExecutorService processingExecutor,
420
    private void cleanup(final ProgressHandle progressHandle,
511
            final ProgressHandle progressHandle, final InputOutputManager.InputOutputData inputOutputData,
421
            final InputOutputManager.InputOutputData inputOutputData,
512
            final boolean managed, final boolean show) {
422
            final boolean managed, final boolean show) {
513
423
514
        boolean interrupted = false;
515
        if (processingExecutor != null) {
516
            try {
517
                AccessController.doPrivileged(new PrivilegedAction<Void>() {
518
                    public Void run() {
519
                        processingExecutor.shutdown();
520
                        return null;
521
                    }
522
                });
523
                for (Cancellable cancellable : tasks) {
524
                    cancellable.cancel();
525
                }
526
                while (!processingExecutor.awaitTermination(EXECUTOR_SHUTDOWN_SLICE, TimeUnit.MILLISECONDS)) {
527
                    LOGGER.log(Level.INFO, "Awaiting processing finish");
528
                }
529
            } catch (InterruptedException ex) {
530
                interrupted = true;
531
            }
532
        }
533
534
        cleanup(progressHandle, inputOutputData, show);
424
        cleanup(progressHandle, inputOutputData, show);
535
425
536
        synchronized (InputOutputManager.class) {
426
        synchronized (InputOutputManager.class) {
Lines 538-547 Link Here
538
                InputOutputManager.addInputOutput(inputOutputData);
428
                InputOutputManager.addInputOutput(inputOutputData);
539
            }
429
            }
540
        }
430
        }
541
542
        if (interrupted) {
543
            Thread.currentThread().interrupt();
544
        }
545
    }
431
    }
546
432
547
    private void cleanup(final ProgressHandle progressHandle,
433
    private void cleanup(final ProgressHandle progressHandle,
Lines 575-587 Link Here
575
            outProcessor = InputProcessors.bridge(LineProcessors.printing(writer,
461
            outProcessor = InputProcessors.bridge(LineProcessors.printing(writer,
576
                    convertorFactory != null ? convertorFactory.newLineConvertor() : null, true));
462
                    convertorFactory != null ? convertorFactory.newLineConvertor() : null, true));
577
        } else {
463
        } else {
578
            outProcessor = InputProcessors.printing(writer,
464
            outProcessor = org.netbeans.api.extexecution.print.InputProcessors.printing(writer,
579
                    convertorFactory != null ? convertorFactory.newLineConvertor() : null, true);
465
                    convertorFactory != null ? convertorFactory.newLineConvertor() : null, true);
580
        }
466
        }
581
467
582
        InputProcessorFactory descriptorOutFactory = descriptor.getOutProcessorFactory();
468
        InputProcessorFactory descriptorOutFactory = descriptor.getOutProcessorFactory();
583
        if (descriptorOutFactory != null) {
469
        if (descriptorOutFactory != null) {
584
            outProcessor = descriptorOutFactory.newInputProcessor(outProcessor);
470
            outProcessor = new BaseInputProcessor(descriptorOutFactory.newInputProcessor(
471
                    new DelegatingInputProcessor(outProcessor)));
472
        } else {
473
            InputProcessorFactory2 descriptorOutFactory2 = descriptor.getOutProcessorFactory2();
474
            if (descriptorOutFactory2 != null) {
475
                outProcessor = descriptorOutFactory2.newInputProcessor(outProcessor);
476
            }
585
        }
477
        }
586
478
587
        return outProcessor;
479
        return outProcessor;
Lines 594-615 Link Here
594
            errProcessor = InputProcessors.bridge(LineProcessors.printing(writer,
486
            errProcessor = InputProcessors.bridge(LineProcessors.printing(writer,
595
                    convertorFactory != null ? convertorFactory.newLineConvertor() : null, false));
487
                    convertorFactory != null ? convertorFactory.newLineConvertor() : null, false));
596
        } else {
488
        } else {
597
            errProcessor = InputProcessors.printing(writer,
489
            errProcessor = org.netbeans.api.extexecution.print.InputProcessors.printing(writer,
598
                    convertorFactory != null ? convertorFactory.newLineConvertor() : null, false);
490
                    convertorFactory != null ? convertorFactory.newLineConvertor() : null, false);
599
        }
491
        }
600
492
601
        InputProcessorFactory descriptorErrFactory = descriptor.getErrProcessorFactory();
493
        InputProcessorFactory descriptorErrFactory = descriptor.getErrProcessorFactory();
602
        if (descriptorErrFactory != null) {
494
        if (descriptorErrFactory != null) {
603
            errProcessor = descriptorErrFactory.newInputProcessor(errProcessor);
495
            errProcessor = new BaseInputProcessor(descriptorErrFactory.newInputProcessor(
496
                    new DelegatingInputProcessor(errProcessor)));
497
        } else {
498
            InputProcessorFactory2 descriptorErrFactory2 = descriptor.getErrProcessorFactory2();
499
            if (descriptorErrFactory2 != null) {
500
                errProcessor = descriptorErrFactory2.newInputProcessor(errProcessor);
501
            }
604
        }
502
        }
605
503
606
        return errProcessor;
504
        return errProcessor;
607
    }
505
    }
608
506
609
    private InputProcessor createInProcessor(OutputStream os) {
610
        return InputProcessors.copying(new OutputStreamWriter(os));
611
    }
612
613
    private static class ProgressCancellable implements Cancellable {
507
    private static class ProgressCancellable implements Cancellable {
614
508
615
        private Future<Integer> task;
509
        private Future<Integer> task;
Lines 622-627 Link Here
622
            this.task = task;
516
            this.task = task;
623
        }
517
        }
624
518
519
        @Override
625
        public synchronized boolean cancel() {
520
        public synchronized boolean cancel() {
626
            if (task != null) {
521
            if (task != null) {
627
                task.cancel(true);
522
                task.cancel(true);
Lines 638-653 Link Here
638
            this.io = io;
533
            this.io = io;
639
        }
534
        }
640
535
536
        @Override
641
        public void actionPerformed(ActionEvent e) {
537
        public void actionPerformed(ActionEvent e) {
642
            io.select();
538
            io.select();
643
        }
539
        }
644
    }
540
    }
645
646
    private static class WrappedException extends Exception {
647
648
        public WrappedException(Throwable cause) {
649
            super(cause);
650
        }
651
652
    }
653
}
541
}
(-)a/extexecution/src/org/netbeans/api/extexecution/ExternalProcessBuilder.java (-2 / +1 lines)
Lines 69-79 Link Here
69
 * Builder handle command, working directory, <code>PATH</code> variable and HTTP proxy.
69
 * Builder handle command, working directory, <code>PATH</code> variable and HTTP proxy.
70
 * <p>
70
 * <p>
71
 * This class is <i>immutable</i>.
71
 * This class is <i>immutable</i>.
72
 * <p>
73
 * Also see {@link ProcessBuilder#getLocal()}.
74
 *
72
 *
75
 * @author Petr Hejl
73
 * @author Petr Hejl
76
 * @see #call()
74
 * @see #call()
75
 * @deprecated use {@link org.netbeans.api.extexecution.base.ProcessBuilder#getLocal()}
77
 */
76
 */
78
public final class ExternalProcessBuilder implements Callable<Process> {
77
public final class ExternalProcessBuilder implements Callable<Process> {
79
78
(-)a/extexecution/src/org/netbeans/api/extexecution/ExternalProcessSupport.java (+2 lines)
Lines 44-49 Link Here
44
44
45
import java.util.Map;
45
import java.util.Map;
46
import org.netbeans.api.annotations.common.NonNull;
46
import org.netbeans.api.annotations.common.NonNull;
47
import org.netbeans.api.extexecution.base.Processes;
47
import org.netbeans.modules.extexecution.WrapperProcess;
48
import org.netbeans.modules.extexecution.WrapperProcess;
48
import org.netbeans.spi.extexecution.destroy.ProcessDestroyPerformer;
49
import org.netbeans.spi.extexecution.destroy.ProcessDestroyPerformer;
49
import org.openide.util.Lookup;
50
import org.openide.util.Lookup;
Lines 55-60 Link Here
55
 *
56
 *
56
 * @author mkleint
57
 * @author mkleint
57
 * @since 1.16
58
 * @since 1.16
59
 * @deprecated use {@link Processes}
58
 */
60
 */
59
public final class ExternalProcessSupport {
61
public final class ExternalProcessSupport {
60
62
(-)a/extexecution/src/org/netbeans/api/extexecution/ProcessBuilder.java (-15 / +14 lines)
Lines 41-47 Link Here
41
 */
41
 */
42
package org.netbeans.api.extexecution;
42
package org.netbeans.api.extexecution;
43
43
44
import java.io.File;
45
import java.io.IOException;
44
import java.io.IOException;
46
import java.util.ArrayList;
45
import java.util.ArrayList;
47
import java.util.HashMap;
46
import java.util.HashMap;
Lines 50-55 Link Here
50
import java.util.concurrent.Callable;
49
import java.util.concurrent.Callable;
51
import org.netbeans.api.annotations.common.NonNull;
50
import org.netbeans.api.annotations.common.NonNull;
52
import org.netbeans.api.annotations.common.NullAllowed;
51
import org.netbeans.api.annotations.common.NullAllowed;
52
import org.netbeans.api.extexecution.base.Environment;
53
import org.netbeans.modules.extexecution.ProcessBuilderAccessor;
53
import org.netbeans.modules.extexecution.ProcessBuilderAccessor;
54
import org.netbeans.spi.extexecution.ProcessBuilderImplementation;
54
import org.netbeans.spi.extexecution.ProcessBuilderImplementation;
55
import org.openide.util.NbBundle;
55
import org.openide.util.NbBundle;
Lines 74-79 Link Here
74
 *
74
 *
75
 * @author Petr Hejl
75
 * @author Petr Hejl
76
 * @since 1.28
76
 * @since 1.28
77
 * @deprecated use {@link org.netbeans.api.extexecution.base.ProcessBuilder}
77
 */
78
 */
78
public final class ProcessBuilder implements Callable<Process> {
79
public final class ProcessBuilder implements Callable<Process> {
79
80
Lines 88-100 Link Here
88
    private String workingDirectory;
89
    private String workingDirectory;
89
90
90
    /**<i>GuardedBy("this")</i>*/
91
    /**<i>GuardedBy("this")</i>*/
91
    private List<String> arguments = new ArrayList<String>();
92
    private final List<String> arguments = new ArrayList<String>();
92
93
93
    /**<i>GuardedBy("this")</i>*/
94
    /**<i>GuardedBy("this")</i>*/
94
    private List<String> paths = new ArrayList<String>();
95
    private final List<String> paths = new ArrayList<String>();
95
96
96
    /**<i>GuardedBy("this")</i>*/
97
    /**<i>GuardedBy("this")</i>*/
97
    private Map<String, String> envVariables = new HashMap<String, String>();
98
    private final Map<String, String> envVariables = new HashMap<String, String>();
98
99
99
    /**<i>GuardedBy("this")</i>*/
100
    /**<i>GuardedBy("this")</i>*/
100
    private boolean redirectErrorStream;
101
    private boolean redirectErrorStream;
Lines 232-238 Link Here
232
     * <p>
233
     * <p>
233
     * Since version 1.35 implementors of this method are advised to throw
234
     * Since version 1.35 implementors of this method are advised to throw
234
     * a {@link UserQuestionException} in case the execution cannot be
235
     * a {@link UserQuestionException} in case the execution cannot be
235
     * performed and requires additional user confirmation, or configuration. 
236
     * performed and requires additional user confirmation, or configuration.
236
     * Callers of this method may check for this exception and handle it
237
     * Callers of this method may check for this exception and handle it
237
     * appropriately.
238
     * appropriately.
238
     *
239
     *
Lines 278-297 Link Here
278
        public Process createProcess(String executable, String workingDirectory, List<String> arguments,
279
        public Process createProcess(String executable, String workingDirectory, List<String> arguments,
279
                List<String> paths, Map<String, String> environment, boolean redirectErrorStream) throws IOException {
280
                List<String> paths, Map<String, String> environment, boolean redirectErrorStream) throws IOException {
280
281
281
            ExternalProcessBuilder builder = new ExternalProcessBuilder(executable);
282
            org.netbeans.api.extexecution.base.ProcessBuilder builder = org.netbeans.api.extexecution.base.ProcessBuilder.getLocal();
282
            if (workingDirectory != null) {
283
            builder.setExecutable(executable);
283
                builder = builder.workingDirectory(new File(workingDirectory));
284
            builder.setWorkingDirectory(workingDirectory);
284
            }
285
            builder.setArguments(arguments);
285
            for (String argument : arguments) {
286
            builder.setRedirectErrorStream(redirectErrorStream);
286
                builder = builder.addArgument(argument);
287
            Environment env  = builder.getEnvironment();
287
            }
288
            for (String path : paths) {
288
            for (String path : paths) {
289
                builder = builder.prependPath(new File(path));
289
                env.prependPath("PATH", path);
290
            }
290
            }
291
            for (Map.Entry<String, String> entry : environment.entrySet()) {
291
            for (Map.Entry<String, String> entry : environment.entrySet()) {
292
                builder = builder.addEnvironmentVariable(entry.getKey(), entry.getValue());
292
                env.setVariable(entry.getKey(), entry.getValue());
293
            }
293
            }
294
            builder = builder.redirectErrorStream(redirectErrorStream);
295
294
296
            return builder.call();
295
            return builder.call();
297
        }
296
        }
(-)a/extexecution/src/org/netbeans/api/extexecution/input/InputProcessor.java (+1 lines)
Lines 54-59 Link Here
54
 *
54
 *
55
 * @author Petr Hejl
55
 * @author Petr Hejl
56
 * @see InputReader
56
 * @see InputReader
57
 * @deprecated use {@link org.netbeans.api.extexecution.base.input.InputProcessor}
57
 */
58
 */
58
public interface InputProcessor extends Closeable {
59
public interface InputProcessor extends Closeable {
59
60
(-)a/extexecution/src/org/netbeans/api/extexecution/input/InputProcessors.java (-307 / +19 lines)
Lines 42-71 Link Here
42
42
43
package org.netbeans.api.extexecution.input;
43
package org.netbeans.api.extexecution.input;
44
44
45
import java.io.IOException;
45
import org.netbeans.modules.extexecution.input.BaseInputProcessor;
46
import org.netbeans.modules.extexecution.input.DelegatingInputProcessor;
46
import java.io.Writer;
47
import java.io.Writer;
47
import java.util.ArrayList;
48
import java.util.Arrays;
49
import java.util.List;
50
import java.util.logging.Level;
51
import java.util.logging.Logger;
48
import java.util.logging.Logger;
52
import org.netbeans.api.annotations.common.NonNull;
49
import org.netbeans.api.annotations.common.NonNull;
53
import org.netbeans.api.annotations.common.NullAllowed;
50
import org.netbeans.api.annotations.common.NullAllowed;
54
import org.netbeans.api.extexecution.print.ConvertedLine;
55
import org.netbeans.api.extexecution.print.LineConvertor;
51
import org.netbeans.api.extexecution.print.LineConvertor;
56
import org.netbeans.modules.extexecution.input.LineParsingHelper;
57
import org.openide.util.Parameters;
58
import org.openide.windows.OutputWriter;
52
import org.openide.windows.OutputWriter;
59
53
60
/**
54
/**
61
 * Factory methods for {@link InputProcessor} classes.
55
 * Factory methods for {@link InputProcessor} classes.
62
 *
56
 *
63
 * @author Petr Hejl
57
 * @author Petr Hejl
58
 * @deprecated use {@link org.netbeans.api.extexecution.base.input.InputProcessors}
59
 *             and {@link org.netbeans.api.extexecution.print.InputProcessors}
64
 */
60
 */
65
public final class InputProcessors {
61
public final class InputProcessors {
66
62
67
    private static final Logger LOGGER = Logger.getLogger(InputProcessors.class.getName());
68
69
    private InputProcessors() {
63
    private InputProcessors() {
70
        super();
64
        super();
71
    }
65
    }
Lines 84-90 Link Here
84
     */
78
     */
85
    @NonNull
79
    @NonNull
86
    public static InputProcessor bridge(@NonNull LineProcessor lineProcessor) {
80
    public static InputProcessor bridge(@NonNull LineProcessor lineProcessor) {
87
        return new Bridge(lineProcessor);
81
        return new DelegatingInputProcessor(org.netbeans.api.extexecution.base.input.InputProcessors.bridge(new LineProcessors.BaseLineProcessor(lineProcessor)));
88
    }
82
    }
89
83
90
    /**
84
    /**
Lines 100-106 Link Here
100
     */
94
     */
101
    @NonNull
95
    @NonNull
102
    public static InputProcessor proxy(@NonNull InputProcessor... processors) {
96
    public static InputProcessor proxy(@NonNull InputProcessor... processors) {
103
        return new ProxyInputProcessor(processors);
97
        org.netbeans.api.extexecution.base.input.InputProcessor[] wrapped = new org.netbeans.api.extexecution.base.input.InputProcessor[processors.length];
98
        for (int i = 0; i < processors.length; i++) {
99
            if (processors[i] != null) {
100
                wrapped[i] = new BaseInputProcessor(processors[i]);
101
            } else {
102
                wrapped[i] = null;
103
            }
104
        }
105
        return new DelegatingInputProcessor(org.netbeans.api.extexecution.base.input.InputProcessors.proxy(wrapped));
104
    }
106
    }
105
107
106
    /**
108
    /**
Lines 118-124 Link Here
118
     */
120
     */
119
    @NonNull
121
    @NonNull
120
    public static InputProcessor copying(@NonNull Writer writer) {
122
    public static InputProcessor copying(@NonNull Writer writer) {
121
        return new CopyingInputProcessor(writer);
123
        return new DelegatingInputProcessor(org.netbeans.api.extexecution.base.input.InputProcessors.copying(writer));
122
    }
124
    }
123
125
124
    /**
126
    /**
Lines 139-145 Link Here
139
     */
141
     */
140
    @NonNull
142
    @NonNull
141
    public static InputProcessor printing(@NonNull OutputWriter out, boolean resetEnabled) {
143
    public static InputProcessor printing(@NonNull OutputWriter out, boolean resetEnabled) {
142
        return printing(out, null, resetEnabled);
144
        return new DelegatingInputProcessor(org.netbeans.api.extexecution.print.InputProcessors.printing(out, resetEnabled));
143
    }
145
    }
144
146
145
    /**
147
    /**
Lines 166-172 Link Here
166
     */
168
     */
167
    @NonNull
169
    @NonNull
168
    public static InputProcessor printing(@NonNull OutputWriter out, @NullAllowed LineConvertor convertor, boolean resetEnabled) {
170
    public static InputProcessor printing(@NonNull OutputWriter out, @NullAllowed LineConvertor convertor, boolean resetEnabled) {
169
        return new PrintingInputProcessor(out, convertor, resetEnabled);
171
        return new DelegatingInputProcessor(org.netbeans.api.extexecution.print.InputProcessors.printing(out, convertor, resetEnabled));
170
    }
172
    }
171
173
172
    /**
174
    /**
Lines 186-482 Link Here
186
     */
188
     */
187
    @NonNull
189
    @NonNull
188
    public static InputProcessor ansiStripping(@NonNull InputProcessor delegate) {
190
    public static InputProcessor ansiStripping(@NonNull InputProcessor delegate) {
189
        return new AnsiStrippingInputProcessor(delegate);
191
        return new DelegatingInputProcessor(org.netbeans.api.extexecution.base.input.InputProcessors.ansiStripping(new BaseInputProcessor(delegate)));
190
    }
192
    }
191
193
    
192
    private static class Bridge implements InputProcessor {
193
194
        private final LineProcessor lineProcessor;
195
196
        private final LineParsingHelper helper = new LineParsingHelper();
197
198
        private boolean closed;
199
200
        public Bridge(LineProcessor lineProcessor) {
201
            Parameters.notNull("lineProcessor", lineProcessor);
202
203
            this.lineProcessor = lineProcessor;
204
        }
205
206
        public final void processInput(char[] chars) {
207
            if (closed) {
208
                throw new IllegalStateException("Already closed processor");
209
            }
210
211
            String[] lines = helper.parse(chars);
212
            for (String line : lines) {
213
                lineProcessor.processLine(line);
214
            }
215
        }
216
217
        public final void reset() {
218
            if (closed) {
219
                throw new IllegalStateException("Already closed processor");
220
            }
221
222
            flush();
223
            lineProcessor.reset();
224
        }
225
226
        public final void close() {
227
            closed = true;
228
229
            flush();
230
            lineProcessor.close();
231
        }
232
233
        private void flush() {
234
            String line = helper.getTrailingLine(true);
235
            if (line != null) {
236
                lineProcessor.processLine(line);
237
            }
238
        }
239
    }
240
241
    private static class ProxyInputProcessor implements InputProcessor {
242
243
        private final List<InputProcessor> processors = new ArrayList<InputProcessor>();
244
245
        private boolean closed;
246
247
        public ProxyInputProcessor(InputProcessor... processors) {
248
            for (InputProcessor processor : processors) {
249
                if (processor != null) {
250
                    this.processors.add(processor);
251
                }
252
            }
253
        }
254
255
        public void processInput(char[] chars) throws IOException {
256
            if (closed) {
257
                throw new IllegalStateException("Already closed processor");
258
            }
259
260
            for (InputProcessor processor : processors) {
261
                processor.processInput(chars);
262
            }
263
        }
264
265
        public void reset() throws IOException {
266
            if (closed) {
267
                throw new IllegalStateException("Already closed processor");
268
            }
269
270
            for (InputProcessor processor : processors) {
271
                processor.reset();
272
            }
273
        }
274
275
        public void close() throws IOException {
276
            closed = true;
277
278
            for (InputProcessor processor : processors) {
279
                processor.close();
280
            }
281
        }
282
    }
283
284
    private static class PrintingInputProcessor implements InputProcessor {
285
286
        private final OutputWriter out;
287
288
        private final LineConvertor convertor;
289
290
        private final boolean resetEnabled;
291
292
        private final LineParsingHelper helper = new LineParsingHelper();
293
294
        private boolean closed;
295
296
        public PrintingInputProcessor(OutputWriter out, LineConvertor convertor,
297
                boolean resetEnabled) {
298
299
            assert out != null;
300
301
            this.out = out;
302
            this.convertor = convertor;
303
            this.resetEnabled = resetEnabled;
304
        }
305
306
        public void processInput(char[] chars) {
307
            assert chars != null;
308
309
            if (closed) {
310
                throw new IllegalStateException("Already closed processor");
311
            }
312
313
// TODO this does not color standard error lines :(
314
//            if (convertor == null) {
315
//                out.print(String.valueOf(chars));
316
//                return;
317
//            }
318
319
            String[] lines = helper.parse(chars);
320
            for (String line : lines) {
321
                LOGGER.log(Level.FINEST, "{0}\\n", line);
322
323
                convert(line);
324
                out.flush();
325
            }
326
327
            String line = helper.getTrailingLine(true);
328
            if (line != null) {
329
                LOGGER.log(Level.FINEST, line);
330
331
                out.print(line);
332
                out.flush();
333
            }
334
        }
335
336
        public void reset() throws IOException {
337
            if (closed) {
338
                throw new IllegalStateException("Already closed processor");
339
            }
340
341
            if (!resetEnabled) {
342
                return;
343
            }
344
345
            out.reset();
346
        }
347
348
        public void close() throws IOException {
349
            closed = true;
350
351
            out.close();
352
        }
353
354
        private void convert(String line) {
355
            if (convertor == null) {
356
                out.println(line);
357
                return;
358
            }
359
360
            List<ConvertedLine> convertedLines = convertor.convert(line);
361
            if (convertedLines == null) {
362
                out.println(line);
363
                return;
364
            }
365
366
            for (ConvertedLine converted : convertedLines) {
367
                if (converted.getListener() == null) {
368
                    out.println(converted.getText());
369
                } else {
370
                    try {
371
                        out.println(converted.getText(), converted.getListener());
372
                    } catch (IOException ex) {
373
                        LOGGER.log(Level.INFO, null, ex);
374
                        out.println(converted.getText());
375
                    }
376
                }
377
            }
378
        }
379
    }
380
381
    private static class CopyingInputProcessor implements InputProcessor {
382
383
        private final Writer writer;
384
385
        private boolean closed;
386
387
        public CopyingInputProcessor(Writer writer) {
388
            this.writer = writer;
389
        }
390
391
        public void processInput(char[] chars) throws IOException {
392
            if (closed) {
393
                throw new IllegalStateException("Already closed processor");
394
            }
395
396
            LOGGER.log(Level.FINEST, Arrays.toString(chars));
397
            writer.write(chars);
398
            writer.flush();
399
        }
400
401
        public void reset() {
402
            // noop
403
        }
404
405
        public void close() throws IOException {
406
            closed = true;
407
408
            writer.close();
409
        }
410
    }
411
412
    private static class AnsiStrippingInputProcessor implements InputProcessor {
413
414
        private final InputProcessor delegate;
415
416
        private boolean closed;
417
418
        public AnsiStrippingInputProcessor(InputProcessor delegate) {
419
            this.delegate = delegate;
420
        }
421
422
        public void processInput(char[] chars) throws IOException {
423
            if (closed) {
424
                throw new IllegalStateException("Already closed processor");
425
            }
426
427
            // FIXME optimize me
428
            String sequence = new String(chars);
429
            if (containsAnsiColors(sequence)) {
430
                sequence = stripAnsiColors(sequence);
431
            }
432
            delegate.processInput(sequence.toCharArray());
433
        }
434
435
        public void reset() throws IOException {
436
            if (closed) {
437
                throw new IllegalStateException("Already closed processor");
438
            }
439
440
            delegate.reset();
441
        }
442
443
        public void close() throws IOException {
444
            closed = true;
445
446
            delegate.close();
447
        }
448
449
        private static boolean containsAnsiColors(String sequence) {
450
            // RSpec will color output with ANSI color sequence terminal escapes
451
            return sequence.indexOf("\033[") != -1; // NOI18N
452
        }
453
454
        private static String stripAnsiColors(String sequence) {
455
            StringBuilder sb = new StringBuilder(sequence.length());
456
            int index = 0;
457
            int max = sequence.length();
458
            while (index < max) {
459
                int nextEscape = sequence.indexOf("\033[", index); // NOI18N
460
                if (nextEscape == -1) {
461
                    nextEscape = sequence.length();
462
                }
463
464
                for (int n = (nextEscape == -1) ? max : nextEscape; index < n; index++) {
465
                    sb.append(sequence.charAt(index));
466
                }
467
468
                if (nextEscape != -1) {
469
                    for (; index < max; index++) {
470
                        char c = sequence.charAt(index);
471
                        if (c == 'm') {
472
                            index++;
473
                            break;
474
                        }
475
                    }
476
                }
477
            }
478
479
            return sb.toString();
480
        }
481
    }
482
}
194
}
(-)a/extexecution/src/org/netbeans/api/extexecution/input/InputReader.java (+2 lines)
Lines 54-59 Link Here
54
 * interface has to be responsive to interruption.
54
 * interface has to be responsive to interruption.
55
 *
55
 *
56
 * @author Petr Hejl
56
 * @author Petr Hejl
57
 * @deprecated use {@link org.netbeans.api.extexecution.base.input.InputReader}
57
 */
58
 */
58
public interface InputReader extends Closeable {
59
public interface InputReader extends Closeable {
59
60
Lines 72-77 Link Here
72
    /**
73
    /**
73
     * Closes the reader releasing the resources held by it.
74
     * Closes the reader releasing the resources held by it.
74
     */
75
     */
76
    @Override
75
    void close() throws IOException;
77
    void close() throws IOException;
76
78
77
}
79
}
(-)a/extexecution/src/org/netbeans/api/extexecution/input/InputReaderTask.java (-113 / +35 lines)
Lines 44-52 Link Here
44
44
45
package org.netbeans.api.extexecution.input;
45
package org.netbeans.api.extexecution.input;
46
46
47
import org.netbeans.modules.extexecution.input.BaseInputProcessor;
48
import org.netbeans.modules.extexecution.input.DelegatingInputProcessor;
47
import java.io.IOException;
49
import java.io.IOException;
48
import java.util.logging.Level;
49
import java.util.logging.Logger;
50
import org.netbeans.api.annotations.common.NonNull;
50
import org.netbeans.api.annotations.common.NonNull;
51
import org.netbeans.api.annotations.common.NullAllowed;
51
import org.netbeans.api.annotations.common.NullAllowed;
52
import org.openide.util.Cancellable;
52
import org.openide.util.Cancellable;
Lines 97-127 Link Here
97
 * </div>
97
 * </div>
98
 *
98
 *
99
 * @author Petr Hejl
99
 * @author Petr Hejl
100
 * @deprecated use {@link org.netbeans.api.extexecution.base.input.InputReaderTask}
100
 */
101
 */
101
public final class InputReaderTask implements Runnable, Cancellable {
102
public final class InputReaderTask implements Runnable, Cancellable {
102
103
103
    private static final Logger LOGGER = Logger.getLogger(InputReaderTask.class.getName());
104
    private final org.netbeans.api.extexecution.base.input.InputReaderTask delegate;
104
105
105
    private static final int MIN_DELAY = 50;
106
    private InputReaderTask(org.netbeans.api.extexecution.base.input.InputReaderTask delegate) {
106
107
        this.delegate = delegate;
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
    }
108
    }
126
109
127
    /**
110
    /**
Lines 138-144 Link Here
138
    public static InputReaderTask newTask(@NonNull InputReader reader, @NullAllowed InputProcessor processor) {
121
    public static InputReaderTask newTask(@NonNull InputReader reader, @NullAllowed InputProcessor processor) {
139
        Parameters.notNull("reader", reader);
122
        Parameters.notNull("reader", reader);
140
123
141
        return new InputReaderTask(reader, processor, false);
124
        return new InputReaderTask(org.netbeans.api.extexecution.base.input.InputReaderTask.newTask(
125
                new BaseInputReader(reader), processor == null ? null : new BaseInputProcessor(processor)));
142
    }
126
    }
143
127
144
    /**
128
    /**
Lines 156-162 Link Here
156
    public static InputReaderTask newDrainingTask(@NonNull InputReader reader, @NullAllowed InputProcessor processor) {
140
    public static InputReaderTask newDrainingTask(@NonNull InputReader reader, @NullAllowed InputProcessor processor) {
157
        Parameters.notNull("reader", reader);
141
        Parameters.notNull("reader", reader);
158
142
159
        return new InputReaderTask(reader, processor, true);
143
        return new InputReaderTask(org.netbeans.api.extexecution.base.input.InputReaderTask.newDrainingTask(
144
                new BaseInputReader(reader), processor == null ? null : new BaseInputProcessor(processor)));
160
    }
145
    }
161
146
162
    /**
147
    /**
Lines 166-254 Link Here
166
     * It is not allowed to invoke run multiple times.
151
     * It is not allowed to invoke run multiple times.
167
     */
152
     */
168
    public void run() {
153
    public void run() {
169
        synchronized (this) {
154
        delegate.run();
170
            if (running) {
171
                throw new IllegalStateException("Already running task");
172
            }
173
            running = true;
174
        }
175
176
        boolean interrupted = false;
177
        try {
178
            long delay = MIN_DELAY;
179
            int emptyReads = 0;
180
181
            while (true) {
182
                synchronized (this) {
183
                    if (Thread.currentThread().isInterrupted() || cancelled) {
184
                        interrupted = Thread.interrupted();
185
                        break;
186
                    }
187
                }
188
189
                int count = inputReader.readInput(inputProcessor);
190
191
                // compute the delay based on how often we really get the data
192
                if (count > 0) {
193
                    delay = MIN_DELAY;
194
                    emptyReads = 0;
195
                } else {
196
                    // increase the delay only slowly - once for
197
                    // MAX_DELAY / DELAY_INCREMENT unsuccesfull read attempts
198
                    if (emptyReads > (MAX_DELAY / DELAY_INCREMENT)) {
199
                        emptyReads = 0;
200
                        delay = Math.min(delay + DELAY_INCREMENT, MAX_DELAY);
201
                    } else {
202
                        emptyReads++;
203
                    }
204
                }
205
206
                if (LOGGER.isLoggable(Level.FINEST)) {
207
                    LOGGER.log(Level.FINEST, "Task {0} sleeping for {1} ms",
208
                            new Object[] {Thread.currentThread().getName(), delay});
209
                }
210
                try {
211
                    // give the producer some time to write the output
212
                    Thread.sleep(delay);
213
                } catch (InterruptedException e) {
214
                    interrupted = true;
215
                    break;
216
                }
217
            }
218
219
            synchronized (this) {
220
                if (Thread.currentThread().isInterrupted() || cancelled) {
221
                    interrupted = Thread.interrupted();
222
                }
223
            }
224
        } catch (Exception ex) {
225
            LOGGER.log(Level.FINE, null, ex);
226
        } finally {
227
            // drain the rest
228
            if (draining) {
229
                try {
230
                    while (inputReader.readInput(inputProcessor) > 0) {
231
                        LOGGER.log(Level.FINE, "Draining the rest of the reader");
232
                    }
233
                } catch (IOException ex) {
234
                    LOGGER.log(Level.FINE, null, ex);
235
                }
236
            }
237
238
            // perform cleanup
239
            try {
240
                if (inputProcessor != null) {
241
                    inputProcessor.close();
242
                }
243
                inputReader.close();
244
            } catch (IOException ex) {
245
                LOGGER.log(Level.INFO, null, ex);
246
            } finally {
247
                if (interrupted) {
248
                    Thread.currentThread().interrupt();
249
                }
250
            }
251
        }
252
    }
155
    }
253
156
254
    /**
157
    /**
Lines 258-269 Link Here
258
     * @return <code>true</code> if the task was successfully cancelled
161
     * @return <code>true</code> if the task was successfully cancelled
259
     */
162
     */
260
    public boolean cancel() {
163
    public boolean cancel() {
261
        synchronized (this) {
164
        return delegate.cancel();
262
            if (cancelled) {
165
    }
263
                return false;
166
    
167
    private static class BaseInputReader implements org.netbeans.api.extexecution.base.input.InputReader {
168
        
169
        private final InputReader delegate;
170
171
        public BaseInputReader(InputReader delegate) {
172
            this.delegate = delegate;
173
        }
174
175
        public int readInput(org.netbeans.api.extexecution.base.input.InputProcessor processor) throws IOException {
176
            InputProcessor p = null;
177
            if (processor != null) {
178
                if (processor instanceof BaseInputProcessor) {
179
                    p = ((BaseInputProcessor) processor).getDelegate();
180
                } else {
181
                    p = new DelegatingInputProcessor(processor);
182
                }
264
            }
183
            }
265
            cancelled = true;
184
            return delegate.readInput(p);
266
            return true;
185
        }
186
187
        public void close() throws IOException {
188
            delegate.close();
267
        }
189
        }
268
    }
190
    }
269
}
191
}
(-)a/extexecution/src/org/netbeans/api/extexecution/input/InputReaders.java (-5 / +38 lines)
Lines 42-62 Link Here
42
42
43
package org.netbeans.api.extexecution.input;
43
package org.netbeans.api.extexecution.input;
44
44
45
import org.netbeans.modules.extexecution.input.BaseInputProcessor;
45
import java.io.File;
46
import java.io.File;
47
import java.io.IOException;
46
import java.io.InputStream;
48
import java.io.InputStream;
47
import java.io.InputStreamReader;
49
import java.io.InputStreamReader;
48
import java.io.Reader;
50
import java.io.Reader;
49
import java.nio.charset.Charset;
51
import java.nio.charset.Charset;
50
import org.netbeans.api.annotations.common.CheckForNull;
52
import org.netbeans.api.annotations.common.CheckForNull;
51
import org.netbeans.api.annotations.common.NonNull;
53
import org.netbeans.api.annotations.common.NonNull;
52
import org.netbeans.modules.extexecution.input.FileInputReader;
54
import org.netbeans.api.extexecution.base.input.InputProcessor;
53
import org.netbeans.modules.extexecution.input.DefaultInputReader;
54
import org.openide.util.Parameters;
55
import org.openide.util.Parameters;
55
56
56
/**
57
/**
57
 * Factory methods for {@link InputReader} classes.
58
 * Factory methods for {@link InputReader} classes.
58
 *
59
 *
59
 * @author Petr Hejl
60
 * @author Petr Hejl
61
 * @deprecated use {@link org.netbeans.api.extexecution.base.input.InputReaders}
60
 */
62
 */
61
public final class InputReaders {
63
public final class InputReaders {
62
64
Lines 82-88 Link Here
82
     */
84
     */
83
    @NonNull
85
    @NonNull
84
    public static InputReader forReader(@NonNull Reader reader) {
86
    public static InputReader forReader(@NonNull Reader reader) {
85
        return new DefaultInputReader(reader, true);
87
        final org.netbeans.api.extexecution.base.input.InputReader delegate = org.netbeans.api.extexecution.base.input.InputReaders.forReader(reader);
88
        return new InputReader() {
89
90
            @Override
91
            public int readInput(org.netbeans.api.extexecution.input.InputProcessor processor) throws IOException {
92
                return delegate.readInput(processor == null ? null : new BaseInputProcessor(processor));
93
            }
94
95
            @Override
96
            public void close() throws IOException {
97
                delegate.close();
98
            }
99
        };
86
    }
100
    }
87
101
88
    /**
102
    /**
Lines 157-166 Link Here
157
     * @return input reader for the given provider
171
     * @return input reader for the given provider
158
     */
172
     */
159
    @NonNull
173
    @NonNull
160
    public static InputReader forFileInputProvider(@NonNull FileInput.Provider fileProvider) {
174
    public static InputReader forFileInputProvider(@NonNull final FileInput.Provider fileProvider) {
161
        Parameters.notNull("fileProvider", fileProvider);
175
        Parameters.notNull("fileProvider", fileProvider);
162
176
163
        return new FileInputReader(fileProvider);
177
        final org.netbeans.api.extexecution.base.input.InputReader delegate = org.netbeans.api.extexecution.base.input.InputReaders.forFileInputProvider(new org.netbeans.api.extexecution.base.input.InputReaders.FileInput.Provider() {
178
179
            @Override
180
            public org.netbeans.api.extexecution.base.input.InputReaders.FileInput getFileInput() {
181
                FileInput input = fileProvider.getFileInput();
182
                return new org.netbeans.api.extexecution.base.input.InputReaders.FileInput(input.getFile(), input.getCharset());
183
            }
184
        });
185
        return new InputReader() {
186
187
            @Override
188
            public int readInput(org.netbeans.api.extexecution.input.InputProcessor processor) throws IOException {
189
                return delegate.readInput(processor == null ? null : new BaseInputProcessor(processor));
190
            }
191
192
            @Override
193
            public void close() throws IOException {
194
                delegate.close();
195
            }
196
        };
164
    }
197
    }
165
198
166
    /**
199
    /**
(-)a/extexecution/src/org/netbeans/api/extexecution/input/LineProcessor.java (+1 lines)
Lines 57-62 Link Here
57
 * @author Petr Hejl
57
 * @author Petr Hejl
58
 * @see InputProcessors#bridge(LineProcessor)
58
 * @see InputProcessors#bridge(LineProcessor)
59
 * @see InputReader
59
 * @see InputReader
60
 * @deprecated use {@link org.netbeans.api.extexecution.base.input.LineProcessor}
60
 */
61
 */
61
public interface LineProcessor extends Closeable {
62
public interface LineProcessor extends Closeable {
62
63
(-)a/extexecution/src/org/netbeans/api/extexecution/input/LineProcessors.java (-149 / +38 lines)
Lines 42-57 Link Here
42
42
43
package org.netbeans.api.extexecution.input;
43
package org.netbeans.api.extexecution.input;
44
44
45
import java.io.IOException;
46
import java.util.ArrayList;
47
import java.util.List;
48
import java.util.concurrent.CountDownLatch;
45
import java.util.concurrent.CountDownLatch;
49
import java.util.logging.Level;
50
import java.util.logging.Logger;
46
import java.util.logging.Logger;
51
import java.util.regex.Pattern;
47
import java.util.regex.Pattern;
52
import org.netbeans.api.annotations.common.NonNull;
48
import org.netbeans.api.annotations.common.NonNull;
53
import org.netbeans.api.annotations.common.NullAllowed;
49
import org.netbeans.api.annotations.common.NullAllowed;
54
import org.netbeans.api.extexecution.print.ConvertedLine;
55
import org.netbeans.api.extexecution.print.LineConvertor;
50
import org.netbeans.api.extexecution.print.LineConvertor;
56
import org.openide.windows.OutputWriter;
51
import org.openide.windows.OutputWriter;
57
52
Lines 63-73 Link Here
63
 *
58
 *
64
 * @author Petr Hejl
59
 * @author Petr Hejl
65
 * @see InputProcessors#bridge(org.netbeans.api.extexecution.input.LineProcessor)
60
 * @see InputProcessors#bridge(org.netbeans.api.extexecution.input.LineProcessor)
61
 * @deprecated use {@link org.netbeans.api.extexecution.base.input.LineProcessors}
62
 *             and {@link org.netbeans.api.extexecution.print.LineProcessors}
66
 */
63
 */
67
public final class LineProcessors {
64
public final class LineProcessors {
68
65
69
    private static final Logger LOGGER = Logger.getLogger(LineProcessors.class.getName());
70
71
    private LineProcessors() {
66
    private LineProcessors() {
72
        super();
67
        super();
73
    }
68
    }
Lines 85-91 Link Here
85
     */
80
     */
86
    @NonNull
81
    @NonNull
87
    public static LineProcessor proxy(@NonNull LineProcessor... processors) {
82
    public static LineProcessor proxy(@NonNull LineProcessor... processors) {
88
        return new ProxyLineProcessor(processors);
83
        org.netbeans.api.extexecution.base.input.LineProcessor[] wrapped = new org.netbeans.api.extexecution.base.input.LineProcessor[processors.length];
84
        for (int i = 0; i < processors.length; i++) {
85
            if (processors[i] != null) {
86
                wrapped[i] = new BaseLineProcessor(processors[i]);
87
            } else {
88
                wrapped[i] = null;
89
            }
90
        }
91
        return new DelegatingLineProcessor(org.netbeans.api.extexecution.base.input.LineProcessors.proxy(wrapped));
89
    }
92
    }
90
93
91
    /**
94
    /**
Lines 106-112 Link Here
106
     */
109
     */
107
    @NonNull
110
    @NonNull
108
    public static LineProcessor printing(@NonNull OutputWriter out, boolean resetEnabled) {
111
    public static LineProcessor printing(@NonNull OutputWriter out, boolean resetEnabled) {
109
        return printing(out, null, resetEnabled);
112
        return new DelegatingLineProcessor(org.netbeans.api.extexecution.print.LineProcessors.printing(out, resetEnabled));
110
    }
113
    }
111
114
112
    /**
115
    /**
Lines 132-138 Link Here
132
     */
135
     */
133
    @NonNull
136
    @NonNull
134
    public static LineProcessor printing(@NonNull OutputWriter out, @NullAllowed LineConvertor convertor, boolean resetEnabled) {
137
    public static LineProcessor printing(@NonNull OutputWriter out, @NullAllowed LineConvertor convertor, boolean resetEnabled) {
135
        return new PrintingLineProcessor(out, convertor, resetEnabled);
138
        return new DelegatingLineProcessor(org.netbeans.api.extexecution.print.LineProcessors.printing(out, convertor, resetEnabled));
136
    }
139
    }
137
140
138
    /**
141
    /**
Lines 151-318 Link Here
151
     */
154
     */
152
    @NonNull
155
    @NonNull
153
    public static LineProcessor patternWaiting(@NonNull Pattern pattern, @NonNull CountDownLatch latch) {
156
    public static LineProcessor patternWaiting(@NonNull Pattern pattern, @NonNull CountDownLatch latch) {
154
        return new WaitingLineProcessor(pattern, latch);
157
        return new DelegatingLineProcessor(org.netbeans.api.extexecution.base.input.LineProcessors.patternWaiting(pattern, latch));
155
    }
158
    }
159
    
160
    static class DelegatingLineProcessor implements LineProcessor {
161
        
162
        private final org.netbeans.api.extexecution.base.input.LineProcessor delegate;
156
163
157
    private static class ProxyLineProcessor implements LineProcessor {
164
        public DelegatingLineProcessor(org.netbeans.api.extexecution.base.input.LineProcessor delegate) {
158
165
            this.delegate = delegate;
159
        private final List<LineProcessor> processors = new ArrayList<LineProcessor>();
160
161
        private boolean closed;
162
163
        public ProxyLineProcessor(LineProcessor... processors) {
164
            for (LineProcessor processor : processors) {
165
                if (processor != null) {
166
                    this.processors.add(processor);
167
                }
168
            }
169
        }
166
        }
170
167
168
        @Override
171
        public void processLine(String line) {
169
        public void processLine(String line) {
172
            if (closed) {
170
            delegate.processLine(line);
173
                throw new IllegalStateException("Already closed processor");
174
            }
175
176
            for (LineProcessor processor : processors) {
177
                processor.processLine(line);
178
            }
179
        }
171
        }
180
172
173
        @Override
181
        public void reset() {
174
        public void reset() {
182
            if (closed) {
175
            delegate.reset();
183
                throw new IllegalStateException("Already closed processor");
184
            }
185
186
            for (LineProcessor processor : processors) {
187
                processor.reset();
188
            }
189
        }
176
        }
190
177
178
        @Override
191
        public void close() {
179
        public void close() {
192
            closed = true;
180
            delegate.close();
193
194
            for (LineProcessor processor : processors) {
195
                processor.close();
196
            }
197
        }
181
        }
198
    }
182
    }
183
    
184
    static class BaseLineProcessor implements org.netbeans.api.extexecution.base.input.LineProcessor {
185
        
186
        private final LineProcessor delegate;
199
187
200
    private static class PrintingLineProcessor implements LineProcessor {
188
        public BaseLineProcessor(LineProcessor delegate) {
201
189
            this.delegate = delegate;
202
        private final OutputWriter out;
203
204
        private final LineConvertor convertor;
205
206
        private final boolean resetEnabled;
207
208
        private boolean closed;
209
210
        public PrintingLineProcessor(OutputWriter out, LineConvertor convertor, boolean resetEnabled) {
211
            assert out != null;
212
213
            this.out = out;
214
            this.convertor = convertor;
215
            this.resetEnabled = resetEnabled;
216
        }
190
        }
217
191
192
        @Override
218
        public void processLine(String line) {
193
        public void processLine(String line) {
219
            assert line != null;
194
            delegate.processLine(line);
220
221
            if (closed) {
222
                throw new IllegalStateException("Already closed processor");
223
            }
224
225
            LOGGER.log(Level.FINEST, line);
226
227
            if (convertor != null) {
228
                List<ConvertedLine> convertedLines = convertor.convert(line);
229
                if (convertedLines != null) {
230
                    for (ConvertedLine converted : convertedLines) {
231
                        if (converted.getListener() == null) {
232
                            out.println(converted.getText());
233
                        } else {
234
                            try {
235
                                out.println(converted.getText(), converted.getListener());
236
                            } catch (IOException ex) {
237
                                LOGGER.log(Level.INFO, null, ex);
238
                                out.println(converted.getText());
239
                            }
240
                        }
241
                    }
242
                } else {
243
                    out.println(line);
244
                }
245
            } else {
246
                out.println(line);
247
            }
248
            out.flush();
249
        }
195
        }
250
196
197
        @Override
251
        public void reset() {
198
        public void reset() {
252
            if (closed) {
199
            delegate.reset();
253
                throw new IllegalStateException("Already closed processor");
254
            }
255
256
            if (!resetEnabled) {
257
                return;
258
            }
259
260
            try {
261
                out.reset();
262
            } catch (IOException ex) {
263
                LOGGER.log(Level.INFO, null, ex);
264
            }
265
        }
200
        }
266
201
202
        @Override
267
        public void close() {
203
        public void close() {
268
            closed = true;
204
            delegate.close();
269
270
            out.flush();
271
            out.close();
272
        }
273
    }
274
275
    private static class WaitingLineProcessor implements LineProcessor {
276
277
        private final Pattern pattern;
278
279
        private final CountDownLatch latch;
280
281
        /**<i>GuardedBy("this")</i>*/
282
        private boolean processed;
283
284
        /**<i>GuardedBy("this")</i>*/
285
        private boolean closed;
286
287
        public WaitingLineProcessor(Pattern pattern, CountDownLatch latch) {
288
            assert pattern != null;
289
            assert latch != null;
290
291
            this.pattern = pattern;
292
            this.latch = latch;
293
        }
294
295
        public synchronized void processLine(String line) {
296
            assert line != null;
297
298
            if (closed) {
299
                throw new IllegalStateException("Already closed processor");
300
            }
301
302
            if (!processed && pattern.matcher(line).matches()) {
303
                latch.countDown();
304
                processed = true;
305
            }
306
        }
307
308
        public synchronized void reset() {
309
            if (closed) {
310
                throw new IllegalStateException("Already closed processor");
311
            }
312
        }
313
314
        public synchronized void close() {
315
            closed = true;
316
        }
205
        }
317
    }
206
    }
318
}
207
}
(-)a/extexecution/src/org/netbeans/api/extexecution/input/package-info.java (+1 lines)
Lines 48-53 Link Here
48
 * is character or line based.
48
 * is character or line based.
49
 *
49
 *
50
 * @see org.netbeans.api.extexecution.input.InputReaderTask
50
 * @see org.netbeans.api.extexecution.input.InputReaderTask
51
 * @deprecated use {@link org.netbeans.api.extexecution.base.input}
51
 */
52
 */
52
package org.netbeans.api.extexecution.input;
53
package org.netbeans.api.extexecution.input;
53
54
(-)a/extexecution/src/org/netbeans/api/extexecution/print/InputProcessors.java (+214 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.print;
44
45
import java.io.IOException;
46
import java.util.List;
47
import java.util.logging.Level;
48
import java.util.logging.Logger;
49
import org.netbeans.api.annotations.common.NonNull;
50
import org.netbeans.api.annotations.common.NullAllowed;
51
import org.netbeans.api.extexecution.base.input.InputProcessor;
52
import org.netbeans.modules.extexecution.input.LineParsingHelper;
53
import org.openide.windows.OutputWriter;
54
55
/**
56
 * Factory methods for {@link InputProcessor} classes.
57
 *
58
 * @author Petr Hejl
59
 * @since 1.43
60
 */
61
public final class InputProcessors {
62
63
    private static final Logger LOGGER = Logger.getLogger(InputProcessors.class.getName());
64
65
    private InputProcessors() {
66
        super();
67
    }
68
69
    /**
70
     * Returns the processor printing all characters passed for processing to
71
     * the given output writer.
72
     * <p>
73
     * Reset action on the returned processor resets the writer if it is enabled
74
     * by passing <code>true</code> as <code>resetEnabled</code>. Processor
75
     * closes the output writer on {@link InputProcessor#close()}.
76
     * <p>
77
     * Returned processor is <i> not thread safe</i>.
78
     *
79
     * @param out where to print received characters
80
     * @param resetEnabled determines whether the reset operation will work
81
     *             (will reset the writer if so)
82
     * @return the processor printing all characters passed for processing to
83
     *             the given output writer
84
     */
85
    @NonNull
86
    public static InputProcessor printing(@NonNull OutputWriter out, boolean resetEnabled) {
87
        return printing(out, null, resetEnabled);
88
    }
89
90
    /**
91
     * Returns the processor converting <i>whole</i> lines with convertor and
92
     * printing the result including unterminated tail (if present) to the
93
     * given output writer. If the convertor does not handle line passed to it
94
     * (returning <code>null</code>) raw lines are printed.
95
     * <p>
96
     * Reset action on the returned processor resets the writer if it is enabled
97
     * by passing <code>true</code> as <code>resetEnabled</code>. Processor
98
     * closes the output writer on {@link InputProcessor#close()}.
99
     * <p>
100
     * Returned processor is <i> not thread safe</i>.
101
     *
102
     * @param out where to print converted lines and characters
103
     * @param convertor convertor converting the <i>whole</i> lines
104
     *             before printing, may be <code>null</code>
105
     * @param resetEnabled determines whether the reset operation will work
106
     *             (will reset the writer if so)
107
     * @return the processor converting the <i>whole</i> lines with convertor and
108
     *             printing the result including unterminated tail (if present)
109
     *             to the given output writer
110
     * @see LineConvertor
111
     */
112
    @NonNull
113
    public static InputProcessor printing(@NonNull OutputWriter out, @NullAllowed LineConvertor convertor, boolean resetEnabled) {
114
        return new PrintingInputProcessor(out, convertor, resetEnabled);
115
    }
116
117
    private static class PrintingInputProcessor implements InputProcessor {
118
119
        private final OutputWriter out;
120
121
        private final LineConvertor convertor;
122
123
        private final boolean resetEnabled;
124
125
        private final LineParsingHelper helper = new LineParsingHelper();
126
127
        private boolean closed;
128
129
        public PrintingInputProcessor(OutputWriter out, LineConvertor convertor,
130
                boolean resetEnabled) {
131
132
            assert out != null;
133
134
            this.out = out;
135
            this.convertor = convertor;
136
            this.resetEnabled = resetEnabled;
137
        }
138
139
        public void processInput(char[] chars) {
140
            assert chars != null;
141
142
            if (closed) {
143
                throw new IllegalStateException("Already closed processor");
144
            }
145
146
// TODO this does not color standard error lines :(
147
//            if (convertor == null) {
148
//                out.print(String.valueOf(chars));
149
//                return;
150
//            }
151
152
            String[] lines = helper.parse(chars);
153
            for (String line : lines) {
154
                LOGGER.log(Level.FINEST, "{0}\\n", line);
155
156
                convert(line);
157
                out.flush();
158
            }
159
160
            String line = helper.getTrailingLine(true);
161
            if (line != null) {
162
                LOGGER.log(Level.FINEST, line);
163
164
                out.print(line);
165
                out.flush();
166
            }
167
        }
168
169
        public void reset() throws IOException {
170
            if (closed) {
171
                throw new IllegalStateException("Already closed processor");
172
            }
173
174
            if (!resetEnabled) {
175
                return;
176
            }
177
178
            out.reset();
179
        }
180
181
        public void close() throws IOException {
182
            closed = true;
183
184
            out.close();
185
        }
186
187
        private void convert(String line) {
188
            if (convertor == null) {
189
                out.println(line);
190
                return;
191
            }
192
193
            List<ConvertedLine> convertedLines = convertor.convert(line);
194
            if (convertedLines == null) {
195
                out.println(line);
196
                return;
197
            }
198
199
            for (ConvertedLine converted : convertedLines) {
200
                if (converted.getListener() == null) {
201
                    out.println(converted.getText());
202
                } else {
203
                    try {
204
                        out.println(converted.getText(), converted.getListener());
205
                    } catch (IOException ex) {
206
                        LOGGER.log(Level.INFO, null, ex);
207
                        out.println(converted.getText());
208
                    }
209
                }
210
            }
211
        }
212
    }
213
    
214
}
(-)a/extexecution/src/org/netbeans/api/extexecution/print/LineProcessors.java (+194 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.print;
44
45
import java.io.IOException;
46
import java.util.List;
47
import java.util.logging.Level;
48
import java.util.logging.Logger;
49
import org.netbeans.api.annotations.common.NonNull;
50
import org.netbeans.api.annotations.common.NullAllowed;
51
import org.netbeans.api.extexecution.base.input.InputProcessor;
52
import org.netbeans.api.extexecution.base.input.LineProcessor;
53
import org.openide.windows.OutputWriter;
54
55
/**
56
 * Factory methods for {@link LineProcessor} classes.
57
 * <p>
58
 * Note that main difference between {@link InputProcessor} and
59
 * {@link LineProcessor} is that LineProcessor always process whole lines.
60
 *
61
 * @author Petr Hejl
62
 * @see org.netbeans.api.extexecution.base.input.InputProcessors#bridge(org.netbeans.api.extexecution.base.input.LineProcessor)
63
 * @since 1.43
64
 */
65
public final class LineProcessors {
66
67
    private static final Logger LOGGER = Logger.getLogger(LineProcessors.class.getName());
68
69
    private LineProcessors() {
70
        super();
71
    }
72
73
    /**
74
     * Returns the processor printing all lines passed for processing to
75
     * the given output writer.
76
     * <p>
77
     * Reset action on the returned processor resets the writer if it is enabled
78
     * by passing <code>true</code> as <code>resetEnabled</code>. Processor
79
     * closes the output writer on {@link InputProcessor#close()}.
80
     * <p>
81
     * Returned processor is <i> not thread safe</i>.
82
     *
83
     * @param out where to print received lines
84
     * @param resetEnabled determines whether the reset operation will work
85
     *             (will reset the writer if so)
86
     * @return the processor printing all lines passed for processing to
87
     *             the given output writer
88
     */
89
    @NonNull
90
    public static LineProcessor printing(@NonNull OutputWriter out, boolean resetEnabled) {
91
        return printing(out, null, resetEnabled);
92
    }
93
94
    /**
95
     * Returns the processor converting lines with convertor and
96
     * printing the result to the given output writer. If the covertor does
97
     * not handle line passed to it (returning <code>null</code>) raw
98
     * lines are printed.
99
     * <p>
100
     * Reset action on the returned processor resets the writer if it is enabled
101
     * by passing <code>true</code> as <code>resetEnabled</code>. Processor
102
     * closes the output writer on {@link InputProcessor#close()}.
103
     * <p>
104
     * Returned processor is <i> not thread safe</i>.
105
     *
106
     * @param out where to print converted lines and characters
107
     * @param convertor convertor converting the lines before printing,
108
     *             may be <code>null</code>
109
     * @param resetEnabled determines whether the reset operation will work
110
     *             (will reset the writer if so)
111
     * @return the processor converting the lines with convertor and
112
     *             printing the result to the given output writer
113
     * @see LineConvertor
114
     */
115
    @NonNull
116
    public static LineProcessor printing(@NonNull OutputWriter out, @NullAllowed LineConvertor convertor, boolean resetEnabled) {
117
        return new PrintingLineProcessor(out, convertor, resetEnabled);
118
    }
119
120
    private static class PrintingLineProcessor implements LineProcessor {
121
122
        private final OutputWriter out;
123
124
        private final LineConvertor convertor;
125
126
        private final boolean resetEnabled;
127
128
        private boolean closed;
129
130
        public PrintingLineProcessor(OutputWriter out, LineConvertor convertor, boolean resetEnabled) {
131
            assert out != null;
132
133
            this.out = out;
134
            this.convertor = convertor;
135
            this.resetEnabled = resetEnabled;
136
        }
137
138
        public void processLine(String line) {
139
            assert line != null;
140
141
            if (closed) {
142
                throw new IllegalStateException("Already closed processor");
143
            }
144
145
            LOGGER.log(Level.FINEST, line);
146
147
            if (convertor != null) {
148
                List<ConvertedLine> convertedLines = convertor.convert(line);
149
                if (convertedLines != null) {
150
                    for (ConvertedLine converted : convertedLines) {
151
                        if (converted.getListener() == null) {
152
                            out.println(converted.getText());
153
                        } else {
154
                            try {
155
                                out.println(converted.getText(), converted.getListener());
156
                            } catch (IOException ex) {
157
                                LOGGER.log(Level.INFO, null, ex);
158
                                out.println(converted.getText());
159
                            }
160
                        }
161
                    }
162
                } else {
163
                    out.println(line);
164
                }
165
            } else {
166
                out.println(line);
167
            }
168
            out.flush();
169
        }
170
171
        public void reset() {
172
            if (closed) {
173
                throw new IllegalStateException("Already closed processor");
174
            }
175
176
            if (!resetEnabled) {
177
                return;
178
            }
179
180
            try {
181
                out.reset();
182
            } catch (IOException ex) {
183
                LOGGER.log(Level.INFO, null, ex);
184
            }
185
        }
186
187
        public void close() {
188
            closed = true;
189
190
            out.flush();
191
            out.close();
192
        }
193
    }
194
}
(-)a/extexecution/src/org/netbeans/modules/extexecution/ProcessInputStream.java (-196 lines)
Lines 1-196 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;
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/src/org/netbeans/modules/extexecution/input/BaseInputProcessor.java (+78 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.modules.extexecution.input;
44
45
import java.io.IOException;
46
import org.netbeans.api.extexecution.input.InputProcessor;
47
48
/**
49
 *
50
 * @author Petr Hejl
51
 */
52
public class BaseInputProcessor implements org.netbeans.api.extexecution.base.input.InputProcessor {
53
    private final InputProcessor delegate;
54
55
    public BaseInputProcessor(InputProcessor delegate) {
56
        this.delegate = delegate;
57
    }
58
59
    @Override
60
    public void processInput(char[] chars) throws IOException {
61
        delegate.processInput(chars);
62
    }
63
64
    @Override
65
    public void reset() throws IOException {
66
        delegate.reset();
67
    }
68
69
    @Override
70
    public void close() throws IOException {
71
        delegate.close();
72
    }
73
74
    public InputProcessor getDelegate() {
75
        return delegate;
76
    }
77
    
78
}
(-)a/extexecution/src/org/netbeans/modules/extexecution/input/DefaultInputReader.java (-115 lines)
Lines 1-115 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.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.input.InputProcessor;
53
import org.netbeans.api.extexecution.input.InputReader;
54
55
/**
56
 *
57
 * This class is <i>NotThreadSafe</i>.
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
    public int readInput(InputProcessor inputProcessor) throws IOException {
83
        if (closed) {
84
            throw new IllegalStateException("Already closed reader");
85
        }
86
87
        if (!reader.ready()) {
88
            return 0;
89
        }
90
91
        int fetched = 0;
92
        // TODO optimization possible
93
        StringBuilder builder = new StringBuilder();
94
        do {
95
            int size = reader.read(buffer);
96
            if (size > 0) {
97
                builder.append(buffer, 0, size);
98
                fetched += size;
99
            }
100
        } while (reader.ready() && greedy);
101
102
        if (inputProcessor != null && fetched > 0) {
103
            inputProcessor.processInput(builder.toString().toCharArray());
104
        }
105
106
        return fetched;
107
    }
108
109
    public void close() throws IOException {
110
        closed = true;
111
        reader.close();
112
        LOGGER.log(Level.FINEST, "Reader closed");
113
    }
114
115
}
(-)a/extexecution/src/org/netbeans/modules/extexecution/input/DelegatingInputProcessor.java (+74 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.modules.extexecution.input;
44
45
import java.io.IOException;
46
import org.netbeans.api.extexecution.input.InputProcessor;
47
48
/**
49
 *
50
 * @author Petr Hejl
51
 */
52
public class DelegatingInputProcessor implements InputProcessor {
53
    private final org.netbeans.api.extexecution.base.input.InputProcessor delegate;
54
55
    public DelegatingInputProcessor(org.netbeans.api.extexecution.base.input.InputProcessor delegate) {
56
        this.delegate = delegate;
57
    }
58
59
    @Override
60
    public void processInput(char[] chars) throws IOException {
61
        delegate.processInput(chars);
62
    }
63
64
    @Override
65
    public void reset() throws IOException {
66
        delegate.reset();
67
    }
68
69
    @Override
70
    public void close() throws IOException {
71
        delegate.close();
72
    }
73
    
74
}
(-)a/extexecution/src/org/netbeans/modules/extexecution/input/FileInputReader.java (-155 lines)
Lines 1-155 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.input;
46
47
import java.io.BufferedReader;
48
import java.io.FileInputStream;
49
import java.io.IOException;
50
import java.io.InputStreamReader;
51
import java.io.Reader;
52
import java.util.logging.Level;
53
import java.util.logging.Logger;
54
import org.netbeans.api.extexecution.input.InputProcessor;
55
import org.netbeans.api.extexecution.input.InputReader;
56
import org.netbeans.api.extexecution.input.InputReaders;
57
58
/**
59
 *
60
 * This class is <i>NotThreadSafe</i>.
61
 * @author Petr Hejl
62
 */
63
public class FileInputReader implements InputReader {
64
65
    private static final Logger LOGGER = Logger.getLogger(FileInputReader.class.getName());
66
67
    private static final int BUFFER_SIZE = 512;
68
69
    private final InputReaders.FileInput.Provider fileProvider;
70
71
    private final char[] buffer = new char[BUFFER_SIZE];
72
73
    private InputReaders.FileInput currentFile;
74
75
    private Reader reader;
76
77
    private long fileLength;
78
79
    private boolean closed;
80
81
    public FileInputReader(InputReaders.FileInput.Provider fileProvider) {
82
        assert fileProvider != null;
83
84
        this.fileProvider = fileProvider;
85
    }
86
87
    public int readInput(InputProcessor inputProcessor) {
88
        if (closed) {
89
            throw new IllegalStateException("Already closed reader");
90
        }
91
92
        int fetched = 0;
93
        try {
94
            InputReaders.FileInput file = fileProvider.getFileInput();
95
96
            if ((currentFile != file && (currentFile == null || !currentFile.equals(file)))
97
                    || fileLength > currentFile.getFile().length() || reader == null) {
98
99
                if (reader != null) {
100
                    reader.close();
101
                }
102
103
                currentFile = file;
104
105
                if (currentFile != null && currentFile.getFile().exists()
106
                        && currentFile.getFile().canRead()) {
107
108
                    reader = new BufferedReader(new InputStreamReader(
109
                            new FileInputStream(currentFile.getFile()), currentFile.getCharset()));
110
                }
111
                if (fileLength > 0) {
112
                    inputProcessor.reset();
113
                }
114
                fileLength = 0;
115
            }
116
117
            if (reader == null) {
118
                return fetched;
119
            }
120
121
            int size = reader.read(buffer);
122
            if (size > 0) {
123
                fileLength += size;
124
                fetched += size;
125
126
                if (inputProcessor != null) {
127
                    char[] toProcess = new char[size];
128
                    System.arraycopy(buffer, 0, toProcess, 0, size);
129
                    inputProcessor.processInput(toProcess);
130
                }
131
            }
132
        } catch (Exception ex) {
133
            LOGGER.log(Level.INFO, null, ex);
134
            // we will try the next loop (if any)
135
            if (reader != null) {
136
                try {
137
                    reader.close();
138
                } catch (IOException iex) {
139
                    LOGGER.log(Level.FINE, null, ex);
140
                }
141
            }
142
        }
143
144
        return fetched;
145
    }
146
147
    public void close() throws IOException {
148
        closed = true;
149
        if (reader != null) {
150
            reader.close();
151
            reader = null;
152
        }
153
    }
154
155
}
(-)a/extexecution/src/org/netbeans/spi/extexecution/ProcessBuilderFactory.java (+2 lines)
Lines 49-54 Link Here
49
 *
49
 *
50
 * @author Petr Hejl
50
 * @author Petr Hejl
51
 * @since 1.28
51
 * @since 1.28
52
 * @deprecated use {@link org.netbeans.spi.extexecution.base.ProcessBuilderFactory}
53
 *             and {@link org.netbeans.spi.extexecution.base.ProcessBuilderImplementation}
52
 */
54
 */
53
public class ProcessBuilderFactory {
55
public class ProcessBuilderFactory {
54
56
(-)a/extexecution/src/org/netbeans/spi/extexecution/ProcessBuilderImplementation.java (+2 lines)
Lines 62-67 Link Here
62
 * @see org.netbeans.api.extexecution.ProcessBuilder
62
 * @see org.netbeans.api.extexecution.ProcessBuilder
63
 * @author Petr Hejl
63
 * @author Petr Hejl
64
 * @since 1.28
64
 * @since 1.28
65
 * @deprecated use {@link org.netbeans.spi.extexecution.base.ProcessBuilderImplementation}
66
 *             and {@link org.netbeans.spi.extexecution.base.ProcessBuilderFactory}
65
 */
67
 */
66
public interface ProcessBuilderImplementation {
68
public interface ProcessBuilderImplementation {
67
69
(-)a/extexecution/src/org/netbeans/spi/extexecution/destroy/ProcessDestroyPerformer.java (+3 lines)
Lines 43-48 Link Here
43
package org.netbeans.spi.extexecution.destroy;
43
package org.netbeans.spi.extexecution.destroy;
44
44
45
import java.util.Map;
45
import java.util.Map;
46
import org.netbeans.api.extexecution.base.Processes;
47
import org.netbeans.spi.extexecution.base.ProcessesImplementation;
46
48
47
/**
49
/**
48
 * A service capable of properly terminating external process along with any
50
 * A service capable of properly terminating external process along with any
Lines 60-65 Link Here
60
 *
62
 *
61
 * @author mkleint
63
 * @author mkleint
62
 * @since 1.16
64
 * @since 1.16
65
 * @deprecated use {@link ProcessesImplementation} and {@link Processes}
63
 */
66
 */
64
public interface ProcessDestroyPerformer {
67
public interface ProcessDestroyPerformer {
65
68
(-)a/extexecution/src/org/netbeans/spi/extexecution/destroy/package-info.java (+1 lines)
Lines 46-51 Link Here
46
 * The support SPI for terminating external processes.
46
 * The support SPI for terminating external processes.
47
 *
47
 *
48
 * @see org.netbeans.spi.extexecution.destroy.ProcessDestroyPerformer
48
 * @see org.netbeans.spi.extexecution.destroy.ProcessDestroyPerformer
49
 * @deprecated use {@link org.netbeans.spi.extexecution.base}
49
 */
50
 */
50
package org.netbeans.spi.extexecution.destroy;
51
package org.netbeans.spi.extexecution.destroy;
51
52
(-)a/extexecution/src/org/netbeans/spi/extexecution/package-info.java (+1 lines)
Lines 46-51 Link Here
46
 * The support SPI for creation of external processes.
46
 * The support SPI for creation of external processes.
47
 *
47
 *
48
 * @see org.netbeans.spi.extexecution.ProcessBuilderImplementation
48
 * @see org.netbeans.spi.extexecution.ProcessBuilderImplementation
49
 * @deprecated use {@link org.netbeans.spi.extexecution.base}
49
 */
50
 */
50
package org.netbeans.spi.extexecution;
51
package org.netbeans.spi.extexecution;
51
52
(-)a/extexecution/test/unit/src/org/netbeans/api/extexecution/input/InputProcessorsTest.java (-85 / +3 lines)
Lines 40-54 Link Here
40
 * Portions Copyrighted 2008 Sun Microsystems, Inc.
40
 * Portions Copyrighted 2008 Sun Microsystems, Inc.
41
 */
41
 */
42
42
43
package org.netbeans.api.extexecution.input;
43
package org.netbeans.api.extexecution.print;
44
44
45
import java.io.ByteArrayOutputStream;
45
import java.io.ByteArrayOutputStream;
46
import java.io.IOException;
46
import java.io.IOException;
47
import java.io.PrintWriter;
47
import java.io.PrintWriter;
48
import java.util.ArrayList;
48
import java.util.ArrayList;
49
import java.util.Arrays;
50
import java.util.Collections;
49
import java.util.Collections;
51
import java.util.List;
50
import java.util.List;
51
import org.netbeans.api.extexecution.base.input.InputProcessor;
52
import org.netbeans.api.extexecution.input.TestInputWriter;
52
import org.netbeans.junit.NbTestCase;
53
import org.netbeans.junit.NbTestCase;
53
54
54
/**
55
/**
Lines 57-142 Link Here
57
 */
58
 */
58
public class InputProcessorsTest extends NbTestCase {
59
public class InputProcessorsTest extends NbTestCase {
59
60
60
    private static final char[] PROXY_CHARS_CHUNK1 = "abcdefghij".toCharArray();
61
62
    private static final char[] PROXY_CHARS_CHUNK2 = "jihgfedcba".toCharArray();
63
64
    private static final char[][] PROXY_TEST_CHARS = new char[][] {
65
        PROXY_CHARS_CHUNK1, PROXY_CHARS_CHUNK2
66
    };
67
68
    private static final List<String> BRIDGE_TEST_LINES = new ArrayList<String>();
69
70
    private static final char[][] BRIDGE_TEST_CHARS;
71
72
    static {
73
        Collections.addAll(BRIDGE_TEST_LINES, "test1", "test2");
74
75
        BRIDGE_TEST_CHARS = new char[BRIDGE_TEST_LINES.size()][];
76
        for (int i = 0; i < BRIDGE_TEST_LINES.size(); i++) {
77
            BRIDGE_TEST_CHARS[i] = (BRIDGE_TEST_LINES.get(i) + "\n").toCharArray();
78
        }
79
    }
80
81
    public InputProcessorsTest(String name) {
61
    public InputProcessorsTest(String name) {
82
        super(name);
62
        super(name);
83
    }
63
    }
84
64
85
    public void testBridge() throws IOException {
86
        TestLineProcessor processor = new TestLineProcessor(false);
87
        InputProcessor bridge = InputProcessors.bridge(processor);
88
89
        for (char[] chunk : BRIDGE_TEST_CHARS) {
90
            bridge.processInput(chunk);
91
        }
92
93
        assertEquals(0, processor.getResetCount());
94
        assertEquals(BRIDGE_TEST_LINES, processor.getLinesProcessed());
95
96
        bridge.reset();
97
        assertEquals(1, processor.getResetCount());
98
99
        bridge.close();
100
        assertClosedConditions(bridge);
101
        assertTrue(processor.isClosed());
102
    }
103
104
    public void testProxy() throws IOException {
105
        TestInputProcessor processor1 = new TestInputProcessor(false);
106
        TestInputProcessor processor2 = new TestInputProcessor(false);
107
108
        InputProcessor proxy = InputProcessors.proxy(processor1, processor2);
109
        int size = 0;
110
        for (char[] chunk : PROXY_TEST_CHARS) {
111
            proxy.processInput(chunk);
112
            size += chunk.length;
113
        }
114
115
        char[] expected = new char[size];
116
        int position = 0;
117
        for (char[] chunk : PROXY_TEST_CHARS) {
118
            System.arraycopy(chunk, 0, expected, position, chunk.length);
119
            position += chunk.length;
120
        }
121
122
        assertEquals(0, processor1.getResetCount());
123
        assertEquals(0, processor2.getResetCount());
124
125
        assertTrue(Arrays.equals(expected, processor1.getCharsProcessed()));
126
        assertTrue(Arrays.equals(expected, processor2.getCharsProcessed()));
127
128
        proxy.reset();
129
130
        assertEquals(1, processor1.getResetCount());
131
        assertEquals(1, processor2.getResetCount());
132
133
        proxy.close();
134
        assertClosedConditions(proxy);
135
136
        assertTrue(processor1.isClosed());
137
        assertTrue(processor2.isClosed());
138
    }
139
140
    public void testPrinting() throws IOException {
65
    public void testPrinting() throws IOException {
141
        TestInputWriter writer = new TestInputWriter(new PrintWriter(new ByteArrayOutputStream()));
66
        TestInputWriter writer = new TestInputWriter(new PrintWriter(new ByteArrayOutputStream()));
142
        InputProcessor processor = InputProcessors.printing(writer, true);
67
        InputProcessor processor = InputProcessors.printing(writer, true);
Lines 191-203 Link Here
191
        assertClosedConditions(processor);
116
        assertClosedConditions(processor);
192
    }
117
    }
193
118
194
    private static <T> void assertEquals(List<T> expected, List<T> value) {
195
        assertEquals(expected.size(), value.size());
196
        for (int i = 0; i < expected.size(); i++) {
197
            assertEquals(expected.get(i), value.get(i));
198
        }
199
    }
200
201
    private static void assertClosedConditions(InputProcessor inputProcessor) throws IOException {
119
    private static void assertClosedConditions(InputProcessor inputProcessor) throws IOException {
202
        try {
120
        try {
203
            inputProcessor.processInput(new char[] {'0'});
121
            inputProcessor.processInput(new char[] {'0'});
(-)a/extexecution/test/unit/src/org/netbeans/api/extexecution/input/LineProcessorsTest.java (-180 / +3 lines)
Lines 40-63 Link Here
40
 * Portions Copyrighted 2008 Sun Microsystems, Inc.
40
 * Portions Copyrighted 2008 Sun Microsystems, Inc.
41
 */
41
 */
42
42
43
package org.netbeans.api.extexecution.input;
43
package org.netbeans.api.extexecution.print;
44
44
45
import java.io.ByteArrayOutputStream;
45
import java.io.ByteArrayOutputStream;
46
import java.io.PrintWriter;
46
import java.io.PrintWriter;
47
import java.util.ArrayList;
47
import java.util.ArrayList;
48
import java.util.Collections;
48
import java.util.Collections;
49
import java.util.List;
49
import java.util.List;
50
import java.util.Random;
51
import java.util.concurrent.BrokenBarrierException;
52
import java.util.concurrent.CountDownLatch;
53
import java.util.concurrent.CyclicBarrier;
54
import java.util.concurrent.ExecutorService;
50
import java.util.concurrent.ExecutorService;
55
import java.util.concurrent.Executors;
51
import java.util.concurrent.Executors;
56
import java.util.concurrent.TimeUnit;
52
import org.netbeans.api.extexecution.base.input.LineProcessor;
57
import java.util.concurrent.TimeoutException;
53
import org.netbeans.api.extexecution.input.TestInputWriter;
58
import java.util.regex.Pattern;
59
import org.netbeans.junit.NbTestCase;
54
import org.netbeans.junit.NbTestCase;
60
import org.netbeans.junit.RandomlyFails;
61
55
62
/**
56
/**
63
 *
57
 *
Lines 65-86 Link Here
65
 */
59
 */
66
public class LineProcessorsTest extends NbTestCase {
60
public class LineProcessorsTest extends NbTestCase {
67
61
68
    private static final String WAIT_RELEASE_STRING = "test"; // NOI18N
69
70
    private static final long DEADLOCK_TIMEOUT = 1000;
71
72
    private static final int WAIT_THREAD_COUNT = 5;
73
74
    private static final int PRODUCER_THREAD_COUNT = 5;
75
76
    private static final long TEST_TIMEOUT = 5000;
77
78
    private static final List<String> PROXY_TEST_LINES = new ArrayList<String>();
79
80
    private static final List<String> PRINTING_TEST_LINES = new ArrayList<String>(5);
62
    private static final List<String> PRINTING_TEST_LINES = new ArrayList<String>(5);
81
63
82
    static {
64
    static {
83
        Collections.addAll(PROXY_TEST_LINES, "test1", "test2");
84
65
85
        Collections.addAll(PRINTING_TEST_LINES,
66
        Collections.addAll(PRINTING_TEST_LINES,
86
                "the first test line",
67
                "the first test line",
Lines 108-140 Link Here
108
        executor.shutdownNow();
89
        executor.shutdownNow();
109
    }
90
    }
110
91
111
    public void testProxy() {
112
        TestLineProcessor processor1 = new TestLineProcessor(false);
113
        TestLineProcessor processor2 = new TestLineProcessor(false);
114
115
        LineProcessor proxy = LineProcessors.proxy(processor1, processor2);
116
        for (String line : PROXY_TEST_LINES) {
117
            proxy.processLine(line);
118
        }
119
120
        assertEquals(0, processor1.getResetCount());
121
        assertEquals(0, processor2.getResetCount());
122
123
        assertEquals(PROXY_TEST_LINES, processor1.getLinesProcessed());
124
        assertEquals(PROXY_TEST_LINES, processor2.getLinesProcessed());
125
126
        proxy.reset();
127
128
        assertEquals(1, processor1.getResetCount());
129
        assertEquals(1, processor2.getResetCount());
130
131
        proxy.close();
132
        assertClosedConditions(proxy);
133
134
        assertTrue(processor1.isClosed());
135
        assertTrue(processor2.isClosed());
136
    }
137
138
    public void testPrinting() {
92
    public void testPrinting() {
139
        TestInputWriter writer = new TestInputWriter(new PrintWriter(new ByteArrayOutputStream()));
93
        TestInputWriter writer = new TestInputWriter(new PrintWriter(new ByteArrayOutputStream()));
140
        LineProcessor lineProcessor = LineProcessors.printing(writer, true);
94
        LineProcessor lineProcessor = LineProcessors.printing(writer, true);
Lines 192-262 Link Here
192
        assertClosedConditions(lineProcessor);
146
        assertClosedConditions(lineProcessor);
193
    }
147
    }
194
148
195
    public void testWaiting() throws InterruptedException, BrokenBarrierException {
196
        final CountDownLatch latch = new CountDownLatch(1);
197
        final LineProcessor lineProcessor = LineProcessors.patternWaiting(
198
                Pattern.compile(WAIT_RELEASE_STRING), latch);
199
        CyclicBarrier barrier = new CyclicBarrier(2);
200
201
        executor.execute(new WaitRunnable(latch, barrier));
202
        barrier.await();
203
        lineProcessor.processLine(WAIT_RELEASE_STRING);
204
205
        try {
206
            barrier.await(DEADLOCK_TIMEOUT, TimeUnit.MILLISECONDS);
207
        } catch (TimeoutException ex) {
208
            fail("Deadlock occurs");
209
        }
210
211
        executor.execute(new WaitRunnable(latch, barrier));
212
        barrier.await();
213
        try {
214
            barrier.await(DEADLOCK_TIMEOUT, TimeUnit.MILLISECONDS);
215
        } catch (TimeoutException ex) {
216
            fail("Deadlock occurs");
217
        }
218
219
        lineProcessor.close();
220
        assertClosedConditions(lineProcessor);
221
    }
222
223
    @RandomlyFails // NB-Core-Build #8029
224
    public void testWaitingThreadSafety() throws InterruptedException, BrokenBarrierException {
225
        final CountDownLatch latch = new CountDownLatch(1);
226
        final LineProcessor lineProcessor = LineProcessors.patternWaiting(
227
                Pattern.compile(WAIT_RELEASE_STRING), latch);
228
        CyclicBarrier barrier = new CyclicBarrier(WAIT_THREAD_COUNT + 1);
229
230
        for (int i = 0; i < WAIT_THREAD_COUNT; i++) {
231
            executor.execute(new WaitRunnable(latch, barrier));
232
        }
233
234
        barrier.await();
235
236
        Random random = new Random();
237
        for (int i = 0; i < PRODUCER_THREAD_COUNT; i++) {
238
            executor.execute(new ProducerRunnable(lineProcessor, WAIT_RELEASE_STRING, random.nextInt(5)));
239
        }
240
241
        // guarantee finish
242
        executor.execute(new Runnable() {
243
            public void run() {
244
                try {
245
                    Thread.sleep(TEST_TIMEOUT);
246
                    lineProcessor.processLine(WAIT_RELEASE_STRING);
247
                } catch (InterruptedException ex) {
248
                    //throw new RuntimeException(ex);
249
                }
250
            }
251
        });
252
253
        try {
254
            barrier.await(TEST_TIMEOUT + DEADLOCK_TIMEOUT, TimeUnit.MILLISECONDS);
255
        } catch (TimeoutException ex) {
256
            fail("Deadlock occurs");
257
        }
258
    }
259
260
    private static <T> void assertEquals(List<T> expected, List<T> value) {
149
    private static <T> void assertEquals(List<T> expected, List<T> value) {
261
        assertEquals(expected.size(), value.size());
150
        assertEquals(expected.size(), value.size());
262
        for (int i = 0; i < expected.size(); i++) {
151
        for (int i = 0; i < expected.size(); i++) {
Lines 279-348 Link Here
279
            // expected
168
            // expected
280
        }
169
        }
281
    }
170
    }
282
283
    private static class WaitRunnable implements Runnable {
284
285
        private final CountDownLatch latch;
286
287
        private final CyclicBarrier barrier;
288
289
        public WaitRunnable(CountDownLatch latch, CyclicBarrier barrier) {
290
            this.latch = latch;
291
            this.barrier = barrier;
292
        }
293
294
        public void run() {
295
            try {
296
                barrier.await();
297
                latch.await();
298
                barrier.await();
299
            } catch (InterruptedException ex) {
300
                // timeouted test
301
                Thread.currentThread().interrupt();
302
            } catch (BrokenBarrierException ex) {
303
                // timeouted test
304
            }
305
        }
306
307
    }
308
309
    private static class ProducerRunnable implements Runnable {
310
311
        private final LineProcessor lineProcessor;
312
313
        private final String releaseString;
314
315
        private final Random random = new Random();
316
317
        private final int iterations;
318
319
        public ProducerRunnable(LineProcessor lineProcessor, String releaseString, int iterations) {
320
            this.lineProcessor = lineProcessor;
321
            this.releaseString = releaseString;
322
            this.iterations = iterations;
323
        }
324
325
        public void run() {
326
            for (int i = 0; i < iterations; i++) {
327
                if (Thread.interrupted()) {
328
                    return;
329
                }
330
331
                int val = random.nextInt(10);
332
                if (val == 0) {
333
                    lineProcessor.processLine(releaseString);
334
                    return;
335
                } else {
336
                    lineProcessor.processLine("generated " + val);
337
                }
338
339
                try {
340
                    Thread.sleep(random.nextInt(300));
341
                } catch (InterruptedException ex) {
342
                    Thread.currentThread().interrupt();
343
                    return;
344
                }
345
            }
346
        }
347
    }
348
}
171
}
(-)a/j2ee.weblogic9/nbproject/project.properties (-1 / +1 lines)
Lines 43-49 Link Here
43
#
43
#
44
44
45
javac.source=1.6
45
javac.source=1.6
46
spec.version.base=1.38.0
46
spec.version.base=1.39.0
47
47
48
test.config.stableBTD.includes=**/*Test.class
48
test.config.stableBTD.includes=**/*Test.class
49
test.config.stableBTD.excludes=\
49
test.config.stableBTD.excludes=\
(-)a/j2ee.weblogic9/nbproject/project.xml (+9 lines)
Lines 109-114 Link Here
109
                    </run-dependency>
109
                    </run-dependency>
110
                </dependency>
110
                </dependency>
111
                <dependency>
111
                <dependency>
112
                    <code-name-base>org.netbeans.modules.extexecution.base</code-name-base>
113
                    <build-prerequisite/>
114
                    <compile-dependency/>
115
                    <run-dependency>
116
                        <release-version>2</release-version>
117
                        <specification-version>1.0</specification-version>
118
                    </run-dependency>
119
                </dependency>
120
                <dependency>
112
                    <code-name-base>org.netbeans.modules.j2ee.common</code-name-base>
121
                    <code-name-base>org.netbeans.modules.j2ee.common</code-name-base>
113
                    <build-prerequisite/>
122
                    <build-prerequisite/>
114
                    <compile-dependency/>
123
                    <compile-dependency/>
(-)a/j2ee.weblogic9/src/org/netbeans/modules/j2ee/weblogic9/deploy/CommandBasedDeployer.java (-47 / +76 lines)
Lines 49-55 Link Here
49
import java.io.InputStream;
49
import java.io.InputStream;
50
import java.net.MalformedURLException;
50
import java.net.MalformedURLException;
51
import java.net.URL;
51
import java.net.URL;
52
import java.util.ArrayList;
53
import java.util.Arrays;
52
import java.util.Collection;
54
import java.util.Collection;
55
import java.util.List;
53
import java.util.Set;
56
import java.util.Set;
54
import java.util.concurrent.ExecutionException;
57
import java.util.concurrent.ExecutionException;
55
import java.util.concurrent.Future;
58
import java.util.concurrent.Future;
Lines 66-77 Link Here
66
import javax.enterprise.deploy.spi.Target;
69
import javax.enterprise.deploy.spi.Target;
67
import javax.enterprise.deploy.spi.TargetModuleID;
70
import javax.enterprise.deploy.spi.TargetModuleID;
68
import javax.enterprise.deploy.spi.status.ProgressObject;
71
import javax.enterprise.deploy.spi.status.ProgressObject;
69
import org.netbeans.api.extexecution.ExecutionDescriptor;
72
import org.netbeans.api.extexecution.base.BaseExecutionDescriptor;
70
import org.netbeans.api.extexecution.ExecutionService;
73
import org.netbeans.api.extexecution.base.BaseExecutionService;
71
import org.netbeans.api.extexecution.ExternalProcessBuilder;
74
import org.netbeans.api.extexecution.base.input.InputProcessor;
72
import org.netbeans.api.extexecution.input.InputProcessor;
75
import org.netbeans.api.extexecution.base.input.InputProcessors;
73
import org.netbeans.api.extexecution.input.InputProcessors;
76
import org.netbeans.api.extexecution.base.input.LineProcessor;
74
import org.netbeans.api.extexecution.input.LineProcessor;
77
import org.netbeans.api.extexecution.base.input.LineProcessors;
75
import org.netbeans.api.java.platform.JavaPlatform;
78
import org.netbeans.api.java.platform.JavaPlatform;
76
import org.netbeans.api.java.platform.JavaPlatformManager;
79
import org.netbeans.api.java.platform.JavaPlatformManager;
77
import org.netbeans.modules.j2ee.dd.api.application.Application;
80
import org.netbeans.modules.j2ee.dd.api.application.Application;
Lines 88-101 Link Here
88
import org.netbeans.modules.j2ee.weblogic9.config.WLMessageDestination;
91
import org.netbeans.modules.j2ee.weblogic9.config.WLMessageDestination;
89
import org.netbeans.modules.j2ee.weblogic9.dd.model.WebApplicationModel;
92
import org.netbeans.modules.j2ee.weblogic9.dd.model.WebApplicationModel;
90
import org.netbeans.modules.j2ee.weblogic9.ui.FailedAuthenticationSupport;
93
import org.netbeans.modules.j2ee.weblogic9.ui.FailedAuthenticationSupport;
91
import org.netbeans.spi.java.classpath.support.ClassPathSupport;
92
import org.openide.filesystems.FileObject;
94
import org.openide.filesystems.FileObject;
93
import org.openide.filesystems.FileUtil;
95
import org.openide.filesystems.FileUtil;
94
import org.openide.filesystems.JarFileSystem;
96
import org.openide.filesystems.JarFileSystem;
95
import org.openide.util.NbBundle;
97
import org.openide.util.NbBundle;
96
import org.openide.util.RequestProcessor;
98
import org.openide.util.RequestProcessor;
97
import org.openide.util.Utilities;
99
import org.openide.util.Utilities;
98
import org.openide.windows.InputOutput;
99
import org.xml.sax.InputSource;
100
import org.xml.sax.InputSource;
100
import org.xml.sax.SAXException;
101
import org.xml.sax.SAXException;
101
102
Lines 110-117 Link Here
110
111
111
    private static final RequestProcessor URL_WAIT_RP = new RequestProcessor("Weblogic URL Wait", 10); // NOI18N
112
    private static final RequestProcessor URL_WAIT_RP = new RequestProcessor("Weblogic URL Wait", 10); // NOI18N
112
113
113
    private static final boolean SHOW_CONSOLE = Boolean.getBoolean(CommandBasedDeployer.class.getName() + ".showConsole");;
114
115
    public CommandBasedDeployer(WLDeploymentManager deploymentManager) {
114
    public CommandBasedDeployer(WLDeploymentManager deploymentManager) {
116
        super(deploymentManager);
115
        super(deploymentManager);
117
    }
116
    }
Lines 151-157 Link Here
151
                LastLineProcessor lineProcessor = new LastLineProcessor();
150
                LastLineProcessor lineProcessor = new LastLineProcessor();
152
                for (TargetModuleID module : targetModuleID) {
151
                for (TargetModuleID module : targetModuleID) {
153
                    String name = module.getModuleID();
152
                    String name = module.getModuleID();
154
                    ExecutionService service = createService("-undeploy", lineProcessor, "-name", name);
153
                    BaseExecutionService service = createService("-undeploy", lineProcessor, "-name", name);
155
                    progress.fireProgressEvent(null, new WLDeploymentStatus(
154
                    progress.fireProgressEvent(null, new WLDeploymentStatus(
156
                            ActionType.EXECUTE, CommandType.UNDEPLOY, StateType.RUNNING,
155
                            ActionType.EXECUTE, CommandType.UNDEPLOY, StateType.RUNNING,
157
                            NbBundle.getMessage(CommandBasedDeployer.class, "MSG_Undeploying", name)));
156
                            NbBundle.getMessage(CommandBasedDeployer.class, "MSG_Undeploying", name)));
Lines 219-225 Link Here
219
                LastLineProcessor lineProcessor = new LastLineProcessor();
218
                LastLineProcessor lineProcessor = new LastLineProcessor();
220
                for (TargetModuleID module : targetModuleID) {
219
                for (TargetModuleID module : targetModuleID) {
221
                    String name = module.getModuleID();
220
                    String name = module.getModuleID();
222
                    ExecutionService service = createService("-start", lineProcessor, "-name", name);
221
                    BaseExecutionService service = createService("-start", lineProcessor, "-name", name);
223
                    progress.fireProgressEvent(null, new WLDeploymentStatus(
222
                    progress.fireProgressEvent(null, new WLDeploymentStatus(
224
                            ActionType.EXECUTE, CommandType.START, StateType.RUNNING,
223
                            ActionType.EXECUTE, CommandType.START, StateType.RUNNING,
225
                            NbBundle.getMessage(CommandBasedDeployer.class, "MSG_Starting", name)));
224
                            NbBundle.getMessage(CommandBasedDeployer.class, "MSG_Starting", name)));
Lines 288-294 Link Here
288
                LastLineProcessor lineProcessor = new LastLineProcessor();
287
                LastLineProcessor lineProcessor = new LastLineProcessor();
289
                for (TargetModuleID module : targetModuleID) {
288
                for (TargetModuleID module : targetModuleID) {
290
                    String name = module.getModuleID();
289
                    String name = module.getModuleID();
291
                    ExecutionService service = createService("-stop", lineProcessor, "-name", name);
290
                    BaseExecutionService service = createService("-stop", lineProcessor, "-name", name);
292
                    progress.fireProgressEvent(null, new WLDeploymentStatus(
291
                    progress.fireProgressEvent(null, new WLDeploymentStatus(
293
                            ActionType.EXECUTE, CommandType.STOP, StateType.RUNNING,
292
                            ActionType.EXECUTE, CommandType.STOP, StateType.RUNNING,
294
                            NbBundle.getMessage(CommandBasedDeployer.class, "MSG_Stopping", name)));
293
                            NbBundle.getMessage(CommandBasedDeployer.class, "MSG_Stopping", name)));
Lines 372-378 Link Here
372
                        LOGGER.log(Level.INFO, "Could not deploy {0}", appModule.getName());
371
                        LOGGER.log(Level.INFO, "Could not deploy {0}", appModule.getName());
373
                        continue;
372
                        continue;
374
                    }
373
                    }
375
                    ExecutionService service = createService("-deploy", lineProcessor, "-name",
374
                    BaseExecutionService service = createService("-deploy", lineProcessor, "-name",
376
                            appModule.getName(), "-upload", appModule.getOrigin().getAbsolutePath());
375
                            appModule.getName(), "-upload", appModule.getOrigin().getAbsolutePath());
377
                    progress.fireProgressEvent(null, new WLDeploymentStatus(
376
                    progress.fireProgressEvent(null, new WLDeploymentStatus(
378
                            ActionType.EXECUTE, CommandType.START, StateType.RUNNING,
377
                            ActionType.EXECUTE, CommandType.START, StateType.RUNNING,
Lines 445-451 Link Here
445
                boolean failed = false;
444
                boolean failed = false;
446
                LastLineProcessor lineProcessor = new LastLineProcessor();
445
                LastLineProcessor lineProcessor = new LastLineProcessor();
447
                for (File library : libraries) {
446
                for (File library : libraries) {
448
                    ExecutionService service = createService("-deploy", lineProcessor,
447
                    BaseExecutionService service = createService("-deploy", lineProcessor,
449
                            "-library" , library.getAbsolutePath()); // NOI18N
448
                            "-library" , library.getAbsolutePath()); // NOI18N
450
                    Future<Integer> result = service.run();
449
                    Future<Integer> result = service.run();
451
                    try {
450
                    try {
Lines 518-524 Link Here
518
                }
517
                }
519
518
520
                LastLineProcessor lineProcessor = new LastLineProcessor();
519
                LastLineProcessor lineProcessor = new LastLineProcessor();
521
                ExecutionService service = createService("-deploy", lineProcessor, execParams); // NOI18N
520
                BaseExecutionService service = createService("-deploy", lineProcessor, execParams); // NOI18N
522
                Future<Integer> result = service.run();
521
                Future<Integer> result = service.run();
523
                try {
522
                try {
524
                    Integer value = result.get(TIMEOUT, TimeUnit.MILLISECONDS);
523
                    Integer value = result.get(TIMEOUT, TimeUnit.MILLISECONDS);
Lines 578-584 Link Here
578
                    if (parameters.length > 0) {
577
                    if (parameters.length > 0) {
579
                        System.arraycopy(parameters, 0, execParams, 2, parameters.length);
578
                        System.arraycopy(parameters, 0, execParams, 2, parameters.length);
580
                    }
579
                    }
581
                    ExecutionService service = createService("-redeploy", lineProcessor, execParams); // NOI18N
580
                    BaseExecutionService service = createService("-redeploy", lineProcessor, execParams); // NOI18N
582
                    progress.fireProgressEvent(null, new WLDeploymentStatus(
581
                    progress.fireProgressEvent(null, new WLDeploymentStatus(
583
                            ActionType.EXECUTE, CommandType.DISTRIBUTE, StateType.RUNNING,
582
                            ActionType.EXECUTE, CommandType.DISTRIBUTE, StateType.RUNNING,
584
                            NbBundle.getMessage(CommandBasedDeployer.class, "MSG_Redeploying", name)));
583
                            NbBundle.getMessage(CommandBasedDeployer.class, "MSG_Redeploying", name)));
Lines 632-638 Link Here
632
        return progress;
631
        return progress;
633
    }
632
    }
634
633
635
    private ExecutionService createService(final String command,
634
    private BaseExecutionService createService(final String command,
636
            final LineProcessor processor, String... parameters) {
635
            final LineProcessor processor, String... parameters) {
637
636
638
        InstanceProperties ip = getDeploymentManager().getInstanceProperties();
637
        InstanceProperties ip = getDeploymentManager().getInstanceProperties();
Lines 646-686 Link Here
646
        String host = parts[0];
645
        String host = parts[0];
647
        String port = parts.length > 1 ? parts[1] : "";
646
        String port = parts.length > 1 ? parts[1] : "";
648
647
649
        ExternalProcessBuilder builder = new ExternalProcessBuilder(getJavaBinary())
648
        org.netbeans.api.extexecution.base.ProcessBuilder builder = org.netbeans.api.extexecution.base.ProcessBuilder.getLocal();
650
                .redirectErrorStream(true);
649
        builder.setExecutable(getJavaBinary());
650
        builder.setRedirectErrorStream(true);
651
        List<String> arguments = new ArrayList<String>();
651
        // NB supports only JDK6+ while WL 9, only JDK 5
652
        // NB supports only JDK6+ while WL 9, only JDK 5
652
        if (getDeploymentManager().getDomainVersion() == null
653
        if (getDeploymentManager().getDomainVersion() == null
653
                || !getDeploymentManager().getDomainVersion().isAboveOrEqual(WLDeploymentFactory.VERSION_10)) {
654
                || !getDeploymentManager().getDomainVersion().isAboveOrEqual(WLDeploymentFactory.VERSION_10)) {
654
            builder= builder.addArgument("-Dsun.lang.ClassLoader.allowArraySyntax=true"); // NOI18N
655
            arguments.add("-Dsun.lang.ClassLoader.allowArraySyntax=true"); // NOI18N
655
        }
656
        }
656
        builder = builder.addArgument("-cp") // NOI18N
657
        arguments.add("-cp"); // NOI18N
657
                .addArgument(getClassPath())
658
        arguments.add(getClassPath());
658
                .addArgument("weblogic.Deployer") // NOI18N
659
        arguments.add("weblogic.Deployer"); // NOI18N
659
                .addArgument("-adminurl") // NOI18N
660
        arguments.add("-adminurl"); // NOI18N
660
                .addArgument("t3://" + host + ":" + port) // NOI18N
661
        arguments.add("t3://" + host + ":" + port); // NOI18N
661
                .addArgument("-username") // NOI18N
662
        arguments.add("-username"); // NOI18N
662
                .addArgument(username)
663
        arguments.add(username);
663
                .addArgument("-password") // NOI18N
664
        arguments.add("-password"); // NOI18N
664
                .addArgument(password)
665
        arguments.add(password);
665
                .addArgument(command);
666
        arguments.add(command);
667
        
668
        arguments.addAll(Arrays.asList(parameters));
669
        builder.setArguments(arguments);
666
670
667
        for (String param : parameters) {
671
        final LineProcessor realProcessor;
668
            builder = builder.addArgument(param);
672
        if (processor != null || LOGGER.isLoggable(Level.FINEST)) {
673
            if (processor == null) {
674
                realProcessor = new LoggingLineProcessor(Level.FINEST);
675
            } else if (!LOGGER.isLoggable(Level.FINEST)) {
676
                realProcessor = processor;
677
            } else {
678
                realProcessor = LineProcessors.proxy(processor, new LoggingLineProcessor(Level.FINEST));
679
            }
680
        } else {
681
            realProcessor = null;
669
        }
682
        }
683
        BaseExecutionDescriptor descriptor = new BaseExecutionDescriptor().outProcessorFactory(new BaseExecutionDescriptor.InputProcessorFactory() {
670
684
671
        ExecutionDescriptor descriptor = new ExecutionDescriptor().inputVisible(true).outLineBased(true);
685
            @Override
672
        if (processor != null) {
686
            public InputProcessor newInputProcessor() {
673
            descriptor = descriptor.outProcessorFactory(new ExecutionDescriptor.InputProcessorFactory() {
687
                return InputProcessors.bridge(realProcessor);
674
688
            }
675
                public InputProcessor newInputProcessor(InputProcessor defaultProcessor) {
689
        });
676
                    return InputProcessors.proxy(defaultProcessor, InputProcessors.bridge(processor));
690
        return BaseExecutionService.newService(builder, descriptor);
677
                }
678
            });
679
        }
680
        if (!SHOW_CONSOLE) {
681
            descriptor = descriptor.inputOutput(InputOutput.NULL);
682
        }
683
        return ExecutionService.newService(builder, descriptor, "weblogic.Deployer " + command);
684
    }
691
    }
685
692
686
    private String getClassPath() {
693
    private String getClassPath() {
Lines 905-911 Link Here
905
        }
912
        }
906
    }
913
    }
907
914
908
    private static class LastLineProcessor implements LineProcessor {
915
    private static class LastLineProcessor implements org.netbeans.api.extexecution.base.input.LineProcessor {
909
916
910
        private static final Pattern STACK_TRACE_PATTERN = Pattern.compile("^\\s+((at)|(\\.\\.\\.)).*$"); // NOI18N
917
        private static final Pattern STACK_TRACE_PATTERN = Pattern.compile("^\\s+((at)|(\\.\\.\\.)).*$"); // NOI18N
911
918
Lines 930-935 Link Here
930
        public void close() {
937
        public void close() {
931
        }
938
        }
932
    }
939
    }
940
    
941
    private static class LoggingLineProcessor implements org.netbeans.api.extexecution.base.input.LineProcessor {
942
943
        private final Level level;
944
945
        public LoggingLineProcessor(Level level) {
946
            this.level = level;
947
        }
948
        
949
        @Override
950
        public void processLine(String line) {
951
            LOGGER.log(level, line);
952
        }
953
954
        @Override
955
        public void reset() {
956
        }
957
958
        @Override
959
        public void close() {
960
        }
961
    }
933
962
934
    private static class ZipEntryInputStream extends InputStream {
963
    private static class ZipEntryInputStream extends InputStream {
935
964
(-)a/j2ee.weblogic9/src/org/netbeans/modules/j2ee/weblogic9/optional/WLStartServer.java (-9 / +9 lines)
Lines 65-74 Link Here
65
import javax.enterprise.deploy.spi.Target;
65
import javax.enterprise.deploy.spi.Target;
66
import javax.enterprise.deploy.spi.status.ProgressObject;
66
import javax.enterprise.deploy.spi.status.ProgressObject;
67
import org.netbeans.api.extexecution.ExternalProcessBuilder;
67
import org.netbeans.api.extexecution.ExternalProcessBuilder;
68
import org.netbeans.api.extexecution.ExternalProcessSupport;
68
import org.netbeans.api.extexecution.base.Processes;
69
import org.netbeans.api.extexecution.input.InputProcessors;
69
import org.netbeans.api.extexecution.base.input.InputProcessors;
70
import org.netbeans.api.extexecution.input.InputReaderTask;
70
import org.netbeans.api.extexecution.base.input.InputReaderTask;
71
import org.netbeans.api.extexecution.input.InputReaders;
71
import org.netbeans.api.extexecution.base.input.InputReaders;
72
import org.netbeans.api.extexecution.startup.StartupExtender;
72
import org.netbeans.api.extexecution.startup.StartupExtender;
73
import org.netbeans.modules.j2ee.deployment.plugins.api.CommonServerBridge;
73
import org.netbeans.modules.j2ee.deployment.plugins.api.CommonServerBridge;
74
import org.netbeans.modules.j2ee.deployment.plugins.api.InstanceProperties;
74
import org.netbeans.modules.j2ee.deployment.plugins.api.InstanceProperties;
Lines 335-344 Link Here
335
335
336
        service.submit(InputReaderTask.newTask(InputReaders.forStream(
336
        service.submit(InputReaderTask.newTask(InputReaders.forStream(
337
                process.getInputStream(), Charset.defaultCharset()), 
337
                process.getInputStream(), Charset.defaultCharset()), 
338
                InputProcessors.printing(io.getOut(), new ErrorLineConvertor(), true)));
338
                org.netbeans.api.extexecution.print.InputProcessors.printing(io.getOut(), new ErrorLineConvertor(), true)));
339
        service.submit(InputReaderTask.newTask(InputReaders.forStream(
339
        service.submit(InputReaderTask.newTask(InputReaders.forStream(
340
                process.getErrorStream(), Charset.defaultCharset()), 
340
                process.getErrorStream(), Charset.defaultCharset()), 
341
                InputProcessors.printing(io.getErr(), new ErrorLineConvertor(), false)));
341
                org.netbeans.api.extexecution.print.InputProcessors.printing(io.getErr(), new ErrorLineConvertor(), false)));
342
    }
342
    }
343
343
344
    private static void stopService(String uri, final ExecutorService service) {
344
    private static void stopService(String uri, final ExecutorService service) {
Lines 412-418 Link Here
412
                if (process != null) {
412
                if (process != null) {
413
                    Map<String, String> mark = new HashMap<String, String>();
413
                    Map<String, String> mark = new HashMap<String, String>();
414
                    mark.put(WLStartTask.KEY_UUID, dm.getUri());
414
                    mark.put(WLStartTask.KEY_UUID, dm.getUri());
415
                    ExternalProcessSupport.destroy(process, mark);
415
                    Processes.killTree(process, mark);
416
                }
416
                }
417
            }
417
            }
418
        }
418
        }
Lines 797-803 Link Here
797
                        }
797
                        }
798
                        Map<String, String> mark = new HashMap<String, String>();
798
                        Map<String, String> mark = new HashMap<String, String>();
799
                        mark.put(WLStartTask.KEY_UUID, dm.getUri());
799
                        mark.put(WLStartTask.KEY_UUID, dm.getUri());
800
                        ExternalProcessSupport.destroy(process, mark);
800
                        Processes.killTree(process, mark);
801
                }
801
                }
802
802
803
                while ((System.currentTimeMillis() - start) < TIMEOUT) {
803
                while ((System.currentTimeMillis() - start) < TIMEOUT) {
Lines 846-852 Link Here
846
                if (stopProcess != null) {
846
                if (stopProcess != null) {
847
                    Map<String, String> mark = new HashMap<String, String>();
847
                    Map<String, String> mark = new HashMap<String, String>();
848
                    mark.put(KEY_UUID, uuid);
848
                    mark.put(KEY_UUID, uuid);
849
                    ExternalProcessSupport.destroy(stopProcess, mark);
849
                    Processes.killTree(stopProcess, mark);
850
                    stopService(uri, stopService);
850
                    stopService(uri, stopService);
851
                }
851
                }
852
            }
852
            }
(-)a/nbbuild/cluster.properties (+1 lines)
Lines 327-332 Link Here
327
        editor.util,\
327
        editor.util,\
328
        extbrowser,\
328
        extbrowser,\
329
        extexecution,\
329
        extexecution,\
330
        extexecution.base,\
330
        extexecution.impl,\
331
        extexecution.impl,\
331
        git,\
332
        git,\
332
        gototest,\
333
        gototest,\
(-)a/nbbuild/javadoctools/links.xml (+1 lines)
Lines 226-228 Link Here
226
<link href="${javadoc.docs.org-openide-filesystems-compat8}" offline="true" packagelistloc="${netbeans.javadoc.dir}/org-openide-filesystems-compat8"/>
226
<link href="${javadoc.docs.org-openide-filesystems-compat8}" offline="true" packagelistloc="${netbeans.javadoc.dir}/org-openide-filesystems-compat8"/>
227
<link href="${javadoc.docs.org-openide-filesystems-compat8}" offline="true" packagelistloc="${netbeans.javadoc.dir}/org-openide-filesystems-compat8"/>
227
<link href="${javadoc.docs.org-openide-filesystems-compat8}" offline="true" packagelistloc="${netbeans.javadoc.dir}/org-openide-filesystems-compat8"/>
228
<link href="${javadoc.docs.org-netbeans-modules-parsing-indexing}" offline="true" packagelistloc="${netbeans.javadoc.dir}/org-netbeans-modules-parsing-indexing"/>
228
<link href="${javadoc.docs.org-netbeans-modules-parsing-indexing}" offline="true" packagelistloc="${netbeans.javadoc.dir}/org-netbeans-modules-parsing-indexing"/>
229
<link href="${javadoc.docs.org-netbeans-modules-extexecution-base}" offline="true" packagelistloc="${netbeans.javadoc.dir}/org-netbeans-modules-extexecution-base"/>
(-)a/nbbuild/javadoctools/properties.xml (+1 lines)
Lines 224-226 Link Here
224
<property name="javadoc.docs.org-openide-filesystems-compat8" value="${javadoc.web.root}/org-openide-filesystems-compat8"/>
224
<property name="javadoc.docs.org-openide-filesystems-compat8" value="${javadoc.web.root}/org-openide-filesystems-compat8"/>
225
<property name="javadoc.docs.org-openide-filesystems-compat8" value="${javadoc.web.root}/org-openide-filesystems-compat8"/>
225
<property name="javadoc.docs.org-openide-filesystems-compat8" value="${javadoc.web.root}/org-openide-filesystems-compat8"/>
226
<property name="javadoc.docs.org-netbeans-modules-parsing-indexing" value="${javadoc.web.root}/org-netbeans-modules-parsing-indexing"/>
226
<property name="javadoc.docs.org-netbeans-modules-parsing-indexing" value="${javadoc.web.root}/org-netbeans-modules-parsing-indexing"/>
227
<property name="javadoc.docs.org-netbeans-modules-extexecution-base" value="${javadoc.web.root}/org-netbeans-modules-extexecution-base"/>
(-)a/nbbuild/javadoctools/replaces.xml (+1 lines)
Lines 224-226 Link Here
224
<replacefilter token="@org-openide-filesystems-compat8@" value="${javadoc.docs.org-openide-filesystems-compat8}"/>
224
<replacefilter token="@org-openide-filesystems-compat8@" value="${javadoc.docs.org-openide-filesystems-compat8}"/>
225
<replacefilter token="@org-openide-filesystems-compat8@" value="${javadoc.docs.org-openide-filesystems-compat8}"/>
225
<replacefilter token="@org-openide-filesystems-compat8@" value="${javadoc.docs.org-openide-filesystems-compat8}"/>
226
<replacefilter token="@org-netbeans-modules-parsing-indexing@" value="${javadoc.docs.org-netbeans-modules-parsing-indexing}"/>
226
<replacefilter token="@org-netbeans-modules-parsing-indexing@" value="${javadoc.docs.org-netbeans-modules-parsing-indexing}"/>
227
<replacefilter token="@org-netbeans-modules-extexecution-base@" value="${javadoc.docs.org-netbeans-modules-extexecution-base}"/>

Return to bug 244308