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

(-)a/api.intent/arch.xml (+1176 lines)
Line 0 Link Here
1
<?xml version="1.0" encoding="UTF-8"?>
2
<!DOCTYPE api-answers PUBLIC "-//NetBeans//DTD Arch Answers//EN" "../nbbuild/antsrc/org/netbeans/nbbuild/Arch.dtd" [
3
  <!ENTITY api-questions SYSTEM "../nbbuild/antsrc/org/netbeans/nbbuild/Arch-api-questions.xml">
4
]>
5
6
<api-answers
7
  question-version="1.29"
8
  author="jhavlin@netbeans.org"
9
>
10
11
  &api-questions;
12
13
    <!--
14
            <question id="arch-overall" when="init">
15
                Describe the overall architecture.
16
                <hint>
17
                What will be API for
18
                <a href="http://wiki.netbeans.org/API_Design#Separate_API_for_clients_from_support_API">
19
                    clients and what support API</a>?
20
                What parts will be pluggable?
21
                How will plug-ins be registered? Please use <code>&lt;api type="export"/&gt;</code>
22
                to describe your general APIs and specify their
23
                <a href="http://wiki.netbeans.org/API_Stability#Private">
24
                stability categories</a>.
25
                If possible please provide simple diagrams.
26
                </hint>
27
            </question>
28
    -->
29
    <answer id="arch-overall">
30
        <p>
31
            Intent is an description of some intended operation. It is specified
32
            by action type (String) and a URI. When some Intent is executed,
33
            proper handler is chosen and it performs the actual operation.
34
        </p>
35
        <p>
36
            Intents provide loose coupling between modules that may request an
37
            operation and modules that can perform it. They can be easily
38
            serialized, so they are suitable for distributed heterogenous
39
            systems.
40
        </p>
41
42
        <api
43
            name="IntentAPI"
44
            group="java"
45
            type="export"
46
            category="official"
47
            url="@org-netbeans-api-intent@/org/netbeans/api/intent/package-summary.html"
48
        >
49
            <p>
50
                API for describing and executing intended operations.
51
            </p>
52
        </api>
53
        <api
54
            name="IntentHandlerSPI"
55
            group="java"
56
            type="export"
57
            category="official"
58
            url="@org-netbeans-api-intent@/org/netbeans/spi/intent/package-summary.html"
59
        >
60
            <p>
61
                SPI for handlers that are able to invoke proper operation for
62
                specified intents.
63
            </p>
64
        </api>
65
    </answer>
66
67
68
69
    <!--
70
            <question id="arch-quality" when="init">
71
                How will the <a href="http://www.netbeans.org/community/guidelines/q-evangelism.html">quality</a>
72
                of your code be tested and
73
                how are future regressions going to be prevented?
74
                <hint>
75
                What kind of testing do
76
                you want to use? How much functionality, in which areas,
77
                should be covered by the tests? How you find out that your
78
                project was successful?
79
                </hint>
80
            </question>
81
    -->
82
    <answer id="arch-quality">
83
        <p>
84
            The code is checked by unit tests.
85
        </p>
86
    </answer>
87
88
89
90
    <!--
91
            <question id="arch-time" when="init">
92
                What are the time estimates of the work?
93
                <hint>
94
                Please express your estimates of how long the design, implementation,
95
                stabilization are likely to last. How many people will be needed to
96
                implement this and what is the expected milestone by which the work should be
97
                ready?
98
                </hint>
99
            </question>
100
    -->
101
    <answer id="arch-time">
102
        <p>
103
            Done.
104
        </p>
105
    </answer>
106
107
108
109
    <!--
110
        <question id="arch-usecases" when="init">
111
            <hint>
112
                Content of this answer will be displayed as part of page at
113
                http://www.netbeans.org/download/dev/javadoc/usecases.html
114
                You can use tags &lt;usecase name="name&gt; regular html description &lt;/usecase&gt;
115
                and if you want to use an URL you can prefix if with @TOP@ to begin
116
                at the root of your javadoc
117
            </hint>
118
119
                Describe the main <a href="http://wiki.netbeans.org/API_Design#The_Importance_of_Being_Use_Case_Oriented">
120
                use cases</a> of the new API. Who will use it under
121
                what circumstances? What kind of code would typically need to be written
122
                to use the module?
123
            </question>
124
    -->
125
    <answer id="arch-usecases">
126
        <usecase id="execIntentBasic" name="Create an Intent, execute it and wait for result">
127
            <pre>
128
    Future&lt;Object&gt; result = new Intent(Intent.ACTION_VIEW, new URI("scheme://path/")).execute();
129
    Object value = result.get();
130
            </pre>
131
        </usecase>
132
133
        <usecase id="execIntentCallback" name="Create an Intent and execute it with callback">
134
            <pre>
135
    new Intent(Intent.ACTION_VIEW, new URI("scheme://path/")).execute(new Callback() {
136
      void success(Object result) {
137
        // use the result somehow
138
      }
139
      void failure(Exception exception) {
140
        // report the failure somehow
141
      }
142
    });
143
            </pre>
144
        </usecase>
145
146
        <usecase id="handleIntentSync" name="Handle some Intent">
147
            <pre>
148
   &nbsp;&#64;IntentHandlerRegistration(
149
                displayName = "Show my item in MyEditor",
150
                position = 800,
151
                uriPattern = "myscheme://.*",
152
                actions = {Intent.ACTION_VIEW, Intent.ACTION_EDIT}
153
    )
154
    public static Object handleIntent(Intent intent) {
155
        SomeType result = parseAndPerformIntentSomehow(intent);
156
        return result;
157
    }
158
            </pre>
159
        </usecase>
160
161
        <usecase id="handleIntentAsync" name="Handle some Intent using Result object">
162
            <pre>
163
   &nbsp;&#64;IntentHandlerRegistration(
164
                displayName = "Show my item in MyEditor",
165
                position = 800,
166
                uriPattern = "myscheme://.*",
167
                actions = "*"
168
    )
169
    public static void handleIntent(final Intent intent, final Result result) {
170
        // Move the execution to another thread. Do not wait for the result
171
        // here, just pass the result object.
172
        EventQueue.invokeLater(new Runnable() {
173
            public void run() {
174
                try {
175
                    Object result = doSomethingInEDT(intent);
176
                    result.setResult(e);
177
                } catch (Exception e) {
178
                    result.setException(e);
179
                }
180
            }
181
        });
182
    }
183
            </pre>
184
        </usecase>
185
    </answer>
186
187
188
189
    <!--
190
            <question id="arch-what" when="init">
191
                What is this project good for?
192
                <hint>
193
                Please provide here a few lines describing the project,
194
                what problem it should solve, provide links to documentation,
195
                specifications, etc.
196
                </hint>
197
            </question>
198
    -->
199
    <answer id="arch-what">
200
        <p>
201
            This module provides a contract between API clients that can express
202
            some intention to invoke an operation and SPI providers that can
203
            handle that intention.
204
        </p>
205
        <p>
206
            This is useful in client-server environments, where the intention
207
            can be constructed on server-side, but handled on client-side. The
208
            objects that describe the intention should be easy to construct,
209
            transfer and interpret.
210
        </p>
211
    </answer>
212
213
214
215
    <!--
216
            <question id="arch-where" when="impl">
217
                Where one can find sources for your module?
218
                <hint>
219
                    Please provide link to the Hg web client at
220
                    http://hg.netbeans.org/
221
                    or just use tag defaultanswer generate='here'
222
                </hint>
223
            </question>
224
    -->
225
    <answer id="arch-where">
226
        <defaultanswer generate='here' />
227
    </answer>
228
229
230
231
    <!--
232
            <question id="compat-deprecation" when="init">
233
                How the introduction of your project influences functionality
234
                provided by previous version of the product?
235
                <hint>
236
                If you are planning to deprecate/remove/change any existing APIs,
237
                list them here accompanied with the reason explaining why you
238
                are doing so.
239
                </hint>
240
            </question>
241
    -->
242
    <answer id="compat-deprecation">
243
        <p>
244
            No deprecation needed.
245
        </p>
246
    </answer>
247
248
249
250
    <!--
251
            <question id="compat-i18n" when="impl">-<replacefilter token="@org-netbeans-modules-masterfs-ui@" value="${javadoc.docs.org-netbeans-modules-masterfs-ui}"/>
252
-<replacefilter token="@org-netbeans-modules-parsing-nb@" value="${javadoc.docs.org-netbeans-modules-parsing-nb}"/>
253
-<replacefilter token="@org-netbeans-modules-project-libraries-ui@" value="${javadoc.docs.org-netbeans-modules-project-libraries-ui}"/>
254
-<replacefilter token="@org-openide-filesystems-nb@" value="${javadoc.docs.org-openide-filesystems-nb}"/>
255
                Is your module correctly internationalized?
256
                <hint>
257
                Correct internationalization means that it obeys instructions
258
                at <a href="http://www.netbeans.org/download/dev/javadoc/org-openide-modules/org/openide/modules/doc-files/i18n-branding.html">
259
                NetBeans I18N pages</a>.
260
                </hint>
261
            </question>
262
    -->
263
    <answer id="compat-i18n">
264
        <p>
265
            Yes.
266
        </p>
267
    </answer>
268
269
270
271
    <!--
272
            <question id="compat-standards" when="init">
273
                Does the module implement or define any standards? Is the
274
                implementation exact or does it deviate somehow?
275
            </question>
276
    -->
277
    <answer id="compat-standards">
278
        <p>
279
            No standards.
280
        </p>
281
    </answer>
282
283
284
285
<!--
286
        <question id="compat-version" when="impl">
287
            Can your module coexist with earlier and future
288
            versions of itself? Can you correctly read all old settings? Will future
289
            versions be able to read your current settings? Can you read
290
            or politely ignore settings stored by a future version?
291
292
                <hint>
293
                Very helpful for reading settings is to store version number
294
                there, so future versions can decide whether how to read/convert
295
                the settings and older versions can ignore the new ones.
296
                </hint>
297
            </question>
298
    -->
299
    <answer id="compat-version">
300
        <p>
301
            No settings are read or written.
302
        </p>
303
    </answer>
304
305
306
307
    <!--
308
            <question id="dep-jre" when="final">
309
                Which version of JRE do you need (1.2, 1.3, 1.4, etc.)?
310
                <hint>
311
                It is expected that if your module runs on 1.x that it will run
312
                on 1.x+1 if no, state that please. Also describe here cases where
313
                you run different code on different versions of JRE and why.
314
                </hint>
315
            </question>
316
    -->
317
    <answer id="dep-jre">
318
        <p>
319
            1.6
320
        </p>
321
    </answer>
322
323
324
325
    <!--
326
            <question id="dep-jrejdk" when="final">
327
                Do you require the JDK or is the JRE enough?
328
            </question>
329
    -->
330
    <answer id="dep-jrejdk">
331
        <p>
332
            JRE
333
        </p>
334
    </answer>
335
336
337
338
    <!--
339
            <question id="dep-nb" when="init">
340
                What other NetBeans projects and modules does this one depend on?
341
                <hint>
342
                Depending on other NetBeans projects influnces the ability of
343
                users of your work to customize their own branded version of
344
                NetBeans by enabling and disabling some modules. Too
345
                much dependencies restrict this kind of customization. If that
346
                is your case, then you may want to split your functionality into
347
                pieces of autoload, eager and regular modules which can be
348
                enabled independently. Usually the answer to this question
349
                is generated from your <code>project.xml</code> file, but
350
                if it is not guessed correctly, you can suppress it by
351
                specifying &lt;defaultanswer generate="none"/&gt; and
352
                write here your own. Please describe such projects as imported APIs using
353
                the <code>&lt;api name="identification" type="import or export" category="stable" url="where is the description" /&gt;</code>.
354
                By doing this information gets listed in the summary page of your
355
                javadoc.
356
                </hint>
357
            </question>
358
    -->
359
    <answer id="dep-nb">
360
        <defaultanswer generate='here' />
361
    </answer>
362
363
364
365
    <!--
366
        <question id="dep-non-nb" when="init">
367
            What other projects outside NetBeans does this one depend on?
368
369
                <hint>
370
                Depending on 3rd party libraries is always problematic,
371
                especially if they are not open source, as that complicates
372
                the licensing scheme of NetBeans. Please enumerate your
373
                external dependencies here, so it is correctly understood since
374
                the begining what are the legal implications of your project.
375
                Also please note that
376
                some non-NetBeans projects are packaged as NetBeans modules
377
                (see <a href="http://libs.netbeans.org/">libraries</a>) and
378
                it is preferred to use this approach when more modules may
379
                depend and share such third-party libraries.
380
                </hint>
381
            </question>
382
    -->
383
    <answer id="dep-non-nb">
384
        <p>
385
            No non-NB dependencies.
386
        </p>
387
    </answer>
388
389
390
391
    <!--
392
            <question id="dep-platform" when="init">
393
                On which platforms does your module run? Does it run in the same
394
                way on each?
395
                <hint>
396
                If you plan any dependency on OS or any usage of native code,
397
                please describe why you are doing so and describe how you envision
398
                to enforce the portability of your code.
399
                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
400
                enabled modules</a> which together with autoload/eager modules
401
                can allow you to enable to provide the best OS aware support
402
                on certain OSes while providing compatibility bridge on the not
403
                supported ones.
404
                Also please list the supported
405
                OSes/HW platforms and mentioned the lovest version of JDK required
406
                for your project to run on. Also state whether JRE is enough or
407
                you really need JDK.
408
                </hint>
409
            </question>
410
    -->
411
    <answer id="dep-platform">
412
        <p>
413
            Any platform.
414
        </p>
415
    </answer>
416
417
418
419
    <!--
420
            <question id="deploy-dependencies" when="final">
421
                What do other modules need to do to declare a dependency on this one,
422
                in addition to or instead of the normal module dependency declaration
423
                (e.g. tokens to require)?
424
                <hint>
425
                    Provide a sample of the actual lines you would add to a module manifest
426
                    to declare a dependency, for example OpenIDE-Module-Requires: some.token.
427
                    If other modules should not depend on this module, or should just use a
428
                    simple regular module dependency, you can just answer "nothing". If you
429
                    intentionally expose a semistable API to clients using implementation
430
                    dependencies, you should mention that here (but there is no need to give
431
                    an example of usage).
432
                </hint>
433
            </question>
434
    -->
435
    <answer id="deploy-dependencies">
436
        <p>
437
            Standard module dependency is sufficient.
438
        </p>
439
    </answer>
440
441
442
443
    <!--
444
        <question id="deploy-jar" when="impl">
445
            Do you deploy just module JAR file(s) or other files as well?
446
            <hint>
447
            Usually a module consist of one JAR file (perhaps with Class-Path
448
            extensions) and also a configuration file that enables it. If you
449
            have any other files, use
450
            &lt;api group="java.io.File" name="yourname" type="export" category="friend"&gt;...&lt;/api&gt;
451
            to define the location, name and stability of your files (of course
452
            changing "yourname" and "friend" to suit your needs).
453
454
                If it uses more than one JAR, describe where they are located, how
455
                they refer to each other.
456
                If it consist of module JAR(s) and other files, please describe
457
                what is their purpose, why other files are necessary. Please
458
                make sure that installation/uninstallation leaves the system
459
                in state as it was before installation.
460
                </hint>
461
            </question>
462
    -->
463
    <answer id="deploy-jar">
464
        <p>
465
            Just module JAR.
466
        </p>
467
    </answer>
468
469
470
471
    <!--
472
            <question id="deploy-nbm" when="impl">
473
                Can you deploy an NBM via the Update Center?
474
                <hint>
475
                If not why?
476
                </hint>
477
            </question>
478
    -->
479
    <answer id="deploy-nbm">
480
        <p>
481
            Yes.
482
        </p>
483
    </answer>
484
485
486
487
<!--
488
        <question id="deploy-packages" when="init">
489
            Are packages of your module made inaccessible by not declaring them
490
            public?
491
492
                <hint>
493
                By default NetBeans build harness treats all packages are private.
494
                If you export some of them - either as public or friend packages,
495
                you should have a reason. If the reason is described elsewhere
496
                in this document, you can ignore this question.
497
                </hint>
498
            </question>
499
    -->
500
    <answer id="deploy-packages">
501
        <p>
502
            Only API and SPI packages are public.
503
        </p>
504
    </answer>
505
506
507
508
    <!--
509
            <question id="deploy-shared" when="final">
510
                Do you need to be installed in the shared location only, or in the user directory only,
511
                or can your module be installed anywhere?
512
                <hint>
513
                Installation location shall not matter, if it does explain why.
514
                Consider also whether <code>InstalledFileLocator</code> can help.
515
                </hint>
516
            </question>
517
    -->
518
    <answer id="deploy-shared">
519
        <p>
520
            Installation location does not matter.
521
        </p>
522
    </answer>
523
524
525
526
    <!--
527
        <question id="exec-ant-tasks" when="impl">
528
            Do you define or register any ant tasks that other can use?
529
530
                <hint>
531
                If you provide an ant task that users can use, you need to be very
532
                careful about its syntax and behaviour, as it most likely forms an
533
                      API for end users and as there is a lot of end users, their reaction
534
                when such API gets broken can be pretty strong.
535
                </hint>
536
            </question>
537
    -->
538
    <answer id="exec-ant-tasks">
539
        <p>
540
            No.
541
        </p>
542
    </answer>
543
544
545
546
    <!--
547
            <question id="exec-classloader" when="impl">
548
                Does your code create its own class loader(s)?
549
                <hint>
550
                A bit unusual. Please explain why and what for.
551
                </hint>
552
            </question>
553
    -->
554
    <answer id="exec-classloader">
555
        <p>
556
            No.
557
        </p>
558
    </answer>
559
560
561
562
    <!--
563
        <question id="exec-component" when="impl">
564
            Is execution of your code influenced by any (string) property
565
            of any of your components?
566
567
                <hint>
568
                Often <code>JComponent.getClientProperty</code>, <code>Action.getValue</code>
569
                or <code>PropertyDescriptor.getValue</code>, etc. are used to influence
570
                a behavior of some code. This of course forms an interface that should
571
                be documented. Also if one depends on some interface that an object
572
                implements (<code>component instanceof Runnable</code>) that forms an
573
                API as well.
574
                </hint>
575
            </question>
576
    -->
577
    <answer id="exec-component">
578
        <p>
579
            No.
580
        </p>
581
    </answer>
582
583
584
585
    <!--
586
            <question id="exec-introspection" when="impl">
587
                Does your module use any kind of runtime type information (<code>instanceof</code>,
588
                work with <code>java.lang.Class</code>, etc.)?
589
                <hint>
590
                Check for cases when you have an object of type A and you also
591
                expect it to (possibly) be of type B and do some special action. That
592
                should be documented. The same applies on operations in meta-level
593
                (Class.isInstance(...), Class.isAssignableFrom(...), etc.).
594
                </hint>
595
            </question>
596
    -->
597
    <answer id="exec-introspection">
598
        <p>
599
            No.
600
        </p>
601
    </answer>
602
603
604
605
    <!--
606
            <question id="exec-privateaccess" when="final">
607
                Are you aware of any other parts of the system calling some of
608
                your methods by reflection?
609
                <hint>
610
                If so, describe the "contract" as an API. Likely private or friend one, but
611
                still API and consider rewrite of it.
612
                </hint>
613
            </question>
614
    -->
615
    <answer id="exec-privateaccess">
616
        <p>
617
            No.
618
        </p>
619
    </answer>
620
621
622
623
    <!--
624
            <question id="exec-process" when="impl">
625
                Do you execute an external process from your module? How do you ensure
626
                that the result is the same on different platforms? Do you parse output?
627
                Do you depend on result code?
628
                <hint>
629
                If you feed an input, parse the output please declare that as an API.
630
                </hint>
631
            </question>
632
    -->
633
    <answer id="exec-process">
634
        <p>
635
            No.
636
        </p>
637
    </answer>
638
639
640
641
    <!--
642
            <question id="exec-property" when="impl">
643
                Is execution of your code influenced by any environment or
644
                Java system (<code>System.getProperty</code>) property?
645
                On a similar note, is there something interesting that you
646
                pass to <code>java.util.logging.Logger</code>? Or do you observe
647
                what others log?
648
                <hint>
649
                If there is a property that can change the behavior of your
650
                code, somebody will likely use it. You should describe what it does
651
                and the <a href="http://wiki.netbeans.org/API_Stability">stability category</a>
652
                of this API. You may use
653
                <pre>
654
                    &lt;api type="export" group="property" name="id" category="private" url="http://..."&gt;
655
                        description of the property, where it is used, what it influence, etc.
656
                    &lt;/api&gt;
657
                </pre>
658
                </hint>
659
            </question>
660
    -->
661
    <answer id="exec-property">
662
        <p>
663
            No.
664
        </p>
665
    </answer>
666
667
668
669
    <!--
670
            <question id="exec-reflection" when="impl">
671
                Does your code use Java Reflection to execute other code?
672
                <hint>
673
                This usually indicates a missing or insufficient API in the other
674
                part of the system. If the other side is not aware of your dependency
675
                this contract can be easily broken.
676
                </hint>
677
            </question>
678
    -->
679
    <answer id="exec-reflection">
680
        <p>
681
            No.
682
        </p>
683
    </answer>
684
685
686
687
    <!--
688
            <question id="exec-threading" when="init">
689
                What threading models, if any, does your module adhere to? How the
690
                project behaves with respect to threading?
691
                <hint>
692
                    Is your API threadsafe? Can it be accessed from any threads or
693
                    just from some dedicated ones? Any special relation to AWT and
694
                    its Event Dispatch thread? Also
695
                    if your module calls foreign APIs which have a specific threading model,
696
                    indicate how you comply with the requirements for multithreaded access
697
                    (synchronization, mutexes, etc.) applicable to those APIs.
698
                    If your module defines any APIs, or has complex internal structures
699
                    that might be used from multiple threads, declare how you protect
700
                    data against concurrent access, race conditions, deadlocks, etc.,
701
                    and whether such rules are enforced by runtime warnings, errors, assertions, etc.
702
                    Examples: a class might be non-thread-safe (like Java Collections); might
703
                    be fully thread-safe (internal locking); might require access through a mutex
704
                    (and may or may not automatically acquire that mutex on behalf of a client method);
705
                    might be able to run only in the event queue; etc.
706
                    Also describe when any events are fired: synchronously, asynchronously, etc.
707
                    Ideas: <a href="http://core.netbeans.org/proposals/threading/index.html#recommendations">Threading Recommendations</a> (in progress)
708
                </hint>
709
            </question>
710
    -->
711
    <answer id="exec-threading">
712
        <p>
713
            The API is threadsafe. SPI implementations should ensure proper
714
            synchronization.
715
        </p>
716
    </answer>
717
718
719
720
    <!--
721
        <question id="format-clipboard" when="impl">
722
            Which data flavors (if any) does your code read from or insert to
723
            the clipboard (by access to clipboard on means calling methods on <code>java.awt.datatransfer.Transferable</code>?
724
725
                <hint>
726
                Often Node's deal with clipboard by usage of <code>Node.clipboardCopy, Node.clipboardCut and Node.pasteTypes</code>.
727
                Check your code for overriding these methods.
728
                </hint>
729
            </question>
730
    -->
731
    <answer id="format-clipboard">
732
        <p>
733
            No clipboard access.
734
        </p>
735
    </answer>
736
737
738
739
    <!--
740
            <question id="format-dnd" when="impl">
741
                Which protocols (if any) does your code understand during Drag &amp; Drop?
742
                <hint>
743
                Often Node's deal with clipboard by usage of <code>Node.drag, Node.getDropType</code>.
744
                Check your code for overriding these methods. Btw. if they are not overridden, they
745
                by default delegate to <code>Node.clipboardCopy, Node.clipboardCut and Node.pasteTypes</code>.
746
                </hint>
747
            </question>
748
    -->
749
    <answer id="format-dnd">
750
        <p>
751
            No Drag &amp; Drop support.
752
        </p>
753
    </answer>
754
755
756
757
<!--
758
        <question id="format-types" when="impl">
759
            Which protocols and file formats (if any) does your module read or write on disk,
760
            or transmit or receive over the network? Do you generate an ant build script?
761
            Can it be edited and modified?
762
763
            <hint>
764
                <p>
765
                Files can be read and written by other programs, modules and users. If they influence
766
                your behaviour, make sure you either document the format or claim that it is a private
767
                api (using the &lt;api&gt; tag).
768
                </p>
769
                <p>
770
                If you generate an ant build file, this is very likely going to be seen by end users and
771
                they will be attempted to edit it. You should be ready for that and provide here a link
772
                to documentation that you have for such purposes and also describe how you are going to
773
                understand such files during next release, when you (very likely) slightly change the
774
                format.
775
                </p>
776
                </hint>
777
            </question>
778
    -->
779
    <answer id="format-types">
780
        <p>
781
            No files are read or written by this module.
782
        </p>
783
    </answer>
784
785
786
787
<!--
788
        <question id="lookup-lookup" when="init">
789
            Does your module use <code>org.openide.util.Lookup</code>
790
            or any similar technology to find any components to communicate with? Which ones?
791
792
                <hint>
793
                NetBeans is build around a generic registry of services called
794
                lookup. It is preferable to use it for registration and discovery
795
                if possible. See
796
                <a href="http://www.netbeans.org/download/dev/javadoc/org-openide-util/org/openide/util/lookup/doc-files/index.html">
797
                The Solution to Comunication Between Components
798
                </a>. If you do not plan to use lookup and insist usage
799
                of other solution, then please describe why it is not working for
800
                you.
801
                <br/>
802
                When filling the final version of your arch document, please
803
                describe the interfaces you are searching for, where
804
                are defined, whether you are searching for just one or more of them,
805
                if the order is important, etc. Also classify the stability of such
806
                API contract. Use &lt;api group=&amp;lookup&amp; /&gt; tag, so
807
                your information gets listed in the summary page of your javadoc.
808
                </hint>
809
            </question>
810
    -->
811
    <answer id="lookup-lookup">
812
        <p>
813
            No.
814
        </p>
815
    </answer>
816
817
818
819
    <!--
820
            <question id="lookup-register" when="final">
821
                Do you register anything into lookup for other code to find?
822
                <hint>
823
                Do you register using layer file or using a declarative annotation such as <code>@ServiceProvider</code>?
824
                Who is supposed to find your component?
825
                </hint>
826
            </question>
827
    -->
828
    <answer id="lookup-register">
829
        <p>
830
            The annotation processor is registered using ServiceProvider.
831
        </p>
832
    </answer>
833
834
835
836
    <!--
837
            <question id="lookup-remove" when="final">
838
                Do you remove entries of other modules from lookup?
839
                <hint>
840
                Why? Of course, that is possible, but it can be dangerous. Is the module
841
                your are masking resource from aware of what you are doing?
842
                </hint>
843
            </question>
844
    -->
845
    <answer id="lookup-remove">
846
        <p>
847
            No.
848
        </p>
849
    </answer>
850
851
852
853
    <!--
854
            <question id="perf-exit" when="final">
855
                Does your module run any code on exit?
856
            </question>
857
    -->
858
    <answer id="perf-exit">
859
        <p>
860
            No.
861
        </p>
862
    </answer>
863
864
865
866
    <!--
867
            <question id="perf-huge_dialogs" when="final">
868
                Does your module contain any dialogs or wizards with a large number of
869
                GUI controls such as combo boxes, lists, trees, or text areas?
870
            </question>
871
    -->
872
    <answer id="perf-huge_dialogs">
873
        <p>
874
            No.
875
        </p>
876
    </answer>
877
878
879
880
    <!--
881
            <question id="perf-limit" when="init">
882
                Are there any hard-coded or practical limits in the number or size of
883
                elements your code can handle?
884
                <hint>
885
                    Most of algorithms have increasing memory and speed complexity
886
                    with respect to size of data they operate on. What is the critical
887
                    part of your project that can be seen as a bottleneck with
888
                    respect to speed or required memory? What are the practical
889
                    sizes of data you tested your project with? What is your estimate
890
                    of potential size of data that would cause visible performance
891
                    problems? Is there some kind of check to detect such situation
892
                    and prevent "hard" crashes - for example the CloneableEditorSupport
893
                    checks for size of a file to be opened in editor
894
                    and if it is larger than 1Mb it shows a dialog giving the
895
                    user the right to decide - e.g. to cancel or commit suicide.
896
                </hint>
897
            </question>
898
    -->
899
    <answer id="perf-limit">
900
        <p>
901
            No.
902
        </p>
903
    </answer>
904
905
906
907
    <!--
908
            <question id="perf-mem" when="final">
909
                How much memory does your component consume? Estimate
910
                with a relation to the number of windows, etc.
911
            </question>
912
    -->
913
    <answer id="perf-mem">
914
        <p>
915
            Very little memory consumed.
916
        </p>
917
    </answer>
918
919
920
921
    <!--
922
            <question id="perf-menus" when="final">
923
                Does your module use dynamically updated context menus, or
924
                context-sensitive actions with complicated and slow enablement logic?
925
                <hint>
926
                    If you do a lot of tricks when adding actions to regular or context menus, you can significantly
927
                    slow down display of the menu, even when the user is not using your action. Pay attention to
928
                    actions you add to the main menu bar, and to context menus of foreign nodes or components. If
929
                    the action is conditionally enabled, or changes its display dynamically, you need to check the
930
                    impact on performance. In some cases it may be more appropriate to make a simple action that is
931
                    always enabled but does more detailed checks in a dialog if it is actually run.
932
                </hint>
933
            </question>
934
    -->
935
    <answer id="perf-menus">
936
        <p>
937
            No.
938
        </p>
939
    </answer>
940
941
942
943
    <!--
944
        <question id="perf-progress" when="final">
945
            Does your module execute any long-running tasks?
946
947
                <hint>Long running tasks should never block
948
                AWT thread as it badly hurts the UI
949
                <a href="http://performance.netbeans.org/responsiveness/issues.html">
950
                responsiveness</a>.
951
                Tasks like connecting over
952
                network, computing huge amount of data, compilation
953
                be done asynchronously (for example
954
                using <code>RequestProcessor</code>), definitively it should
955
                not block AWT thread.
956
                </hint>
957
            </question>
958
    -->
959
    <answer id="perf-progress">
960
        <p>
961
            No.
962
        </p>
963
    </answer>
964
965
966
967
    <!--
968
            <question id="perf-scale" when="init">
969
                Which external criteria influence the performance of your
970
                program (size of file in editor, number of files in menu,
971
                in source directory, etc.) and how well your code scales?
972
                <hint>
973
                Please include some estimates, there are other more detailed
974
                questions to answer in later phases of implementation.
975
                </hint>
976
            </question>
977
    -->
978
    <answer id="perf-scale">
979
        <p>
980
            Code in the module is very simple. Performance is incluenced mosly
981
            by SPI implementations, which should run quite quickly.
982
        </p>
983
    </answer>
984
985
986
987
    <!--
988
            <question id="perf-spi" when="init">
989
                How the performance of the plugged in code will be enforced?
990
                <hint>
991
                If you allow foreign code to be plugged into your own module, how
992
                do you enforce that it will behave correctly and quickly and will not
993
                negatively influence the performance of your own module?
994
                </hint>
995
            </question>
996
    -->
997
    <answer id="perf-spi">
998
        <p>
999
            No performance criteria are enforced. The plugged-in code is invoked
1000
            by a dedicated executor.
1001
        </p>
1002
    </answer>
1003
1004
1005
1006
    <!--
1007
            <question id="perf-startup" when="final">
1008
                Does your module run any code on startup?
1009
            </question>
1010
    -->
1011
    <answer id="perf-startup">
1012
        <p>
1013
            No.
1014
        </p>
1015
    </answer>
1016
1017
1018
1019
    <!--
1020
            <question id="perf-wakeup" when="final">
1021
                Does any piece of your code wake up periodically and do something
1022
                even when the system is otherwise idle (no user interaction)?
1023
            </question>
1024
    -->
1025
    <answer id="perf-wakeup">
1026
        <p>
1027
            No.
1028
        </p>
1029
    </answer>
1030
1031
1032
1033
    <!--
1034
        <question id="resources-file" when="final">
1035
            Does your module use <code>java.io.File</code> directly?
1036
1037
                <hint>
1038
                NetBeans provide a logical wrapper over plain files called
1039
                <code>org.openide.filesystems.FileObject</code> that
1040
                provides uniform access to such resources and is the preferred
1041
                way that should be used. But of course there can be situations when
1042
                this is not suitable.
1043
                </hint>
1044
            </question>
1045
    -->
1046
    <answer id="resources-file">
1047
        <p>
1048
            No.
1049
        </p>
1050
    </answer>
1051
1052
1053
1054
    <!--
1055
        <question id="resources-layer" when="final">
1056
            Does your module provide own layer? Does it create any files or
1057
            folders in it? What it is trying to communicate by that and with which
1058
            components?
1059
1060
                <hint>
1061
                NetBeans allows automatic and declarative installation of resources
1062
                by module layers. Module register files into appropriate places
1063
                and other components use that information to perform their task
1064
                (build menu, toolbar, window layout, list of templates, set of
1065
                options, etc.).
1066
                </hint>
1067
            </question>
1068
    -->
1069
    <answer id="resources-layer">
1070
        <p>
1071
            No.
1072
        </p>
1073
    </answer>
1074
1075
1076
1077
    <!--
1078
        <question id="resources-mask" when="final">
1079
            Does your module mask/hide/override any resources provided by other modules in
1080
            their layers?
1081
1082
                <hint>
1083
                If you mask a file provided by another module, you probably depend
1084
                on that and do not want the other module to (for example) change
1085
                the file's name. That module shall thus make that file available as an API
1086
                of some stability category.
1087
                </hint>
1088
            </question>
1089
    -->
1090
    <answer id="resources-mask">
1091
        <p>
1092
            No.
1093
        </p>
1094
    </answer>
1095
1096
1097
1098
    <!--
1099
            <question id="resources-preferences" when="final">
1100
                Does your module uses preferences via Preferences API? Does your module use NbPreferences or
1101
                or regular JDK Preferences ? Does it read, write or both ?
1102
                Does it share preferences with other modules ? If so, then why ?
1103
                <hint>
1104
                    You may use
1105
                        &lt;api type="export" group="preferences"
1106
                        name="preference node name" category="private"&gt;
1107
                        description of individual keys, where it is used, what it
1108
                        influences, whether the module reads/write it, etc.
1109
                        &lt;/api&gt;
1110
                    Due to XML ID restrictions, rather than /org/netbeans/modules/foo give the "name" as org.netbeans.modules.foo.
1111
                    Note that if you use NbPreferences this name will then be the same as the code name base of the module.
1112
                </hint>
1113
            </question>
1114
    -->
1115
    <answer id="resources-preferences">
1116
        <p>
1117
            No.
1118
        </p>
1119
    </answer>
1120
1121
1122
1123
    <!--
1124
        <question id="resources-read" when="final">
1125
            Does your module read any resources from layers? For what purpose?
1126
1127
                <hint>
1128
                As this is some kind of intermodule dependency, it is a kind of API.
1129
                Please describe it and classify according to
1130
                <a href="http://wiki.netbeans.org/API_Design#What_is_an_API.3F">
1131
                common stability categories</a>.
1132
                </hint>
1133
            </question>
1134
    -->
1135
    <answer id="resources-read">
1136
        <p>
1137
            No.
1138
        </p>
1139
    </answer>
1140
1141
1142
1143
    <!--
1144
            <question id="security-grant" when="final">
1145
                Does your code grant additional rights to some other code?
1146
                <hint>Avoid using a class loader that adds extra
1147
                permissions to loaded code unless really necessary.
1148
                Also note that your API implementation
1149
                can also expose unneeded permissions to enemy code by
1150
                calling AccessController.doPrivileged().</hint>
1151
            </question>
1152
    -->
1153
    <answer id="security-grant">
1154
        <p>
1155
            No.
1156
        </p>
1157
    </answer>
1158
1159
1160
1161
    <!--
1162
            <question id="security-policy" when="final">
1163
                Does your functionality require modifications to the standard policy file?
1164
                <hint>Your code might pass control to third-party code not
1165
                coming from trusted domains. This could be code downloaded over the
1166
                network or code coming from libraries that are not bundled
1167
                with NetBeans. Which permissions need to be granted to which domains?</hint>
1168
            </question>
1169
    -->
1170
    <answer id="security-policy">
1171
        <p>
1172
            No.
1173
        </p>
1174
    </answer>
1175
1176
</api-answers>
(-)a/api.intent/build.xml (+5 lines)
Line 0 Link Here
1
<?xml version="1.0" encoding="UTF-8"?>
2
<project basedir="." default="netbeans" name="api.intent">
3
    <description>Builds, tests, and runs the project org.netbeans.api.intent</description>
4
    <import file="../nbbuild/templates/projectized.xml"/>
5
</project>
(-)a/api.intent/manifest.mf (+6 lines)
Line 0 Link Here
1
Manifest-Version: 1.0
2
AutoUpdate-Show-In-Client: true
3
OpenIDE-Module: org.netbeans.api.intent
4
OpenIDE-Module-Localizing-Bundle: org/netbeans/api/intent/Bundle.properties
5
OpenIDE-Module-Specification-Version: 1.0
6
(-)a/api.intent/nbproject/project.properties (+4 lines)
Line 0 Link Here
1
is.autoload=true
2
javac.source=1.7
3
javac.compilerargs=-Xlint -Xlint:-serial
4
javadoc.arch=${basedir}/arch.xml
(-)a/api.intent/nbproject/project.xml (+61 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.api.intent</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.25</specification-version>
15
                    </run-dependency>
16
                </dependency>
17
                <dependency>
18
                    <code-name-base>org.openide.filesystems</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</code-name-base>
27
                    <build-prerequisite/>
28
                    <compile-dependency/>
29
                    <run-dependency>
30
                        <specification-version>9.3</specification-version>
31
                    </run-dependency>
32
                </dependency>
33
                <dependency>
34
                    <code-name-base>org.openide.util.lookup</code-name-base>
35
                    <build-prerequisite/>
36
                    <compile-dependency/>
37
                    <run-dependency>
38
                        <specification-version>8.26</specification-version>
39
                    </run-dependency>
40
                </dependency>
41
            </module-dependencies>
42
            <test-dependencies>
43
                <test-type>
44
                    <name>unit</name>
45
                    <test-dependency>
46
                        <code-name-base>org.netbeans.libs.junit4</code-name-base>
47
                        <compile-dependency/>
48
                    </test-dependency>
49
                    <test-dependency>
50
                        <code-name-base>org.netbeans.modules.nbjunit</code-name-base>
51
                        <compile-dependency/>
52
                    </test-dependency>
53
                </test-type>
54
            </test-dependencies>
55
            <public-packages>
56
                <package>org.netbeans.api.intent</package>
57
                <package>org.netbeans.spi.intent</package>
58
            </public-packages>
59
        </data>
60
    </configuration>
61
</project>
(-)a/api.intent/src/org/netbeans/api/intent/Bundle.properties (+7 lines)
Line 0 Link Here
1
OpenIDE-Module-Display-Category=Infrastructure
2
OpenIDE-Module-Long-Description=\
3
    API for invoking intended operations (described by suitable type of object, e.g. \
4
    URI) by some of registered handlers.\n\
5
    SPI for handlers of possible intended operations.
6
OpenIDE-Module-Name=Intent API
7
OpenIDE-Module-Short-Description=Performing intended operations by suitable handlers
(-)a/api.intent/src/org/netbeans/api/intent/Callback.java (+72 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
package org.netbeans.api.intent;
43
44
import org.netbeans.api.annotations.common.NonNull;
45
import org.netbeans.api.annotations.common.NullAllowed;
46
47
/**
48
 * Callback invoked when an intent action has finished. It is run in a dedicated
49
 * thread in background.
50
 *
51
 * @see Intent#execute(org.netbeans.api.intent.Callback)
52
 *
53
 * @author jhavlin
54
 */
55
public interface Callback {
56
57
    /**
58
     * Invoked when the intent action has completed successfully. The type of
59
     * result depends on implementation of chosen intent handler, it can be
60
     * null.
61
     *
62
     * @param result Result value.
63
     */
64
    public void success(@NullAllowed Object result);
65
66
    /**
67
     * Invoked when the intent action has failed.
68
     *
69
     * @param exception Encountered exception.
70
     */
71
    public void failure(@NonNull Exception exception);
72
}
(-)a/api.intent/src/org/netbeans/api/intent/Intent.java (+290 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
package org.netbeans.api.intent;
43
44
import java.net.URI;
45
import java.util.Arrays;
46
import java.util.Collections;
47
import java.util.Comparator;
48
import java.util.List;
49
import java.util.SortedSet;
50
import java.util.TreeSet;
51
import java.util.concurrent.Callable;
52
import java.util.concurrent.Future;
53
import java.util.logging.Level;
54
import java.util.logging.Logger;
55
import java.util.regex.Pattern;
56
import org.netbeans.api.annotations.common.NonNull;
57
import org.netbeans.api.annotations.common.NullAllowed;
58
import org.netbeans.modules.intent.CallbackResult;
59
import org.netbeans.modules.intent.IntentHandler;
60
import org.netbeans.modules.intent.SettableResult;
61
import org.netbeans.spi.intent.Result;
62
import org.openide.filesystems.FileObject;
63
import org.openide.filesystems.FileUtil;
64
import org.openide.util.Parameters;
65
66
/**
67
 * Description of some intended operation. The operation is described by an
68
 * action and a URI.
69
 *
70
 * <p>
71
 * If the intent is executed, proper registered handler is chosen to perform the
72
 * actual operation.
73
 * </p>
74
 * <p>
75
 * For example, the following code can be used to open a file in editor (if the
76
 * environment is suitable for such operation).
77
 * </p>
78
 * <code>
79
 * new Intent(Intent.ACTION_VIEW, new URI("file://path/file.txt")).execute();
80
 * </code>
81
 *
82
 * @author jhavlin
83
 */
84
public final class Intent {
85
86
    private static final Logger LOG = Logger.getLogger(Intent.class.getName());
87
88
    /**
89
     * Standard VIEW action type.
90
     */
91
    public static final String ACTION_VIEW = "VIEW";                    //NOI18N
92
93
    /**
94
     * Standard EDIT action type.
95
     */
96
    public static final String ACTION_EDIT = "EDIT";                    //NOI18N
97
98
    private final String action;
99
    private final URI uri;
100
101
    /**
102
     * Constructor for an intended operation.
103
     *
104
     * @param action Action type to perform. It is recommended to use either
105
     * standard actions predefined in Intent class (see {@link #ACTION_EDIT},
106
     * {@link #ACTION_VIEW}), or strings similar to fully qualified field names
107
     * (e.g. "org.some.package.ClassName.ACTION_CUSTOM").
108
     *
109
     * @param uri URI specifying the operation.
110
     */
111
    public Intent(@NonNull String action, @NonNull URI uri) {
112
        Parameters.notNull("action", action);
113
        Parameters.notNull("uri", uri);
114
        this.action = action;
115
        this.uri = uri;
116
    }
117
118
    /**
119
     * Get action type.
120
     *
121
     * @return The action type.
122
     */
123
    public @NonNull String getAction() {
124
        return action;
125
    }
126
127
    /**
128
     * Get URI specifying this intent.
129
     *
130
     * @return The URI.
131
     */
132
    public @NonNull URI getUri() {
133
        return uri;
134
    }
135
136
    /**
137
     * Execute the intent. The operation will be run asynchronously.
138
     * <p>
139
     * If the result is ignored, it's recommended to use
140
     * {@code intent.execute(null);}
141
     * </p>
142
     *
143
     * @return {@link Future} Future for result of the action. The type of
144
     * result depends on implementation of chosen intent handler, it can be
145
     * null.
146
     */
147
    public @NonNull Future<Object> execute() {
148
        return IntentHandler.RP.submit(new Callable<Object>() {
149
150
            @Override
151
            public Object call() throws Exception {
152
                SettableResult sr = new SettableResult();
153
                invoke(Intent.this, sr);
154
                if (sr.getException() != null) {
155
                    throw sr.getException();
156
                }
157
                return sr.getResult();
158
            }
159
        });
160
    }
161
162
    /**
163
     * Execute the intent. The operation will be run asynchronously.
164
     *
165
     * @param callback Callback object that will be notified when the execution
166
     * completes. If callback is null, the result will be ignored.
167
     */
168
    public void execute(@NullAllowed final Callback callback) {
169
        IntentHandler.RP.post(new Runnable() {
170
171
            @Override
172
            public void run() {
173
                invoke(Intent.this, callback == null
174
                        ? null
175
                        : new CallbackResult(callback));
176
            }
177
        });
178
    }
179
180
    /**
181
     * Get available actions for the intent.
182
     *
183
     * @return Immutable set of available actions, sorted by priority.
184
     */
185
    public @NonNull SortedSet<? extends IntentAction> getIntentActions() {
186
        SortedSet<IntentHandler> intentHandlers = getIntentHandlers(this);
187
        SortedSet<IntentAction> actions = new TreeSet<>(
188
                new Comparator<IntentAction>() {
189
190
                    @Override
191
                    public int compare(IntentAction o1, IntentAction o2) {
192
                        return o1.getPosition() - o2.getPosition();
193
                    }
194
                });
195
        for (IntentHandler ih : intentHandlers) {
196
            actions.add(new IntentAction(this, ih));
197
        }
198
        return Collections.unmodifiableSortedSet(actions);
199
    }
200
201
    private static SortedSet<IntentHandler> getIntentHandlers(
202
            Intent intent) {
203
204
        FileObject f = FileUtil.getConfigFile("Services/Intent/Handlers");
205
        if (f == null) {
206
            return null;
207
        }
208
        SortedSet<IntentHandler> candidates = new TreeSet<>();
209
        for (FileObject fo : f.getChildren()) {
210
            if ("instance".equals(fo.getExt())) {
211
                Object pattern = fo.getAttribute("uriPattern");
212
                Object displayName = fo.getAttribute("displayName");
213
                Object position = fo.getAttribute("position");
214
                Object actions = fo.getAttribute("actions");
215
                if (pattern instanceof String && displayName instanceof String
216
                        && position instanceof Integer
217
                        && actions instanceof String) {
218
                    if (canSupport((String) pattern, (String) actions, intent)) {
219
                        try {
220
                            IntentHandler ih = FileUtil.getConfigObject(
221
                                    fo.getPath(), IntentHandler.class);
222
                            candidates.add(ih);
223
                        } catch (Exception e) {
224
                            LOG.log(Level.INFO,
225
                                    "Cannot instantiate handler for " //NOI18N
226
                                    + fo.getPath(), e);
227
                        }
228
                    }
229
                } else {
230
                    LOG.log(Level.FINE, "Invalid URI handler {0}", fo.getPath());
231
                }
232
            }
233
        }
234
        return candidates;
235
    }
236
237
    /**
238
     * Check whether an intent is supported by a handler specified by a URI
239
     * pattern and action list.
240
     *
241
     * @param uriPattern Pattern for the URI.
242
     * @param actions Comma-separated actions.
243
     * @param intent Intent to check.
244
     * @return True if the intent matches the URI pattern and action list.
245
     */
246
    private static boolean canSupport(String uriPattern, String actions,
247
            Intent intent) {
248
        Pattern p = Pattern.compile(uriPattern);
249
        if (p.matcher(intent.getUri().toString()).matches()) {
250
            if ("*".equals(actions)) {
251
                return true;
252
            } else {
253
                List<String> actionList = Arrays.asList(actions.split(","));
254
                return actionList.contains(intent.getAction());
255
            }
256
        } else {
257
            return false;
258
        }
259
    }
260
261
    private static void invoke(Intent intent, Result resultOrNull) {
262
263
        Throwable lastException = null;
264
        boolean handled = false;
265
266
        for (IntentHandler h : getIntentHandlers(intent)) {
267
            try {
268
                h.handle(intent, resultOrNull);
269
                handled = true;
270
                break;
271
            } catch (Exception e) {
272
                lastException = e;
273
                LOG.log(Level.WARNING, null, e);
274
            }
275
        }
276
        if (!handled) {
277
            if (resultOrNull != null) {
278
                resultOrNull.setException(lastException == null
279
                        ? new NoAvailableHandlerException(intent)
280
                        : new NoAvailableHandlerException(intent, lastException));
281
            }
282
            LOG.log(Level.INFO, "Intent {0} cannot be handled", intent);//NOI18N
283
        }
284
    }
285
286
    @Override
287
    public String toString() {
288
        return "Intent{" + "action=" + action + ", uri=" + uri + '}';
289
    }
290
}
(-)a/api.intent/src/org/netbeans/api/intent/IntentAction.java (+134 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
package org.netbeans.api.intent;
43
44
import java.util.concurrent.Callable;
45
import java.util.concurrent.Future;
46
import org.netbeans.api.annotations.common.NonNull;
47
import org.netbeans.api.annotations.common.NullAllowed;
48
import org.netbeans.modules.intent.CallbackResult;
49
import org.netbeans.modules.intent.IntentHandler;
50
import org.netbeans.modules.intent.SettableResult;
51
import org.netbeans.spi.intent.Result;
52
53
/**
54
 * Actual action for an Intent. Pair of an Intent and one of its handlers.
55
 *
56
 * @see Intent#getIntentActions()
57
 * @author jhavlin
58
 */
59
public final class IntentAction {
60
61
    private final Intent intent;
62
    private final IntentHandler delegate;
63
64
    IntentAction(Intent intent, IntentHandler delegate) {
65
        this.intent = intent;
66
        this.delegate = delegate;
67
    }
68
69
    int getPosition() {
70
        return delegate.getPosition();
71
    }
72
73
    /**
74
     * Execute the intent action. The operation will be run asynchronously.
75
     *
76
     * @param callback Callback object that will be notified when the execution
77
     * completes. If callback is null, the result will be ignored.
78
     */
79
    public void execute(@NullAllowed final Callback callback) {
80
        IntentHandler.RP.post(new Runnable() {
81
            @Override
82
            public void run() {
83
                Result result = callback == null
84
                        ? null
85
                        : new CallbackResult(callback);
86
                delegate.handle(intent, result);
87
            }
88
        });
89
    }
90
91
    /**
92
     * Execute the intent action. The operation will be run asynchronously.
93
     * <p>
94
     * If the result is ignored, it's recommended to use
95
     * {@code intentAction.execute(null);}
96
     * </p>
97
     *
98
     * @return Future for result of the action. The type of result depends on
99
     * implementation of chosen intent handler, it can be null.
100
     */
101
    public @NonNull Future<Object> execute() {
102
103
        return IntentHandler.RP.submit(new Callable<Object>() {
104
            @Override
105
            public Object call() throws Exception {
106
                SettableResult result = new SettableResult();
107
                delegate.handle(intent, result);
108
                if (result.getException() != null) {
109
                    throw result.getException();
110
                }
111
                return result.getResult();
112
            }
113
        });
114
    }
115
116
    /**
117
     * Get display name of this action.
118
     *
119
     * @return The localized display name.
120
     */
121
    public @NonNull String getDisplayName() {
122
        return delegate.getDisplayName();
123
    }
124
125
    /**
126
     * Get icon of this action.
127
     *
128
     * @return Some resource identifier, e.g. icon id, path or URI.
129
     * Depends on the platform. If not available, empty string is returned.
130
     */
131
    public @NonNull String getIcon() {
132
        return delegate.getIcon();
133
    }
134
}
(-)a/api.intent/src/org/netbeans/api/intent/NoAvailableHandlerException.java (+64 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
package org.netbeans.api.intent;
43
44
/**
45
 * Exception thrown when no handler is available for the Intent, or when
46
 * invocation of all handlers fails. In the latter case, exception thrown by the
47
 * last handler is set as the init cause of this exception.
48
 *
49
 * @author jhavlin
50
 */
51
public class NoAvailableHandlerException extends Exception {
52
53
    public NoAvailableHandlerException(Intent intent) {
54
        super(messageForIntent(intent));
55
    }
56
57
    public NoAvailableHandlerException(Intent intent, Throwable cause) {
58
        super(messageForIntent(intent), cause);
59
    }
60
61
    private static String messageForIntent(Intent intent) {
62
       return "No available handler for intent " + intent;
63
    }
64
}
(-)a/api.intent/src/org/netbeans/api/intent/package-info.java (+72 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
/**
44
 * API for working with {@link org.netbeans.api.intent.Intent}s, abstract descriptions of intended
45
 * operations.
46
 * <p>
47
 *  Intents can be used when we want to perform some standard operation and we
48
 *  believe that the environment (the IDE, some application) is capable of
49
 *  finding and choosing correct action for it.
50
 * </p>
51
 * <p>
52
 *  The operations are specified as pair of action type and a URI. See example:
53
 * </p>
54
 * <code>
55
 *  Intent i = new Intent(Intent.ACTION_VIEW, new URI("file://path/file.txt"));
56
 * </code>
57
 * <p>
58
 *  We can execute an Intent to let the system choose to most appropriate
59
 *  action for the intent and invoke it:
60
 * </p>
61
 * <code>
62
 *  i.execute();
63
 * </code>
64
 * <p>
65
 *  Or we can get list of all available actions, display them somehow, and let
66
 *  the user select one of them:
67
 * </p>
68
 * <code>
69
 *  Set&lt;IntentAction&gt; available = i.getIntentActions();
70
 * </code>
71
 */
72
package org.netbeans.api.intent;
(-)a/api.intent/src/org/netbeans/modules/intent/CallbackResult.java (+88 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
package org.netbeans.modules.intent;
43
44
import org.netbeans.api.annotations.common.NonNull;
45
import org.netbeans.api.annotations.common.NullAllowed;
46
import org.netbeans.api.intent.Callback;
47
import org.netbeans.spi.intent.Result;
48
import org.openide.util.Parameters;
49
import org.openide.util.RequestProcessor;
50
51
/**
52
 *
53
 * @author jhavlin
54
 */
55
public class CallbackResult implements Result {
56
57
    private static final RequestProcessor RP
58
            = new RequestProcessor("Intent Callbacks");
59
60
    private final Callback callback;
61
62
    public CallbackResult(@NonNull Callback callback) {
63
        this.callback = callback;
64
    }
65
66
    @Override
67
    public void setResult(final Object result) {
68
        RP.post(new Runnable() {
69
70
            @Override
71
            public void run() {
72
                callback.success(result);
73
            }
74
        });
75
    }
76
77
    @Override
78
    public void setException(final Exception exception) {
79
        Parameters.notNull("exception", exception);                     //NOI18N
80
        RP.post(new Runnable() {
81
82
            @Override
83
            public void run() {
84
                callback.failure(exception);
85
            }
86
        });
87
    }
88
}
(-)a/api.intent/src/org/netbeans/modules/intent/IntentHandler.java (+163 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
package org.netbeans.modules.intent;
43
44
import java.lang.reflect.InvocationTargetException;
45
import java.lang.reflect.Method;
46
import org.netbeans.api.intent.Intent;
47
import org.netbeans.spi.intent.Result;
48
import org.openide.filesystems.FileObject;
49
import org.openide.util.Lookup;
50
import org.openide.util.RequestProcessor;
51
52
/**
53
 *
54
 * @author jhavlin
55
 */
56
public class IntentHandler implements Comparable<IntentHandler> {
57
58
    public static final RequestProcessor RP = new RequestProcessor(
59
            IntentHandler.class);
60
61
    private static final Result IGNORING_RESULT = new Result() {
62
63
        @Override
64
        public void setResult(Object result) {
65
        }
66
67
        @Override
68
        public void setException(Exception exception) {
69
        }
70
    };
71
72
    @Override
73
    public int compareTo(IntentHandler o) {
74
        return this.getPosition() - o.getPosition();
75
    }
76
77
    private enum Type {
78
        RETURN, SETBACK
79
    }
80
81
    private final String className;
82
    private final String methodName;
83
    private final String displayName;
84
    private final String icon;
85
    private final Type type;
86
    private final int position;
87
88
    public static IntentHandler create(FileObject fo) {
89
        String n = fo.getName();
90
        int lastDash = n.lastIndexOf('-');
91
        if (lastDash <= 0 || lastDash + 1 >= n.length()) {
92
            throw new IllegalArgumentException("Invalid handler file"); //NOI18N
93
        }
94
        String className = n.substring(0, lastDash).replace('-', '.');
95
        String methodName = n.substring(lastDash + 1);
96
        String displayName = (String) fo.getAttribute("displayName");   //NOI18N
97
        String icon = (String) fo.getAttribute("icon");                 //NOI18N
98
        int position = (Integer) fo.getAttribute("position");           //NOI18N
99
        Type type = Type.valueOf((String) fo.getAttribute("type"));     //NOI18N
100
101
        return new IntentHandler(className, methodName, displayName, icon,
102
                type, position);
103
    }
104
105
    private IntentHandler(String className, String methodName,
106
            String displayName, String icon, Type type, int position) {
107
108
        this.className = className;
109
        this.methodName = methodName;
110
        this.displayName = displayName;
111
        this.icon = icon;
112
        this.type = type;
113
        this.position = position;
114
    }
115
116
    public String getDisplayName() {
117
        return displayName;
118
    }
119
120
    public String getIcon() {
121
        return icon;
122
    }
123
124
    public int getPosition() {
125
        return position;
126
    }
127
128
    public boolean isSetBack() {
129
        return type == Type.SETBACK;
130
    }
131
132
    public void handle(Intent intent, Result resultOrNull) {
133
134
        Result result = resultOrNull == null ? IGNORING_RESULT : resultOrNull;
135
136
        ClassLoader cls = Lookup.getDefault().lookup(ClassLoader.class);
137
        if (cls == null) {
138
            throw new IllegalStateException("Classloader not found");   //NOI18N
139
        } else {
140
            try {
141
                Class<?> c = Class.forName(className, true, cls);
142
                if (isSetBack()) {
143
                    Method m = c.getDeclaredMethod(methodName, Intent.class,
144
                            Result.class);
145
                    m.invoke(null, intent, result);
146
                } else {
147
                    Method m = c.getDeclaredMethod(methodName, Intent.class);
148
                    Object res = m.invoke(null, intent);
149
                    result.setResult(res);
150
                }
151
            } catch (InvocationTargetException e) {
152
                Throwable cause = e.getCause();
153
                if (cause instanceof Exception) {
154
                    result.setException((Exception) cause);
155
                } else {
156
                    result.setException(new Exception(cause));
157
                }
158
            } catch (ReflectiveOperationException e) {
159
                result.setException(e);
160
            }
161
        }
162
    }
163
}
(-)a/api.intent/src/org/netbeans/modules/intent/OpenUriHandlerProcessor.java (+215 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
package org.netbeans.modules.intent;
43
44
import java.util.Set;
45
import javax.annotation.processing.Processor;
46
import javax.annotation.processing.RoundEnvironment;
47
import javax.annotation.processing.SupportedAnnotationTypes;
48
import javax.annotation.processing.SupportedSourceVersion;
49
import javax.lang.model.SourceVersion;
50
import javax.lang.model.element.Element;
51
import javax.lang.model.element.ElementKind;
52
import javax.lang.model.element.ExecutableElement;
53
import javax.lang.model.element.Modifier;
54
import javax.lang.model.element.TypeElement;
55
import javax.lang.model.type.TypeMirror;
56
import org.netbeans.api.intent.Intent;
57
import org.netbeans.spi.intent.IntentHandlerRegistration;
58
import org.netbeans.spi.intent.Result;
59
import org.openide.filesystems.annotations.LayerBuilder;
60
import org.openide.filesystems.annotations.LayerBuilder.File;
61
import org.openide.filesystems.annotations.LayerGeneratingProcessor;
62
import org.openide.filesystems.annotations.LayerGenerationException;
63
import org.openide.util.lookup.ServiceProvider;
64
65
/**
66
 *
67
 * @author jhavlin
68
 */
69
@ServiceProvider(service = Processor.class)
70
@SupportedSourceVersion(SourceVersion.RELEASE_7)
71
@SupportedAnnotationTypes("org.netbeans.spi.intent.IntentHandlerRegistration")
72
public class OpenUriHandlerProcessor extends LayerGeneratingProcessor {
73
74
    @Override
75
    protected boolean handleProcess(
76
            Set<? extends TypeElement> annotations,
77
            RoundEnvironment roundEnv) throws LayerGenerationException {
78
79
        for (Element e : roundEnv.getElementsAnnotatedWith(
80
                IntentHandlerRegistration.class)) {
81
            IntentHandlerRegistration r = e.getAnnotation(
82
                    IntentHandlerRegistration.class);
83
            registerHandler(e, r);
84
        }
85
        return true;
86
    }
87
88
    private static final String SUFFIX = ".instance";                   //NOI18N
89
90
    private void registerHandler(Element e, IntentHandlerRegistration r)
91
            throws LayerGenerationException {
92
93
        TypeElement intentTypeElement = getTypeElement(Intent.class);
94
        TypeElement objectTypeElement = getTypeElement(Object.class);
95
        TypeElement resultTypeElement = getTypeElement(Result.class);
96
97
        if (!ElementKind.METHOD.equals(e.getKind())) {
98
            throw error(e, "The annotation can be applied only to"      //NOI18N
99
                    + " a method.");//NOI18N
100
        }
101
        if (!e.getModifiers().contains(Modifier.STATIC)) {
102
            throw error(e, "The annotated method must be static.");     //NOI18N
103
        }
104
105
        ExecutableElement ee;
106
        if (e instanceof ExecutableElement) {
107
            ee = (ExecutableElement) e;
108
        } else {
109
            throw error(e, "Annotated element must be an "              //NOI18N
110
                    + "ExecutableElement");                             //NOI18N
111
112
        }
113
114
        String type;
115
        if (ee.getParameters().size() == 1
116
                && hasParameter(ee, 0, intentTypeElement)
117
                && hasResultType(ee, objectTypeElement)) {
118
            type = "RETURN";
119
        } else if (ee.getParameters().size() == 2
120
                && hasParameter(ee, 0, intentTypeElement)
121
                && hasParameter(ee, 1, resultTypeElement)
122
                && hasVoidResultType(ee)) {
123
            type = "SETBACK";
124
        } else {
125
            throw error(e, "The handler method must take a "            //NOI18N
126
                    + "single argument of type "                        //NOI18N
127
                    + "org.netbeans.api.intent.Intent and return Object"//NOI18N
128
                    + "; or take two arguments of types"                //NOI18N
129
                    + "org.netbeans.api.intent.Intent"                  //NOI18N
130
                    + "and org.netbeans.spi.intent.Result"              //NOI18N
131
                    + " and return void.");                             //NOI18N
132
        }
133
134
        boolean takeAll = false;
135
        boolean empty = true;
136
        StringBuilder sb = new StringBuilder();
137
        for (String action: r.actions()) {
138
            if ("*".equals(action)) {
139
                takeAll = true;
140
                break;
141
            } else {
142
                if (!empty) {
143
                    sb.append(',');
144
                }
145
                sb.append(action);
146
                empty = false;
147
            }
148
        }
149
        String actions = takeAll ? "*" : sb.toString();
150
151
        final LayerBuilder b = layer(e);
152
        File f = b.file("Services/Intent/Handlers/" //NOI18N
153
                + getName(e).replace('.', '-') + SUFFIX);
154
        f.position(r.position());
155
        f.stringvalue("instanceClass",                                  //NOI18N
156
                IntentHandler.class.getCanonicalName());
157
        f.methodvalue("instanceCreate", IntentHandler.class.getCanonicalName(),
158
                "create");                                              //NOI18N
159
        f.bundlevalue("displayName", r.displayName());                  //NOI18N
160
        f.stringvalue("uriPattern", r.uriPattern());                    //NOI18N
161
        f.stringvalue("icon", r.icon());                                //NOI18N
162
        f.stringvalue("type", type);                                    //NOI18N
163
        f.stringvalue("actions", actions);                              //NOI18N
164
        f.write();
165
    }
166
167
    private String getName(Element e) {
168
        if (e.getKind().isClass() || e.getKind().isInterface()) {
169
            return processingEnv.getElementUtils().getBinaryName(
170
                    (TypeElement) e).toString();
171
        } else if (e.getKind() == ElementKind.PACKAGE) {
172
            return e.getSimpleName().toString();
173
        } else {
174
            return getName(e.getEnclosingElement()) + '.' + e.getSimpleName();
175
        }
176
    }
177
178
    private boolean hasParameter(ExecutableElement ee, int pos,
179
            Element typeElement) {
180
        return processingEnv.getTypeUtils().asElement(
181
                ee.getParameters().get(pos).asType()).equals(
182
                        typeElement);
183
    }
184
185
    private boolean hasVoidResultType(ExecutableElement ee) {
186
        TypeMirror returnType = ee.getReturnType();
187
        Element returnTypeElement = processingEnv.getTypeUtils().asElement(
188
                returnType);
189
        return returnTypeElement == null;
190
    }
191
192
    private boolean hasResultType(ExecutableElement ee, Element typeElement) {
193
        TypeMirror returnType = ee.getReturnType();
194
        Element returnTypeElement = processingEnv.getTypeUtils().asElement(
195
                returnType);
196
        return returnTypeElement.equals(typeElement);
197
    }
198
199
    private TypeElement getTypeElement(Class<?> cls) {
200
        TypeElement typeElement = processingEnv.getElementUtils()
201
                .getTypeElement(cls.getCanonicalName());
202
        return typeElement;
203
    }
204
205
    private IllegalArgumentException error(Element e, String msg) {
206
        StringBuilder sb = new StringBuilder();
207
        sb.append(e.getEnclosingElement().toString());
208
        sb.append("."); //NOI18N
209
        sb.append(e.getSimpleName());
210
        sb.append(":"); //NOI18N
211
        sb.append(System.lineSeparator());
212
        sb.append(msg);
213
        return new IllegalArgumentException(sb.toString());
214
    }
215
}
(-)a/api.intent/src/org/netbeans/modules/intent/SettableResult.java (+91 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
package org.netbeans.modules.intent;
43
44
import java.util.concurrent.CountDownLatch;
45
import org.netbeans.spi.intent.Result;
46
import org.openide.util.Parameters;
47
48
/**
49
 *
50
 * @author jhavlin
51
 */
52
public final class SettableResult implements Result {
53
54
    private final CountDownLatch latch = new CountDownLatch(1);
55
56
    private Object result = null;
57
    private Exception exception = null;
58
59
    public Object getResult() {
60
        try {
61
            latch.await();
62
        } catch (InterruptedException ex) {
63
            setException(ex);
64
            latch.countDown();
65
        }
66
        return result;
67
    }
68
69
    public synchronized Exception getException() {
70
        try {
71
            latch.await();
72
        } catch (InterruptedException ex) {
73
            setException(ex);
74
            latch.countDown();
75
        }
76
        return exception;
77
    }
78
79
    @Override
80
    public synchronized void setResult(Object result) {
81
        this.result = result;
82
        latch.countDown();
83
    }
84
85
    @Override
86
    public synchronized void setException(Exception exception) {
87
        Parameters.notNull("exception", exception);                     //NOI18N
88
        this.exception = exception;
89
        latch.countDown();
90
    }
91
}
(-)a/api.intent/src/org/netbeans/spi/intent/IntentHandlerRegistration.java (+90 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
package org.netbeans.spi.intent;
43
44
import java.util.regex.Pattern;
45
46
/**
47
 * Annotation for registering Intent handlers into the application.
48
 * See {@link org.netbeans.spi.intent} for more info and examples.
49
 *
50
 * @see org.netbeans.spi.intent
51
 */
52
public @interface IntentHandlerRegistration {
53
54
    /**
55
     * Position of the handler. The lesser value, the bigger priority.
56
     *
57
     * @return The position.
58
     */
59
    int position();
60
61
    /**
62
     * List of supported action types. To support all actions, use "*" wildcard.
63
     *
64
     * @return List of supported action types. If some of contained values
65
     * equals "*", all actions are supported.
66
     */
67
    String[] actions();
68
69
    /**
70
     * Pattern of supported URIs. See {@link Pattern}. Examples: To handle
71
     * all URIs, use ".*", to handle http adresses, use "http://.*".
72
     *
73
     * @return The URI pattern.
74
     */
75
    String uriPattern();
76
77
    /**
78
     * Display name of this handler. Bundle keys can be used here.
79
     *
80
     * @return The display name.
81
     */
82
    String displayName();
83
84
    /**
85
     * Identifier for an icon, e.g. path or URI.
86
     *
87
     * @return Icon identifier.
88
     */
89
    String icon() default "";
90
}
(-)a/api.intent/src/org/netbeans/spi/intent/Result.java (+67 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
package org.netbeans.spi.intent;
43
44
import org.netbeans.api.annotations.common.NullAllowed;
45
46
/**
47
 * Object passed to intent handler which should be notified about computed
48
 * result.
49
 *
50
 * @author jhavlin
51
 */
52
public interface Result {
53
54
    /**
55
     * Set computed result.
56
     *
57
     * @param result The result.
58
     */
59
    public void setResult(@NullAllowed Object result);
60
61
    /**
62
     * Set encountered exception.
63
     *
64
     * @param exception The exception.
65
     */
66
    public void setException(Exception exception);
67
}
(-)a/api.intent/src/org/netbeans/spi/intent/package-info.java (+105 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
 * SPI for Intent handlers.
44
 * <p>
45
 * Handling some type of Intents is as simple as registering a method using
46
 * annotation {@link org.netbeans.spi.intent.IntentHandlerRegistration}.
47
 * </p>
48
 * <p>
49
 * Currently two types of handling methods are supported:
50
 * </p>
51
 * <ul>
52
 * <li>
53
 * Public static method taking {@link org.netbeans.api.intent.Intent} and
54
 * returning {@link java.lang.Object}. This method will be invoked in a
55
 * background thread. It is suitable if no waiting for asynchronous operations
56
 * is needed and when the method will finish reasonably quickly (so that it
57
 * will not block execution of other intents).
58
 * </li>
59
 * <li>
60
 * Public static method taking {@link org.netbeans.api.intent.Intent} and
61
 * {@link org.netbeans.spi.intent.Result} with no return type (void). It will be
62
 * invoked in a background thread, but it can simply pass the result object to
63
 * other threads. When the computation is finished, either
64
 * {@link org.netbeans.spi.intent.Result#setException(java.lang.Exception)} or
65
 * {@link org.netbeans.spi.intent.Result#setResult(java.lang.Object)}
66
 * <b>MUST</b> be called on the result object.
67
 * </li>
68
 * </ul>
69
 * <p>See examples:</p>
70
 * <p>Basic handler:</p>
71
 * <pre>
72
 *  &nbsp;&#64;IntentHandlerRegistration(
73
 *               displayName = "Show my item in MyEditor",
74
 *               position = 800,
75
 *               uriPattern = "myscheme://.*",
76
 *               actions = {Intent.ACTION_VIEW, Intent.ACTION_EDIT}
77
 *   )
78
 *   public static Object handleIntent(Intent intent) {
79
 *       SomeType result = parseAndPerformIntentSomehow(intent);
80
 *       return result;
81
 *   }
82
 * </pre>
83
 * <p>Handler that uses {@link org.netbeans.spi.intent.Result}:</p>
84
 * <pre>
85
 *  &nbsp;&#64;IntentHandlerRegistration(
86
 *               displayName = "Show my item in MyEditor",
87
 *               position = 800,
88
 *               uriPattern = "myscheme://.*",
89
 *               actions = "*"
90
 *   )
91
 *   public static void handleIntent(final Intent intent, final Result result) {
92
 *       EventQueue.invokeLater(new Runnable() {
93
 *           public void run() {
94
 *               try {
95
 *                   Object value = doSomethingInEDT(intent);
96
 *                   result.setResult(value);
97
 *               } catch (Exception e) {
98
 *                   result.setException(e);
99
 *               }
100
 *           }
101
 *       });
102
 *   }
103
 * </pre>
104
 */
105
package org.netbeans.spi.intent;
(-)a/api.intent/test/unit/src/org/netbeans/api/intent/IntentTest.java (+326 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
package org.netbeans.api.intent;
43
44
import java.net.URI;
45
import java.net.URISyntaxException;
46
import java.util.concurrent.ExecutionException;
47
import java.util.concurrent.Future;
48
import java.util.concurrent.Semaphore;
49
import org.junit.Test;
50
import static org.junit.Assert.*;
51
import org.junit.Before;
52
import org.netbeans.spi.intent.IntentHandlerRegistration;
53
import org.netbeans.spi.intent.Result;
54
import org.openide.util.Exceptions;
55
56
/**
57
 *
58
 * @author jhavlin
59
 */
60
public class IntentTest {
61
62
    private static boolean handled = false;
63
64
    private static final String HANDLED_BY_TEST = "Greetings from Test";
65
    private static final String HANDLED_BY_NB = "Greetings from NB";
66
    private static final String HANDLED_BY_NB_PARAM
67
            = "Greetings from NB parametrized";
68
    private static final String HANDLED_BY_BROKEN = "";
69
    private static final String HANDLED_BY_BROKEN_SB = "";
70
    private static final String HANDLED_BY_SETBACK = "Greetings from setback";
71
72
    @Before
73
    public void setUp() {
74
        handled = false;
75
    }
76
77
    @Test
78
    public void testOpenUri() throws URISyntaxException, InterruptedException,
79
            ExecutionException {
80
81
        Future<Object> res3 = new Intent("TEST",
82
                new URI("scheme://x/y/z/")).execute();
83
        assertNotNull(res3.get());
84
85
        assertFalse(handled);
86
        Future<Object> res2 = new Intent(Intent.ACTION_VIEW,
87
                new URI("test://a/b/c/")).execute();
88
        Exception e = null;
89
        try {
90
            assertNotNull(res2.get());
91
        } catch (InterruptedException | ExecutionException ex) {
92
            e = ex;
93
        }
94
        assertNotNull(e);
95
    }
96
97
    @Test
98
    @SuppressWarnings("ThrowableResultIgnored")
99
    public void testSelectAppropriateHandler()
100
            throws URISyntaxException, InterruptedException,
101
            ExecutionException {
102
103
        Future<Object> x0 = new Intent("NONE",
104
                new URI("unsupported://resource")).execute();
105
106
        Exception e = null;
107
        try {
108
            x0.get();
109
        } catch (InterruptedException | ExecutionException ex) {
110
           e = ex;
111
        }
112
        assertTrue(e instanceof ExecutionException
113
                && (e.getCause() instanceof NoAvailableHandlerException));
114
115
        Future<Object> x1 = new Intent("NONE",
116
                new URI("broken://resource")).execute();
117
        try {
118
            x1.get();
119
        } catch (InterruptedException | ExecutionException ex) {
120
           e = ex;
121
        }
122
        assertTrue(e instanceof ExecutionException);
123
124
        Future<Object> x2 = new Intent("NONE",
125
                new URI("brokensb://resource")).execute();
126
        try {
127
            x2.get();
128
        } catch (InterruptedException | ExecutionException ex) {
129
           e = ex;
130
        }
131
        assertTrue(e instanceof ExecutionException);
132
133
        Future<Object> f0 = new Intent("TEST",
134
                new URI("unsupported://resource")).execute();
135
        assertEquals(HANDLED_BY_TEST, f0.get());
136
137
        Future<Object> f1 = new Intent(Intent.ACTION_VIEW,
138
                new URI("netbeans://resource")).execute();
139
        assertEquals(HANDLED_BY_NB, f1.get());
140
141
        Future<Object> f2 = new Intent(Intent.ACTION_VIEW,
142
                new URI("netbeans://resource?someParam=x")).execute();
143
        assertEquals(HANDLED_BY_NB, f2.get());
144
145
        Future<Object> f3 = new Intent(Intent.ACTION_VIEW,
146
                new URI("netbeans://resource?x=y&requiredParam=123")).execute();
147
        assertEquals(HANDLED_BY_NB_PARAM, f3.get());
148
149
        Future<Object> f4 = new Intent(Intent.ACTION_VIEW,
150
                new URI("setback://resource")).execute();
151
        assertEquals(HANDLED_BY_SETBACK, f4.get());
152
    }
153
154
    @Test
155
    public void testExecutionWithCallback() throws URISyntaxException, InterruptedException, ExecutionException {
156
157
        class CheckingCallback implements Callback {
158
159
            private final Semaphore s = new Semaphore(0);
160
161
            private Exception lastException = null;
162
            private Object lastResult = null;
163
164
            @Override
165
            public void success(Object result) {
166
                lastException = null;
167
                lastResult = result;
168
                s.release();
169
            }
170
171
            @Override
172
            public void failure(Exception exception) {
173
                lastException = exception;
174
                lastResult = null;
175
                s.release();
176
            }
177
178
            public void checkLastResult(Object expectedResult) {
179
                try {
180
                    s.acquire();
181
                } catch (InterruptedException ex) {
182
                    Exceptions.printStackTrace(ex);
183
                }
184
                assertEquals(expectedResult, lastResult);
185
            }
186
187
            public void checkLastFailure(Class<? extends Exception> ec) {
188
                try {
189
                    s.acquire();
190
                } catch (InterruptedException ex) {
191
                    Exceptions.printStackTrace(ex);
192
                }
193
                assertNotNull(lastException);
194
                assertEquals(ec, lastException.getClass());
195
            }
196
        }
197
198
        CheckingCallback cb = new CheckingCallback();
199
200
        new Intent("NONE", new URI("broken://resource")).execute(cb);
201
        cb.checkLastFailure(RuntimeException.class);
202
203
        new Intent("NONE", new URI("brokensb://resource")).execute(cb);
204
        cb.checkLastFailure(RuntimeException.class);
205
206
        new Intent("NONE", new URI("unsupported://resource")).execute(cb);
207
        cb.checkLastFailure(NoAvailableHandlerException.class);
208
209
        new Intent("TEST",
210
                new URI("unsupported://resource")).execute(cb);
211
        cb.checkLastResult(HANDLED_BY_TEST);
212
213
        new Intent(Intent.ACTION_VIEW,
214
                new URI("netbeans://resource")).execute(cb);
215
        cb.checkLastResult(HANDLED_BY_NB);
216
217
        new Intent(Intent.ACTION_VIEW,
218
                new URI("netbeans://resource?someParam=x")).execute(cb);
219
        cb.checkLastResult(HANDLED_BY_NB);
220
221
        new Intent(Intent.ACTION_VIEW,
222
                new URI("netbeans://resource?x=y&requiredParam=123")).execute(cb);
223
        cb.checkLastResult(HANDLED_BY_NB_PARAM);
224
225
        new Intent(Intent.ACTION_VIEW,
226
                new URI("setback://resource")).execute(cb);
227
        cb.checkLastResult(HANDLED_BY_SETBACK);
228
    }
229
230
    /**
231
     * Handler that claims to support all URI patterns, but that actually
232
     * accepts only scheme "test".
233
     *
234
     * @param intent
235
     * @return
236
     */
237
    @SuppressWarnings("PublicInnerClass")
238
    @IntentHandlerRegistration(
239
            displayName = "Test",
240
            position = 999,
241
            uriPattern = ".*",
242
            actions = "TEST")
243
    public static Object handleIntent(Intent intent) {
244
        return HANDLED_BY_TEST;
245
    }
246
247
    /**
248
     * Handler for URIs with scheme "netbeans".
249
     *
250
     * @param intent
251
     * @return
252
     */
253
    @SuppressWarnings("PublicInnerClass")
254
    @IntentHandlerRegistration(
255
            displayName = HANDLED_BY_NB,
256
            position = 998,
257
            uriPattern = "netbeans://.*",
258
            actions = "*")
259
    public static Object handleNetBeansIntent(Intent intent) {
260
        return HANDLED_BY_NB;
261
    }
262
263
    /**
264
     * Handler for URIs with scheme "netbeans" and parameter "requiredParam".
265
     *
266
     * @param intent
267
     * @return
268
     */
269
    @SuppressWarnings("PublicInnerClass")
270
    @IntentHandlerRegistration(
271
            displayName = HANDLED_BY_NB_PARAM,
272
            position = 997,
273
            uriPattern = "netbeans://.*[?&]requiredParam=.+",
274
            actions = {Intent.ACTION_VIEW, Intent.ACTION_EDIT})
275
    public static Object handleParametrizedNetBeansIntent(Intent intent) {
276
        return HANDLED_BY_NB_PARAM;
277
    }
278
279
    /**
280
     * Handler for URIs with scheme "broken".
281
     *
282
     * @param intent
283
     * @return
284
     */
285
    @SuppressWarnings("PublicInnerClass")
286
    @IntentHandlerRegistration(
287
            displayName = HANDLED_BY_BROKEN,
288
            position = 997,
289
            uriPattern = "broken://.*",
290
            actions = "*")
291
    public static Object handleBroken(Intent intent) {
292
        throw new RuntimeException("Intentionally broken");
293
    }
294
295
    /**
296
     * Handler for URIs with scheme "brokensb".
297
     *
298
     * @param intent
299
     * @param result
300
     */
301
    @SuppressWarnings("PublicInnerClass")
302
    @IntentHandlerRegistration(
303
            displayName = HANDLED_BY_BROKEN_SB,
304
            position = 997,
305
            uriPattern = "brokensb://.*",
306
            actions = "*")
307
    public static void handleBrokenSb(Intent intent, Result result) {
308
        result.setException(new RuntimeException("Intentionally broken"));
309
    }
310
311
    /**
312
     * Handler for URIs with scheme "setback".
313
     *
314
     * @param intent
315
     * @param result
316
     */
317
    @SuppressWarnings("PublicInnerClass")
318
    @IntentHandlerRegistration(
319
            displayName = HANDLED_BY_SETBACK,
320
            position = 997,
321
            uriPattern = "setback://.*",
322
            actions = "*")
323
    public static void handleSetBack(Intent intent, Result result) {
324
        result.setResult(HANDLED_BY_SETBACK);
325
    }
326
}
(-)a/nbbuild/build.properties (+1 lines)
Lines 100-105 Link Here
100
config.javadoc.stable=\
100
config.javadoc.stable=\
101
    api.annotations.common,\
101
    api.annotations.common,\
102
    api.html4j,\
102
    api.html4j,\
103
    api.intent,\
103
    api.io,\
104
    api.io,\
104
    api.maven,\
105
    api.maven,\
105
    api.templates,\
106
    api.templates,\
(-)a/nbbuild/cluster.properties (+1 lines)
Lines 195-200 Link Here
195
nb.cluster.platform=\
195
nb.cluster.platform=\
196
        api.annotations.common,\
196
        api.annotations.common,\
197
        api.html4j,\
197
        api.html4j,\
198
        api.intent,\
198
        api.io,\
199
        api.io,\
199
        api.progress,\
200
        api.progress,\
200
        api.progress.compat8,\
201
        api.progress.compat8,\
(-)a/nbbuild/javadoctools/links.xml (+1 lines)
Lines 240-244 Link Here
240
<link href="${javadoc.docs.org-netbeans-modules-parsing-nb}" offline="true" packagelistloc="${netbeans.javadoc.dir}/org-netbeans-modules-parsing-nb"/>
240
<link href="${javadoc.docs.org-netbeans-modules-parsing-nb}" offline="true" packagelistloc="${netbeans.javadoc.dir}/org-netbeans-modules-parsing-nb"/>
241
<link href="${javadoc.docs.org-netbeans-modules-project-libraries-ui}" offline="true" packagelistloc="${netbeans.javadoc.dir}/org-netbeans-modules-project-libraries-ui"/>
241
<link href="${javadoc.docs.org-netbeans-modules-project-libraries-ui}" offline="true" packagelistloc="${netbeans.javadoc.dir}/org-netbeans-modules-project-libraries-ui"/>
242
<link href="${javadoc.docs.org-openide-filesystems-nb}" offline="true" packagelistloc="${netbeans.javadoc.dir}/org-openide-filesystems-nb"/>
242
<link href="${javadoc.docs.org-openide-filesystems-nb}" offline="true" packagelistloc="${netbeans.javadoc.dir}/org-openide-filesystems-nb"/>
243
<link href="${javadoc.docs.org-netbeans-api-intent}" offline="true" packagelistloc="${netbeans.javadoc.dir}\org-netbeans-api-intent"/>
243
<link href="${javadoc.docs.org-netbeans-api-templates}" offline="true" packagelistloc="${netbeans.javadoc.dir}/org-netbeans-api-templates"/>
244
<link href="${javadoc.docs.org-netbeans-api-templates}" offline="true" packagelistloc="${netbeans.javadoc.dir}/org-netbeans-api-templates"/>
244
<link href="${javadoc.docs.org-netbeans-api-io}" offline="true" packagelistloc="${netbeans.javadoc.dir}\org-netbeans-api-io"/>
245
<link href="${javadoc.docs.org-netbeans-api-io}" offline="true" packagelistloc="${netbeans.javadoc.dir}\org-netbeans-api-io"/>
(-)a/nbbuild/javadoctools/properties.xml (+1 lines)
Lines 239-243 Link Here
239
<property name="javadoc.docs.org-netbeans-modules-parsing-nb" value="${javadoc.web.root}/org-netbeans-modules-parsing-nb"/>
239
<property name="javadoc.docs.org-netbeans-modules-parsing-nb" value="${javadoc.web.root}/org-netbeans-modules-parsing-nb"/>
240
<property name="javadoc.docs.org-netbeans-modules-project-libraries-ui" value="${javadoc.web.root}/org-netbeans-modules-project-libraries-ui"/>
240
<property name="javadoc.docs.org-netbeans-modules-project-libraries-ui" value="${javadoc.web.root}/org-netbeans-modules-project-libraries-ui"/>
241
<property name="javadoc.docs.org-openide-filesystems-nb" value="${javadoc.web.root}/org-openide-filesystems-nb"/>
241
<property name="javadoc.docs.org-openide-filesystems-nb" value="${javadoc.web.root}/org-openide-filesystems-nb"/>
242
<property name="javadoc.docs.org-netbeans-api-intent" value="${javadoc.web.root}/org-netbeans-api-intent"/>
242
<property name="javadoc.docs.org-netbeans-api-templates" value="${javadoc.web.root}/org-netbeans-api-templates"/>
243
<property name="javadoc.docs.org-netbeans-api-templates" value="${javadoc.web.root}/org-netbeans-api-templates"/>
243
<property name="javadoc.docs.org-netbeans-api-io" value="${javadoc.web.root}/org-netbeans-api-io"/>
244
<property name="javadoc.docs.org-netbeans-api-io" value="${javadoc.web.root}/org-netbeans-api-io"/>
(-)a/nbbuild/javadoctools/replaces.xml (+1 lines)
Lines 239-243 Link Here
239
<replacefilter token="@org-netbeans-modules-parsing-nb@" value="${javadoc.docs.org-netbeans-modules-parsing-nb}"/>
239
<replacefilter token="@org-netbeans-modules-parsing-nb@" value="${javadoc.docs.org-netbeans-modules-parsing-nb}"/>
240
<replacefilter token="@org-netbeans-modules-project-libraries-ui@" value="${javadoc.docs.org-netbeans-modules-project-libraries-ui}"/>
240
<replacefilter token="@org-netbeans-modules-project-libraries-ui@" value="${javadoc.docs.org-netbeans-modules-project-libraries-ui}"/>
241
<replacefilter token="@org-openide-filesystems-nb@" value="${javadoc.docs.org-openide-filesystems-nb}"/>
241
<replacefilter token="@org-openide-filesystems-nb@" value="${javadoc.docs.org-openide-filesystems-nb}"/>
242
<replacefilter token="@org-netbeans-api-intent@" value="${javadoc.docs.org-netbeans-api-intent}"/>
242
<replacefilter token="@org-netbeans-api-templates@" value="${javadoc.docs.org-netbeans-api-templates}"/>
243
<replacefilter token="@org-netbeans-api-templates@" value="${javadoc.docs.org-netbeans-api-templates}"/>
243
<replacefilter token="@org-netbeans-api-io@" value="${javadoc.docs.org-netbeans-api-io}"/>
244
<replacefilter token="@org-netbeans-api-io@" value="${javadoc.docs.org-netbeans-api-io}"/>

Return to bug 248126