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

(-)a/api.java.classpath/arch.xml (+1041 lines)
Line 0 Link Here
1
<?xml version="1.0" encoding="UTF-8"?>
2
<!--
3
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4
5
Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
6
7
8
The contents of this file are subject to the terms of either the GNU
9
General Public License Version 2 only ("GPL") or the Common
10
Development and Distribution License("CDDL") (collectively, the
11
"License"). You may not use this file except in compliance with the
12
License. You can obtain a copy of the License at
13
http://www.netbeans.org/cddl-gplv2.html
14
or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
15
specific language governing permissions and limitations under the
16
License.  When distributing the software, include this License Header
17
Notice in each file and include the License file at
18
nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
19
particular file as subject to the "Classpath" exception as provided
20
by Sun in the GPL Version 2 section of the License file that
21
accompanied this code. If applicable, add the following below the
22
License Header, with the fields enclosed by brackets [] replaced by
23
your own identifying information:
24
"Portions Copyrighted [year] [name of copyright owner]"
25
26
Contributor(s):
27
28
The Original Software is NetBeans. The Initial Developer of the Original
29
Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
30
Microsystems, Inc. All Rights Reserved.
31
32
If you wish your version of this file to be governed by only the CDDL
33
or only the GPL Version 2, indicate your decision by adding
34
"[Contributor] elects to include this software in this distribution
35
under the [CDDL or GPL Version 2] license." If you do not indicate a
36
single choice of license, a recipient has the option to distribute
37
your version of this file under either the CDDL, the GPL Version 2 or
38
to extend the choice of license to its licensees as provided above.
39
However, if you add GPL Version 2 code and therefore, elected the GPL
40
Version 2 license, then the option applies only if the new code is
41
made subject to such option by the copyright holder.
42
-->
43
<!DOCTYPE api-answers PUBLIC "-//NetBeans//DTD Arch Answers//EN" "../nbbuild/antsrc/org/netbeans/nbbuild/Arch.dtd" [
44
  <!ENTITY api-questions SYSTEM "../nbbuild/antsrc/org/netbeans/nbbuild/Arch-api-questions.xml">
45
]>
46
47
<api-answers
48
  question-version="1.24"
49
  author="tzezula@netbeans.org"
50
>
51
52
  &api-questions;
53
54
55
<!--
56
        <question id="arch-overall" when="init">
57
            Describe the overall architecture.
58
            <hint>
59
            What will be API for
60
            <a href="http://openide.netbeans.org/tutorial/api-design.html#design.apiandspi">
61
                clients and what support API</a>? 
62
            What parts will be pluggable?
63
            How will plug-ins be registered? Please use <code>&lt;api type="export"/&gt;</code>
64
            to describe your general APIs.
65
            If possible please provide 
66
            simple diagrams. 
67
            </hint>
68
        </question>
69
-->
70
 <answer id="arch-overall">
71
  <api group="java" name="JavaSupportAPIs" type="export" category="official">
72
   The ClassPath APIs provides java classpath like ordered collection of (source)
73
   roots with ability to listen on changes and helper methods like finding the file
74
   under the roots, returning a path from root to given file. It also provides a
75
   registry where projects register their classpaths to make them visible to languages
76
   infrastructure.
77
  </api>
78
 </answer>
79
80
81
82
<!--
83
        <question id="arch-quality" when="init">
84
            How the <a href="http://www.netbeans.org/community/guidelines/q-evangelism.html">quality</a>
85
            of your code will be tested and 
86
            how future regressions are going to be prevented?
87
            <hint>
88
            What kind of testing
89
            you want to use? What/how much area of functionality
90
            should be covered by the tests? 
91
            </hint>
92
        </question>
93
-->
94
 <answer id="arch-quality">
95
  <p>
96
   Ought to be covered by unit tests.
97
  </p>
98
 </answer>
99
100
101
102
<!--
103
        <question id="arch-time" when="init">
104
            What are the time estimates of the work?
105
            <hint>
106
            Please express your estimates of how long the design, implementation,
107
            stabilization are likely to last. How many people will be needed to
108
            implement this and what is the expected milestone the work should be 
109
            ready.
110
            </hint>
111
        </question>
112
-->
113
 <answer id="arch-time">
114
  <p>
115
   Essentially done.
116
  </p>
117
 </answer>
118
119
120
121
<!--
122
        <question id="arch-usecases" when="init">
123
            Describe the main <a href="http://openide.netbeans.org/tutorial/api-design.html#usecase">
124
            use cases</a> of the new API. Who will use it at
125
            what circumstances and what will be the typical code to write
126
            to use the module.
127
        </question>
128
-->
129
 <answer id="arch-usecases">
130
  <p>
131
   The API is widely used by all sorts of IDE modules which need to work with
132
   sources. The SPI is intended mainly for (java) platforms and
133
   library providers, and project type providers, to declare all of this
134
   information.
135
  </p>
136
 </answer>
137
138
139
140
<!--
141
        <question id="arch-what" when="init">
142
            What is this project good for?
143
            <hint>
144
            Please provide here a few lines describing the project, 
145
            what problem it should solve, provide links to documentation, 
146
            specifications, etc.
147
            </hint>
148
        </question>
149
-->
150
 <answer id="arch-what">
151
  <p>
152
   Models basic aspects of the metadata surrounding list of source roots, such as
153
   the classpath. More information in the Javadoc.
154
  </p>
155
 </answer>
156
157
158
159
<!--
160
        <question id="compat-i18n" when="impl">
161
            Is your module correctly internationalized?
162
            <hint>
163
            Correct internationalization means that it obeys instructions 
164
            at <a href="http://www.netbeans.org/download/dev/javadoc/org-openide-modules/org/openide/modules/doc-files/i18n-branding.html">
165
            NetBeans I18N pages</a>.
166
            </hint>
167
        </question>
168
-->
169
 <answer id="compat-i18n">
170
  <p>
171
   No I18N issues.
172
  </p>
173
 </answer>
174
175
176
177
<!--
178
        <question id="compat-standards" when="init">
179
            Does the module implement or define any standards? Is the 
180
            implementation exact or does it deviate somehow?
181
        </question>
182
-->
183
 <answer id="compat-standards">
184
  <p>
185
   No.
186
  </p>
187
 </answer>
188
189
190
191
<!--
192
        <question id="compat-version" when="impl">
193
            Can your module coexist with earlier and future
194
            versions of itself? Can you correctly read all old settings? Will future
195
            versions be able to read your current settings? Can you read
196
            or politely ignore settings stored by a future version?
197
            
198
            <hint>
199
            Very helpful for reading settings is to store version number
200
            there, so future versions can decide whether how to read/convert
201
            the settings and older versions can ignore the new ones.
202
            </hint>
203
        </question>
204
-->
205
 <answer id="compat-version">
206
  <p>
207
   No settings.
208
  </p>
209
 </answer>
210
211
212
213
<!--
214
        <question id="dep-jre" when="final">
215
            Which version of JRE do you need (1.2, 1.3, 1.4, etc.)?
216
            <hint>
217
            It is expected that if your module runs on 1.x that it will run 
218
            on 1.x+1 if no, state that please. Also describe here cases where
219
            you run different code on different versions of JRE and why.
220
            </hint>
221
        </question>
222
-->
223
 <answer id="dep-jre">
224
  <p>
225
   1.5+.
226
  </p>
227
 </answer>
228
229
230
231
<!--
232
        <question id="dep-jrejdk" when="final">
233
            Do you require the JDK or is the JRE enough?
234
        </question>
235
-->
236
 <answer id="dep-jrejdk">
237
  <p>
238
   JRE.
239
  </p>
240
 </answer>
241
242
243
244
<!--
245
        <question id="dep-nb" when="init">
246
            What other NetBeans projects and modules does this one depend on?
247
            <hint>
248
            If you want, describe such projects as imported API using
249
            the <code>&lt;api name="identification" type="import or export" category="stable" url="where is the description" /&gt;</code>
250
            </hint>
251
        </question>
252
-->
253
 <answer id="dep-nb">
254
  <ul>
255
   <li>
256
    <api group="java" name="Filesystems" type="import" category="official">
257
     <p>
258
      For many purposes.
259
     </p>
260
    </api>
261
   </li>
262
   <li>
263
    <api group="java" name="Execution" type="import" category="official">
264
     <p>
265
      <code>NbClassLoader</code> is used by
266
      <code>ClassPath.getClassLoader(...)</code>.
267
     </p>
268
    </api>
269
   </li>
270
  </ul>
271
 </answer>
272
273
274
275
<!--
276
        <question id="dep-non-nb" when="init">
277
            What other projects outside NetBeans does this one depend on?
278
            
279
            <hint>
280
            Some non-NetBeans projects are packaged as NetBeans modules
281
            (see <a href="http://libs.netbeans.org/">libraries</a>) and
282
            it is preferred to use this approach when more modules may
283
            depend on such third-party library.
284
            </hint>
285
        </question>
286
-->
287
 <answer id="dep-non-nb">
288
  <p>
289
   None.
290
  </p>
291
 </answer>
292
293
294
295
<!--
296
        <question id="dep-platform" when="init">
297
            On which platforms does your module run? Does it run in the same
298
            way on each?
299
            <hint>
300
            If your module is using JNI or deals with special differences of
301
            OSes like filesystems, etc. please describe here what they are.
302
            </hint>
303
        </question>
304
-->
305
 <answer id="dep-platform">
306
  <p>
307
   Any.
308
  </p>
309
 </answer>
310
311
312
313
 <answer id="deploy-dependencies">
314
Nothing.
315
 </answer>
316
317
318
319
<!--
320
        <question id="deploy-jar" when="impl">
321
            Do you deploy just module JAR file(s) or other files as well?
322
            <hint>
323
            If your module consists of just one module JAR file, just confirm that.
324
            If it uses more than one JAR, describe where they are located, how
325
            they refer to each other. 
326
            If it consist of module JAR(s) and other files, please describe
327
            what is their purpose, why other files are necessary. Please 
328
            make sure that installation/uninstallation leaves the system 
329
            in state as it was before installation.
330
            </hint>
331
        </question>
332
-->
333
 <answer id="deploy-jar">
334
  <p>
335
   Just a JAR.
336
  </p>
337
 </answer>
338
339
340
341
<!--
342
        <question id="deploy-nbm" when="impl">
343
            Can you deploy an NBM via the Update Center?
344
            <hint>
345
            If not why?
346
            </hint>
347
        </question>
348
-->
349
 <answer id="deploy-nbm">
350
  <p>
351
   Yes.
352
  </p>
353
 </answer>
354
355
356
357
<!--
358
        <question id="deploy-packages" when="init">
359
            Are packages of your module made inaccessible by not declaring them
360
            public?
361
            
362
            <hint>
363
            NetBeans module system allows restriction of access rights to
364
            public classes of your module from other modules. This prevents
365
            unwanted dependencies of others on your code and should be used
366
            whenever possible (<a href="http://www.netbeans.org/download/javadoc/OpenAPIs/org/openide/doc-files/upgrade.html#3.4-public-packages">
367
            public packages
368
            </a>). If you do not restrict access to your classes you are
369
            making it too easy for other people to misuse your implementation
370
            details, that is why you should have good reason for not 
371
            restricting package access.
372
            </hint>
373
        </question>
374
-->
375
 <answer id="deploy-packages">
376
  <p>
377
   Yes, only API and SPI packages are exported.
378
  </p>
379
 </answer>
380
381
382
383
<!--
384
        <question id="deploy-shared" when="final">
385
            Do you need to be installed in the shared location only, or in the user directory only,
386
            or can your module be installed anywhere?
387
            <hint>
388
            Installation location shall not matter, if it does explain why.
389
            Consider also whether <code>InstalledFileLocator</code> can help.
390
            </hint>
391
        </question>
392
-->
393
 <answer id="deploy-shared">
394
  <p>
395
   Anywhere.
396
  </p>
397
 </answer>
398
399
400
401
<!--
402
        <question id="exec-classloader" when="impl">
403
            Does your code create its own class loader(s)?
404
            <hint>
405
            A bit unusual. Please explain why and what for.
406
            </hint>
407
        </question>
408
-->
409
 <answer id="exec-classloader">
410
  <p>
411
   There is support for getting a class loader corresponding to a given
412
   classpath, useful e.g. for loading user JavaBeans to introspect. This is not
413
   used within the module itself.
414
  </p>
415
 </answer>
416
417
418
419
<!--
420
        <question id="exec-component" when="impl">
421
            Is execution of your code influenced by any (string) property
422
            of any of your components?
423
            
424
            <hint>
425
            Often <code>JComponent.getClientProperty</code>, <code>Action.getValue</code>
426
            or <code>PropertyDescriptor.getValue</code>, etc. are used to influence
427
            a behavior of some code. This of course forms an interface that should
428
            be documented. Also if one depends on some interface that an object
429
            implements (<code>component instanceof Runnable</code>) that forms an
430
            API as well.
431
            </hint>
432
        </question>
433
-->
434
 <answer id="exec-component">
435
  <p>
436
   No.
437
  </p>
438
 </answer>
439
440
441
442
<!--
443
        <question id="exec-introspection" when="impl">
444
            Does your module use any kind of runtime type information (<code>instanceof</code>,
445
            work with <code>java.lang.Class</code>, etc.)?
446
            <hint>
447
            Check for cases when you have an object of type A and you also
448
            expect it to (possibly) be of type B and do some special action. That
449
            should be documented. The same applies on operations in meta-level
450
            (Class.isInstance(...), Class.isAssignableFrom(...), etc.).
451
            </hint>
452
        </question>
453
-->
454
 <answer id="exec-introspection">
455
  <p>
456
   No.
457
  </p>
458
 </answer>
459
460
461
462
<!--
463
        <question id="exec-privateaccess" when="final">
464
            Are you aware of any other parts of the system calling some of 
465
            your methods by reflection?
466
            <hint>
467
            If so, describe the "contract" as an API. Likely private or friend one, but
468
            still API and consider rewrite of it.
469
            </hint>
470
        </question>
471
-->
472
 <answer id="exec-privateaccess">
473
  <p>
474
   No.
475
  </p>
476
 </answer>
477
478
479
480
<!--
481
        <question id="exec-process" when="impl">
482
            Do you execute an external process from your module? How do you ensure
483
            that the result is the same on different platforms? Do you parse output?
484
            Do you depend on result code?
485
            <hint>
486
            If you feed an input, parse the output please declare that as an API.
487
            </hint>
488
        </question>
489
-->
490
 <answer id="exec-process">
491
  <p>
492
   No.
493
  </p>
494
 </answer>
495
496
497
498
<!--
499
        <question id="exec-property" when="impl">
500
            Is execution of your code influenced by any environment or
501
            Java system (<code>System.getProperty</code>) property?
502
            
503
            <hint>
504
            If there is a property that can change the behavior of your 
505
            code, somebody will likely use it. You should describe what it does 
506
            and the <a href="http://openide.netbeans.org/tutorial/api-design.html#life">stability category</a>
507
            of this API. You may use
508
            <pre>
509
                &lt;api type="export" group="property" name="id" category="private" url="http://..."&gt;
510
                    description of the property, where it is used, what it influence, etc.
511
                &lt;/api&gt;            
512
            </pre>
513
            </hint>
514
        </question>
515
-->
516
 <answer id="exec-property">
517
  <p>
518
   No.
519
  </p>
520
 </answer>
521
522
523
524
<!--
525
        <question id="exec-reflection" when="impl">
526
            Does your code use Java Reflection to execute other code?
527
            <hint>
528
            This usually indicates a missing or insufficient API in the other
529
            part of the system. If the other side is not aware of your dependency
530
            this contract can be easily broken.
531
            </hint>
532
        </question>
533
-->
534
 <answer id="exec-reflection">
535
  <p>
536
   No.
537
  </p>
538
 </answer>
539
540
541
542
<!--
543
        <question id="exec-threading" when="impl">
544
            What threading models, if any, does your module adhere to?
545
            <hint>
546
                If your module calls foreign APIs which have a specific threading model,
547
                indicate how you comply with the requirements for multithreaded access
548
                (synchronization, mutexes, etc.) applicable to those APIs.
549
                If your module defines any APIs, or has complex internal structures
550
                that might be used from multiple threads, declare how you protect
551
                data against concurrent access, race conditions, deadlocks, etc.,
552
                and whether such rules are enforced by runtime warnings, errors, assertions, etc.
553
                Examples: a class might be non-thread-safe (like Java Collections); might
554
                be fully thread-safe (internal locking); might require access through a mutex
555
                (and may or may not automatically acquire that mutex on behalf of a client method);
556
                might be able to run only in the event queue; etc.
557
                Also describe when any events are fired: synchronously, asynchronously, etc.
558
                Ideas: <a href="http://core.netbeans.org/proposals/threading/index.html#recommendations">Threading Recommendations</a> (in progress)
559
            </hint>
560
        </question>
561
-->
562
 <answer id="exec-threading">
563
  <p>
564
   Currently each data structure is intended to be thread-safe.
565
  </p>
566
 </answer>
567
568
569
570
<!--
571
        <question id="format-clipboard" when="impl">
572
            Which data flavors (if any) does your code read from or insert to
573
            the clipboard (by access to clipboard on means calling methods on <code>java.awt.datatransfer.Transferable</code>?
574
            
575
            <hint>
576
            Often Node's deal with clipboard by usage of <code>Node.clipboardCopy, Node.clipboardCut and Node.pasteTypes</code>.
577
            Check your code for overriding these methods.
578
            </hint>
579
        </question>
580
-->
581
 <answer id="format-clipboard">
582
  <p>
583
   None.
584
  </p>
585
 </answer>
586
587
588
589
<!--
590
        <question id="format-dnd" when="impl">
591
            Which protocols (if any) does your code understand during Drag &amp; Drop?
592
            <hint>
593
            Often Node's deal with clipboard by usage of <code>Node.drag, Node.getDropType</code>. 
594
            Check your code for overriding these methods. Btw. if they are not overridden, they
595
            by default delegate to <code>Node.clipboardCopy, Node.clipboardCut and Node.pasteTypes</code>.
596
            </hint>
597
        </question>
598
-->
599
 <answer id="format-dnd">
600
  <p>
601
   None.
602
  </p>
603
 </answer>
604
605
606
607
<!--
608
        <question id="format-types" when="impl">
609
            Which protocols and file formats (if any) does your module read or write on disk,
610
            or transmit or receive over the network?
611
        </question>
612
-->
613
 <answer id="format-types">
614
  <p>
615
   None.
616
  </p>
617
 </answer>
618
619
620
621
<!--
622
        <question id="lookup-lookup" when="init">
623
            Does your module use <code>org.openide.util.Lookup</code>
624
            or any similar technology to find any components to communicate with? Which ones?
625
            
626
            <hint>
627
            Please describe the interfaces you are searching for, where 
628
            are defined, whether you are searching for just one or more of them,
629
            if the order is important, etc. Also classify the stability of such
630
            API contract.
631
            </hint>
632
        </question>
633
-->
634
 <answer id="lookup-lookup">
635
  <p>
636
   Yes, query implementations are found using Lookup as usual.
637
  </p>
638
 </answer>
639
640
641
642
<!--
643
        <question id="lookup-register" when="final">
644
            Do you register anything into lookup for other code to find?
645
            <hint>
646
            Do you register using layer file or using <code>META-INF/services</code>?
647
            Who is supposed to find your component?
648
            </hint>
649
        </question>
650
-->
651
 <answer id="lookup-register">
652
  <p>
653
   No.
654
  </p>
655
 </answer>
656
657
658
659
<!--
660
        <question id="lookup-remove" when="final">
661
            Do you remove entries of other modules from lookup?
662
            <hint>
663
            Why? Of course, that is possible, but it can be dangerous. Is the module
664
            your are masking resource from aware of what you are doing?
665
            </hint>
666
        </question>
667
-->
668
 <answer id="lookup-remove">
669
  <p>
670
   No.
671
  </p>
672
 </answer>
673
674
675
676
<!--
677
        <question id="perf-exit" when="final">
678
            Does your module run any code on exit?
679
        </question>
680
-->
681
 <answer id="perf-exit">
682
  <p>
683
   No.
684
  </p>
685
 </answer>
686
687
688
689
<!--
690
        <question id="perf-huge_dialogs" when="final">
691
            Does your module contain any dialogs or wizards with a large number of
692
            GUI controls such as combo boxes, lists, trees, or text areas?
693
        </question>
694
-->
695
 <answer id="perf-huge_dialogs">
696
  <p>
697
   No.
698
  </p>
699
 </answer>
700
701
702
703
<!--
704
        <question id="perf-limit" when="init">
705
            Are there any hard-coded or practical limits in the number or size of
706
            elements your code can handle?
707
        </question>
708
-->
709
 <answer id="perf-limit">
710
  <p>
711
   None known.
712
  </p>
713
 </answer>
714
715
716
717
<!--
718
        <question id="perf-mem" when="final">
719
            How much memory does your component consume? Estimate
720
            with a relation to the number of windows, etc.
721
        </question>
722
-->
723
 <answer id="perf-mem">
724
  <p>
725
   TBD, but probably little.
726
  </p>
727
 </answer>
728
729
730
731
<!--
732
        <question id="perf-menus" when="final">
733
            Does your module use dynamically updated context menus, or
734
            context-sensitive actions with complicated enablement logic?
735
        </question>
736
-->
737
 <answer id="perf-menus">
738
  <p>
739
   No.
740
  </p>
741
 </answer>
742
743
744
745
<!--
746
        <question id="perf-progress" when="final">
747
            Does your module execute any long-running tasks?
748
            
749
            <hint>Long running tasks should never block 
750
            AWT thread as it badly hurts the UI
751
            <a href="http://performance.netbeans.org/responsiveness/issues.html">
752
            responsiveness</a>.
753
            Tasks like connecting over
754
            network, computing huge amount of data, compilation
755
            be done asynchronously (for example
756
            using <code>RequestProcessor</code>), definitively it should 
757
            not block AWT thread.
758
            </hint>
759
        </question>
760
-->
761
 <answer id="perf-progress">
762
  <p>
763
   No.
764
  </p>
765
 </answer>
766
767
768
769
<!--
770
        <question id="perf-scale" when="init">
771
            Which external criteria influence the performance of your
772
            program (size of file in editor, number of files in menu, 
773
            in source directory, etc.) and how well your code scales?
774
            <hint>
775
            Please include some estimates, there are other more detailed 
776
            questions to answer in later phases of implementation. 
777
            </hint>
778
        </question>
779
-->
780
 <answer id="perf-scale">
781
  <p>
782
   Queries perform linearly in number of implementations, but as usual there will
783
   typically be only one or two implementations, e.g. delegating to owner
784
   projects.
785
  </p>
786
  <p>
787
   Currently <code>ClassPath</code>s keep global file change listeners to permit
788
   roots to be invalidated, and this makes file change events linear in the
789
   number of <code>ClassPath</code> objects. This area is being studied and will
790
   hopefully be optimized, perhaps reducing overhead to a small constant.
791
   May require explicit support from the Filesystems API to fully optimize.
792
  </p>
793
 </answer>
794
795
796
797
<!--
798
        <question id="perf-spi" when="init">
799
            How the performance of the plugged in code will be enforced?
800
            <hint>
801
            If you allow foreign code to be plugged into your own module, how
802
            do you enforce, that it will behave correctly and fast and will not
803
            negatively influence the performance of your own module?
804
            </hint>
805
        </question>
806
-->
807
 <answer id="perf-spi">
808
  <p>
809
   No special provisions.
810
  </p>
811
 </answer>
812
813
814
815
<!--
816
        <question id="perf-startup" when="final">
817
            Does your module run any code on startup?
818
        </question>
819
-->
820
 <answer id="perf-startup">
821
  <p>
822
   No.
823
  </p>
824
 </answer>
825
826
827
828
<!--
829
        <question id="perf-wakeup" when="final">
830
            Does any piece of your code wake up periodically and do something
831
            even when the system is otherwise idle (no user interaction)?
832
        </question>
833
-->
834
 <answer id="perf-wakeup">
835
  <p>
836
   No.
837
  </p>
838
 </answer>
839
840
841
842
<!--
843
        <question id="resources-file" when="final">
844
            Does your module use <code>java.io.File</code> directly?
845
            
846
            <hint>
847
            NetBeans provide a logical wrapper over plain files called 
848
            <code>org.openide.filesystems.FileObject</code> that
849
            provides uniform access to such resources and is the preferred
850
            way that should be used. But of course there can be situations when
851
            this is not suitable.
852
            </hint>
853
        </question>
854
-->
855
 <answer id="resources-file">
856
  <p>
857
   No.
858
  </p>
859
 </answer>
860
861
862
863
<!--
864
        <question id="resources-layer" when="final">
865
            Does your module provide own layer? Does it create any files or
866
            folders in it? What it is trying to communicate by that and with which 
867
            components?
868
            
869
            <hint>
870
            NetBeans allows automatic and declarative installation of resources 
871
            by module layers. Module register files into appropriate places
872
            and other components use that information to perform their task
873
            (build menu, toolbar, window layout, list of templates, set of
874
            options, etc.). 
875
            </hint>
876
        </question>
877
-->
878
 <answer id="resources-layer">
879
  <p>
880
   No.
881
  </p>
882
 </answer>
883
884
885
886
<!--
887
        <question id="resources-mask" when="final">
888
            Does your module mask/hide/override any resources provided by other modules in
889
            their layers?
890
            
891
            <hint>
892
            If you mask a file provided by another module, you probably depend
893
            on that and do not want the other module to (for example) change
894
            the file's name. That module shall thus make that file available as an API
895
            of some stability category.
896
            </hint>
897
        </question>
898
-->
899
 <answer id="resources-mask">
900
  <p>
901
   No.
902
  </p>
903
 </answer>
904
905
906
907
<!--
908
        <question id="resources-read" when="final">
909
            Does your module read any resources from layers? For what purpose?
910
            
911
            <hint>
912
            As this is some kind of intermodule dependency, it is a kind of API.
913
            Please describe it and classify according to 
914
            <a href="http://openide.netbeans.org/tutorial/api-design.html#categories">
915
            common stability categories</a>.
916
            </hint>
917
        </question>
918
-->
919
 <answer id="resources-read">
920
  <p>
921
   No.
922
  </p>
923
 </answer>
924
925
926
<!--
927
        <question id="security-grant" when="final">
928
            Does your code grant additional rights to some other code?
929
            <hint>Avoid using a class loader that adds extra
930
            permissions to loaded code unless really necessary.
931
            Also note that your API implementation
932
            can also expose unneeded permissions to enemy code by
933
            calling AccessController.doPrivileged().</hint>
934
        </question>
935
-->
936
 <answer id="security-grant">
937
  <p>
938
   <code>ClassPath.getClassLoader(...)</code> is granted all permissions.
939
  </p>
940
 </answer>
941
942
943
944
<!--
945
        <question id="security-policy" when="final">
946
            Does your functionality require modifications to the standard policy file?
947
            <hint>Your code might pass control to third-party code not
948
            coming from trusted domains. This could be code downloaded over the
949
            network or code coming from libraries that are not bundled
950
            with NetBeans. Which permissions need to be granted to which domains?</hint>
951
        </question>
952
-->
953
 <answer id="security-policy">
954
  <p>
955
   No.
956
  </p>
957
 </answer>
958
959
960
961
962
963
<!--
964
        <question id="arch-where" when="impl">
965
            Where one can find sources for your module?
966
            <hint>
967
                Please provide link to the Hg web client at
968
                http://hg.netbeans.org/
969
                or just use tag defaultanswer generate='here'
970
            </hint>
971
        </question>
972
-->
973
 <answer id="arch-where">
974
  <defaultanswer generate='here' />
975
 </answer>
976
977
978
979
<!--
980
        <question id="compat-deprecation" when="init">
981
            How the introduction of your project influences functionality
982
            provided by previous version of the product?
983
            <hint>
984
            If you are planning to deprecate/remove/change any existing APIs,
985
            list them here accompanied with the reason explaining why you
986
            are doing so.
987
            </hint>
988
        </question>
989
-->
990
 <answer id="compat-deprecation">
991
  <p>
992
   XXX no answer for compat-deprecation
993
  </p>
994
 </answer>
995
996
997
998
<!--
999
        <question id="exec-ant-tasks" when="impl">
1000
            Do you define or register any ant tasks that other can use?
1001
            
1002
            <hint>
1003
            If you provide an ant task that users can use, you need to be very
1004
            careful about its syntax and behaviour, as it most likely forms an
1005
	          API for end users and as there is a lot of end users, their reaction
1006
            when such API gets broken can be pretty strong.
1007
            </hint>
1008
        </question>
1009
-->
1010
 <answer id="exec-ant-tasks">
1011
  <p>
1012
   XXX no answer for exec-ant-tasks
1013
  </p>
1014
 </answer>
1015
1016
1017
1018
<!--
1019
        <question id="resources-preferences" when="final">
1020
            Does your module uses preferences via Preferences API? Does your module use NbPreferences or
1021
            or regular JDK Preferences ? Does it read, write or both ? 
1022
            Does it share preferences with other modules ? If so, then why ?
1023
            <hint>
1024
                You may use
1025
                    &lt;api type="export" group="preferences"
1026
                    name="preference node name" category="private"&gt;
1027
                    description of individual keys, where it is used, what it
1028
                    influences, whether the module reads/write it, etc.
1029
                    &lt;/api&gt;
1030
                Due to XML ID restrictions, rather than /org/netbeans/modules/foo give the "name" as org.netbeans.modules.foo.
1031
                Note that if you use NbPreferences this name will then be the same as the code name base of the module.
1032
            </hint>
1033
        </question>
1034
-->
1035
 <answer id="resources-preferences">
1036
  <p>
1037
   XXX no answer for resources-preferences
1038
  </p>
1039
 </answer>
1040
1041
</api-answers>
(-)a/api.java.classpath/build.xml (+5 lines)
Line 0 Link Here
1
<?xml version="1.0" encoding="UTF-8"?>
2
<project basedir="." default="netbeans" name="api.java.classpath">
3
    <description>Builds, tests, and runs the project org.netbeans.api.java.classpath</description>
4
    <import file="../nbbuild/templates/projectized.xml"/>
5
</project>
(-)a/api.java.classpath/manifest.mf (+5 lines)
Line 0 Link Here
1
Manifest-Version: 1.0
2
OpenIDE-Module: org.netbeans.api.java.classpath/1
3
OpenIDE-Module-Localizing-Bundle: org/netbeans/api/java/classpath/Bundle.properties
4
OpenIDE-Module-Specification-Version: 1.0
5
(-)a/api.java.classpath/nbproject/project.properties (+4 lines)
Line 0 Link Here
1
is.autoload=true
2
javac.source=1.5
3
javac.compilerargs=-Xlint -Xlint:-serial
4
test.unit.run.cp.extra=${o.n.core.dir}/lib/boot.jar:${o.n.core.dir}/core/core.jar
(-)a/api.java.classpath/nbproject/project.xml (+68 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.java.classpath</code-name-base>
7
            <module-dependencies>
8
                <dependency>
9
                    <code-name-base>org.openide.execution</code-name-base>
10
                    <build-prerequisite/>
11
                    <compile-dependency/>
12
                    <run-dependency>
13
                        <specification-version>1.12</specification-version>
14
                    </run-dependency>
15
                </dependency>
16
                <dependency>
17
                    <code-name-base>org.openide.filesystems</code-name-base>
18
                    <build-prerequisite/>
19
                    <compile-dependency/>
20
                    <run-dependency>
21
                        <specification-version>7.9</specification-version>
22
                    </run-dependency>
23
                </dependency>
24
                <dependency>
25
                    <code-name-base>org.openide.io</code-name-base>
26
                    <build-prerequisite/>
27
                    <compile-dependency/>
28
                    <run-dependency>
29
                        <specification-version>1.13</specification-version>
30
                    </run-dependency>
31
                </dependency>
32
                <dependency>
33
                    <code-name-base>org.openide.util</code-name-base>
34
                    <build-prerequisite/>
35
                    <compile-dependency/>
36
                    <run-dependency>
37
                        <specification-version>7.13</specification-version>
38
                    </run-dependency>
39
                </dependency>
40
            </module-dependencies>
41
            <test-dependencies>
42
                <test-type>
43
                    <name>unit</name>
44
                    <test-dependency>
45
                        <code-name-base>org.openide.util</code-name-base>
46
                    </test-dependency>
47
                    <test-dependency>
48
                        <code-name-base>org.openide.modules</code-name-base>
49
                    </test-dependency>
50
                    <test-dependency>
51
                        <code-name-base>org.netbeans.modules.masterfs</code-name-base>
52
                    </test-dependency>
53
                </test-type>
54
                <test-type>
55
                    <name>qa-functional</name>
56
                </test-type>
57
            </test-dependencies>
58
            <public-packages>
59
                <package>org.netbeans.api.java.classpath</package>
60
                <package>org.netbeans.api.java.queries</package>
61
                <package>org.netbeans.spi.java.classpath</package>
62
                <package>org.netbeans.spi.java.classpath.support</package>
63
                <package>org.netbeans.spi.java.queries</package>
64
                <package>org.netbeans.spi.java.queries.support</package>
65
            </public-packages>
66
        </data>
67
    </configuration>
68
</project>
(-)a/api.java/src/org/netbeans/api/java/classpath/Bundle.properties (-46 / +5 lines)
Lines 1-46 Link Here
1
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
1
OpenIDE-Module-Display-Category=Base IDE
2
#
2
OpenIDE-Module-Long-Description=\
3
# Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
3
    Provides Classpath representing list of (source) roots and operations on them.
4
#
4
OpenIDE-Module-Name=Classpath APIs
5
# The contents of this file are subject to the terms of either the GNU
5
OpenIDE-Module-Short-Description=Classpath APIs
6
# General Public License Version 2 only ("GPL") or the Common
7
# Development and Distribution License("CDDL") (collectively, the
8
# "License"). You may not use this file except in compliance with the
9
# License. You can obtain a copy of the License at
10
# http://www.netbeans.org/cddl-gplv2.html
11
# or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
12
# specific language governing permissions and limitations under the
13
# License.  When distributing the software, include this License Header
14
# Notice in each file and include the License file at
15
# nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
16
# particular file as subject to the "Classpath" exception as provided
17
# by Sun in the GPL Version 2 section of the License file that
18
# accompanied this code. If applicable, add the following below the
19
# License Header, with the fields enclosed by brackets [] replaced by
20
# your own identifying information:
21
# "Portions Copyrighted [year] [name of copyright owner]"
22
#
23
# Contributor(s):
24
#
25
# The Original Software is NetBeans. The Initial Developer of the Original
26
# Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
27
# Microsystems, Inc. All Rights Reserved.
28
#
29
# If you wish your version of this file to be governed by only the CDDL
30
# or only the GPL Version 2, indicate your decision by adding
31
# "[Contributor] elects to include this software in this distribution
32
# under the [CDDL or GPL Version 2] license." If you do not indicate a
33
# single choice of license, a recipient has the option to distribute
34
# your version of this file under either the CDDL, the GPL Version 2 or
35
# to extend the choice of license to its licensees as provided above.
36
# However, if you add GPL Version 2 code and therefore, elected the GPL
37
# Version 2 license, then the option applies only if the new code is
38
# made subject to such option by the copyright holder.
39
40
# Localizable strings from module's manifest
41
OpenIDE-Module-Name=Java Support APIs
42
OpenIDE-Module-Display-Category=Infrastructure
43
OpenIDE-Module-Short-Description=APIs for Java development support modules
44
OpenIDE-Module-Long-Description=Allows other modules to use services \
45
provided by Java module.
46
(-)a/api.java.classpath/src/org/netbeans/modules/java/classpath/ClassPathAccessor.java (+65 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * Contributor(s):
25
 *
26
 * The Original Software is NetBeans. The Initial Developer of the Original
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
 * Microsystems, Inc. All Rights Reserved.
29
 *
30
 * If you wish your version of this file to be governed by only the CDDL
31
 * or only the GPL Version 2, indicate your decision by adding
32
 * "[Contributor] elects to include this software in this distribution
33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
34
 * single choice of license, a recipient has the option to distribute
35
 * your version of this file under either the CDDL, the GPL Version 2 or
36
 * to extend the choice of license to its licensees as provided above.
37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
38
 * Version 2 license, then the option applies only if the new code is
39
 * made subject to such option by the copyright holder.
40
 */
41
package org.netbeans.modules.java.classpath;
42
43
import org.netbeans.api.java.classpath.ClassPath;
44
import org.netbeans.spi.java.classpath.ClassPathImplementation;
45
46
47
public abstract class ClassPathAccessor {
48
49
    public static ClassPathAccessor DEFAULT;
50
51
    // force loading of ClassPath class. That will set DEFAULT variable.
52
    static {
53
        Class c = ClassPath.class;
54
        try {
55
            Class.forName(c.getName(), true, c.getClassLoader());
56
        } catch (Exception ex) {
57
            ex.printStackTrace();
58
        }
59
    }
60
61
    public abstract ClassPath createClassPath(ClassPathImplementation spiClasspath);
62
63
    public abstract ClassPathImplementation getClassPathImpl (ClassPath cp);
64
65
}
(-)a/api.java.classpath/src/org/netbeans/modules/java/classpath/ProxyClassPathImplementation.java (+145 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * Contributor(s):
25
 *
26
 * The Original Software is NetBeans. The Initial Developer of the Original
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
 * Microsystems, Inc. All Rights Reserved.
29
 *
30
 * If you wish your version of this file to be governed by only the CDDL
31
 * or only the GPL Version 2, indicate your decision by adding
32
 * "[Contributor] elects to include this software in this distribution
33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
34
 * single choice of license, a recipient has the option to distribute
35
 * your version of this file under either the CDDL, the GPL Version 2 or
36
 * to extend the choice of license to its licensees as provided above.
37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
38
 * Version 2 license, then the option applies only if the new code is
39
 * made subject to such option by the copyright holder.
40
 */
41
package org.netbeans.modules.java.classpath;
42
43
import org.netbeans.spi.java.classpath.ClassPathImplementation;
44
import org.netbeans.spi.java.classpath.PathResourceImplementation;
45
46
import java.util.List;
47
import java.util.ArrayList;
48
import java.util.Iterator;
49
import java.util.Collections;
50
import java.beans.PropertyChangeListener;
51
import java.beans.PropertyChangeEvent;
52
import org.openide.util.WeakListeners;
53
54
/** ProxyClassPathImplementation provides read only proxy for ClassPathImplementations.
55
 *  The order of the resources is given by the order of its delegates.
56
 *  The proxy is designed to be used as a union of class paths.
57
 *  E.g. to be able to easily iterate or listen on all design resources = sources + compile resources
58
 */
59
public class ProxyClassPathImplementation implements ClassPathImplementation {
60
61
    private ClassPathImplementation[] classPaths;
62
    private List<PathResourceImplementation> resourcesCache;
63
    private ArrayList<PropertyChangeListener> listeners;
64
    private PropertyChangeListener classPathsListener;
65
66
    public ProxyClassPathImplementation (ClassPathImplementation[] classPaths) {
67
        if (classPaths == null)
68
            throw new IllegalArgumentException ();
69
        List<ClassPathImplementation> impls = new ArrayList<ClassPathImplementation> ();
70
        classPathsListener = new DelegatesListener ();
71
        for (ClassPathImplementation cpImpl : classPaths) {
72
            if (cpImpl == null)
73
                continue;
74
            cpImpl.addPropertyChangeListener (WeakListeners.propertyChange(classPathsListener,cpImpl));
75
            impls.add (cpImpl);
76
        }
77
        this.classPaths = impls.toArray(new ClassPathImplementation[impls.size()]);
78
    }
79
80
81
82
    public List <? extends PathResourceImplementation> getResources() {
83
        synchronized (this) {
84
            if (this.resourcesCache != null) {
85
                return this.resourcesCache;
86
            }
87
        }
88
        
89
        ArrayList<PathResourceImplementation> result = new ArrayList<PathResourceImplementation> (classPaths.length*10);
90
        for (ClassPathImplementation cpImpl : classPaths) {
91
            List<? extends PathResourceImplementation> subPath = cpImpl.getResources();
92
            assert subPath != null : "ClassPathImplementation.getResources() returned null. ClassPathImplementation.class: " 
93
                + cpImpl.getClass().toString() + " ClassPathImplementation: " + cpImpl.toString();
94
            result.addAll (subPath);
95
        }
96
        
97
        synchronized (this) {
98
            if (this.resourcesCache == null) {
99
                resourcesCache = Collections.unmodifiableList (result);
100
            }
101
            return this.resourcesCache;
102
        }
103
    }
104
105
    public synchronized void addPropertyChangeListener(PropertyChangeListener listener) {
106
        if (this.listeners == null)
107
            this.listeners = new ArrayList<PropertyChangeListener> ();
108
        this.listeners.add (listener);
109
    }
110
111
    public synchronized void removePropertyChangeListener(PropertyChangeListener listener) {
112
        if (this.listeners == null)
113
            return;
114
        this.listeners.remove (listener);
115
    }
116
    
117
    public String toString () {
118
        StringBuilder builder = new StringBuilder("[");   //NOI18N
119
        for (ClassPathImplementation cpImpl : this.classPaths) {
120
            builder.append (cpImpl.toString());
121
            builder.append(", ");   //NOI18N
122
        }
123
        builder.append ("]");   //NOI18N
124
        return builder.toString ();
125
    }
126
127
128
    private class DelegatesListener implements PropertyChangeListener {
129
130
        public void propertyChange(PropertyChangeEvent evt) {
131
            PropertyChangeListener[] _listeners;
132
            synchronized (ProxyClassPathImplementation.this) {
133
                ProxyClassPathImplementation.this.resourcesCache = null;    //Clean the cache
134
                if (ProxyClassPathImplementation.this.listeners == null)
135
                    return;
136
                _listeners = ProxyClassPathImplementation.this.listeners.toArray(new PropertyChangeListener[ProxyClassPathImplementation.this.listeners.size()]);
137
            }
138
            PropertyChangeEvent event = new PropertyChangeEvent (ProxyClassPathImplementation.this, evt.getPropertyName(),null,null);
139
            for (PropertyChangeListener l : _listeners) {
140
                l.propertyChange (event);
141
            }
142
        }
143
    }
144
145
}
(-)a/api.java.classpath/src/org/netbeans/modules/java/classpath/SimpleClassPathImplementation.java (+91 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * Contributor(s):
25
 *
26
 * The Original Software is NetBeans. The Initial Developer of the Original
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
 * Microsystems, Inc. All Rights Reserved.
29
 *
30
 * If you wish your version of this file to be governed by only the CDDL
31
 * or only the GPL Version 2, indicate your decision by adding
32
 * "[Contributor] elects to include this software in this distribution
33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
34
 * single choice of license, a recipient has the option to distribute
35
 * your version of this file under either the CDDL, the GPL Version 2 or
36
 * to extend the choice of license to its licensees as provided above.
37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
38
 * Version 2 license, then the option applies only if the new code is
39
 * made subject to such option by the copyright holder.
40
 */
41
package org.netbeans.modules.java.classpath;
42
43
import java.util.List;
44
import java.beans.PropertyChangeListener;
45
import java.net.URL;
46
47
import java.util.ArrayList;
48
import java.util.Collections;
49
import java.util.Iterator;
50
51
import org.netbeans.spi.java.classpath.ClassPathImplementation;
52
import org.netbeans.spi.java.classpath.PathResourceImplementation;
53
54
55
public class SimpleClassPathImplementation implements ClassPathImplementation {
56
57
    List<? extends PathResourceImplementation> entries;
58
59
    public SimpleClassPathImplementation() {
60
        this(new ArrayList<PathResourceImplementation>());
61
    }
62
63
    public SimpleClassPathImplementation(List<? extends PathResourceImplementation> entries) {
64
        this.entries = entries;
65
    }
66
    
67
    public List <? extends PathResourceImplementation> getResources() {
68
        return Collections.unmodifiableList(entries);
69
    }
70
71
    public void addPropertyChangeListener(PropertyChangeListener listener) {
72
        // XXX TBD
73
    }
74
75
    public void removePropertyChangeListener(PropertyChangeListener listener) {
76
        // XXX TBD
77
    }
78
    
79
    public String toString () {
80
        StringBuilder builder = new StringBuilder ("SimpleClassPathImplementation["); //NOI18N
81
        for (PathResourceImplementation impl : this.entries) {
82
            URL[] roots = impl.getRoots();
83
            for (URL root : roots) {
84
                builder.append (root.toExternalForm());
85
                builder.append (", ");  //NOI18N
86
            }
87
        }
88
        builder.append ("]");   //NOI18N
89
        return builder.toString ();
90
    }    
91
}
(-)a/api.java.classpath/src/org/netbeans/modules/java/classpath/SimplePathResourceImplementation.java (+91 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * Contributor(s):
25
 *
26
 * The Original Software is NetBeans. The Initial Developer of the Original
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
 * Microsystems, Inc. All Rights Reserved.
29
 *
30
 * If you wish your version of this file to be governed by only the CDDL
31
 * or only the GPL Version 2, indicate your decision by adding
32
 * "[Contributor] elects to include this software in this distribution
33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
34
 * single choice of license, a recipient has the option to distribute
35
 * your version of this file under either the CDDL, the GPL Version 2 or
36
 * to extend the choice of license to its licensees as provided above.
37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
38
 * Version 2 license, then the option applies only if the new code is
39
 * made subject to such option by the copyright holder.
40
 */
41
package org.netbeans.modules.java.classpath;
42
43
44
import org.netbeans.spi.java.classpath.support.PathResourceBase;
45
import org.netbeans.spi.java.classpath.ClassPathImplementation;
46
47
import java.net.URL;
48
49
50
/**
51
 * Provides implementation of the single rooted PathResoruceImplementation
52
 */
53
54
public final class SimplePathResourceImplementation  extends PathResourceBase {
55
56
    private URL[] url;
57
58
59
60
    public SimplePathResourceImplementation (URL root) {
61
        if (root == null)
62
            throw new IllegalArgumentException ();
63
        this.url = new URL[] {root};
64
    }
65
66
67
    public URL[] getRoots() {
68
        return this.url;
69
    }
70
71
    public ClassPathImplementation getContent() {
72
        return null;
73
    }
74
75
    public String toString () {
76
        return "SimplePathResource{"+this.getRoots()[0]+"}";   //NOI18N
77
    }
78
79
    public int hashCode () {
80
        return this.url[0].hashCode();
81
    }
82
83
    public boolean equals (Object other) {
84
        if (other instanceof SimplePathResourceImplementation) {
85
            SimplePathResourceImplementation opr = (SimplePathResourceImplementation) other;
86
            return this.url[0].equals (opr.url[0]);
87
        }
88
        else
89
            return false;
90
    }
91
}
(-)a/api.java.classpath/src/org/netbeans/modules/java/queries/SFBQImpl2Result.java (+83 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 * 
4
 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
5
 * 
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 * 
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 * 
35
 * Contributor(s):
36
 * 
37
 * Portions Copyrighted 2008 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.modules.java.queries;
41
42
import javax.swing.event.ChangeListener;
43
import org.netbeans.api.java.queries.SourceForBinaryQuery;
44
import org.netbeans.spi.java.queries.SourceForBinaryQueryImplementation2;
45
import org.openide.filesystems.FileObject;
46
import org.openide.filesystems.FileUtil;
47
48
/**
49
 *
50
 * @author Tomas Zezula
51
 */
52
public class SFBQImpl2Result implements SourceForBinaryQueryImplementation2.Result {
53
    
54
    private final SourceForBinaryQuery.Result delegate;
55
    
56
    public SFBQImpl2Result (final SourceForBinaryQuery.Result result) {
57
        assert result != null;
58
        this.delegate = result;
59
    }
60
61
    public boolean preferSources() {
62
        //Preserve the old behavior from 4.0 to 6.1, ignore sources inside archives
63
        final FileObject[] roots = this.delegate.getRoots();
64
        for (FileObject root : roots) {
65
            if (FileUtil.getArchiveFile(root) != null) {
66
                return false;
67
            }
68
        }
69
        return true;
70
    }
71
72
    public FileObject[] getRoots () {
73
        return this.delegate.getRoots();
74
    }
75
76
    public void addChangeListener(ChangeListener l) {
77
        this.delegate.addChangeListener(l);
78
    }
79
80
    public void removeChangeListener(ChangeListener l) {
81
        this.delegate.removeChangeListener(l);
82
    }
83
}
(-)a/api.java.classpath/src/org/netbeans/spi/java/classpath/ClassPathFactory.java (+88 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * Contributor(s):
25
 *
26
 * The Original Software is NetBeans. The Initial Developer of the Original
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
 * Microsystems, Inc. All Rights Reserved.
29
 *
30
 * If you wish your version of this file to be governed by only the CDDL
31
 * or only the GPL Version 2, indicate your decision by adding
32
 * "[Contributor] elects to include this software in this distribution
33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
34
 * single choice of license, a recipient has the option to distribute
35
 * your version of this file under either the CDDL, the GPL Version 2 or
36
 * to extend the choice of license to its licensees as provided above.
37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
38
 * Version 2 license, then the option applies only if the new code is
39
 * made subject to such option by the copyright holder.
40
 */
41
42
package org.netbeans.spi.java.classpath;
43
44
import java.net.URL;
45
import org.netbeans.api.java.classpath.ClassPath;
46
import org.netbeans.modules.java.classpath.ClassPathAccessor;
47
import org.openide.filesystems.FileUtil;
48
49
/**
50
 * Most general way to create {@link ClassPath} instances.
51
 * You are not permitted to create them directly; instead you implement
52
 * {@link ClassPathImplementation} and use this factory.
53
 * See also {@link org.netbeans.spi.java.classpath.support.ClassPathSupport}
54
 * for easier ways to create classpaths.
55
 * @since org.netbeans.api.java/1 1.4
56
 */
57
public final class ClassPathFactory {
58
59
    private ClassPathFactory() {
60
    }
61
62
    /**
63
     * Create API classpath instance for the given SPI classpath.
64
     * @param spiClasspath instance of SPI classpath
65
     * @return instance of API classpath
66
     */
67
    public static ClassPath createClassPath(ClassPathImplementation spiClasspath) {
68
//        assert checkEntries (spiClasspath) : "ClassPathImplementation contains invalid root: " + spiClasspath.toString();    //Commented, not to decrease the performance even in the dev build.
69
        return ClassPathAccessor.DEFAULT.createClassPath(spiClasspath);
70
    }
71
    
72
    
73
    private static boolean checkEntries (ClassPathImplementation spiClasspath) {
74
        for (PathResourceImplementation impl : spiClasspath.getResources()) {
75
            URL[] roots = impl.getRoots();
76
            for (URL root : roots) {
77
                if (FileUtil.isArchiveFile(root)) {
78
                    return false;
79
                }
80
                if (root.toExternalForm().endsWith("/")) {  // NOI18N
81
                    return false;
82
                }
83
            }
84
        }
85
        return true;
86
    }
87
88
}
(-)a/api.java.classpath/src/org/netbeans/spi/java/classpath/ClassPathImplementation.java (+74 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * Contributor(s):
25
 *
26
 * The Original Software is NetBeans. The Initial Developer of the Original
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
 * Microsystems, Inc. All Rights Reserved.
29
 *
30
 * If you wish your version of this file to be governed by only the CDDL
31
 * or only the GPL Version 2, indicate your decision by adding
32
 * "[Contributor] elects to include this software in this distribution
33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
34
 * single choice of license, a recipient has the option to distribute
35
 * your version of this file under either the CDDL, the GPL Version 2 or
36
 * to extend the choice of license to its licensees as provided above.
37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
38
 * Version 2 license, then the option applies only if the new code is
39
 * made subject to such option by the copyright holder.
40
 */
41
package org.netbeans.spi.java.classpath;
42
43
import java.util.List;
44
import java.beans.PropertyChangeListener;
45
46
/**
47
 * SPI interface for ClassPath.
48
 * @see ClassPathFactory
49
 * @since org.netbeans.api.java/1 1.4
50
 */
51
public interface ClassPathImplementation {
52
53
    public static final String PROP_RESOURCES = "resources";    //NOI18N
54
55
    /**
56
     * Returns list of entries, the list is unmodifiable.
57
     * @return List of PathResourceImplementation, never returns null
58
     * it may return an empty List
59
     */
60
    public List<? extends PathResourceImplementation> getResources();
61
62
    /**
63
     * Adds property change listener.
64
     * The listener is notified when the set of entries has changed.
65
     * @param listener
66
     */
67
    public void addPropertyChangeListener(PropertyChangeListener listener);
68
69
    /**
70
     * Removes property change listener
71
     * @param listener
72
     */
73
    public void removePropertyChangeListener(PropertyChangeListener listener);
74
}
(-)a/api.java.classpath/src/org/netbeans/spi/java/classpath/ClassPathProvider.java (+123 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * Contributor(s):
25
 *
26
 * The Original Software is NetBeans. The Initial Developer of the Original
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
 * Microsystems, Inc. All Rights Reserved.
29
 *
30
 * If you wish your version of this file to be governed by only the CDDL
31
 * or only the GPL Version 2, indicate your decision by adding
32
 * "[Contributor] elects to include this software in this distribution
33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
34
 * single choice of license, a recipient has the option to distribute
35
 * your version of this file under either the CDDL, the GPL Version 2 or
36
 * to extend the choice of license to its licensees as provided above.
37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
38
 * Version 2 license, then the option applies only if the new code is
39
 * made subject to such option by the copyright holder.
40
 */
41
42
package org.netbeans.spi.java.classpath;
43
44
import org.netbeans.api.java.classpath.ClassPath;
45
import org.openide.filesystems.FileObject;
46
47
/**
48
 * Provider interface for Java classpaths.
49
 * <p>
50
 * The <code>org.netbeans.modules.java.project</code> module registers an
51
 * implementation of this interface to global lookup which looks for the
52
 * project which owns a file (if any) and checks its lookup for this interface,
53
 * and if it finds an instance, delegates to it. Therefore it is not normally
54
 * necessary for a project type provider to register its own instance just to
55
 * define the classpaths for files it owns, assuming it depends on the Java
56
 * Project module.
57
 * </p>
58
 * <div class="nonnormative">
59
 * <p>
60
 * Note that to make editor code completion functionality work for a Java source file the
61
 * following classpaths must be available for it:
62
 * </p>
63
 * <ol>
64
 * <li>The {@link ClassPath#BOOT} type of classpath
65
 *     is required or the source file will not be parsable and 
66
 *     code completion will be disabled. See also
67
 *     {@link org.netbeans.spi.java.queries.SourceLevelQueryImplementation}.</li>
68
 * <li>The {@link ClassPath#SOURCE} type of classpath
69
 *     is required or code completion will be disabled.
70
 *     Providing this classpath will enable code completion, but only elements
71
 *     defined on this classpath will be offered if the compile classpath is missing.</li>
72
 * <li>The {@link ClassPath#COMPILE} type of classpath
73
 *     is recommended to be provide to make code completion work fully
74
 *     by suggesting all classes against which the source is developed.</li>
75
 * </ol>
76
 * <p>{@link ClassPath#EXECUTE} is also recommended for e.g. I18N functionality to work.
77
 * This should contain the full run-time classpath of the class, including its build
78
 * location (bytecode).</p>
79
 * <p>You should return these classpaths for the package root folder and any
80
 * files or folders inside it.</p>
81
 * <p>You should register classpaths for source files of all these types in
82
 * {@link org.netbeans.api.java.classpath.GlobalPathRegistry}
83
 * when they are to be exposed in the GUI as available for use (e.g. for the editor's Fast Open dialog),
84
 * and unregister them when they are no longer to be exposed. Typically this is done as part of
85
 * <a href="@PROJECTS/PROJECTUIAPI@/org/netbeans/spi/project/ui/ProjectOpenedHook.html">ProjectOpenedHook</a>.
86
 * <p>It is also desirable to produce classpath information for compiled class files
87
 * (bytecode), including their package roots (whether a disk folder or a JAR root).
88
 * This will enable parsing of the class files, which is sometimes needed (e.g. for
89
 * expanding the class file node and seeing its members).
90
 * Compiled classes should have:</p>
91
 * <ol>
92
 * <li>{@link ClassPath#BOOT} corresponding to the Java platform to be used with the classes.</li>
93
 * <li>{@link ClassPath#EXECUTE} containing the bytecode's package root itself, plus any other
94
 * libraries it needs to resolve against. Should normally be the same as the execute classpath
95
 * of the corresponding source files.</li>
96
 * </ol>
97
 * <p>If no specific class path providers are available for a given source file or bytecode file,
98
 * i.e. <code>null</code> is returned from all providers, there may be a fallback implementation
99
 * which would provide reasonable defaults. For source files, this could mean a boot classpath
100
 * corresponding to the default Java platform (i.e. the JDK being used to run the IDE); empty
101
 * compile and execute classpaths; and a sourcepath computed based on the package statement in the
102
 * source file (if this is possible). For class files, this could mean a boot classpath determined
103
 * as for source files, and an execute classpath containing the package root apparently owning the
104
 * class file (computed according to the class file's package information, if this is possible).</p>
105
 * </div>
106
 * @see ClassPath#getClassPath
107
 * @see org.netbeans.api.java.classpath.GlobalPathRegistry
108
 * @author Jesse Glick
109
 * @since org.netbeans.api.java/1 1.4
110
 */
111
public interface ClassPathProvider {
112
    
113
    /**
114
     * Find some kind of a classpath for a given file.
115
     * @param file a file somewhere, or a source root
116
     * @param type a classpath type such as {@link ClassPath#COMPILE}
117
     * @return an appropriate classpath, or null for no answer
118
     * @see ClassPathFactory
119
     * @see org.netbeans.spi.java.classpath.support.ClassPathSupport
120
     */
121
    ClassPath findClassPath(FileObject file, String type);
122
    
123
}
(-)a/api.java.classpath/src/org/netbeans/spi/java/classpath/FilteringPathResourceImplementation.java (+75 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * Contributor(s):
25
 *
26
 * The Original Software is NetBeans. The Initial Developer of the Original
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
 * Microsystems, Inc. All Rights Reserved.
29
 *
30
 * If you wish your version of this file to be governed by only the CDDL
31
 * or only the GPL Version 2, indicate your decision by adding
32
 * "[Contributor] elects to include this software in this distribution
33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
34
 * single choice of license, a recipient has the option to distribute
35
 * your version of this file under either the CDDL, the GPL Version 2 or
36
 * to extend the choice of license to its licensees as provided above.
37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
38
 * Version 2 license, then the option applies only if the new code is
39
 * made subject to such option by the copyright holder.
40
 */
41
42
package org.netbeans.spi.java.classpath;
43
44
import java.net.URL;
45
46
/**
47
 * SPI interface for a classpath entry which can include or exclude particular files.
48
 * @author Jesse Glick
49
 * @see "issue #49026"
50
 * @since org.netbeans.api.java/1 1.13
51
 */
52
public interface FilteringPathResourceImplementation extends PathResourceImplementation {
53
54
    /**
55
     * Property name to fire in case {@link #includes} would change.
56
     * (The old and new value should be left null.)
57
     * <p>
58
     * <strong>Special usage note:</strong>
59
     * If multiple {@link FilteringPathResourceImplementation}s inside a single
60
     * {@link ClassPathImplementation} fire changes in this pseudo-property in
61
     * succession, all using the same non-null {@link java.beans.PropertyChangeEvent#setPropagationId},
62
     * {@link org.netbeans.api.java.classpath.ClassPath#PROP_INCLUDES} will be fired just once. This can be used
63
     * to prevent "event storms" from triggering excessive Java source root rescanning.
64
     */
65
    String PROP_INCLUDES = "includes"; // NOI18N
66
67
    /**
68
     * Determines whether a given resource is included in the classpath or not.
69
     * @param root one of the roots given by {@link #getRoots} (else may throw {@link IllegalArgumentException})
70
     * @param resource a relative resource path within that root; may refer to a file or slash-terminated folder; the empty string refers to the root itself
71
     * @return true if included (or, in the case of a folder, at least partially included); false if excluded
72
     */
73
    boolean includes(URL root, String resource);
74
75
}
(-)a/api.java.classpath/src/org/netbeans/spi/java/classpath/PathResourceImplementation.java (+87 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * Contributor(s):
25
 *
26
 * The Original Software is NetBeans. The Initial Developer of the Original
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
 * Microsystems, Inc. All Rights Reserved.
29
 *
30
 * If you wish your version of this file to be governed by only the CDDL
31
 * or only the GPL Version 2, indicate your decision by adding
32
 * "[Contributor] elects to include this software in this distribution
33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
34
 * single choice of license, a recipient has the option to distribute
35
 * your version of this file under either the CDDL, the GPL Version 2 or
36
 * to extend the choice of license to its licensees as provided above.
37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
38
 * Version 2 license, then the option applies only if the new code is
39
 * made subject to such option by the copyright holder.
40
 */
41
package org.netbeans.spi.java.classpath;
42
43
import java.beans.PropertyChangeListener;
44
import java.net.URL;
45
46
/**
47
 * SPI interface for one classpath entry.
48
 * @see ClassPathImplementation
49
 * @since org.netbeans.api.java/1 1.4
50
 */
51
public interface PathResourceImplementation {
52
53
    public static final String PROP_ROOTS = "roots";    //NOI18N
54
55
    /** Roots of the class path entry.
56
     *  In the case of simple resource it returns array containing just one URL.
57
     *  In the case of composite resource it returns array containing one or more URL.
58
     * @return array of URL, never returns null.
59
     */
60
    public URL[] getRoots();
61
62
    /**
63
     * Returns ClassPathImplementation representing the content of the PathResourceImplementation.
64
     * If the PathResourceImplementation represents leaf resource, it returns null.
65
     * The ClassPathImplementation is live and can be used for path resource content
66
     * modification.
67
     * <p><strong>Semi-deprecated.</strong> There was never a real reason for this method to exist.
68
     * If implementing <code>PathResourceImplementation</code> you can simply return null;
69
     * it is unlikely anyone will call this method anyway.
70
     * @return classpath handle in case of composite resource; null for leaf resource
71
     */
72
    public ClassPathImplementation getContent();
73
74
    /**
75
     * Adds property change listener.
76
     * The listener is notified when the roots of the entry are changed.
77
     * @param listener
78
     */
79
    public void addPropertyChangeListener(PropertyChangeListener listener);
80
81
    /**
82
     * Removes property change listener.
83
     * @param listener
84
     */
85
    public void removePropertyChangeListener(PropertyChangeListener listener);
86
87
}
(-)a/api.java.classpath/src/org/netbeans/spi/java/classpath/package.html (+73 lines)
Line 0 Link Here
1
<!--
2
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
4
Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
5
6
7
The contents of this file are subject to the terms of either the GNU
8
General Public License Version 2 only ("GPL") or the Common
9
Development and Distribution License("CDDL") (collectively, the
10
"License"). You may not use this file except in compliance with the
11
License. You can obtain a copy of the License at
12
http://www.netbeans.org/cddl-gplv2.html
13
or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
14
specific language governing permissions and limitations under the
15
License.  When distributing the software, include this License Header
16
Notice in each file and include the License file at
17
nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
18
particular file as subject to the "Classpath" exception as provided
19
by Sun in the GPL Version 2 section of the License file that
20
accompanied this code. If applicable, add the following below the
21
License Header, with the fields enclosed by brackets [] replaced by
22
your own identifying information:
23
"Portions Copyrighted [year] [name of copyright owner]"
24
25
Contributor(s):
26
27
The Original Software is NetBeans. The Initial Developer of the Original
28
Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
29
Microsystems, Inc. All Rights Reserved.
30
31
If you wish your version of this file to be governed by only the CDDL
32
or only the GPL Version 2, indicate your decision by adding
33
"[Contributor] elects to include this software in this distribution
34
under the [CDDL or GPL Version 2] license." If you do not indicate a
35
single choice of license, a recipient has the option to distribute
36
your version of this file under either the CDDL, the GPL Version 2 or
37
to extend the choice of license to its licensees as provided above.
38
However, if you add GPL Version 2 code and therefore, elected the GPL
39
Version 2 license, then the option applies only if the new code is
40
made subject to such option by the copyright holder.
41
-->
42
<html>
43
<body>
44
45
SPI permitting new classpaths to be constructed and registered.
46
47
<p>{@link org.netbeans.spi.java.classpath.ClassPathProvider}s can be registered
48
to default lookup in order to associate information about classpaths with files.
49
For example, a Java-oriented project type would normally indicate that its Java
50
sources have a certain classpath associated with them.<br>
51
For a source file the ClassPathProvider has to return a
52
{@link org.netbeans.api.java.classpath.ClassPath} of the following ClassPath types:
53
<ul>
54
<li>ClassPath.SOURCE - the classpath contains the source roots of the project</li>
55
<li>ClassPath.BOOT - the classpath contains the jdk runtime libraries</li>
56
<li>ClassPath.COMPILE - the classpath contains the project compile libraries (compile classpath)</li>
57
</ul>
58
it may also return a ClassPath of type ClassPath.EXEC pointing to the build output folder.
59
<br>
60
For build output the ClassPathProvider has to return a ClassPath of the following
61
types:
62
<ul>
63
<li>ClassPath.BOOT - the classpath contains the jdk runtime libraries</li>
64
<li>ClassPath.COMPILE - the classpath contains the project compile libraries (compile classpath)</li>
65
<li>ClassPath.EXEC - the classpath contains the build output folder</li>
66
</ul>
67
</p>
68
69
<p>{@link org.netbeans.spi.java.classpath.ClassPathFactory} may be used to
70
create new {@link org.netbeans.api.java.classpath.ClassPath} instances.</p>
71
  
72
</body>
73
</html>
(-)a/api.java.classpath/src/org/netbeans/spi/java/classpath/support/ClassPathSupport.java (+213 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * Contributor(s):
25
 *
26
 * The Original Software is NetBeans. The Initial Developer of the Original
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
 * Microsystems, Inc. All Rights Reserved.
29
 *
30
 * If you wish your version of this file to be governed by only the CDDL
31
 * or only the GPL Version 2, indicate your decision by adding
32
 * "[Contributor] elects to include this software in this distribution
33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
34
 * single choice of license, a recipient has the option to distribute
35
 * your version of this file under either the CDDL, the GPL Version 2 or
36
 * to extend the choice of license to its licensees as provided above.
37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
38
 * Version 2 license, then the option applies only if the new code is
39
 * made subject to such option by the copyright holder.
40
 */
41
package org.netbeans.spi.java.classpath.support;
42
43
import java.io.File;
44
import org.netbeans.spi.java.classpath.PathResourceImplementation;
45
import org.netbeans.spi.java.classpath.ClassPathImplementation;
46
import org.netbeans.spi.java.classpath.ClassPathFactory;
47
import org.netbeans.modules.java.classpath.*;
48
import org.netbeans.api.java.classpath.ClassPath;
49
import org.openide.ErrorManager;
50
import org.openide.filesystems.FileObject;
51
52
import java.net.URL;
53
import java.util.List;
54
import java.util.ArrayList;
55
import org.openide.filesystems.FileStateInvalidException;
56
import org.openide.filesystems.FileUtil;
57
58
/**
59
 * Convenience factory for creating classpaths of common sorts.
60
 * @since org.netbeans.api.java/1 1.4
61
 */
62
public class ClassPathSupport {
63
64
    private ClassPathSupport () {
65
    }
66
67
68
    /** Creates leaf PathResourceImplementation.
69
     * The created PathResourceImplementation has exactly one immutable root.
70
     * @param url the root of the resource. The URL must refer to folder. In the case of archive file
71
     * the jar protocol URL must be used.
72
     * @return PathResourceImplementation
73
     */
74
    public static PathResourceImplementation createResource (URL url) {
75
        if (url == null) {
76
            throw new NullPointerException("Cannot pass null URL to ClassPathSupport.createResource"); // NOI18N
77
        }
78
        // FU.iAF is a bit slow, so don't call it except when assertions are on:
79
        boolean assertions = false;
80
        assert assertions = true;
81
        if (assertions && FileUtil.isArchiveFile(url)) {
82
            throw new IllegalArgumentException("File URL pointing to " + // NOI18N
83
                "JAR is not valid classpath entry. Use jar: URL. Was: "+url); // NOI18N
84
        }
85
        if (!url.toExternalForm().endsWith("/")) { // NOI18N
86
            throw new IllegalArgumentException("URL must be a folder URL (append '/' if necessary): " + url); // NOI18N
87
        }
88
        return new SimplePathResourceImplementation (url);
89
    }
90
91
92
    /**
93
     * Create ClassPathImplementation for the given list of
94
     * {@link PathResourceImplementation} entries.
95
     * @param entries list of {@link PathResourceImplementation} instances;
96
     *     cannot be null; can be empty
97
     * @return SPI classpath
98
     */
99
    public static ClassPathImplementation createClassPathImplementation(List< ? extends PathResourceImplementation> entries) {
100
        if (entries == null) {
101
            throw new NullPointerException("Cannot pass null entries"); // NOI18N
102
        }
103
        return new SimpleClassPathImplementation(entries);
104
    }
105
106
107
    /**
108
     * Create ClassPath for the given list of
109
     * {@link PathResourceImplementation} entries.
110
     * @param entries list of {@link PathResourceImplementation} instances;
111
     *     cannot be null; can be empty
112
     * @return API classpath
113
     */
114
    public static ClassPath createClassPath(List<? extends PathResourceImplementation> entries) {
115
        if (entries == null) {
116
            throw new NullPointerException("Cannot pass null entries"); // NOI18N
117
        }
118
        return ClassPathFactory.createClassPath(createClassPathImplementation(entries));
119
    }
120
121
122
    /**
123
     * Create ClassPath for the given array of class path roots
124
     * @param roots array of fileobjects which must correspond to directory.
125
     * In the case of archive file, the FileObject representing the root of the
126
     * archive must be used.  Cannot be null; can be empty array; array can contain nulls.
127
     * @return API classpath
128
     */
129
    public static ClassPath createClassPath(FileObject... roots) {
130
        assert roots != null;
131
        List<PathResourceImplementation> l = new ArrayList<PathResourceImplementation> ();
132
        for (FileObject root : roots) {
133
            if (root == null) {
134
                continue;
135
            }
136
            try {
137
                URL u = root.getURL();            
138
                l.add(createResource(u));
139
            } catch (FileStateInvalidException e) {
140
                ErrorManager.getDefault().notify (e);
141
            }
142
        }
143
        return createClassPath (l);
144
    }
145
146
147
    /**
148
     * Create ClassPath for the given array of class path roots
149
     * @param roots array of URLs which must correspond to directory.
150
     * In the case of archive file, the jar protocol URL must be used.
151
     *   Cannot be null; can be empty array; array can contain nulls.
152
     * @return API classpath
153
     */
154
    public static ClassPath createClassPath(URL... roots) {
155
        assert roots != null;
156
        List<PathResourceImplementation> l = new ArrayList<PathResourceImplementation> ();
157
        for (URL root : roots) {
158
            if (root == null)
159
                continue;
160
            l.add (createResource(root));
161
        }
162
        return createClassPath(l);
163
    }
164
165
    /**
166
     * Convenience method to create a classpath object from a conventional string representation.
167
     * @param jvmPath a JVM-style classpath (folder or archive paths separated by {@link File#pathSeparator})
168
     * @return a corresponding classpath object
169
     * @throws IllegalArgumentException in case a path entry looks to be invalid
170
     * @since org.netbeans.api.java/1 1.15
171
     * @see FileUtil#urlForArchiveOrDir
172
     * @see ClassPath#toJVMPath
173
     */
174
    public static ClassPath createClassPath(String jvmPath) throws IllegalArgumentException {
175
        List<PathResourceImplementation> l = new ArrayList<PathResourceImplementation>();
176
        for (String piece : jvmPath.split(File.pathSeparator)) {
177
            File f = FileUtil.normalizeFile(new File(piece));
178
            URL u = FileUtil.urlForArchiveOrDir(f);
179
            if (u == null) {
180
                throw new IllegalArgumentException("Path entry looks to be invalid: " + piece); // NOI18N
181
            }
182
            l.add(createResource(u));
183
        }
184
        return createClassPath(l);
185
    }
186
187
    /**
188
     * Creates read only proxy ClassPathImplementation for given delegates.
189
     * The order of resources is given by the order of the delegates
190
     * @param delegates ClassPathImplementations to delegate to.
191
     * @return SPI classpath
192
     */
193
    public static ClassPathImplementation createProxyClassPathImplementation(ClassPathImplementation... delegates) {
194
        return new ProxyClassPathImplementation (delegates);
195
    }
196
197
198
    /**
199
     * Creates read only proxy ClassPath for given delegates.
200
     * The order of resources is given by the order of the delegates
201
     * @param delegates ClassPaths to delegate to.
202
     * @return API classpath
203
     */
204
    public static ClassPath createProxyClassPath(ClassPath... delegates) {
205
        assert delegates != null;
206
        ClassPathImplementation[] impls = new ClassPathImplementation [delegates.length];
207
        for (int i = 0; i < delegates.length; i++) {
208
             impls[i] = ClassPathAccessor.DEFAULT.getClassPathImpl (delegates[i]);
209
        }
210
        return ClassPathFactory.createClassPath (createProxyClassPathImplementation(impls));
211
    }
212
213
}
(-)a/api.java.classpath/src/org/netbeans/spi/java/classpath/support/CompositePathResourceBase.java (+157 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * Contributor(s):
25
 *
26
 * The Original Software is NetBeans. The Initial Developer of the Original
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
 * Microsystems, Inc. All Rights Reserved.
29
 *
30
 * If you wish your version of this file to be governed by only the CDDL
31
 * or only the GPL Version 2, indicate your decision by adding
32
 * "[Contributor] elects to include this software in this distribution
33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
34
 * single choice of license, a recipient has the option to distribute
35
 * your version of this file under either the CDDL, the GPL Version 2 or
36
 * to extend the choice of license to its licensees as provided above.
37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
38
 * Version 2 license, then the option applies only if the new code is
39
 * made subject to such option by the copyright holder.
40
 */
41
package org.netbeans.spi.java.classpath.support;
42
43
import org.netbeans.spi.java.classpath.PathResourceImplementation;
44
import org.netbeans.spi.java.classpath.ClassPathImplementation;
45
46
import java.net.URL;
47
import java.beans.PropertyChangeListener;
48
import java.beans.PropertyChangeEvent;
49
import java.util.ArrayList;
50
import java.util.Iterator;
51
import java.util.List;
52
import java.util.Arrays;
53
54
/**
55
 * This class provides a base class for PathResource implementations
56
 * @since org.netbeans.api.java/1 1.4
57
 */
58
public abstract class CompositePathResourceBase implements PathResourceImplementation {
59
60
    private URL[] roots;
61
    private ClassPathImplementation model;
62
    private ArrayList<PropertyChangeListener> pListeners;
63
64
    /**
65
     * Returns the roots of the PathResource
66
     * @return URL[]
67
     */
68
    public final URL[] getRoots() {
69
        if (this.roots == null) {
70
            synchronized (this) {
71
                if (this.roots == null) {
72
                    initContent ();
73
                    List<URL> result = new ArrayList<URL> ();
74
                    for (PathResourceImplementation pri : this.model.getResources()) {
75
                        result.addAll (Arrays.asList(pri.getRoots()));
76
                    }
77
                    this.roots = result.toArray (new URL [result.size()]);
78
                }
79
            }
80
        }
81
        return this.roots;
82
    }
83
84
85
    /**
86
     * Returns the ClassPathImplementation representing the content of this PathResourceImplementation
87
     * @return ClassPathImplementation
88
     */
89
    public final ClassPathImplementation getContent() {
90
		initContent ();
91
    	return this.model;
92
    }
93
94
    /**
95
     * Adds property change listener.
96
     * The listener is notified when the roots of the PathResource are changed.
97
     * @param listener
98
     */
99
    public synchronized final void addPropertyChangeListener(PropertyChangeListener listener) {
100
        if (this.pListeners == null)
101
            this.pListeners = new ArrayList<PropertyChangeListener> ();
102
        this.pListeners.add (listener);
103
    }
104
105
    /**
106
     * Removes PropertyChangeListener
107
     * @param listener
108
     */
109
    public synchronized final void removePropertyChangeListener(PropertyChangeListener listener) {
110
        if (this.pListeners == null)
111
            return;
112
        this.pListeners.remove (listener);
113
    }
114
115
    /**
116
     * Fires PropertyChangeEvent
117
     * @param propName name of property
118
     * @param oldValue old property value or null
119
     * @param newValue new property value or null
120
     */
121
    protected final void firePropertyChange (String propName, Object oldValue, Object newValue) {
122
        PropertyChangeListener[] _listeners;
123
        synchronized (this) {
124
            if (this.pListeners == null)
125
                return;
126
            _listeners = this.pListeners.toArray(new PropertyChangeListener[this.pListeners.size()]);
127
        }
128
        PropertyChangeEvent event = new PropertyChangeEvent (this, propName, oldValue, newValue);
129
        for (PropertyChangeListener l : _listeners) {
130
            l.propertyChange (event);
131
        }
132
    }
133
134
    /** Creates the array of the roots of PathResource.
135
     * Most PathResource (directory, jar) have single root,
136
     * but the PathResource can have more than one root to
137
     * represent more complex resources like libraries.
138
     * The returned value is cached.
139
     * @return ClassPathImplementation
140
     */
141
    protected abstract ClassPathImplementation createContent ();
142
143
144
	private synchronized void initContent () {
145
		if (this.model == null) {
146
			ClassPathImplementation cp = createContent ();
147
			assert cp != null;
148
			cp.addPropertyChangeListener (new PropertyChangeListener () {
149
				public void propertyChange (PropertyChangeEvent event) {
150
					roots = null;
151
					firePropertyChange (PROP_ROOTS, null,null);
152
				}
153
			});
154
            this.model = cp;
155
		}
156
	}
157
}
(-)a/api.java.classpath/src/org/netbeans/spi/java/classpath/support/PathResourceBase.java (+98 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * Contributor(s):
25
 *
26
 * The Original Software is NetBeans. The Initial Developer of the Original
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
 * Microsystems, Inc. All Rights Reserved.
29
 *
30
 * If you wish your version of this file to be governed by only the CDDL
31
 * or only the GPL Version 2, indicate your decision by adding
32
 * "[Contributor] elects to include this software in this distribution
33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
34
 * single choice of license, a recipient has the option to distribute
35
 * your version of this file under either the CDDL, the GPL Version 2 or
36
 * to extend the choice of license to its licensees as provided above.
37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
38
 * Version 2 license, then the option applies only if the new code is
39
 * made subject to such option by the copyright holder.
40
 */
41
package org.netbeans.spi.java.classpath.support;
42
43
44
import java.beans.PropertyChangeListener;
45
import java.beans.PropertyChangeEvent;
46
import java.util.ArrayList;
47
import java.util.Iterator;
48
import org.netbeans.spi.java.classpath.PathResourceImplementation;
49
50
/**
51
 * This class provides a base class for PathResource implementations
52
 * @since org.netbeans.api.java/1 1.4
53
 */
54
public abstract class PathResourceBase implements PathResourceImplementation {
55
56
    private ArrayList<PropertyChangeListener> pListeners;
57
58
59
    /**
60
     * Adds property change listener.
61
     * The listener is notified when the roots of the PathResource are changed.
62
     * @param listener
63
     */
64
    public synchronized final void addPropertyChangeListener(PropertyChangeListener listener) {
65
        if (this.pListeners == null)
66
            this.pListeners = new ArrayList<PropertyChangeListener> ();
67
        this.pListeners.add (listener);
68
    }
69
70
    /**
71
     * Removes PropertyChangeListener
72
     * @param listener
73
     */
74
    public synchronized final void removePropertyChangeListener(PropertyChangeListener listener) {
75
        if (this.pListeners == null)
76
            return;
77
        this.pListeners.remove (listener);
78
    }
79
80
    /**
81
     * Fires PropertyChangeEvent
82
     * @param propName name of property
83
     * @param oldValue old property value or null
84
     * @param newValue new property value or null
85
     */
86
    protected final void firePropertyChange (String propName, Object oldValue, Object newValue) {
87
        PropertyChangeListener[] _listeners;
88
        synchronized (this) {
89
            if (this.pListeners == null)
90
                return;
91
            _listeners = this.pListeners.toArray(new PropertyChangeListener[this.pListeners.size()]);
92
        }
93
        PropertyChangeEvent event = new PropertyChangeEvent (this, propName, oldValue, newValue);
94
        for (PropertyChangeListener l : _listeners) {
95
            l.propertyChange (event);
96
        }
97
    }
98
}
(-)a/api.java.classpath/src/org/netbeans/spi/java/classpath/support/package.html (+56 lines)
Line 0 Link Here
1
<!--
2
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
4
Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
5
6
7
The contents of this file are subject to the terms of either the GNU
8
General Public License Version 2 only ("GPL") or the Common
9
Development and Distribution License("CDDL") (collectively, the
10
"License"). You may not use this file except in compliance with the
11
License. You can obtain a copy of the License at
12
http://www.netbeans.org/cddl-gplv2.html
13
or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
14
specific language governing permissions and limitations under the
15
License.  When distributing the software, include this License Header
16
Notice in each file and include the License file at
17
nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
18
particular file as subject to the "Classpath" exception as provided
19
by Sun in the GPL Version 2 section of the License file that
20
accompanied this code. If applicable, add the following below the
21
License Header, with the fields enclosed by brackets [] replaced by
22
your own identifying information:
23
"Portions Copyrighted [year] [name of copyright owner]"
24
25
Contributor(s):
26
27
The Original Software is NetBeans. The Initial Developer of the Original
28
Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
29
Microsystems, Inc. All Rights Reserved.
30
31
If you wish your version of this file to be governed by only the CDDL
32
or only the GPL Version 2, indicate your decision by adding
33
"[Contributor] elects to include this software in this distribution
34
under the [CDDL or GPL Version 2] license." If you do not indicate a
35
single choice of license, a recipient has the option to distribute
36
your version of this file under either the CDDL, the GPL Version 2 or
37
to extend the choice of license to its licensees as provided above.
38
However, if you add GPL Version 2 code and therefore, elected the GPL
39
Version 2 license, then the option applies only if the new code is
40
made subject to such option by the copyright holder.
41
-->
42
<html>
43
<body>
44
45
Convenience classes to make it easier to create classpaths.
46
47
<p>{@link org.netbeans.spi.java.classpath.support.ClassPathSupport} provides
48
various ways to create {@link org.netbeans.api.java.classpath.ClassPath} objects
49
beyond what the plain SPI provides.</p>
50
51
<p>{@link org.netbeans.spi.java.classpath.support.PathResourceBase} and
52
{@link org.netbeans.spi.java.classpath.support.CompositePathResourceBase} can be
53
used to define parts of a classpath in a controlled way.</p>
54
55
</body>
56
</html>
(-)a/api.java.classpath/src/org/netbeans/spi/java/queries/support/SourceForBinaryQueryImpl2Base.java (+73 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 * 
4
 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
5
 * 
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 * 
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 * 
35
 * Contributor(s):
36
 * 
37
 * Portions Copyrighted 2008 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.spi.java.queries.support;
41
42
import org.netbeans.api.java.queries.SourceForBinaryQuery;
43
import org.netbeans.modules.java.queries.SFBQImpl2Result;
44
import org.netbeans.spi.java.queries.SourceForBinaryQueryImplementation2;
45
import org.openide.util.Parameters;
46
47
/**
48
 * Base class for {@link SourceForBinaryQueryImplementation2} which need to delegate
49
 * to other {@link SourceForBinaryQueryImplementation}.
50
 * @since 1.16
51
 * @author Tomas Zezula
52
 */
53
public abstract class SourceForBinaryQueryImpl2Base implements SourceForBinaryQueryImplementation2 {
54
55
    /**
56
     * Creates a wrapper for {@link SourceForBinaryQuery.Result}. This method
57
     * should be used by delegating {@link SourceForBinaryQueryImplementation2}
58
     * which need to delegate to {@link SourceForBinaryQueryImplementation}. 
59
     * @param result returned by {@link SourceForBinaryQueryImplementation},
60
     * When result is already instanceof {@link SourceForBinaryQueryImplementation2.Result}
61
     * it's returned without wrapping.
62
     * @return a {@link SourceForBinaryQueryImplementation2.Result}.
63
     */
64
    protected final Result asResult (SourceForBinaryQuery.Result result) {
65
        Parameters.notNull("result", result);   //NOI18N
66
        if (result instanceof Result) {
67
            return (Result) result;
68
        }
69
        else {
70
            return new SFBQImpl2Result(result);
71
        }
72
    }
73
}
(-)a/api.java.classpath/test/unit/src/org/netbeans/api/java/classpath/ClassPathTest.java (+701 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * Contributor(s):
25
 *
26
 * The Original Software is NetBeans. The Initial Developer of the Original
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
 * Microsystems, Inc. All Rights Reserved.
29
 *
30
 * If you wish your version of this file to be governed by only the CDDL
31
 * or only the GPL Version 2, indicate your decision by adding
32
 * "[Contributor] elects to include this software in this distribution
33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
34
 * single choice of license, a recipient has the option to distribute
35
 * your version of this file under either the CDDL, the GPL Version 2 or
36
 * to extend the choice of license to its licensees as provided above.
37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
38
 * Version 2 license, then the option applies only if the new code is
39
 * made subject to such option by the copyright holder.
40
 */
41
42
package org.netbeans.api.java.classpath;
43
44
import java.io.File;
45
import java.beans.PropertyChangeEvent;
46
import java.beans.PropertyChangeListener;
47
import java.beans.PropertyChangeSupport;
48
import java.io.FileOutputStream;
49
import java.lang.ref.Reference;
50
import java.lang.ref.WeakReference;
51
import java.net.URL;
52
import java.net.URLClassLoader;
53
import java.util.ArrayList;
54
import java.util.Arrays;
55
import java.util.Collections;
56
import java.util.Enumeration;
57
import java.util.HashSet;
58
import java.util.Iterator;
59
import java.util.List;
60
import java.util.Set;
61
import java.util.SortedSet;
62
import java.util.StringTokenizer;
63
import java.util.TreeSet;
64
import java.util.jar.JarOutputStream;
65
import java.util.logging.Level;
66
import java.util.zip.ZipEntry;
67
import org.netbeans.junit.Log;
68
import org.netbeans.junit.NbTestCase;
69
import org.netbeans.spi.java.classpath.support.ClassPathSupport;
70
import org.netbeans.spi.java.classpath.ClassPathImplementation;
71
import org.netbeans.spi.java.classpath.ClassPathFactory;
72
import org.netbeans.spi.java.classpath.FilteringPathResourceImplementation;
73
import org.netbeans.spi.java.classpath.PathResourceImplementation;
74
import org.openide.filesystems.FileObject;
75
import org.openide.filesystems.FileUtil;
76
77
public class ClassPathTest extends NbTestCase {
78
79
    public ClassPathTest(String testName) {
80
        super(testName);
81
    }
82
83
    protected @Override void setUp() throws Exception {
84
        super.setUp();
85
        clearWorkDir();
86
    }
87
88
    private File getBaseDir() throws Exception {
89
        return FileUtil.normalizeFile(getWorkDir());
90
    }
91
92
    /**
93
     * Tests ClassPath.getResourceName ();
94
     */
95
    public void testGetResourceName() throws Exception {
96
        File f = getBaseDir();        
97
        f = new File(f.getPath()+"/w.e.i.r.d/f  o  l  d  e  r");
98
        f.mkdirs();
99
        File f2 = new File(f, "org/netbeans/test");
100
        f2.mkdirs();
101
        File f3 = new File(f2, "Main.java");
102
        f3.createNewFile();
103
104
        FileObject cpRoot = FileUtil.toFileObject(f);
105
        FileObject cpItem = FileUtil.toFileObject(f2);
106
        FileObject clazz = FileUtil.toFileObject(f3);
107
        ClassPath cp = ClassPathSupport.createClassPath(new FileObject[]{cpRoot});
108
        String pkg = cp.getResourceName(cpItem);
109
        assertEquals("org/netbeans/test", pkg);
110
        
111
        pkg = cp.getResourceName(cpItem, '.', true);
112
        assertEquals("org.netbeans.test", pkg);
113
        
114
        pkg = cp.getResourceName(cpItem, '.', false);
115
        assertEquals("org.netbeans.test", pkg);
116
        
117
        pkg = cp.getResourceName(cpItem, '#', true);
118
        assertEquals("org#netbeans#test", pkg);
119
        
120
        pkg = cp.getResourceName(cpItem, '#', false);
121
        assertEquals("org#netbeans#test", pkg);
122
        
123
        pkg = cp.getResourceName(clazz);
124
        assertEquals("org/netbeans/test/Main.java", pkg);
125
        
126
        pkg = cp.getResourceName(clazz, '.', true);
127
        assertEquals("org.netbeans.test.Main.java", pkg);
128
        
129
        pkg = cp.getResourceName(clazz, '.', false);
130
        assertEquals("org.netbeans.test.Main", pkg);
131
        
132
        pkg = cp.getResourceName(clazz, '@', true);
133
        assertEquals("org@netbeans@test@Main.java", pkg);
134
        
135
        pkg = cp.getResourceName(clazz, '@', false);
136
        assertEquals("org@netbeans@test@Main", pkg);
137
    }
138
    
139
    /**
140
     * Tests ClassPath.findAllResources(), ClassPath.findResoruce(), 
141
     * ClassPath.contains (), ClassPath.findOwnerRoot(),
142
     * ClassPath.isResourceVisible ()
143
     */
144
    public void testGetResource () throws Exception {
145
        File root_1 = new File (getBaseDir(),"root_1");
146
        root_1.mkdir();
147
        File root_2 = new File (getBaseDir(),"root_2");
148
        root_2.mkdir();
149
        FileObject[] roots = new FileObject [] {
150
            FileUtil.toFileObject(root_1),
151
            FileUtil.toFileObject(root_2),
152
        };
153
        
154
        FileObject tmp = roots[0].createFolder("org");
155
        tmp = tmp.createFolder("me");
156
        FileObject testFo_1 = tmp.createData("Foo","txt");
157
        tmp = roots[1].createFolder("org");
158
        tmp = tmp.createFolder("me");
159
        FileObject testFo_2 = tmp.createData("Foo","txt");        
160
        ClassPath cp = ClassPathSupport.createClassPath(roots);        
161
        
162
        //findResource
163
        assertTrue(cp.findResource ("org/me/Foo.txt")==testFo_1);
164
        assertTrue (cp.findResource("org/me/None.txt")==null);
165
        
166
        //findAllResources
167
        List res = cp.findAllResources ("org/me/Foo.txt");
168
        assertTrue (res.size() == 2);
169
        assertTrue (res.contains(testFo_1));
170
        assertTrue (res.contains(testFo_2));
171
        
172
        //contains
173
        assertTrue (cp.contains (testFo_1));
174
        assertTrue (cp.contains (testFo_2));
175
        assertFalse (cp.contains (roots[0].getParent()));
176
        
177
        //findOwnerRoot
178
        assertTrue (cp.findOwnerRoot(testFo_1)==roots[0]);
179
        assertTrue (cp.findOwnerRoot(testFo_2)==roots[1]);
180
181
        /*
182
        //isResourceVisible
183
        assertTrue (cp.isResourceVisible(testFo_1));
184
        assertFalse (cp.isResourceVisible(testFo_2));
185
         */
186
        
187
        cp = null;
188
        roots[0].delete();
189
        roots[1].delete();
190
    }
191
    
192
    /**
193
     * Test ClassPath.getRoots(), ClassPath.addPropertyChangeListener (),
194
     * ClassPath.entries () and classpath SPI.
195
     */
196
    public void testListening() throws Exception {
197
        // XXX unreliable, would be improved by usage of TestFileUtils methods:
198
199
        File root_1 = new File (getBaseDir(),"root_1");
200
        root_1.mkdir();
201
        File root_2 = new File (getBaseDir(),"root_2");
202
        root_2.mkdir();
203
        File root_3 = new File (getBaseDir(),"root_3.jar");
204
        JarOutputStream out = new JarOutputStream ( new FileOutputStream (root_3));
205
        try {            
206
            out.putNextEntry(new ZipEntry("test.txt"));
207
            out.write ("test".getBytes());
208
        } finally {
209
            out.close ();
210
        }        
211
        assertNotNull("Cannot find file",FileUtil.toFileObject(root_1));
212
        assertNotNull("Cannot find file",FileUtil.toFileObject(root_2));
213
        assertNotNull("Cannot find file",FileUtil.toFileObject(root_3));
214
        TestClassPathImplementation impl = new TestClassPathImplementation();
215
	ClassPath cp = ClassPathFactory.createClassPath (impl);
216
        impl.addResource(root_1.toURI().toURL());
217
        cp.addPropertyChangeListener (impl);
218
        impl.addResource (root_2.toURI().toURL());
219
        impl.assertEvents(ClassPath.PROP_ENTRIES, ClassPath.PROP_ROOTS);
220
        assertTrue (cp.getRoots().length==2);
221
        impl.removeResource (root_2.toURI().toURL());
222
        impl.assertEvents(ClassPath.PROP_ENTRIES, ClassPath.PROP_ROOTS);
223
        assertTrue (cp.getRoots().length==1);
224
        FileObject fo = cp.getRoots()[0];
225
        FileObject parentFolder = fo.getParent();        
226
        fo.delete();
227
        impl.assertEvents(ClassPath.PROP_ROOTS);
228
        assertTrue (cp.getRoots().length==0);
229
        parentFolder.createFolder("root_1");
230
        assertTrue (cp.getRoots().length==1);
231
        impl.assertEvents(ClassPath.PROP_ROOTS);
232
        FileObject archiveFile = FileUtil.toFileObject(root_3);
233
        impl.addResource(FileUtil.getArchiveRoot(archiveFile.getURL()));
234
        assertEquals (cp.getRoots().length,2);
235
        impl.assertEvents(ClassPath.PROP_ENTRIES, ClassPath.PROP_ROOTS);
236
        root_3.delete();
237
        root_3 = new File (getBaseDir(),"root_3.jar");
238
        Thread.sleep(1000);
239
        out = new JarOutputStream ( new FileOutputStream (root_3));
240
        try {            
241
            out.putNextEntry(new ZipEntry("test2.txt"));
242
            out.write ("test2".getBytes());
243
        } finally {
244
            out.close ();
245
        }
246
        archiveFile.refresh();
247
        impl.assertEvents(ClassPath.PROP_ROOTS);
248
        root_1.delete();
249
        root_2.delete();
250
        root_3.delete();
251
        cp = null;
252
    }
253
254
    public void testListening2() throws Exception {
255
        // Checks that changes in PathResourceImplementation.PROP_ROOTS matter.
256
        class FiringPRI implements PathResourceImplementation {
257
            private URL[] roots = new URL[0];
258
            public URL[] getRoots() {
259
                return roots;
260
            }
261
            void changeRoots(URL[] nue) {
262
                roots = nue;
263
                pcs.firePropertyChange(PROP_ROOTS, null, null);
264
            }
265
            public ClassPathImplementation getContent() {
266
                return null;
267
            }
268
            PropertyChangeSupport pcs = new PropertyChangeSupport(this);
269
            public void addPropertyChangeListener(PropertyChangeListener listener) {
270
                pcs.addPropertyChangeListener(listener);
271
            }
272
            public void removePropertyChangeListener(PropertyChangeListener listener) {
273
                pcs.removePropertyChangeListener(listener);
274
            }
275
        }
276
        FiringPRI pri = new FiringPRI();
277
        TestClassPathImplementation impl = new TestClassPathImplementation();
278
        impl.addResource(pri);
279
        ClassPath cp = ClassPathFactory.createClassPath(impl);
280
        assertEquals(Collections.emptyList(), Arrays.asList(cp.getRoots()));
281
        cp.addPropertyChangeListener(impl);
282
        File d = new File(getBaseDir(), "d");
283
        d.mkdir();
284
        pri.changeRoots(new URL[] {d.toURI().toURL()});
285
        impl.assertEvents(ClassPath.PROP_ENTRIES, ClassPath.PROP_ROOTS);
286
        assertEquals(Collections.singletonList(FileUtil.toFileObject(d)), Arrays.asList(cp.getRoots()));
287
    }
288
    
289
    public void testChangesAcknowledgedWithoutListener() throws Exception {
290
        // Discovered in #72573.
291
        clearWorkDir();
292
        File root = new File(getWorkDir(), "root");
293
        URL rootU = root.toURI().toURL();
294
        if (!rootU.toExternalForm().endsWith("/")) {
295
            rootU = new URL(rootU.toExternalForm() + "/");
296
        }
297
        ClassPath cp = ClassPathSupport.createClassPath(new URL[] {rootU});
298
        assertEquals("nothing there yet", null, cp.findResource("f"));
299
        FileObject f = FileUtil.createData(FileUtil.toFileObject(getWorkDir()), "root/f");
300
        assertEquals("found new file", f, cp.findResource("f"));
301
        f.delete();
302
        assertEquals("again empty", null, cp.findResource("f"));
303
    }
304
    
305
    static final class TestClassPathImplementation implements ClassPathImplementation, PropertyChangeListener {
306
307
        private final PropertyChangeSupport support = new PropertyChangeSupport (this);
308
        private final List<PathResourceImplementation> resources = new ArrayList<PathResourceImplementation> ();
309
        private final SortedSet<String> events = new TreeSet<String>();
310
311
        public synchronized void addResource (URL resource) {
312
            PathResourceImplementation pr = ClassPathSupport.createResource (resource);
313
            addResource(pr);
314
        }
315
316
        public synchronized void addResource(PathResourceImplementation pr) {
317
            this.resources.add (pr);
318
            this.support.firePropertyChange (ClassPathImplementation.PROP_RESOURCES,null,null);
319
        }
320
321
        public synchronized void removeResource (URL resource) {
322
            for (Iterator it = this.resources.iterator(); it.hasNext();) {
323
                PathResourceImplementation pr = (PathResourceImplementation) it.next ();
324
                if (Arrays.asList(pr.getRoots()).contains (resource)) {
325
                    this.resources.remove (pr);
326
                    this.support.firePropertyChange (ClassPathImplementation.PROP_RESOURCES,null,null);
327
                    break;
328
                }
329
            }
330
        }
331
332
        public synchronized List<? extends PathResourceImplementation> getResources() {
333
            return this.resources;
334
        }
335
336
        public void addPropertyChangeListener(PropertyChangeListener listener) {
337
            this.support.addPropertyChangeListener (listener);
338
        }
339
340
        public void removePropertyChangeListener(PropertyChangeListener listener) {
341
            this.support.removePropertyChangeListener (listener);
342
        }
343
344
        public void propertyChange (PropertyChangeEvent event) {
345
            events.add(event.getPropertyName());
346
        }
347
348
        void assertEvents(String... events) {
349
            assertEquals(new TreeSet<String>(Arrays.asList(events)), this.events);
350
            this.events.clear();
351
        }
352
    }
353
354
    public void testFilteredClassPaths() throws Exception {
355
        FileObject bd = FileUtil.toFileObject(getBaseDir());
356
        FileObject u1fo = bd.createFolder("u1");
357
        FileObject u2fo = bd.createFolder("u2");
358
        final URL u1 = u1fo.getURL();
359
        final URL u2 = u2fo.getURL();
360
        class FPRI implements FilteringPathResourceImplementation {
361
            private int modulus = 2;
362
            public void changeIncludes(int modulus) {
363
                this.modulus = modulus;
364
                pcs.firePropertyChange(PROP_INCLUDES, null, null);
365
            }
366
            public URL[] getRoots() {
367
                return new URL[] {u1, u2};
368
            }
369
            public boolean includes(URL root, String resource) {
370
                int offset;
371
                if (root.equals(u1)) {
372
                    offset = 0;
373
                } else if (root.equals(u2)) {
374
                    offset = 1;
375
                } else {
376
                    throw new IllegalArgumentException(root.toString());
377
                }
378
                return (offset + resource.length()) % modulus == 0;
379
            }
380
            public ClassPathImplementation getContent() {
381
                return null;
382
            }
383
            private PropertyChangeSupport pcs = new PropertyChangeSupport(this);
384
            public void addPropertyChangeListener(PropertyChangeListener listener) {
385
                pcs.addPropertyChangeListener(listener);
386
            }
387
            public void removePropertyChangeListener(PropertyChangeListener listener) {
388
                pcs.removePropertyChangeListener(listener);
389
            }
390
        }
391
        FPRI pr = new FPRI();
392
        TestClassPathImplementation impl = new TestClassPathImplementation();
393
        impl.addResource(pr);
394
        ClassPath cp = ClassPathFactory.createClassPath(impl);
395
        FileObject xx1 = u1fo.createData("xx");
396
        FileObject xxx1 = u1fo.createData("xxx");
397
        FileObject xy1 = FileUtil.createData(u1fo, "x/y");
398
        FileObject x_1 = u1fo.createData("x ");
399
        String cau = "\u010Dau";
400
        FileObject cau1 = u1fo.createData(cau);
401
        FileObject folder = u1fo.createFolder("folder");
402
        FileObject foldr = u1fo.createFolder("foldr");
403
        FileObject xx2 = u2fo.createData("xx");
404
        FileObject xxx2 = u2fo.createData("xxx");
405
        FileObject xy2 = FileUtil.createData(u2fo, "x/y");
406
        FileObject x_2 = u2fo.createData("x ");
407
        FileObject cau2 = u2fo.createData(cau);
408
        assertEquals(Arrays.asList(u1fo, u2fo), Arrays.asList(cp.getRoots()));
409
        assertTrue(cp.contains(xx1));
410
        assertTrue(cp.contains(x_1));
411
        assertFalse(cp.contains(xxx1));
412
        assertFalse(cp.contains(cau1));
413
        assertFalse(cp.contains(xy1));
414
        assertFalse(cp.contains(xx2));
415
        assertFalse(cp.contains(x_2));
416
        assertTrue(cp.contains(xxx2));
417
        assertTrue(cp.contains(cau2));
418
        assertTrue(cp.contains(xy2));
419
        assertFalse(cp.contains(folder));
420
        assertTrue(cp.contains(foldr));
421
        assertEquals(xx1, cp.findResource("xx"));
422
        assertEquals(x_1, cp.findResource("x "));
423
        assertEquals(xxx2, cp.findResource("xxx"));
424
        assertEquals(cau2, cp.findResource(cau));
425
        assertEquals(xy2, cp.findResource("x/y"));
426
        assertEquals(null, cp.findResource("folder"));
427
        assertEquals(foldr, cp.findResource("foldr"));
428
        assertEquals(Collections.singletonList(xx1), cp.findAllResources("xx"));
429
        assertEquals(Collections.singletonList(x_1), cp.findAllResources("x "));
430
        assertEquals(Collections.singletonList(xxx2), cp.findAllResources("xxx"));
431
        assertEquals(Collections.singletonList(cau2), cp.findAllResources(cau));
432
        assertEquals(Collections.singletonList(xy2), cp.findAllResources("x/y"));
433
        assertEquals(Collections.emptyList(), cp.findAllResources("folder"));
434
        assertEquals(Collections.singletonList(foldr), cp.findAllResources("foldr"));
435
        assertEquals("xx", cp.getResourceName(xx1));
436
        assertEquals("x ", cp.getResourceName(x_1));
437
        assertEquals("xxx", cp.getResourceName(xxx1));
438
        assertEquals(cau, cp.getResourceName(cau1));
439
        assertEquals("x/y", cp.getResourceName(xy1));
440
        assertEquals("folder", cp.getResourceName(folder));
441
        assertEquals("foldr", cp.getResourceName(foldr));
442
        assertEquals(u1fo, cp.findOwnerRoot(xx1));
443
        assertEquals(u1fo, cp.findOwnerRoot(x_1));
444
        assertEquals(u1fo, cp.findOwnerRoot(xxx1));
445
        assertEquals(u1fo, cp.findOwnerRoot(cau1));
446
        assertEquals(u1fo, cp.findOwnerRoot(xy1));
447
        assertEquals(u1fo, cp.findOwnerRoot(folder));
448
        assertEquals(u1fo, cp.findOwnerRoot(foldr));
449
        assertTrue(cp.isResourceVisible(xx1));
450
        assertTrue(cp.isResourceVisible(x_1));
451
        assertFalse(cp.isResourceVisible(xxx1));
452
        assertFalse(cp.isResourceVisible(cau1));
453
        assertFalse(cp.isResourceVisible(xy1));
454
        assertFalse(cp.isResourceVisible(folder));
455
        assertTrue(cp.isResourceVisible(foldr));
456
        ClassPath.Entry e1 = cp.entries().get(0);
457
        assertTrue(e1.includes("xx"));
458
        assertTrue(e1.includes("x "));
459
        assertFalse(e1.includes("xxx"));
460
        assertFalse(e1.includes(cau));
461
        assertFalse(e1.includes("x/y"));
462
        assertFalse(e1.includes("folder/"));
463
        assertTrue(e1.includes("foldr/"));
464
        assertTrue(e1.includes(xx1));
465
        assertTrue(e1.includes(x_1));
466
        assertFalse(e1.includes(xxx1));
467
        assertFalse(e1.includes(cau1));
468
        assertFalse(e1.includes(xy1));
469
        assertFalse(e1.includes(folder));
470
        assertTrue(e1.includes(foldr));
471
        try {
472
            e1.includes(xx2);
473
            fail();
474
        } catch (IllegalArgumentException iae) {}
475
        assertTrue(e1.includes(xx1.getURL()));
476
        assertTrue(e1.includes(x_1.getURL()));
477
        assertFalse(e1.includes(xxx1.getURL()));
478
        assertFalse(e1.includes(cau1.getURL()));
479
        assertFalse(e1.includes(xy1.getURL()));
480
        assertFalse(e1.includes(folder.getURL()));
481
        assertTrue(e1.includes(foldr.getURL()));
482
        try {
483
            e1.includes(xx2.getURL());
484
            fail();
485
        } catch (IllegalArgumentException iae) {}
486
        cp.addPropertyChangeListener(impl);
487
        pr.changeIncludes(3);
488
        impl.assertEvents(ClassPath.PROP_INCLUDES);
489
        assertFalse(cp.contains(xx1));
490
        assertFalse(cp.contains(x_1));
491
        assertTrue(cp.contains(xxx1));
492
        assertTrue(cp.contains(cau1));
493
        assertTrue(cp.contains(xy1));
494
        assertTrue(cp.contains(xx2));
495
        assertTrue(cp.contains(x_2));
496
        assertFalse(cp.contains(xxx2));
497
        assertFalse(cp.contains(cau2));
498
        assertFalse(cp.contains(xy2));
499
        assertEquals(xx2, cp.findResource("xx"));
500
        assertEquals(x_2, cp.findResource("x "));
501
        assertEquals(xxx1, cp.findResource("xxx"));
502
        assertEquals(cau1, cp.findResource(cau));
503
        assertEquals(xy1, cp.findResource("x/y"));
504
        e1 = cp.entries().get(0);
505
        assertFalse(e1.includes("xx"));
506
        assertFalse(e1.includes("x "));
507
        assertTrue(e1.includes("xxx"));
508
        assertTrue(e1.includes(cau));
509
        assertTrue(e1.includes("x/y"));
510
        assertFalse(e1.includes(xx1));
511
        assertFalse(e1.includes(x_1));
512
        assertTrue(e1.includes(xxx1));
513
        assertTrue(e1.includes(cau1));
514
        assertTrue(e1.includes(xy1));
515
        assertFalse(e1.includes(xx1.getURL()));
516
        assertFalse(e1.includes(x_1.getURL()));
517
        assertTrue(e1.includes(xxx1.getURL()));
518
        assertTrue(e1.includes(cau1.getURL()));
519
        assertTrue(e1.includes(xy1.getURL()));
520
    }
521
522
    public void testFpriChangeFiring() throws Exception {
523
        class FPRI implements FilteringPathResourceImplementation {
524
            URL root;
525
            PropertyChangeSupport pcs = new PropertyChangeSupport(this);
526
            FPRI(URL root) {
527
                this.root = root;
528
            }
529
            public boolean includes(URL root, String resource) {
530
                return true;
531
            }
532
            public URL[] getRoots() {
533
                return new URL[] {root};
534
            }
535
            public ClassPathImplementation getContent() {
536
                return null;
537
            }
538
            public void addPropertyChangeListener(PropertyChangeListener listener) {
539
                pcs.addPropertyChangeListener(listener);
540
            }
541
            public void removePropertyChangeListener(PropertyChangeListener listener) {
542
                pcs.removePropertyChangeListener(listener);
543
            }
544
            void fire(Object propid) {
545
                PropertyChangeEvent e = new PropertyChangeEvent(this, FilteringPathResourceImplementation.PROP_INCLUDES, null, null);
546
                e.setPropagationId(propid);
547
                pcs.firePropertyChange(e);
548
            }
549
        }
550
        FPRI fpri1 = new FPRI(new File(getWorkDir(), "src1").toURI().toURL());
551
        FPRI fpri2 = new FPRI(new File(getWorkDir(), "src2").toURI().toURL());
552
        class L implements PropertyChangeListener {
553
            int cnt;
554
            public void propertyChange(PropertyChangeEvent e) {
555
                if (ClassPath.PROP_INCLUDES.equals(e.getPropertyName())) {
556
                    cnt++;
557
                }
558
            }
559
        }
560
        ClassPath cp = ClassPathSupport.createClassPath(Arrays.asList(fpri1, fpri2));
561
        L l = new L();
562
        cp.addPropertyChangeListener(l);        
563
        //No events fired before cp.entries() called
564
        fpri1.fire(null);
565
        assertEquals(0, l.cnt);
566
        cp.entries();
567
        fpri1.fire(null);
568
        assertEquals(1, l.cnt);
569
        fpri2.fire(null);
570
        assertEquals(2, l.cnt);
571
        fpri1.fire("hello");
572
        assertEquals(3, l.cnt);
573
        fpri2.fire("goodbye");
574
        assertEquals(4, l.cnt);
575
        fpri1.fire("fixed");
576
        assertEquals(5, l.cnt);
577
        fpri2.fire("fixed");
578
        assertEquals(5, l.cnt);
579
        fpri1.fire("new");
580
        assertEquals(6, l.cnt);
581
    }
582
583
    public void testLeakingClassPath() throws Exception {
584
        ClassPath cp = ClassPathSupport.createClassPath(new URL("file:///a/"), new URL("file:///b/"));
585
        ClassPath proxyCP = ClassPathSupport.createProxyClassPath(cp);
586
        Reference<ClassPath> proxy = new WeakReference<ClassPath>(proxyCP);
587
        
588
        proxyCP.entries();
589
        
590
        proxyCP = null;
591
        
592
        assertGC("the proxy classpath needs to GCable", proxy);
593
    }
594
    
595
    public void testGetClassLoaderPerf () throws Exception {
596
        final String bootPathProp = System.getProperty("sun.boot.class.path");  //NOI18N
597
        List<URL> roots = new ArrayList<URL> ();
598
        StringTokenizer tk = new StringTokenizer (bootPathProp,File.pathSeparator);
599
        if (tk.hasMoreTokens()) {
600
            final String path = tk.nextToken();
601
            final File f = FileUtil.normalizeFile(new File (path));
602
            if (f.canRead()) {
603
                roots.add(f.toURI().toURL());
604
            }
605
        }
606
        final ClassLoader bootLoader = new URLClassLoader(roots.toArray(new URL[roots.size()]), null);
607
        
608
        final String classPathProp = System.getProperty("java.class.path");     //NOI18N
609
        roots = new ArrayList<URL> ();
610
        List<URL> roots2 = new ArrayList<URL>();
611
        tk = new StringTokenizer (classPathProp,File.pathSeparator);
612
        while (tk.hasMoreTokens()) {
613
            final String path = tk.nextToken();
614
            final File f = FileUtil.normalizeFile(new File (path));
615
            if (!f.canRead()) {
616
                continue;
617
            }
618
            URL url = f.toURI().toURL();
619
            roots2.add(url);
620
            if (FileUtil.isArchiveFile(url)) {
621
                url = FileUtil.getArchiveRoot(url);
622
            }
623
            roots.add(url);
624
        }
625
        
626
        final ClassPath cp = ClassPathSupport.createClassPath(roots.toArray(new URL[roots.size()]));
627
//        final ClassLoader loader = ClassLoaderSupport.create(cp,bootLoader);
628
//        final ClassLoader loader = new URLClassLoader(roots.toArray(new URL[roots.size()]),bootLoader);
629
        final ClassLoader loader = new URLClassLoader(roots2.toArray(new URL[roots2.size()]),bootLoader);
630
        
631
        final Set<String> classNames = getClassNames (cp);
632
        int noLoaded = 0;
633
        int noFailed = 0;
634
        long st = System.currentTimeMillis();
635
        for (String className : classNames) {
636
            try {
637
                final Class<?> c = loader.loadClass(className);
638
                noLoaded++;
639
            } catch (ClassNotFoundException e) {
640
                noFailed++;
641
            }
642
            catch (NoClassDefFoundError e) {
643
                noFailed++;
644
            }
645
        }
646
        long et = System.currentTimeMillis();
647
        System.out.println("Loaded: " + noLoaded + " in: " + (et-st)+"ms");
648
    }
649
    
650
    private Set<String> getClassNames (final ClassPath cp) {
651
        Set<String> classNames = new HashSet<String> ();
652
        for (FileObject root : cp.getRoots()) {
653
            Enumeration<? extends FileObject> fos = root.getChildren(true);
654
            while (fos.hasMoreElements()) {
655
                FileObject fo = fos.nextElement();
656
                if (isImportant (fo)) {
657
                    classNames.add(cp.getResourceName(fo, '.', false));
658
                }
659
            }
660
        }
661
        return classNames;
662
    }
663
    
664
    private boolean isImportant (final FileObject fo) {
665
        if (fo.isFolder()) {
666
            return false;
667
        }
668
        if (!"class".equals(fo.getExt())) {      //NOI18N
669
            return false;
670
        }
671
        return !fo.getName().contains("$");     //NOI18N
672
                
673
    }
674
675
    public void testJVMPathConversion() throws Exception {
676
        String root = getWorkDir().toURI().toString();
677
        ClassPath cp = ClassPathSupport.createClassPath(
678
                new URL(root + "folder/"),
679
                new URL("jar:" + root + "file.zip!/"),
680
                new URL("jar:" + root + "file.zip!/subdir/"));
681
        assertEquals(massagePath("<root>/folder:<root>/file.zip"), cp.toString(ClassPath.PathConversionMode.SKIP));
682
        assertEquals(massagePath("<root>/folder:<root>/file.zip:") + "jar:" + root + "file.zip!/subdir/", cp.toString(ClassPath.PathConversionMode.PRINT));
683
        try {
684
            cp.toString(ClassPath.PathConversionMode.FAIL);
685
            fail();
686
        } catch (IllegalArgumentException x) {/* OK */}
687
        CharSequence warnings = Log.enable(ClassPath.class.getName(), Level.WARNING);
688
        assertEquals(massagePath("<root>/folder:<root>/file.zip"), cp.toString(ClassPath.PathConversionMode.WARN));
689
        assertTrue(warnings.toString(), warnings.toString().contains("subdir"));
690
691
        cp = ClassPathSupport.createClassPath(
692
                new URL(root + "folder/"),
693
                new URL("jar:" + root + "file.zip!/"));
694
        assertEquals(cp.toString(), ClassPathSupport.createClassPath(cp.toString()).toString());
695
        // XXX could also test IAE (tricky - need to have a URLMapper in Lookup, etc.)
696
    }
697
    private String massagePath(String path) throws Exception {
698
        return path.replace('/', File.separatorChar).replace(':', File.pathSeparatorChar).replace("<root>", getWorkDir().getAbsolutePath());
699
    }
700
701
}
(-)a/api.java.classpath/test/unit/src/org/netbeans/api/java/classpath/GlobalPathRegistryTest.java (+381 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * Contributor(s):
25
 *
26
 * The Original Software is NetBeans. The Initial Developer of the Original
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
 * Microsystems, Inc. All Rights Reserved.
29
 *
30
 * If you wish your version of this file to be governed by only the CDDL
31
 * or only the GPL Version 2, indicate your decision by adding
32
 * "[Contributor] elects to include this software in this distribution
33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
34
 * single choice of license, a recipient has the option to distribute
35
 * your version of this file under either the CDDL, the GPL Version 2 or
36
 * to extend the choice of license to its licensees as provided above.
37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
38
 * Version 2 license, then the option applies only if the new code is
39
 * made subject to such option by the copyright holder.
40
 */
41
42
package org.netbeans.api.java.classpath;
43
44
import java.net.URL;
45
import java.util.ArrayList;
46
import java.util.Arrays;
47
import java.util.Collections;
48
import java.util.HashMap;
49
import java.util.HashSet;
50
import java.util.Iterator;
51
import java.util.Set;
52
import java.util.Map;
53
import javax.swing.event.ChangeEvent;
54
import javax.swing.event.ChangeListener;
55
import org.netbeans.api.java.queries.SourceForBinaryQuery;
56
import org.netbeans.junit.MockServices;
57
import org.netbeans.junit.NbTestCase;
58
import org.netbeans.spi.java.classpath.support.ClassPathSupport;
59
import org.netbeans.spi.java.queries.SourceForBinaryQueryImplementation;
60
import org.openide.filesystems.FileObject;
61
import org.netbeans.spi.java.classpath.ClassPathFactory;
62
import org.netbeans.spi.java.classpath.ClassPathImplementation;
63
import org.netbeans.spi.java.classpath.FilteringPathResourceImplementation;
64
import org.netbeans.spi.java.classpath.support.PathResourceBase;
65
import org.openide.filesystems.FileStateInvalidException;
66
import org.openide.filesystems.FileUtil;
67
import org.openide.util.ChangeSupport;
68
import org.openide.util.Lookup;
69
70
/**
71
 * Test functionality of GlobalPathRegistry.
72
 * @author Jesse Glick
73
 */
74
public class GlobalPathRegistryTest extends NbTestCase {
75
    
76
    public GlobalPathRegistryTest(String name) {
77
        super(name);
78
        MockServices.setServices(SFBQImpl.class, DeadLockSFBQImpl.class);
79
    }
80
    
81
    private GlobalPathRegistry r;
82
    private FileObject root;
83
    private ClassPath cp1, cp2, cp3, cp4, cp5;
84
    protected void setUp() throws Exception {
85
        super.setUp();
86
        r = GlobalPathRegistry.getDefault();
87
        r.clear();
88
        clearWorkDir();
89
        root = FileUtil.toFileObject(getWorkDir());
90
        cp1 = ClassPathSupport.createClassPath(new FileObject[] {root.createFolder("1")});
91
        cp2 = ClassPathSupport.createClassPath(new FileObject[] {root.createFolder("2")});
92
        cp3 = ClassPathSupport.createClassPath(new FileObject[] {root.createFolder("3")});
93
        cp4 = ClassPathSupport.createClassPath(new FileObject[] {root.createFolder("4")});
94
        cp5 = ClassPathSupport.createClassPath(new FileObject[] {root.createFolder("5")});
95
    }
96
    
97
    public void testBasicOperation() throws Exception {
98
        assertEquals("initially no paths of type a", Collections.<ClassPath>emptySet(), r.getPaths("a"));
99
        r.register("a", new ClassPath[] {cp1, cp2});
100
        assertEquals("added some paths of type a", new HashSet<ClassPath>(Arrays.asList(new ClassPath[] {cp1, cp2})), r.getPaths("a"));
101
        r.register("a", new ClassPath[0]);
102
        assertEquals("did not add any new paths to a", new HashSet<ClassPath>(Arrays.asList(new ClassPath[] {cp1, cp2})), r.getPaths("a"));
103
        assertEquals("initially no paths of type b", Collections.<ClassPath>emptySet(), r.getPaths("b"));
104
        r.register("b", new ClassPath[] {cp3, cp4, cp5});
105
        assertEquals("added some paths of type b", new HashSet<ClassPath>(Arrays.asList(new ClassPath[] {cp3, cp4, cp5})), r.getPaths("b"));
106
        r.unregister("a", new ClassPath[] {cp1});
107
        assertEquals("only one path left of type a", Collections.<ClassPath>singleton(cp2), r.getPaths("a"));
108
        r.register("a", new ClassPath[] {cp2, cp3});
109
        assertEquals("only one new path added of type a", new HashSet<ClassPath>(Arrays.asList(new ClassPath[] {cp2, cp3})), r.getPaths("a"));
110
        r.unregister("a", new ClassPath[] {cp2});
111
        assertEquals("still have extra cp2 in a", new HashSet<ClassPath>(Arrays.asList(new ClassPath[] {cp2, cp3})), r.getPaths("a"));
112
        r.unregister("a", new ClassPath[] {cp2});
113
        assertEquals("last cp2 removed from a", Collections.<ClassPath>singleton(cp3), r.getPaths("a"));
114
        r.unregister("a", new ClassPath[] {cp3});
115
        assertEquals("a now empty", Collections.<ClassPath>emptySet(), r.getPaths("a"));
116
        r.unregister("a", new ClassPath[0]);
117
        assertEquals("a still empty", Collections.<ClassPath>emptySet(), r.getPaths("a"));
118
        try {
119
            r.unregister("a", new ClassPath[] {cp3});
120
            fail("should not have been permitted to unregister a nonexistent entry");
121
        } catch (IllegalArgumentException x) {
122
            // Good.
123
        }
124
    }
125
    
126
    public void testListening() throws Exception {
127
        assertEquals("initially no paths of type b", Collections.<ClassPath>emptySet(), r.getPaths("b"));
128
        L l = new L();
129
        r.addGlobalPathRegistryListener(l);
130
        r.register("b", new ClassPath[] {cp1, cp2});
131
        GlobalPathRegistryEvent e = l.event();
132
        assertNotNull("got an event", e);
133
        assertTrue("was an addition", l.added());
134
        assertEquals("right registry", r, e.getRegistry());
135
        assertEquals("right ID", "b", e.getId());
136
        assertEquals("right changed paths", new HashSet<ClassPath>(Arrays.asList(new ClassPath[] {cp1, cp2})), e.getChangedPaths());
137
        r.register("b", new ClassPath[] {cp2, cp3});
138
        e = l.event();
139
        assertNotNull("got an event", e);
140
        assertTrue("was an addition", l.added());
141
        assertEquals("right changed paths", Collections.<ClassPath>singleton(cp3), e.getChangedPaths());
142
        r.register("b", new ClassPath[] {cp3});
143
        e = l.event();
144
        assertNull("no event for adding a dupe", e);
145
        r.unregister("b", new ClassPath[] {cp1, cp3, cp3});
146
        e = l.event();
147
        assertNotNull("got an event", e);
148
        assertFalse("was a removal", l.added());
149
        assertEquals("right changed paths", new HashSet<ClassPath>(Arrays.asList(new ClassPath[] {cp1, cp3})), e.getChangedPaths());
150
        r.unregister("b", new ClassPath[] {cp2});
151
        e = l.event();
152
        assertNull("no event for removing an extra", e);
153
        r.unregister("b", new ClassPath[] {cp2});
154
        e = l.event();
155
        assertNotNull("now an event for removing the last copy", e);
156
        assertFalse("was a removal", l.added());
157
        assertEquals("right changed paths", Collections.<ClassPath>singleton(cp2), e.getChangedPaths());
158
    }
159
    
160
    
161
    public void testGetSourceRoots () throws Exception {
162
        SFBQImpl query = Lookup.getDefault().lookup(SFBQImpl.class);
163
        assertNotNull ("SourceForBinaryQueryImplementation not found in lookup",query);                
164
        query.addPair(cp3.getRoots()[0].getURL(),new FileObject[0]);
165
        ClassPathTest.TestClassPathImplementation cpChangingImpl = new ClassPathTest.TestClassPathImplementation();
166
        ClassPath cpChanging = ClassPathFactory.createClassPath(cpChangingImpl);
167
        assertEquals("cpChangingImpl is empty", 0, cpChanging.getRoots().length);
168
        r.register(ClassPath.SOURCE, new ClassPath[] {cp1, cp2, cpChanging});
169
        r.register (ClassPath.COMPILE, new ClassPath[] {cp3});
170
        Set<FileObject> result = r.getSourceRoots();
171
        assertEquals ("Wrong number of source roots",result.size(),cp1.getRoots().length + cp2.getRoots().length);
172
        assertTrue ("Missing roots from cp1",result.containsAll (Arrays.asList(cp1.getRoots())));
173
        assertTrue ("Missing roots from cp2",result.containsAll (Arrays.asList(cp2.getRoots())));                
174
        // simulate classpath change:
175
        URL u = cp5.entries().get(0).getURL();
176
        cpChangingImpl.addResource(u);
177
        assertEquals("cpChangingImpl is not empty", 1, cpChanging.getRoots().length);
178
        result = r.getSourceRoots();
179
        assertEquals ("Wrong number of source roots",result.size(),cp1.getRoots().length + cp2.getRoots().length + cpChanging.getRoots().length);
180
        assertTrue ("Missing roots from cp1",result.containsAll (Arrays.asList(cp1.getRoots())));
181
        assertTrue ("Missing roots from cp2",result.containsAll (Arrays.asList(cp2.getRoots())));                
182
        cpChangingImpl.removeResource(u);
183
        
184
        query.addPair(cp3.getRoots()[0].getURL(),cp4.getRoots());       
185
        result = r.getSourceRoots();
186
        assertEquals ("Wrong number of source roots",result.size(),cp1.getRoots().length + cp2.getRoots().length+cp4.getRoots().length);
187
        assertTrue ("Missing roots from cp1",result.containsAll (Arrays.asList(cp1.getRoots())));
188
        assertTrue ("Missing roots from cp2",result.containsAll (Arrays.asList(cp2.getRoots())));
189
        assertTrue ("Missing roots from cp4",result.containsAll (Arrays.asList(cp4.getRoots())));
190
    }
191
    
192
    /**
193
     * Tests issue: #60976:Deadlock between JavaFastOpen$Evaluator and AntProjectHelper$something
194
     */
195
    public void testGetSourceRootsDeadLock () throws Exception {        
196
        DeadLockSFBQImpl query = Lookup.getDefault().lookup(DeadLockSFBQImpl.class);
197
        assertNotNull ("SourceForBinaryQueryImplementation not found in lookup",query);        
198
        r.register (ClassPath.COMPILE, new ClassPath[] {cp1});
199
        try {            
200
            query.setSynchronizedJob (
201
                new Runnable () {
202
                    public void run () {
203
                        r.register(ClassPath.COMPILE, new ClassPath[] {cp2});
204
                    }
205
                }
206
            );
207
            r.getSourceRoots();
208
        } finally {
209
            query.setSynchronizedJob (null);
210
        }
211
    }
212
213
    public void testFindResource() throws Exception {
214
        final FileObject src1 = root.createFolder("src1");
215
        FileObject src1included = FileUtil.createData(src1, "included/file");
216
        FileUtil.createData(src1, "excluded/file1");
217
        FileUtil.createData(src1, "excluded/file2");
218
        FileObject src2 = root.createFolder("src2");
219
        FileObject src2included = FileUtil.createData(src2, "included/file");
220
        FileObject src2excluded1 = FileUtil.createData(src2, "excluded/file1");
221
        class PRI extends PathResourceBase implements FilteringPathResourceImplementation {
222
            public URL[] getRoots() {
223
                try {
224
                    return new URL[] {src1.getURL()};
225
                } catch (FileStateInvalidException x) {
226
                    throw new AssertionError(x);
227
                }
228
            }
229
            public boolean includes(URL root, String resource) {
230
                return resource.startsWith("incl");
231
            }
232
            public ClassPathImplementation getContent() {
233
                return null;
234
            }
235
        }
236
        r.register(ClassPath.SOURCE, new ClassPath[] {
237
            ClassPathSupport.createClassPath(Collections.singletonList(new PRI())),
238
            ClassPathSupport.createClassPath(new FileObject[] {src2})
239
        });
240
        assertTrue(Arrays.asList(src1included, src2included).contains(r.findResource("included/file")));
241
        assertEquals(src2excluded1, r.findResource("excluded/file1"));
242
        assertEquals(null, r.findResource("excluded/file2"));
243
        assertEquals(null, r.findResource("nonexistent"));
244
    }
245
    
246
    public void testMemoryLeak124055 () throws Exception {
247
        final GlobalPathRegistry reg = GlobalPathRegistry.getDefault();
248
        final Set<? extends ClassPath> src = reg.getPaths(ClassPath.SOURCE);
249
        final Set<? extends ClassPath> boot = reg.getPaths(ClassPath.BOOT);
250
        final Set<? extends ClassPath> compile = reg.getPaths(ClassPath.COMPILE);
251
        assertTrue(src.isEmpty());
252
        assertTrue(boot.isEmpty());
253
        assertTrue(compile.isEmpty());
254
        assertTrue(reg.getSourceRoots().isEmpty());
255
        r.register(ClassPath.COMPILE, new ClassPath[] {cp3});
256
        SFBQImpl query = Lookup.getDefault().lookup(SFBQImpl.class);
257
        query.addPair(cp3.getRoots()[0].getURL(),cp4.getRoots());       
258
        //There should be one translated source root
259
        assertEquals(1, reg.getSourceRoots().size());
260
        assertEquals(1, reg.getResults().size());
261
        r.unregister(ClassPath.COMPILE, new ClassPath[] {cp3});
262
        //There shouldn't be registered source root
263
        assertTrue(reg.getSourceRoots().isEmpty());
264
        assertTrue(reg.getResults().isEmpty());
265
    }
266
    
267
    private static final class L implements GlobalPathRegistryListener {
268
        
269
        private GlobalPathRegistryEvent e;
270
        private boolean added;
271
        
272
        public L() {}
273
        
274
        public synchronized GlobalPathRegistryEvent event() {
275
            GlobalPathRegistryEvent _e = e;
276
            e = null;
277
            return _e;
278
        }
279
        
280
        public boolean added() {
281
            return added;
282
        }
283
        
284
        public synchronized void pathsAdded(GlobalPathRegistryEvent e) {
285
            assertNull("checked for last event", this.e);
286
            this.e = e;
287
            added = true;
288
        }
289
        
290
        public synchronized void pathsRemoved(GlobalPathRegistryEvent e) {
291
            assertNull("checked for last event", this.e);
292
            this.e = e;
293
            added = false;
294
        }
295
        
296
    }
297
    
298
    
299
    public static class SFBQImpl implements SourceForBinaryQueryImplementation {
300
        
301
        private Map<URL,SourceForBinaryQuery.Result> pairs = new HashMap<URL,SourceForBinaryQuery.Result> ();
302
        
303
        void addPair (URL binaryRoot, FileObject[] sourceRoots) {
304
            assert binaryRoot != null && sourceRoots != null;
305
            Result r = (Result) this.pairs.get (binaryRoot);
306
            if (r == null) {
307
                r = new Result (sourceRoots);
308
                this.pairs.put (binaryRoot, r);
309
            }
310
            else {
311
                r.setSources(sourceRoots);
312
            }
313
        }
314
                        
315
        public SourceForBinaryQuery.Result findSourceRoots(URL binaryRoot) {
316
            Result result = (Result) this.pairs.get (binaryRoot);
317
            return result;
318
        }
319
        
320
        
321
        private static class Result implements SourceForBinaryQuery.Result {
322
            
323
            private FileObject[] sources;                        
324
            private final ChangeSupport changeSupport = new ChangeSupport(this);
325
            
326
            public Result (FileObject[] sources) {
327
                this.sources = sources;
328
            }
329
            
330
            
331
            void setSources (FileObject[] sources) {
332
                this.sources = sources;
333
                this.changeSupport.fireChange ();
334
            }
335
                        
336
            public void addChangeListener(javax.swing.event.ChangeListener l) {
337
                changeSupport.addChangeListener (l);
338
            }            
339
            
340
            public FileObject[] getRoots() {
341
                return this.sources;
342
            }
343
            
344
            public void removeChangeListener(javax.swing.event.ChangeListener l) {
345
                changeSupport.removeChangeListener (l);
346
            }
347
            
348
        }
349
        
350
    }
351
    
352
    public static class DeadLockSFBQImpl extends Thread implements SourceForBinaryQueryImplementation {
353
        
354
        private Runnable r;
355
        
356
        public SourceForBinaryQuery.Result findSourceRoots(URL binaryRoot) {
357
            if (this.r != null) {                
358
                synchronized (this) {
359
                    this.start();
360
                    try {
361
                        this.wait ();
362
                    } catch (InterruptedException ie) {
363
                        ie.printStackTrace();
364
                    }
365
                }
366
            }
367
            return null;
368
        }
369
        
370
        public synchronized void run () {
371
            r.run();
372
            this.notify();
373
        }
374
        
375
        public void setSynchronizedJob (Runnable r) {
376
            this.r = r;
377
        }
378
        
379
    }
380
    
381
}
(-)a/api.java.classpath/test/unit/src/org/netbeans/modules/java/classpath/ProxyClassPathImplementationTest.java (+138 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * Contributor(s):
25
 *
26
 * The Original Software is NetBeans. The Initial Developer of the Original
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
 * Microsystems, Inc. All Rights Reserved.
29
 *
30
 * If you wish your version of this file to be governed by only the CDDL
31
 * or only the GPL Version 2, indicate your decision by adding
32
 * "[Contributor] elects to include this software in this distribution
33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
34
 * single choice of license, a recipient has the option to distribute
35
 * your version of this file under either the CDDL, the GPL Version 2 or
36
 * to extend the choice of license to its licensees as provided above.
37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
38
 * Version 2 license, then the option applies only if the new code is
39
 * made subject to such option by the copyright holder.
40
 */
41
package org.netbeans.modules.java.classpath;
42
43
44
import java.net.URL;
45
import java.util.concurrent.CountDownLatch;
46
import java.util.concurrent.ExecutorService;
47
import java.util.concurrent.Executors;
48
import java.util.concurrent.locks.ReentrantLock;
49
import junit.framework.TestCase;
50
import junit.framework.*;
51
import org.netbeans.api.java.classpath.ClassPath;
52
import org.netbeans.junit.NbTestCase;
53
import org.netbeans.spi.java.classpath.ClassPathFactory;
54
import org.netbeans.spi.java.classpath.ClassPathImplementation;
55
import org.netbeans.spi.java.classpath.PathResourceImplementation;
56
import java.util.List;
57
import java.util.ArrayList;
58
import java.util.Iterator;
59
import java.util.Collections;
60
import java.beans.PropertyChangeListener;
61
import java.beans.PropertyChangeEvent;
62
import org.netbeans.spi.java.classpath.support.ClassPathSupport;
63
import org.openide.util.WeakListeners;
64
65
/**
66
 *
67
 * @author tom
68
 */
69
public class ProxyClassPathImplementationTest extends NbTestCase {
70
    
71
    public ProxyClassPathImplementationTest(String testName) {
72
        super(testName);
73
    }
74
    
75
    public void testResources () throws Exception {
76
        final URL url1 = new URL ("file:///tmp/a/");
77
        final URL url2 = new URL ("file:///tmp/b/");
78
        final URL url3 = new URL ("file:///tmp/b/");
79
        
80
        final ClassPath cp1 = ClassPathSupport.createClassPath(new URL[] {url1, url2});
81
        final ClassPath cp2 = ClassPathSupport.createClassPath(new URL[] {url3});
82
        final ClassPath prxCp = ClassPathSupport.createProxyClassPath(new ClassPath[] {cp1,cp2});
83
        List<ClassPath.Entry> entries = prxCp.entries();
84
        assertEquals(3,entries.size());
85
        assertEquals(url1,entries.get(0).getURL());
86
        assertEquals(url2,entries.get(1).getURL());
87
        assertEquals(url3,entries.get(2).getURL());
88
    }
89
90
    public void testDeadLock() throws Exception{
91
        List<PathResourceImplementation> resources = Collections.<PathResourceImplementation>emptyList();
92
        final ReentrantLock lock = new ReentrantLock (false);
93
        final CountDownLatch signal = new CountDownLatch (1);
94
        final ClassPath cp = ClassPathFactory.createClassPath(ClassPathSupport.createProxyClassPathImplementation(new ClassPathImplementation[] {new LockClassPathImplementation (resources,lock, signal)}));
95
        lock.lock();
96
        final ExecutorService es = Executors.newSingleThreadExecutor();        
97
        try {
98
            es.submit(new Runnable () {
99
                public void run () {
100
                    cp.entries();
101
                }
102
            });
103
            signal.await();
104
            cp.entries();
105
        } finally {
106
            es.shutdownNow();
107
        }
108
    }  
109
    
110
    
111
    private class LockClassPathImplementation implements ClassPathImplementation {
112
        
113
        private List<? extends PathResourceImplementation> resources;
114
        private ReentrantLock lock;
115
        private CountDownLatch signal;
116
        
117
        public LockClassPathImplementation (final List<? extends PathResourceImplementation> resources, final ReentrantLock lock, final CountDownLatch signal) {
118
            this.resources = resources;
119
            this.lock = lock;
120
            this.signal = signal;
121
        }
122
        
123
        public List<? extends PathResourceImplementation> getResources() {
124
            this.signal.countDown();
125
            this.lock.lock();
126
            return this.resources;
127
        }
128
129
        public void addPropertyChangeListener(PropertyChangeListener listener) {
130
        }
131
132
        public void removePropertyChangeListener(PropertyChangeListener listener) {
133
        }
134
        
135
    }
136
    
137
    
138
}
(-)a/api.java/apichanges.xml (-1 / +16 lines)
Lines 93-99 Link Here
93
            <class package="org.netbeans.spi.java.classpath.support" name="ClassPathSupport"/>
93
            <class package="org.netbeans.spi.java.classpath.support" name="ClassPathSupport"/>
94
            <issue number="59311"/>
94
            <issue number="59311"/>
95
        </change>
95
        </change>
96
96
        <change id="classpath-api-module">
97
            <api name="classpath"/>
98
            <summary>Splitting the java API to independent ClassPath API and the rest of the java API</summary>
99
            <version major="1" minor="18"/>
100
            <date day="5" month="6" year="2008"/>
101
            <author login="tzezula"/>
102
            <compatibility addition="no" modification="no" semantic="compatible" source="incompatible" binary="compatible"/>
103
            <description>
104
                <p>
105
                    The copy of the ClassPath API was used by generic scripting framework, which cannot depend on the java cluster.
106
                    To remove this copy of the ClassPath API the java API needs to be splitted into the ClassPath API (IDE cluster)
107
                    and the rest of the java API (java cluster).
108
                </p>
109
            </description>
110
            <issue number="129884"/>
111
        </change>
97
        <change id="queries-spi-support">
112
        <change id="queries-spi-support">
98
            <api name="queries"/>
113
            <api name="queries"/>
99
            <summary>Support for delegating SourceForBinaryQueryImplementation2</summary>
114
            <summary>Support for delegating SourceForBinaryQueryImplementation2</summary>
(-)a/api.java/arch.xml (-29 / +8 lines)
Lines 127-136 Link Here
127
 <answer id="arch-usecases">
127
 <answer id="arch-usecases">
128
  <p>
128
  <p>
129
   The API is widely used by all sorts of IDE modules which need to work with
129
   The API is widely used by all sorts of IDE modules which need to work with
130
   Java sources. They can obtain the classpath or boot classpath for a file (if
130
   Java sources. They can find Javadoc, unit tests, source level, etc.
131
   there is one), find out where its source root is, find sources corresponding
131
   The SPI is intended mainly for Java platform and
132
   to bytecode class files, find all sources or classpaths corresponding to open
133
   projects, find Javadoc, etc. The SPI is intended mainly for Java platform and
134
   library providers, and project type providers, to declare all of this
132
   library providers, and project type providers, to declare all of this
135
   information.
133
   information.
136
  </p>
134
  </p>
Lines 150-157 Link Here
150
-->
148
-->
151
 <answer id="arch-what">
149
 <answer id="arch-what">
152
  <p>
150
  <p>
153
   Models basic aspects of the metadata surrounding Java source files, such as
151
   Provides java specific queries (javadc, source level) used by other modules like java language infrastructure.
154
   the classpath. More information in the Javadoc.
152
   More information in the Javadoc.
155
  </p>
153
  </p>
156
 </answer>
154
 </answer>
157
155
Lines 259-273 Link Here
259
      For many purposes.
257
      For many purposes.
260
     </p>
258
     </p>
261
    </api>
259
    </api>
262
   </li>
260
   </li>  
263
   <li>
264
    <api group="java" name="Execution" type="import" category="official">
265
     <p>
266
      <code>NbClassLoader</code> is used by
267
      <code>ClassPath.getClassLoader(...)</code>.
268
     </p>
269
    </api>
270
   </li>
271
  </ul>
261
  </ul>
272
 </answer>
262
 </answer>
273
263
Lines 409-417 Link Here
409
-->
399
-->
410
 <answer id="exec-classloader">
400
 <answer id="exec-classloader">
411
  <p>
401
  <p>
412
   There is support for getting a class loader corresponding to a given
402
      No.
413
   classpath, useful e.g. for loading user JavaBeans to introspect. This is not
414
   used within the module itself.
415
  </p>
403
  </p>
416
 </answer>
404
 </answer>
417
405
Lines 783-796 Link Here
783
   Queries perform linearly in number of implementations, but as usual there will
771
   Queries perform linearly in number of implementations, but as usual there will
784
   typically be only one or two implementations, e.g. delegating to owner
772
   typically be only one or two implementations, e.g. delegating to owner
785
   projects.
773
   projects.
786
  </p>
774
  </p>  
787
  <p>
788
   Currently <code>ClassPath</code>s keep global file change listeners to permit
789
   roots to be invalidated, and this makes file change events linear in the
790
   number of <code>ClassPath</code> objects. This area is being studied and will
791
   hopefully be optimized, perhaps reducing overhead to a small constant.
792
   May require explicit support from the Filesystems API to fully optimize.
793
  </p>
794
 </answer>
775
 </answer>
795
776
796
777
Lines 935-943 Link Here
935
        </question>
916
        </question>
936
-->
917
-->
937
 <answer id="security-grant">
918
 <answer id="security-grant">
938
  <p>
919
  No.
939
   <code>ClassPath.getClassLoader(...)</code> is granted all permissions.
940
  </p>
941
 </answer>
920
 </answer>
942
921
943
922
(-)a/api.java/manifest.mf (-2 / +2 lines)
Lines 1-6 Link Here
1
Manifest-Version: 1.0
1
Manifest-Version: 1.0
2
OpenIDE-Module: org.netbeans.api.java/1
2
OpenIDE-Module: org.netbeans.api.java/1
3
OpenIDE-Module-Specification-Version: 1.17
3
OpenIDE-Module-Specification-Version: 1.18
4
OpenIDE-Module-Localizing-Bundle: org/netbeans/api/java/classpath/Bundle.properties
4
OpenIDE-Module-Localizing-Bundle: org/netbeans/api/java/queries/Bundle.properties
5
AutoUpdate-Show-In-Client: false
5
AutoUpdate-Show-In-Client: false
6
6
(-)a/api.java/module-auto-deps.xml (+61 lines)
Line 0 Link Here
1
<?xml version="1.0" encoding="UTF-8"?>
2
<!--
3
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4
5
Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
6
7
8
The contents of this file are subject to the terms of either the GNU
9
General Public License Version 2 only ("GPL") or the Common
10
Development and Distribution License("CDDL") (collectively, the
11
"License"). You may not use this file except in compliance with the
12
License. You can obtain a copy of the License at
13
http://www.netbeans.org/cddl-gplv2.html
14
or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
15
specific language governing permissions and limitations under the
16
License.  When distributing the software, include this License Header
17
Notice in each file and include the License file at
18
nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
19
particular file as subject to the "Classpath" exception as provided
20
by Sun in the GPL Version 2 section of the License file that
21
accompanied this code. If applicable, add the following below the
22
License Header, with the fields enclosed by brackets [] replaced by
23
your own identifying information:
24
"Portions Copyrighted [year] [name of copyright owner]"
25
26
Contributor(s):
27
28
The Original Software is NetBeans. The Initial Developer of the Original
29
Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
30
Microsystems, Inc. All Rights Reserved.
31
32
If you wish your version of this file to be governed by only the CDDL
33
or only the GPL Version 2, indicate your decision by adding
34
"[Contributor] elects to include this software in this distribution
35
under the [CDDL or GPL Version 2] license." If you do not indicate a
36
single choice of license, a recipient has the option to distribute
37
your version of this file under either the CDDL, the GPL Version 2 or
38
to extend the choice of license to its licensees as provided above.
39
However, if you add GPL Version 2 code and therefore, elected the GPL
40
Version 2 license, then the option applies only if the new code is
41
made subject to such option by the copyright holder.
42
-->
43
44
<!DOCTYPE transformations PUBLIC "-//NetBeans//DTD Module Automatic Dependencies 1.0//EN" "http://www.netbeans.org/dtds/module-auto-deps-1_0.dtd">
45
46
<transformations version="1.0">
47
48
    <transformationgroup>
49
        <description>Splitting the api.java to api.java.classpath and api.java</description>
50
        <transformation>
51
            <trigger-dependency type="older">
52
                <module-dependency codenamebase="org.netbeans.api.java" major="1" spec="1.18"/>
53
            </trigger-dependency>
54
            <implies>
55
                <result>
56
                    <module-dependency codenamebase="org.netbeans.api.java.classpath" major="1" spec="1.0"/>
57
                </result>
58
            </implies>
59
        </transformation>
60
    </transformationgroup>
61
</transformations>
(-)a/api.java/nbproject/project.xml (-8 / +3 lines)
Lines 47-57 Link Here
47
            <code-name-base>org.netbeans.api.java</code-name-base>
47
            <code-name-base>org.netbeans.api.java</code-name-base>
48
            <module-dependencies>
48
            <module-dependencies>
49
                <dependency>
49
                <dependency>
50
                    <code-name-base>org.openide.execution</code-name-base>
50
                    <code-name-base>org.netbeans.api.java.classpath</code-name-base>
51
                    <build-prerequisite/>
51
                    <build-prerequisite/>
52
                    <compile-dependency/>
52
                    <compile-dependency/>
53
                    <run-dependency>
53
                    <run-dependency>
54
                        <specification-version>1.2</specification-version>
54
                        <release-version>1</release-version>
55
                        <specification-version>1.0</specification-version>
55
                    </run-dependency>
56
                    </run-dependency>
56
                </dependency>
57
                </dependency>
57
                <dependency>
58
                <dependency>
Lines 61-72 Link Here
61
                    <run-dependency>
62
                    <run-dependency>
62
                        <specification-version>7.8</specification-version>
63
                        <specification-version>7.8</specification-version>
63
                    </run-dependency>
64
                    </run-dependency>
64
                </dependency>
65
                <dependency>
66
                    <code-name-base>org.openide.io</code-name-base>
67
                    <build-prerequisite/>
68
                    <compile-dependency/>
69
                    <run-dependency/>
70
                </dependency>
65
                </dependency>
71
                <dependency>
66
                <dependency>
72
                    <code-name-base>org.openide.util</code-name-base>
67
                    <code-name-base>org.openide.util</code-name-base>
(-)a/api.java/src/org/netbeans/modules/java/classpath/ClassPathAccessor.java (-65 lines)
Lines 1-65 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * Contributor(s):
25
 *
26
 * The Original Software is NetBeans. The Initial Developer of the Original
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
 * Microsystems, Inc. All Rights Reserved.
29
 *
30
 * If you wish your version of this file to be governed by only the CDDL
31
 * or only the GPL Version 2, indicate your decision by adding
32
 * "[Contributor] elects to include this software in this distribution
33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
34
 * single choice of license, a recipient has the option to distribute
35
 * your version of this file under either the CDDL, the GPL Version 2 or
36
 * to extend the choice of license to its licensees as provided above.
37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
38
 * Version 2 license, then the option applies only if the new code is
39
 * made subject to such option by the copyright holder.
40
 */
41
package org.netbeans.modules.java.classpath;
42
43
import org.netbeans.api.java.classpath.ClassPath;
44
import org.netbeans.spi.java.classpath.ClassPathImplementation;
45
46
47
public abstract class ClassPathAccessor {
48
49
    public static ClassPathAccessor DEFAULT;
50
51
    // force loading of ClassPath class. That will set DEFAULT variable.
52
    static {
53
        Class c = ClassPath.class;
54
        try {
55
            Class.forName(c.getName(), true, c.getClassLoader());
56
        } catch (Exception ex) {
57
            ex.printStackTrace();
58
        }
59
    }
60
61
    public abstract ClassPath createClassPath(ClassPathImplementation spiClasspath);
62
63
    public abstract ClassPathImplementation getClassPathImpl (ClassPath cp);
64
65
}
(-)a/api.java/src/org/netbeans/modules/java/classpath/ProxyClassPathImplementation.java (-145 lines)
Lines 1-145 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * Contributor(s):
25
 *
26
 * The Original Software is NetBeans. The Initial Developer of the Original
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
 * Microsystems, Inc. All Rights Reserved.
29
 *
30
 * If you wish your version of this file to be governed by only the CDDL
31
 * or only the GPL Version 2, indicate your decision by adding
32
 * "[Contributor] elects to include this software in this distribution
33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
34
 * single choice of license, a recipient has the option to distribute
35
 * your version of this file under either the CDDL, the GPL Version 2 or
36
 * to extend the choice of license to its licensees as provided above.
37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
38
 * Version 2 license, then the option applies only if the new code is
39
 * made subject to such option by the copyright holder.
40
 */
41
package org.netbeans.modules.java.classpath;
42
43
import org.netbeans.spi.java.classpath.ClassPathImplementation;
44
import org.netbeans.spi.java.classpath.PathResourceImplementation;
45
46
import java.util.List;
47
import java.util.ArrayList;
48
import java.util.Iterator;
49
import java.util.Collections;
50
import java.beans.PropertyChangeListener;
51
import java.beans.PropertyChangeEvent;
52
import org.openide.util.WeakListeners;
53
54
/** ProxyClassPathImplementation provides read only proxy for ClassPathImplementations.
55
 *  The order of the resources is given by the order of its delegates.
56
 *  The proxy is designed to be used as a union of class paths.
57
 *  E.g. to be able to easily iterate or listen on all design resources = sources + compile resources
58
 */
59
public class ProxyClassPathImplementation implements ClassPathImplementation {
60
61
    private ClassPathImplementation[] classPaths;
62
    private List<PathResourceImplementation> resourcesCache;
63
    private ArrayList<PropertyChangeListener> listeners;
64
    private PropertyChangeListener classPathsListener;
65
66
    public ProxyClassPathImplementation (ClassPathImplementation[] classPaths) {
67
        if (classPaths == null)
68
            throw new IllegalArgumentException ();
69
        List<ClassPathImplementation> impls = new ArrayList<ClassPathImplementation> ();
70
        classPathsListener = new DelegatesListener ();
71
        for (ClassPathImplementation cpImpl : classPaths) {
72
            if (cpImpl == null)
73
                continue;
74
            cpImpl.addPropertyChangeListener (WeakListeners.propertyChange(classPathsListener,cpImpl));
75
            impls.add (cpImpl);
76
        }
77
        this.classPaths = impls.toArray(new ClassPathImplementation[impls.size()]);
78
    }
79
80
81
82
    public List <? extends PathResourceImplementation> getResources() {
83
        synchronized (this) {
84
            if (this.resourcesCache != null) {
85
                return this.resourcesCache;
86
            }
87
        }
88
        
89
        ArrayList<PathResourceImplementation> result = new ArrayList<PathResourceImplementation> (classPaths.length*10);
90
        for (ClassPathImplementation cpImpl : classPaths) {
91
            List<? extends PathResourceImplementation> subPath = cpImpl.getResources();
92
            assert subPath != null : "ClassPathImplementation.getResources() returned null. ClassPathImplementation.class: " 
93
                + cpImpl.getClass().toString() + " ClassPathImplementation: " + cpImpl.toString();
94
            result.addAll (subPath);
95
        }
96
        
97
        synchronized (this) {
98
            if (this.resourcesCache == null) {
99
                resourcesCache = Collections.unmodifiableList (result);
100
            }
101
            return this.resourcesCache;
102
        }
103
    }
104
105
    public synchronized void addPropertyChangeListener(PropertyChangeListener listener) {
106
        if (this.listeners == null)
107
            this.listeners = new ArrayList<PropertyChangeListener> ();
108
        this.listeners.add (listener);
109
    }
110
111
    public synchronized void removePropertyChangeListener(PropertyChangeListener listener) {
112
        if (this.listeners == null)
113
            return;
114
        this.listeners.remove (listener);
115
    }
116
    
117
    public String toString () {
118
        StringBuilder builder = new StringBuilder("[");   //NOI18N
119
        for (ClassPathImplementation cpImpl : this.classPaths) {
120
            builder.append (cpImpl.toString());
121
            builder.append(", ");   //NOI18N
122
        }
123
        builder.append ("]");   //NOI18N
124
        return builder.toString ();
125
    }
126
127
128
    private class DelegatesListener implements PropertyChangeListener {
129
130
        public void propertyChange(PropertyChangeEvent evt) {
131
            PropertyChangeListener[] _listeners;
132
            synchronized (ProxyClassPathImplementation.this) {
133
                ProxyClassPathImplementation.this.resourcesCache = null;    //Clean the cache
134
                if (ProxyClassPathImplementation.this.listeners == null)
135
                    return;
136
                _listeners = ProxyClassPathImplementation.this.listeners.toArray(new PropertyChangeListener[ProxyClassPathImplementation.this.listeners.size()]);
137
            }
138
            PropertyChangeEvent event = new PropertyChangeEvent (ProxyClassPathImplementation.this, evt.getPropertyName(),null,null);
139
            for (PropertyChangeListener l : _listeners) {
140
                l.propertyChange (event);
141
            }
142
        }
143
    }
144
145
}
(-)a/api.java/src/org/netbeans/modules/java/classpath/SimpleClassPathImplementation.java (-91 lines)
Lines 1-91 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * Contributor(s):
25
 *
26
 * The Original Software is NetBeans. The Initial Developer of the Original
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
 * Microsystems, Inc. All Rights Reserved.
29
 *
30
 * If you wish your version of this file to be governed by only the CDDL
31
 * or only the GPL Version 2, indicate your decision by adding
32
 * "[Contributor] elects to include this software in this distribution
33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
34
 * single choice of license, a recipient has the option to distribute
35
 * your version of this file under either the CDDL, the GPL Version 2 or
36
 * to extend the choice of license to its licensees as provided above.
37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
38
 * Version 2 license, then the option applies only if the new code is
39
 * made subject to such option by the copyright holder.
40
 */
41
package org.netbeans.modules.java.classpath;
42
43
import java.util.List;
44
import java.beans.PropertyChangeListener;
45
import java.net.URL;
46
47
import java.util.ArrayList;
48
import java.util.Collections;
49
import java.util.Iterator;
50
51
import org.netbeans.spi.java.classpath.ClassPathImplementation;
52
import org.netbeans.spi.java.classpath.PathResourceImplementation;
53
54
55
public class SimpleClassPathImplementation implements ClassPathImplementation {
56
57
    List<? extends PathResourceImplementation> entries;
58
59
    public SimpleClassPathImplementation() {
60
        this(new ArrayList<PathResourceImplementation>());
61
    }
62
63
    public SimpleClassPathImplementation(List<? extends PathResourceImplementation> entries) {
64
        this.entries = entries;
65
    }
66
    
67
    public List <? extends PathResourceImplementation> getResources() {
68
        return Collections.unmodifiableList(entries);
69
    }
70
71
    public void addPropertyChangeListener(PropertyChangeListener listener) {
72
        // XXX TBD
73
    }
74
75
    public void removePropertyChangeListener(PropertyChangeListener listener) {
76
        // XXX TBD
77
    }
78
    
79
    public String toString () {
80
        StringBuilder builder = new StringBuilder ("SimpleClassPathImplementation["); //NOI18N
81
        for (PathResourceImplementation impl : this.entries) {
82
            URL[] roots = impl.getRoots();
83
            for (URL root : roots) {
84
                builder.append (root.toExternalForm());
85
                builder.append (", ");  //NOI18N
86
            }
87
        }
88
        builder.append ("]");   //NOI18N
89
        return builder.toString ();
90
    }    
91
}
(-)a/api.java/src/org/netbeans/modules/java/classpath/SimplePathResourceImplementation.java (-91 lines)
Lines 1-91 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * Contributor(s):
25
 *
26
 * The Original Software is NetBeans. The Initial Developer of the Original
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
 * Microsystems, Inc. All Rights Reserved.
29
 *
30
 * If you wish your version of this file to be governed by only the CDDL
31
 * or only the GPL Version 2, indicate your decision by adding
32
 * "[Contributor] elects to include this software in this distribution
33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
34
 * single choice of license, a recipient has the option to distribute
35
 * your version of this file under either the CDDL, the GPL Version 2 or
36
 * to extend the choice of license to its licensees as provided above.
37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
38
 * Version 2 license, then the option applies only if the new code is
39
 * made subject to such option by the copyright holder.
40
 */
41
package org.netbeans.modules.java.classpath;
42
43
44
import org.netbeans.spi.java.classpath.support.PathResourceBase;
45
import org.netbeans.spi.java.classpath.ClassPathImplementation;
46
47
import java.net.URL;
48
49
50
/**
51
 * Provides implementation of the single rooted PathResoruceImplementation
52
 */
53
54
public final class SimplePathResourceImplementation  extends PathResourceBase {
55
56
    private URL[] url;
57
58
59
60
    public SimplePathResourceImplementation (URL root) {
61
        if (root == null)
62
            throw new IllegalArgumentException ();
63
        this.url = new URL[] {root};
64
    }
65
66
67
    public URL[] getRoots() {
68
        return this.url;
69
    }
70
71
    public ClassPathImplementation getContent() {
72
        return null;
73
    }
74
75
    public String toString () {
76
        return "SimplePathResource{"+this.getRoots()[0]+"}";   //NOI18N
77
    }
78
79
    public int hashCode () {
80
        return this.url[0].hashCode();
81
    }
82
83
    public boolean equals (Object other) {
84
        if (other instanceof SimplePathResourceImplementation) {
85
            SimplePathResourceImplementation opr = (SimplePathResourceImplementation) other;
86
            return this.url[0].equals (opr.url[0]);
87
        }
88
        else
89
            return false;
90
    }
91
}
(-)a/api.java/src/org/netbeans/modules/java/queries/SFBQImpl2Result.java (-83 lines)
Lines 1-83 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 * 
4
 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
5
 * 
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 * 
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 * 
35
 * Contributor(s):
36
 * 
37
 * Portions Copyrighted 2008 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.modules.java.queries;
41
42
import javax.swing.event.ChangeListener;
43
import org.netbeans.api.java.queries.SourceForBinaryQuery;
44
import org.netbeans.spi.java.queries.SourceForBinaryQueryImplementation2;
45
import org.openide.filesystems.FileObject;
46
import org.openide.filesystems.FileUtil;
47
48
/**
49
 *
50
 * @author Tomas Zezula
51
 */
52
public class SFBQImpl2Result implements SourceForBinaryQueryImplementation2.Result {
53
    
54
    private final SourceForBinaryQuery.Result delegate;
55
    
56
    public SFBQImpl2Result (final SourceForBinaryQuery.Result result) {
57
        assert result != null;
58
        this.delegate = result;
59
    }
60
61
    public boolean preferSources() {
62
        //Preserve the old behavior from 4.0 to 6.1, ignore sources inside archives
63
        final FileObject[] roots = this.delegate.getRoots();
64
        for (FileObject root : roots) {
65
            if (FileUtil.getArchiveFile(root) != null) {
66
                return false;
67
            }
68
        }
69
        return true;
70
    }
71
72
    public FileObject[] getRoots () {
73
        return this.delegate.getRoots();
74
    }
75
76
    public void addChangeListener(ChangeListener l) {
77
        this.delegate.addChangeListener(l);
78
    }
79
80
    public void removeChangeListener(ChangeListener l) {
81
        this.delegate.removeChangeListener(l);
82
    }
83
}
(-)a/api.java/src/org/netbeans/spi/java/classpath/ClassPathFactory.java (-88 lines)
Lines 1-88 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * Contributor(s):
25
 *
26
 * The Original Software is NetBeans. The Initial Developer of the Original
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
 * Microsystems, Inc. All Rights Reserved.
29
 *
30
 * If you wish your version of this file to be governed by only the CDDL
31
 * or only the GPL Version 2, indicate your decision by adding
32
 * "[Contributor] elects to include this software in this distribution
33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
34
 * single choice of license, a recipient has the option to distribute
35
 * your version of this file under either the CDDL, the GPL Version 2 or
36
 * to extend the choice of license to its licensees as provided above.
37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
38
 * Version 2 license, then the option applies only if the new code is
39
 * made subject to such option by the copyright holder.
40
 */
41
42
package org.netbeans.spi.java.classpath;
43
44
import java.net.URL;
45
import org.netbeans.api.java.classpath.ClassPath;
46
import org.netbeans.modules.java.classpath.ClassPathAccessor;
47
import org.openide.filesystems.FileUtil;
48
49
/**
50
 * Most general way to create {@link ClassPath} instances.
51
 * You are not permitted to create them directly; instead you implement
52
 * {@link ClassPathImplementation} and use this factory.
53
 * See also {@link org.netbeans.spi.java.classpath.support.ClassPathSupport}
54
 * for easier ways to create classpaths.
55
 * @since org.netbeans.api.java/1 1.4
56
 */
57
public final class ClassPathFactory {
58
59
    private ClassPathFactory() {
60
    }
61
62
    /**
63
     * Create API classpath instance for the given SPI classpath.
64
     * @param spiClasspath instance of SPI classpath
65
     * @return instance of API classpath
66
     */
67
    public static ClassPath createClassPath(ClassPathImplementation spiClasspath) {
68
//        assert checkEntries (spiClasspath) : "ClassPathImplementation contains invalid root: " + spiClasspath.toString();    //Commented, not to decrease the performance even in the dev build.
69
        return ClassPathAccessor.DEFAULT.createClassPath(spiClasspath);
70
    }
71
    
72
    
73
    private static boolean checkEntries (ClassPathImplementation spiClasspath) {
74
        for (PathResourceImplementation impl : spiClasspath.getResources()) {
75
            URL[] roots = impl.getRoots();
76
            for (URL root : roots) {
77
                if (FileUtil.isArchiveFile(root)) {
78
                    return false;
79
                }
80
                if (root.toExternalForm().endsWith("/")) {  // NOI18N
81
                    return false;
82
                }
83
            }
84
        }
85
        return true;
86
    }
87
88
}
(-)a/api.java/src/org/netbeans/spi/java/classpath/ClassPathImplementation.java (-74 lines)
Lines 1-74 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * Contributor(s):
25
 *
26
 * The Original Software is NetBeans. The Initial Developer of the Original
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
 * Microsystems, Inc. All Rights Reserved.
29
 *
30
 * If you wish your version of this file to be governed by only the CDDL
31
 * or only the GPL Version 2, indicate your decision by adding
32
 * "[Contributor] elects to include this software in this distribution
33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
34
 * single choice of license, a recipient has the option to distribute
35
 * your version of this file under either the CDDL, the GPL Version 2 or
36
 * to extend the choice of license to its licensees as provided above.
37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
38
 * Version 2 license, then the option applies only if the new code is
39
 * made subject to such option by the copyright holder.
40
 */
41
package org.netbeans.spi.java.classpath;
42
43
import java.util.List;
44
import java.beans.PropertyChangeListener;
45
46
/**
47
 * SPI interface for ClassPath.
48
 * @see ClassPathFactory
49
 * @since org.netbeans.api.java/1 1.4
50
 */
51
public interface ClassPathImplementation {
52
53
    public static final String PROP_RESOURCES = "resources";    //NOI18N
54
55
    /**
56
     * Returns list of entries, the list is unmodifiable.
57
     * @return List of PathResourceImplementation, never returns null
58
     * it may return an empty List
59
     */
60
    public List<? extends PathResourceImplementation> getResources();
61
62
    /**
63
     * Adds property change listener.
64
     * The listener is notified when the set of entries has changed.
65
     * @param listener
66
     */
67
    public void addPropertyChangeListener(PropertyChangeListener listener);
68
69
    /**
70
     * Removes property change listener
71
     * @param listener
72
     */
73
    public void removePropertyChangeListener(PropertyChangeListener listener);
74
}
(-)a/api.java/src/org/netbeans/spi/java/classpath/ClassPathProvider.java (-123 lines)
Lines 1-123 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * Contributor(s):
25
 *
26
 * The Original Software is NetBeans. The Initial Developer of the Original
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
 * Microsystems, Inc. All Rights Reserved.
29
 *
30
 * If you wish your version of this file to be governed by only the CDDL
31
 * or only the GPL Version 2, indicate your decision by adding
32
 * "[Contributor] elects to include this software in this distribution
33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
34
 * single choice of license, a recipient has the option to distribute
35
 * your version of this file under either the CDDL, the GPL Version 2 or
36
 * to extend the choice of license to its licensees as provided above.
37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
38
 * Version 2 license, then the option applies only if the new code is
39
 * made subject to such option by the copyright holder.
40
 */
41
42
package org.netbeans.spi.java.classpath;
43
44
import org.netbeans.api.java.classpath.ClassPath;
45
import org.openide.filesystems.FileObject;
46
47
/**
48
 * Provider interface for Java classpaths.
49
 * <p>
50
 * The <code>org.netbeans.modules.java.project</code> module registers an
51
 * implementation of this interface to global lookup which looks for the
52
 * project which owns a file (if any) and checks its lookup for this interface,
53
 * and if it finds an instance, delegates to it. Therefore it is not normally
54
 * necessary for a project type provider to register its own instance just to
55
 * define the classpaths for files it owns, assuming it depends on the Java
56
 * Project module.
57
 * </p>
58
 * <div class="nonnormative">
59
 * <p>
60
 * Note that to make editor code completion functionality work for a Java source file the
61
 * following classpaths must be available for it:
62
 * </p>
63
 * <ol>
64
 * <li>The {@link ClassPath#BOOT} type of classpath
65
 *     is required or the source file will not be parsable and 
66
 *     code completion will be disabled. See also
67
 *     {@link org.netbeans.spi.java.queries.SourceLevelQueryImplementation}.</li>
68
 * <li>The {@link ClassPath#SOURCE} type of classpath
69
 *     is required or code completion will be disabled.
70
 *     Providing this classpath will enable code completion, but only elements
71
 *     defined on this classpath will be offered if the compile classpath is missing.</li>
72
 * <li>The {@link ClassPath#COMPILE} type of classpath
73
 *     is recommended to be provide to make code completion work fully
74
 *     by suggesting all classes against which the source is developed.</li>
75
 * </ol>
76
 * <p>{@link ClassPath#EXECUTE} is also recommended for e.g. I18N functionality to work.
77
 * This should contain the full run-time classpath of the class, including its build
78
 * location (bytecode).</p>
79
 * <p>You should return these classpaths for the package root folder and any
80
 * files or folders inside it.</p>
81
 * <p>You should register classpaths for source files of all these types in
82
 * {@link org.netbeans.api.java.classpath.GlobalPathRegistry}
83
 * when they are to be exposed in the GUI as available for use (e.g. for the editor's Fast Open dialog),
84
 * and unregister them when they are no longer to be exposed. Typically this is done as part of
85
 * <a href="@PROJECTS/PROJECTUIAPI@/org/netbeans/spi/project/ui/ProjectOpenedHook.html">ProjectOpenedHook</a>.
86
 * <p>It is also desirable to produce classpath information for compiled class files
87
 * (bytecode), including their package roots (whether a disk folder or a JAR root).
88
 * This will enable parsing of the class files, which is sometimes needed (e.g. for
89
 * expanding the class file node and seeing its members).
90
 * Compiled classes should have:</p>
91
 * <ol>
92
 * <li>{@link ClassPath#BOOT} corresponding to the Java platform to be used with the classes.</li>
93
 * <li>{@link ClassPath#EXECUTE} containing the bytecode's package root itself, plus any other
94
 * libraries it needs to resolve against. Should normally be the same as the execute classpath
95
 * of the corresponding source files.</li>
96
 * </ol>
97
 * <p>If no specific class path providers are available for a given source file or bytecode file,
98
 * i.e. <code>null</code> is returned from all providers, there may be a fallback implementation
99
 * which would provide reasonable defaults. For source files, this could mean a boot classpath
100
 * corresponding to the default Java platform (i.e. the JDK being used to run the IDE); empty
101
 * compile and execute classpaths; and a sourcepath computed based on the package statement in the
102
 * source file (if this is possible). For class files, this could mean a boot classpath determined
103
 * as for source files, and an execute classpath containing the package root apparently owning the
104
 * class file (computed according to the class file's package information, if this is possible).</p>
105
 * </div>
106
 * @see ClassPath#getClassPath
107
 * @see org.netbeans.api.java.classpath.GlobalPathRegistry
108
 * @author Jesse Glick
109
 * @since org.netbeans.api.java/1 1.4
110
 */
111
public interface ClassPathProvider {
112
    
113
    /**
114
     * Find some kind of a classpath for a given file.
115
     * @param file a file somewhere, or a source root
116
     * @param type a classpath type such as {@link ClassPath#COMPILE}
117
     * @return an appropriate classpath, or null for no answer
118
     * @see ClassPathFactory
119
     * @see org.netbeans.spi.java.classpath.support.ClassPathSupport
120
     */
121
    ClassPath findClassPath(FileObject file, String type);
122
    
123
}
(-)a/api.java/src/org/netbeans/spi/java/classpath/FilteringPathResourceImplementation.java (-75 lines)
Lines 1-75 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * Contributor(s):
25
 *
26
 * The Original Software is NetBeans. The Initial Developer of the Original
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
 * Microsystems, Inc. All Rights Reserved.
29
 *
30
 * If you wish your version of this file to be governed by only the CDDL
31
 * or only the GPL Version 2, indicate your decision by adding
32
 * "[Contributor] elects to include this software in this distribution
33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
34
 * single choice of license, a recipient has the option to distribute
35
 * your version of this file under either the CDDL, the GPL Version 2 or
36
 * to extend the choice of license to its licensees as provided above.
37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
38
 * Version 2 license, then the option applies only if the new code is
39
 * made subject to such option by the copyright holder.
40
 */
41
42
package org.netbeans.spi.java.classpath;
43
44
import java.net.URL;
45
46
/**
47
 * SPI interface for a classpath entry which can include or exclude particular files.
48
 * @author Jesse Glick
49
 * @see "issue #49026"
50
 * @since org.netbeans.api.java/1 1.13
51
 */
52
public interface FilteringPathResourceImplementation extends PathResourceImplementation {
53
54
    /**
55
     * Property name to fire in case {@link #includes} would change.
56
     * (The old and new value should be left null.)
57
     * <p>
58
     * <strong>Special usage note:</strong>
59
     * If multiple {@link FilteringPathResourceImplementation}s inside a single
60
     * {@link ClassPathImplementation} fire changes in this pseudo-property in
61
     * succession, all using the same non-null {@link java.beans.PropertyChangeEvent#setPropagationId},
62
     * {@link org.netbeans.api.java.classpath.ClassPath#PROP_INCLUDES} will be fired just once. This can be used
63
     * to prevent "event storms" from triggering excessive Java source root rescanning.
64
     */
65
    String PROP_INCLUDES = "includes"; // NOI18N
66
67
    /**
68
     * Determines whether a given resource is included in the classpath or not.
69
     * @param root one of the roots given by {@link #getRoots} (else may throw {@link IllegalArgumentException})
70
     * @param resource a relative resource path within that root; may refer to a file or slash-terminated folder; the empty string refers to the root itself
71
     * @return true if included (or, in the case of a folder, at least partially included); false if excluded
72
     */
73
    boolean includes(URL root, String resource);
74
75
}
(-)a/api.java/src/org/netbeans/spi/java/classpath/PathResourceImplementation.java (-87 lines)
Lines 1-87 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * Contributor(s):
25
 *
26
 * The Original Software is NetBeans. The Initial Developer of the Original
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
 * Microsystems, Inc. All Rights Reserved.
29
 *
30
 * If you wish your version of this file to be governed by only the CDDL
31
 * or only the GPL Version 2, indicate your decision by adding
32
 * "[Contributor] elects to include this software in this distribution
33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
34
 * single choice of license, a recipient has the option to distribute
35
 * your version of this file under either the CDDL, the GPL Version 2 or
36
 * to extend the choice of license to its licensees as provided above.
37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
38
 * Version 2 license, then the option applies only if the new code is
39
 * made subject to such option by the copyright holder.
40
 */
41
package org.netbeans.spi.java.classpath;
42
43
import java.beans.PropertyChangeListener;
44
import java.net.URL;
45
46
/**
47
 * SPI interface for one classpath entry.
48
 * @see ClassPathImplementation
49
 * @since org.netbeans.api.java/1 1.4
50
 */
51
public interface PathResourceImplementation {
52
53
    public static final String PROP_ROOTS = "roots";    //NOI18N
54
55
    /** Roots of the class path entry.
56
     *  In the case of simple resource it returns array containing just one URL.
57
     *  In the case of composite resource it returns array containing one or more URL.
58
     * @return array of URL, never returns null.
59
     */
60
    public URL[] getRoots();
61
62
    /**
63
     * Returns ClassPathImplementation representing the content of the PathResourceImplementation.
64
     * If the PathResourceImplementation represents leaf resource, it returns null.
65
     * The ClassPathImplementation is live and can be used for path resource content
66
     * modification.
67
     * <p><strong>Semi-deprecated.</strong> There was never a real reason for this method to exist.
68
     * If implementing <code>PathResourceImplementation</code> you can simply return null;
69
     * it is unlikely anyone will call this method anyway.
70
     * @return classpath handle in case of composite resource; null for leaf resource
71
     */
72
    public ClassPathImplementation getContent();
73
74
    /**
75
     * Adds property change listener.
76
     * The listener is notified when the roots of the entry are changed.
77
     * @param listener
78
     */
79
    public void addPropertyChangeListener(PropertyChangeListener listener);
80
81
    /**
82
     * Removes property change listener.
83
     * @param listener
84
     */
85
    public void removePropertyChangeListener(PropertyChangeListener listener);
86
87
}
(-)a/api.java/src/org/netbeans/spi/java/classpath/package.html (-73 lines)
Lines 1-73 Link Here
1
<!--
2
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
4
Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
5
6
7
The contents of this file are subject to the terms of either the GNU
8
General Public License Version 2 only ("GPL") or the Common
9
Development and Distribution License("CDDL") (collectively, the
10
"License"). You may not use this file except in compliance with the
11
License. You can obtain a copy of the License at
12
http://www.netbeans.org/cddl-gplv2.html
13
or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
14
specific language governing permissions and limitations under the
15
License.  When distributing the software, include this License Header
16
Notice in each file and include the License file at
17
nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
18
particular file as subject to the "Classpath" exception as provided
19
by Sun in the GPL Version 2 section of the License file that
20
accompanied this code. If applicable, add the following below the
21
License Header, with the fields enclosed by brackets [] replaced by
22
your own identifying information:
23
"Portions Copyrighted [year] [name of copyright owner]"
24
25
Contributor(s):
26
27
The Original Software is NetBeans. The Initial Developer of the Original
28
Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
29
Microsystems, Inc. All Rights Reserved.
30
31
If you wish your version of this file to be governed by only the CDDL
32
or only the GPL Version 2, indicate your decision by adding
33
"[Contributor] elects to include this software in this distribution
34
under the [CDDL or GPL Version 2] license." If you do not indicate a
35
single choice of license, a recipient has the option to distribute
36
your version of this file under either the CDDL, the GPL Version 2 or
37
to extend the choice of license to its licensees as provided above.
38
However, if you add GPL Version 2 code and therefore, elected the GPL
39
Version 2 license, then the option applies only if the new code is
40
made subject to such option by the copyright holder.
41
-->
42
<html>
43
<body>
44
45
SPI permitting new classpaths to be constructed and registered.
46
47
<p>{@link org.netbeans.spi.java.classpath.ClassPathProvider}s can be registered
48
to default lookup in order to associate information about classpaths with files.
49
For example, a Java-oriented project type would normally indicate that its Java
50
sources have a certain classpath associated with them.<br>
51
For a source file the ClassPathProvider has to return a
52
{@link org.netbeans.api.java.classpath.ClassPath} of the following ClassPath types:
53
<ul>
54
<li>ClassPath.SOURCE - the classpath contains the source roots of the project</li>
55
<li>ClassPath.BOOT - the classpath contains the jdk runtime libraries</li>
56
<li>ClassPath.COMPILE - the classpath contains the project compile libraries (compile classpath)</li>
57
</ul>
58
it may also return a ClassPath of type ClassPath.EXEC pointing to the build output folder.
59
<br>
60
For build output the ClassPathProvider has to return a ClassPath of the following
61
types:
62
<ul>
63
<li>ClassPath.BOOT - the classpath contains the jdk runtime libraries</li>
64
<li>ClassPath.COMPILE - the classpath contains the project compile libraries (compile classpath)</li>
65
<li>ClassPath.EXEC - the classpath contains the build output folder</li>
66
</ul>
67
</p>
68
69
<p>{@link org.netbeans.spi.java.classpath.ClassPathFactory} may be used to
70
create new {@link org.netbeans.api.java.classpath.ClassPath} instances.</p>
71
  
72
</body>
73
</html>
(-)a/api.java/src/org/netbeans/spi/java/classpath/support/ClassPathSupport.java (-213 lines)
Lines 1-213 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * Contributor(s):
25
 *
26
 * The Original Software is NetBeans. The Initial Developer of the Original
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
 * Microsystems, Inc. All Rights Reserved.
29
 *
30
 * If you wish your version of this file to be governed by only the CDDL
31
 * or only the GPL Version 2, indicate your decision by adding
32
 * "[Contributor] elects to include this software in this distribution
33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
34
 * single choice of license, a recipient has the option to distribute
35
 * your version of this file under either the CDDL, the GPL Version 2 or
36
 * to extend the choice of license to its licensees as provided above.
37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
38
 * Version 2 license, then the option applies only if the new code is
39
 * made subject to such option by the copyright holder.
40
 */
41
package org.netbeans.spi.java.classpath.support;
42
43
import java.io.File;
44
import org.netbeans.spi.java.classpath.PathResourceImplementation;
45
import org.netbeans.spi.java.classpath.ClassPathImplementation;
46
import org.netbeans.spi.java.classpath.ClassPathFactory;
47
import org.netbeans.modules.java.classpath.*;
48
import org.netbeans.api.java.classpath.ClassPath;
49
import org.openide.ErrorManager;
50
import org.openide.filesystems.FileObject;
51
52
import java.net.URL;
53
import java.util.List;
54
import java.util.ArrayList;
55
import org.openide.filesystems.FileStateInvalidException;
56
import org.openide.filesystems.FileUtil;
57
58
/**
59
 * Convenience factory for creating classpaths of common sorts.
60
 * @since org.netbeans.api.java/1 1.4
61
 */
62
public class ClassPathSupport {
63
64
    private ClassPathSupport () {
65
    }
66
67
68
    /** Creates leaf PathResourceImplementation.
69
     * The created PathResourceImplementation has exactly one immutable root.
70
     * @param url the root of the resource. The URL must refer to folder. In the case of archive file
71
     * the jar protocol URL must be used.
72
     * @return PathResourceImplementation
73
     */
74
    public static PathResourceImplementation createResource (URL url) {
75
        if (url == null) {
76
            throw new NullPointerException("Cannot pass null URL to ClassPathSupport.createResource"); // NOI18N
77
        }
78
        // FU.iAF is a bit slow, so don't call it except when assertions are on:
79
        boolean assertions = false;
80
        assert assertions = true;
81
        if (assertions && FileUtil.isArchiveFile(url)) {
82
            throw new IllegalArgumentException("File URL pointing to " + // NOI18N
83
                "JAR is not valid classpath entry. Use jar: URL. Was: "+url); // NOI18N
84
        }
85
        if (!url.toExternalForm().endsWith("/")) { // NOI18N
86
            throw new IllegalArgumentException("URL must be a folder URL (append '/' if necessary): " + url); // NOI18N
87
        }
88
        return new SimplePathResourceImplementation (url);
89
    }
90
91
92
    /**
93
     * Create ClassPathImplementation for the given list of
94
     * {@link PathResourceImplementation} entries.
95
     * @param entries list of {@link PathResourceImplementation} instances;
96
     *     cannot be null; can be empty
97
     * @return SPI classpath
98
     */
99
    public static ClassPathImplementation createClassPathImplementation(List< ? extends PathResourceImplementation> entries) {
100
        if (entries == null) {
101
            throw new NullPointerException("Cannot pass null entries"); // NOI18N
102
        }
103
        return new SimpleClassPathImplementation(entries);
104
    }
105
106
107
    /**
108
     * Create ClassPath for the given list of
109
     * {@link PathResourceImplementation} entries.
110
     * @param entries list of {@link PathResourceImplementation} instances;
111
     *     cannot be null; can be empty
112
     * @return API classpath
113
     */
114
    public static ClassPath createClassPath(List<? extends PathResourceImplementation> entries) {
115
        if (entries == null) {
116
            throw new NullPointerException("Cannot pass null entries"); // NOI18N
117
        }
118
        return ClassPathFactory.createClassPath(createClassPathImplementation(entries));
119
    }
120
121
122
    /**
123
     * Create ClassPath for the given array of class path roots
124
     * @param roots array of fileobjects which must correspond to directory.
125
     * In the case of archive file, the FileObject representing the root of the
126
     * archive must be used.  Cannot be null; can be empty array; array can contain nulls.
127
     * @return API classpath
128
     */
129
    public static ClassPath createClassPath(FileObject... roots) {
130
        assert roots != null;
131
        List<PathResourceImplementation> l = new ArrayList<PathResourceImplementation> ();
132
        for (FileObject root : roots) {
133
            if (root == null) {
134
                continue;
135
            }
136
            try {
137
                URL u = root.getURL();            
138
                l.add(createResource(u));
139
            } catch (FileStateInvalidException e) {
140
                ErrorManager.getDefault().notify (e);
141
            }
142
        }
143
        return createClassPath (l);
144
    }
145
146
147
    /**
148
     * Create ClassPath for the given array of class path roots
149
     * @param roots array of URLs which must correspond to directory.
150
     * In the case of archive file, the jar protocol URL must be used.
151
     *   Cannot be null; can be empty array; array can contain nulls.
152
     * @return API classpath
153
     */
154
    public static ClassPath createClassPath(URL... roots) {
155
        assert roots != null;
156
        List<PathResourceImplementation> l = new ArrayList<PathResourceImplementation> ();
157
        for (URL root : roots) {
158
            if (root == null)
159
                continue;
160
            l.add (createResource(root));
161
        }
162
        return createClassPath(l);
163
    }
164
165
    /**
166
     * Convenience method to create a classpath object from a conventional string representation.
167
     * @param jvmPath a JVM-style classpath (folder or archive paths separated by {@link File#pathSeparator})
168
     * @return a corresponding classpath object
169
     * @throws IllegalArgumentException in case a path entry looks to be invalid
170
     * @since org.netbeans.api.java/1 1.15
171
     * @see FileUtil#urlForArchiveOrDir
172
     * @see ClassPath#toJVMPath
173
     */
174
    public static ClassPath createClassPath(String jvmPath) throws IllegalArgumentException {
175
        List<PathResourceImplementation> l = new ArrayList<PathResourceImplementation>();
176
        for (String piece : jvmPath.split(File.pathSeparator)) {
177
            File f = FileUtil.normalizeFile(new File(piece));
178
            URL u = FileUtil.urlForArchiveOrDir(f);
179
            if (u == null) {
180
                throw new IllegalArgumentException("Path entry looks to be invalid: " + piece); // NOI18N
181
            }
182
            l.add(createResource(u));
183
        }
184
        return createClassPath(l);
185
    }
186
187
    /**
188
     * Creates read only proxy ClassPathImplementation for given delegates.
189
     * The order of resources is given by the order of the delegates
190
     * @param delegates ClassPathImplementations to delegate to.
191
     * @return SPI classpath
192
     */
193
    public static ClassPathImplementation createProxyClassPathImplementation(ClassPathImplementation... delegates) {
194
        return new ProxyClassPathImplementation (delegates);
195
    }
196
197
198
    /**
199
     * Creates read only proxy ClassPath for given delegates.
200
     * The order of resources is given by the order of the delegates
201
     * @param delegates ClassPaths to delegate to.
202
     * @return API classpath
203
     */
204
    public static ClassPath createProxyClassPath(ClassPath... delegates) {
205
        assert delegates != null;
206
        ClassPathImplementation[] impls = new ClassPathImplementation [delegates.length];
207
        for (int i = 0; i < delegates.length; i++) {
208
             impls[i] = ClassPathAccessor.DEFAULT.getClassPathImpl (delegates[i]);
209
        }
210
        return ClassPathFactory.createClassPath (createProxyClassPathImplementation(impls));
211
    }
212
213
}
(-)a/api.java/src/org/netbeans/spi/java/classpath/support/CompositePathResourceBase.java (-157 lines)
Lines 1-157 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * Contributor(s):
25
 *
26
 * The Original Software is NetBeans. The Initial Developer of the Original
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
 * Microsystems, Inc. All Rights Reserved.
29
 *
30
 * If you wish your version of this file to be governed by only the CDDL
31
 * or only the GPL Version 2, indicate your decision by adding
32
 * "[Contributor] elects to include this software in this distribution
33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
34
 * single choice of license, a recipient has the option to distribute
35
 * your version of this file under either the CDDL, the GPL Version 2 or
36
 * to extend the choice of license to its licensees as provided above.
37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
38
 * Version 2 license, then the option applies only if the new code is
39
 * made subject to such option by the copyright holder.
40
 */
41
package org.netbeans.spi.java.classpath.support;
42
43
import org.netbeans.spi.java.classpath.PathResourceImplementation;
44
import org.netbeans.spi.java.classpath.ClassPathImplementation;
45
46
import java.net.URL;
47
import java.beans.PropertyChangeListener;
48
import java.beans.PropertyChangeEvent;
49
import java.util.ArrayList;
50
import java.util.Iterator;
51
import java.util.List;
52
import java.util.Arrays;
53
54
/**
55
 * This class provides a base class for PathResource implementations
56
 * @since org.netbeans.api.java/1 1.4
57
 */
58
public abstract class CompositePathResourceBase implements PathResourceImplementation {
59
60
    private URL[] roots;
61
    private ClassPathImplementation model;
62
    private ArrayList<PropertyChangeListener> pListeners;
63
64
    /**
65
     * Returns the roots of the PathResource
66
     * @return URL[]
67
     */
68
    public final URL[] getRoots() {
69
        if (this.roots == null) {
70
            synchronized (this) {
71
                if (this.roots == null) {
72
                    initContent ();
73
                    List<URL> result = new ArrayList<URL> ();
74
                    for (PathResourceImplementation pri : this.model.getResources()) {
75
                        result.addAll (Arrays.asList(pri.getRoots()));
76
                    }
77
                    this.roots = result.toArray (new URL [result.size()]);
78
                }
79
            }
80
        }
81
        return this.roots;
82
    }
83
84
85
    /**
86
     * Returns the ClassPathImplementation representing the content of this PathResourceImplementation
87
     * @return ClassPathImplementation
88
     */
89
    public final ClassPathImplementation getContent() {
90
		initContent ();
91
    	return this.model;
92
    }
93
94
    /**
95
     * Adds property change listener.
96
     * The listener is notified when the roots of the PathResource are changed.
97
     * @param listener
98
     */
99
    public synchronized final void addPropertyChangeListener(PropertyChangeListener listener) {
100
        if (this.pListeners == null)
101
            this.pListeners = new ArrayList<PropertyChangeListener> ();
102
        this.pListeners.add (listener);
103
    }
104
105
    /**
106
     * Removes PropertyChangeListener
107
     * @param listener
108
     */
109
    public synchronized final void removePropertyChangeListener(PropertyChangeListener listener) {
110
        if (this.pListeners == null)
111
            return;
112
        this.pListeners.remove (listener);
113
    }
114
115
    /**
116
     * Fires PropertyChangeEvent
117
     * @param propName name of property
118
     * @param oldValue old property value or null
119
     * @param newValue new property value or null
120
     */
121
    protected final void firePropertyChange (String propName, Object oldValue, Object newValue) {
122
        PropertyChangeListener[] _listeners;
123
        synchronized (this) {
124
            if (this.pListeners == null)
125
                return;
126
            _listeners = this.pListeners.toArray(new PropertyChangeListener[this.pListeners.size()]);
127
        }
128
        PropertyChangeEvent event = new PropertyChangeEvent (this, propName, oldValue, newValue);
129
        for (PropertyChangeListener l : _listeners) {
130
            l.propertyChange (event);
131
        }
132
    }
133
134
    /** Creates the array of the roots of PathResource.
135
     * Most PathResource (directory, jar) have single root,
136
     * but the PathResource can have more than one root to
137
     * represent more complex resources like libraries.
138
     * The returned value is cached.
139
     * @return ClassPathImplementation
140
     */
141
    protected abstract ClassPathImplementation createContent ();
142
143
144
	private synchronized void initContent () {
145
		if (this.model == null) {
146
			ClassPathImplementation cp = createContent ();
147
			assert cp != null;
148
			cp.addPropertyChangeListener (new PropertyChangeListener () {
149
				public void propertyChange (PropertyChangeEvent event) {
150
					roots = null;
151
					firePropertyChange (PROP_ROOTS, null,null);
152
				}
153
			});
154
            this.model = cp;
155
		}
156
	}
157
}
(-)a/api.java/src/org/netbeans/spi/java/classpath/support/PathResourceBase.java (-98 lines)
Lines 1-98 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * Contributor(s):
25
 *
26
 * The Original Software is NetBeans. The Initial Developer of the Original
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
 * Microsystems, Inc. All Rights Reserved.
29
 *
30
 * If you wish your version of this file to be governed by only the CDDL
31
 * or only the GPL Version 2, indicate your decision by adding
32
 * "[Contributor] elects to include this software in this distribution
33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
34
 * single choice of license, a recipient has the option to distribute
35
 * your version of this file under either the CDDL, the GPL Version 2 or
36
 * to extend the choice of license to its licensees as provided above.
37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
38
 * Version 2 license, then the option applies only if the new code is
39
 * made subject to such option by the copyright holder.
40
 */
41
package org.netbeans.spi.java.classpath.support;
42
43
44
import java.beans.PropertyChangeListener;
45
import java.beans.PropertyChangeEvent;
46
import java.util.ArrayList;
47
import java.util.Iterator;
48
import org.netbeans.spi.java.classpath.PathResourceImplementation;
49
50
/**
51
 * This class provides a base class for PathResource implementations
52
 * @since org.netbeans.api.java/1 1.4
53
 */
54
public abstract class PathResourceBase implements PathResourceImplementation {
55
56
    private ArrayList<PropertyChangeListener> pListeners;
57
58
59
    /**
60
     * Adds property change listener.
61
     * The listener is notified when the roots of the PathResource are changed.
62
     * @param listener
63
     */
64
    public synchronized final void addPropertyChangeListener(PropertyChangeListener listener) {
65
        if (this.pListeners == null)
66
            this.pListeners = new ArrayList<PropertyChangeListener> ();
67
        this.pListeners.add (listener);
68
    }
69
70
    /**
71
     * Removes PropertyChangeListener
72
     * @param listener
73
     */
74
    public synchronized final void removePropertyChangeListener(PropertyChangeListener listener) {
75
        if (this.pListeners == null)
76
            return;
77
        this.pListeners.remove (listener);
78
    }
79
80
    /**
81
     * Fires PropertyChangeEvent
82
     * @param propName name of property
83
     * @param oldValue old property value or null
84
     * @param newValue new property value or null
85
     */
86
    protected final void firePropertyChange (String propName, Object oldValue, Object newValue) {
87
        PropertyChangeListener[] _listeners;
88
        synchronized (this) {
89
            if (this.pListeners == null)
90
                return;
91
            _listeners = this.pListeners.toArray(new PropertyChangeListener[this.pListeners.size()]);
92
        }
93
        PropertyChangeEvent event = new PropertyChangeEvent (this, propName, oldValue, newValue);
94
        for (PropertyChangeListener l : _listeners) {
95
            l.propertyChange (event);
96
        }
97
    }
98
}
(-)a/api.java/src/org/netbeans/spi/java/classpath/support/package.html (-56 lines)
Lines 1-56 Link Here
1
<!--
2
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
4
Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
5
6
7
The contents of this file are subject to the terms of either the GNU
8
General Public License Version 2 only ("GPL") or the Common
9
Development and Distribution License("CDDL") (collectively, the
10
"License"). You may not use this file except in compliance with the
11
License. You can obtain a copy of the License at
12
http://www.netbeans.org/cddl-gplv2.html
13
or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
14
specific language governing permissions and limitations under the
15
License.  When distributing the software, include this License Header
16
Notice in each file and include the License file at
17
nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
18
particular file as subject to the "Classpath" exception as provided
19
by Sun in the GPL Version 2 section of the License file that
20
accompanied this code. If applicable, add the following below the
21
License Header, with the fields enclosed by brackets [] replaced by
22
your own identifying information:
23
"Portions Copyrighted [year] [name of copyright owner]"
24
25
Contributor(s):
26
27
The Original Software is NetBeans. The Initial Developer of the Original
28
Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
29
Microsystems, Inc. All Rights Reserved.
30
31
If you wish your version of this file to be governed by only the CDDL
32
or only the GPL Version 2, indicate your decision by adding
33
"[Contributor] elects to include this software in this distribution
34
under the [CDDL or GPL Version 2] license." If you do not indicate a
35
single choice of license, a recipient has the option to distribute
36
your version of this file under either the CDDL, the GPL Version 2 or
37
to extend the choice of license to its licensees as provided above.
38
However, if you add GPL Version 2 code and therefore, elected the GPL
39
Version 2 license, then the option applies only if the new code is
40
made subject to such option by the copyright holder.
41
-->
42
<html>
43
<body>
44
45
Convenience classes to make it easier to create classpaths.
46
47
<p>{@link org.netbeans.spi.java.classpath.support.ClassPathSupport} provides
48
various ways to create {@link org.netbeans.api.java.classpath.ClassPath} objects
49
beyond what the plain SPI provides.</p>
50
51
<p>{@link org.netbeans.spi.java.classpath.support.PathResourceBase} and
52
{@link org.netbeans.spi.java.classpath.support.CompositePathResourceBase} can be
53
used to define parts of a classpath in a controlled way.</p>
54
55
</body>
56
</html>
(-)a/api.java/src/org/netbeans/spi/java/queries/support/SourceForBinaryQueryImpl2Base.java (-73 lines)
Lines 1-73 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 * 
4
 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
5
 * 
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 * 
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 * 
35
 * Contributor(s):
36
 * 
37
 * Portions Copyrighted 2008 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.spi.java.queries.support;
41
42
import org.netbeans.api.java.queries.SourceForBinaryQuery;
43
import org.netbeans.modules.java.queries.SFBQImpl2Result;
44
import org.netbeans.spi.java.queries.SourceForBinaryQueryImplementation2;
45
import org.openide.util.Parameters;
46
47
/**
48
 * Base class for {@link SourceForBinaryQueryImplementation2} which need to delegate
49
 * to other {@link SourceForBinaryQueryImplementation}.
50
 * @since 1.16
51
 * @author Tomas Zezula
52
 */
53
public abstract class SourceForBinaryQueryImpl2Base implements SourceForBinaryQueryImplementation2 {
54
55
    /**
56
     * Creates a wrapper for {@link SourceForBinaryQuery.Result}. This method
57
     * should be used by delegating {@link SourceForBinaryQueryImplementation2}
58
     * which need to delegate to {@link SourceForBinaryQueryImplementation}. 
59
     * @param result returned by {@link SourceForBinaryQueryImplementation},
60
     * When result is already instanceof {@link SourceForBinaryQueryImplementation2.Result}
61
     * it's returned without wrapping.
62
     * @return a {@link SourceForBinaryQueryImplementation2.Result}.
63
     */
64
    protected final Result asResult (SourceForBinaryQuery.Result result) {
65
        Parameters.notNull("result", result);   //NOI18N
66
        if (result instanceof Result) {
67
            return (Result) result;
68
        }
69
        else {
70
            return new SFBQImpl2Result(result);
71
        }
72
    }
73
}
(-)a/api.java/test/unit/src/org/netbeans/api/java/classpath/ClassPathTest.java (-701 lines)
Lines 1-701 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * Contributor(s):
25
 *
26
 * The Original Software is NetBeans. The Initial Developer of the Original
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
 * Microsystems, Inc. All Rights Reserved.
29
 *
30
 * If you wish your version of this file to be governed by only the CDDL
31
 * or only the GPL Version 2, indicate your decision by adding
32
 * "[Contributor] elects to include this software in this distribution
33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
34
 * single choice of license, a recipient has the option to distribute
35
 * your version of this file under either the CDDL, the GPL Version 2 or
36
 * to extend the choice of license to its licensees as provided above.
37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
38
 * Version 2 license, then the option applies only if the new code is
39
 * made subject to such option by the copyright holder.
40
 */
41
42
package org.netbeans.api.java.classpath;
43
44
import java.io.File;
45
import java.beans.PropertyChangeEvent;
46
import java.beans.PropertyChangeListener;
47
import java.beans.PropertyChangeSupport;
48
import java.io.FileOutputStream;
49
import java.lang.ref.Reference;
50
import java.lang.ref.WeakReference;
51
import java.net.URL;
52
import java.net.URLClassLoader;
53
import java.util.ArrayList;
54
import java.util.Arrays;
55
import java.util.Collections;
56
import java.util.Enumeration;
57
import java.util.HashSet;
58
import java.util.Iterator;
59
import java.util.List;
60
import java.util.Set;
61
import java.util.SortedSet;
62
import java.util.StringTokenizer;
63
import java.util.TreeSet;
64
import java.util.jar.JarOutputStream;
65
import java.util.logging.Level;
66
import java.util.zip.ZipEntry;
67
import org.netbeans.junit.Log;
68
import org.netbeans.junit.NbTestCase;
69
import org.netbeans.spi.java.classpath.support.ClassPathSupport;
70
import org.netbeans.spi.java.classpath.ClassPathImplementation;
71
import org.netbeans.spi.java.classpath.ClassPathFactory;
72
import org.netbeans.spi.java.classpath.FilteringPathResourceImplementation;
73
import org.netbeans.spi.java.classpath.PathResourceImplementation;
74
import org.openide.filesystems.FileObject;
75
import org.openide.filesystems.FileUtil;
76
77
public class ClassPathTest extends NbTestCase {
78
79
    public ClassPathTest(String testName) {
80
        super(testName);
81
    }
82
83
    protected @Override void setUp() throws Exception {
84
        super.setUp();
85
        clearWorkDir();
86
    }
87
88
    private File getBaseDir() throws Exception {
89
        return FileUtil.normalizeFile(getWorkDir());
90
    }
91
92
    /**
93
     * Tests ClassPath.getResourceName ();
94
     */
95
    public void testGetResourceName() throws Exception {
96
        File f = getBaseDir();        
97
        f = new File(f.getPath()+"/w.e.i.r.d/f  o  l  d  e  r");
98
        f.mkdirs();
99
        File f2 = new File(f, "org/netbeans/test");
100
        f2.mkdirs();
101
        File f3 = new File(f2, "Main.java");
102
        f3.createNewFile();
103
104
        FileObject cpRoot = FileUtil.toFileObject(f);
105
        FileObject cpItem = FileUtil.toFileObject(f2);
106
        FileObject clazz = FileUtil.toFileObject(f3);
107
        ClassPath cp = ClassPathSupport.createClassPath(new FileObject[]{cpRoot});
108
        String pkg = cp.getResourceName(cpItem);
109
        assertEquals("org/netbeans/test", pkg);
110
        
111
        pkg = cp.getResourceName(cpItem, '.', true);
112
        assertEquals("org.netbeans.test", pkg);
113
        
114
        pkg = cp.getResourceName(cpItem, '.', false);
115
        assertEquals("org.netbeans.test", pkg);
116
        
117
        pkg = cp.getResourceName(cpItem, '#', true);
118
        assertEquals("org#netbeans#test", pkg);
119
        
120
        pkg = cp.getResourceName(cpItem, '#', false);
121
        assertEquals("org#netbeans#test", pkg);
122
        
123
        pkg = cp.getResourceName(clazz);
124
        assertEquals("org/netbeans/test/Main.java", pkg);
125
        
126
        pkg = cp.getResourceName(clazz, '.', true);
127
        assertEquals("org.netbeans.test.Main.java", pkg);
128
        
129
        pkg = cp.getResourceName(clazz, '.', false);
130
        assertEquals("org.netbeans.test.Main", pkg);
131
        
132
        pkg = cp.getResourceName(clazz, '@', true);
133
        assertEquals("org@netbeans@test@Main.java", pkg);
134
        
135
        pkg = cp.getResourceName(clazz, '@', false);
136
        assertEquals("org@netbeans@test@Main", pkg);
137
    }
138
    
139
    /**
140
     * Tests ClassPath.findAllResources(), ClassPath.findResoruce(), 
141
     * ClassPath.contains (), ClassPath.findOwnerRoot(),
142
     * ClassPath.isResourceVisible ()
143
     */
144
    public void testGetResource () throws Exception {
145
        File root_1 = new File (getBaseDir(),"root_1");
146
        root_1.mkdir();
147
        File root_2 = new File (getBaseDir(),"root_2");
148
        root_2.mkdir();
149
        FileObject[] roots = new FileObject [] {
150
            FileUtil.toFileObject(root_1),
151
            FileUtil.toFileObject(root_2),
152
        };
153
        
154
        FileObject tmp = roots[0].createFolder("org");
155
        tmp = tmp.createFolder("me");
156
        FileObject testFo_1 = tmp.createData("Foo","txt");
157
        tmp = roots[1].createFolder("org");
158
        tmp = tmp.createFolder("me");
159
        FileObject testFo_2 = tmp.createData("Foo","txt");        
160
        ClassPath cp = ClassPathSupport.createClassPath(roots);        
161
        
162
        //findResource
163
        assertTrue(cp.findResource ("org/me/Foo.txt")==testFo_1);
164
        assertTrue (cp.findResource("org/me/None.txt")==null);
165
        
166
        //findAllResources
167
        List res = cp.findAllResources ("org/me/Foo.txt");
168
        assertTrue (res.size() == 2);
169
        assertTrue (res.contains(testFo_1));
170
        assertTrue (res.contains(testFo_2));
171
        
172
        //contains
173
        assertTrue (cp.contains (testFo_1));
174
        assertTrue (cp.contains (testFo_2));
175
        assertFalse (cp.contains (roots[0].getParent()));
176
        
177
        //findOwnerRoot
178
        assertTrue (cp.findOwnerRoot(testFo_1)==roots[0]);
179
        assertTrue (cp.findOwnerRoot(testFo_2)==roots[1]);
180
181
        /*
182
        //isResourceVisible
183
        assertTrue (cp.isResourceVisible(testFo_1));
184
        assertFalse (cp.isResourceVisible(testFo_2));
185
         */
186
        
187
        cp = null;
188
        roots[0].delete();
189
        roots[1].delete();
190
    }
191
    
192
    /**
193
     * Test ClassPath.getRoots(), ClassPath.addPropertyChangeListener (),
194
     * ClassPath.entries () and classpath SPI.
195
     */
196
    public void testListening() throws Exception {
197
        // XXX unreliable, would be improved by usage of TestFileUtils methods:
198
199
        File root_1 = new File (getBaseDir(),"root_1");
200
        root_1.mkdir();
201
        File root_2 = new File (getBaseDir(),"root_2");
202
        root_2.mkdir();
203
        File root_3 = new File (getBaseDir(),"root_3.jar");
204
        JarOutputStream out = new JarOutputStream ( new FileOutputStream (root_3));
205
        try {            
206
            out.putNextEntry(new ZipEntry("test.txt"));
207
            out.write ("test".getBytes());
208
        } finally {
209
            out.close ();
210
        }        
211
        assertNotNull("Cannot find file",FileUtil.toFileObject(root_1));
212
        assertNotNull("Cannot find file",FileUtil.toFileObject(root_2));
213
        assertNotNull("Cannot find file",FileUtil.toFileObject(root_3));
214
        TestClassPathImplementation impl = new TestClassPathImplementation();
215
	ClassPath cp = ClassPathFactory.createClassPath (impl);
216
        impl.addResource(root_1.toURI().toURL());
217
        cp.addPropertyChangeListener (impl);
218
        impl.addResource (root_2.toURI().toURL());
219
        impl.assertEvents(ClassPath.PROP_ENTRIES, ClassPath.PROP_ROOTS);
220
        assertTrue (cp.getRoots().length==2);
221
        impl.removeResource (root_2.toURI().toURL());
222
        impl.assertEvents(ClassPath.PROP_ENTRIES, ClassPath.PROP_ROOTS);
223
        assertTrue (cp.getRoots().length==1);
224
        FileObject fo = cp.getRoots()[0];
225
        FileObject parentFolder = fo.getParent();        
226
        fo.delete();
227
        impl.assertEvents(ClassPath.PROP_ROOTS);
228
        assertTrue (cp.getRoots().length==0);
229
        parentFolder.createFolder("root_1");
230
        assertTrue (cp.getRoots().length==1);
231
        impl.assertEvents(ClassPath.PROP_ROOTS);
232
        FileObject archiveFile = FileUtil.toFileObject(root_3);
233
        impl.addResource(FileUtil.getArchiveRoot(archiveFile.getURL()));
234
        assertEquals (cp.getRoots().length,2);
235
        impl.assertEvents(ClassPath.PROP_ENTRIES, ClassPath.PROP_ROOTS);
236
        root_3.delete();
237
        root_3 = new File (getBaseDir(),"root_3.jar");
238
        Thread.sleep(1000);
239
        out = new JarOutputStream ( new FileOutputStream (root_3));
240
        try {            
241
            out.putNextEntry(new ZipEntry("test2.txt"));
242
            out.write ("test2".getBytes());
243
        } finally {
244
            out.close ();
245
        }
246
        archiveFile.refresh();
247
        impl.assertEvents(ClassPath.PROP_ROOTS);
248
        root_1.delete();
249
        root_2.delete();
250
        root_3.delete();
251
        cp = null;
252
    }
253
254
    public void testListening2() throws Exception {
255
        // Checks that changes in PathResourceImplementation.PROP_ROOTS matter.
256
        class FiringPRI implements PathResourceImplementation {
257
            private URL[] roots = new URL[0];
258
            public URL[] getRoots() {
259
                return roots;
260
            }
261
            void changeRoots(URL[] nue) {
262
                roots = nue;
263
                pcs.firePropertyChange(PROP_ROOTS, null, null);
264
            }
265
            public ClassPathImplementation getContent() {
266
                return null;
267
            }
268
            PropertyChangeSupport pcs = new PropertyChangeSupport(this);
269
            public void addPropertyChangeListener(PropertyChangeListener listener) {
270
                pcs.addPropertyChangeListener(listener);
271
            }
272
            public void removePropertyChangeListener(PropertyChangeListener listener) {
273
                pcs.removePropertyChangeListener(listener);
274
            }
275
        }
276
        FiringPRI pri = new FiringPRI();
277
        TestClassPathImplementation impl = new TestClassPathImplementation();
278
        impl.addResource(pri);
279
        ClassPath cp = ClassPathFactory.createClassPath(impl);
280
        assertEquals(Collections.emptyList(), Arrays.asList(cp.getRoots()));
281
        cp.addPropertyChangeListener(impl);
282
        File d = new File(getBaseDir(), "d");
283
        d.mkdir();
284
        pri.changeRoots(new URL[] {d.toURI().toURL()});
285
        impl.assertEvents(ClassPath.PROP_ENTRIES, ClassPath.PROP_ROOTS);
286
        assertEquals(Collections.singletonList(FileUtil.toFileObject(d)), Arrays.asList(cp.getRoots()));
287
    }
288
    
289
    public void testChangesAcknowledgedWithoutListener() throws Exception {
290
        // Discovered in #72573.
291
        clearWorkDir();
292
        File root = new File(getWorkDir(), "root");
293
        URL rootU = root.toURI().toURL();
294
        if (!rootU.toExternalForm().endsWith("/")) {
295
            rootU = new URL(rootU.toExternalForm() + "/");
296
        }
297
        ClassPath cp = ClassPathSupport.createClassPath(new URL[] {rootU});
298
        assertEquals("nothing there yet", null, cp.findResource("f"));
299
        FileObject f = FileUtil.createData(FileUtil.toFileObject(getWorkDir()), "root/f");
300
        assertEquals("found new file", f, cp.findResource("f"));
301
        f.delete();
302
        assertEquals("again empty", null, cp.findResource("f"));
303
    }
304
    
305
    static final class TestClassPathImplementation implements ClassPathImplementation, PropertyChangeListener {
306
307
        private final PropertyChangeSupport support = new PropertyChangeSupport (this);
308
        private final List<PathResourceImplementation> resources = new ArrayList<PathResourceImplementation> ();
309
        private final SortedSet<String> events = new TreeSet<String>();
310
311
        public synchronized void addResource (URL resource) {
312
            PathResourceImplementation pr = ClassPathSupport.createResource (resource);
313
            addResource(pr);
314
        }
315
316
        public synchronized void addResource(PathResourceImplementation pr) {
317
            this.resources.add (pr);
318
            this.support.firePropertyChange (ClassPathImplementation.PROP_RESOURCES,null,null);
319
        }
320
321
        public synchronized void removeResource (URL resource) {
322
            for (Iterator it = this.resources.iterator(); it.hasNext();) {
323
                PathResourceImplementation pr = (PathResourceImplementation) it.next ();
324
                if (Arrays.asList(pr.getRoots()).contains (resource)) {
325
                    this.resources.remove (pr);
326
                    this.support.firePropertyChange (ClassPathImplementation.PROP_RESOURCES,null,null);
327
                    break;
328
                }
329
            }
330
        }
331
332
        public synchronized List<? extends PathResourceImplementation> getResources() {
333
            return this.resources;
334
        }
335
336
        public void addPropertyChangeListener(PropertyChangeListener listener) {
337
            this.support.addPropertyChangeListener (listener);
338
        }
339
340
        public void removePropertyChangeListener(PropertyChangeListener listener) {
341
            this.support.removePropertyChangeListener (listener);
342
        }
343
344
        public void propertyChange (PropertyChangeEvent event) {
345
            events.add(event.getPropertyName());
346
        }
347
348
        void assertEvents(String... events) {
349
            assertEquals(new TreeSet<String>(Arrays.asList(events)), this.events);
350
            this.events.clear();
351
        }
352
    }
353
354
    public void testFilteredClassPaths() throws Exception {
355
        FileObject bd = FileUtil.toFileObject(getBaseDir());
356
        FileObject u1fo = bd.createFolder("u1");
357
        FileObject u2fo = bd.createFolder("u2");
358
        final URL u1 = u1fo.getURL();
359
        final URL u2 = u2fo.getURL();
360
        class FPRI implements FilteringPathResourceImplementation {
361
            private int modulus = 2;
362
            public void changeIncludes(int modulus) {
363
                this.modulus = modulus;
364
                pcs.firePropertyChange(PROP_INCLUDES, null, null);
365
            }
366
            public URL[] getRoots() {
367
                return new URL[] {u1, u2};
368
            }
369
            public boolean includes(URL root, String resource) {
370
                int offset;
371
                if (root.equals(u1)) {
372
                    offset = 0;
373
                } else if (root.equals(u2)) {
374
                    offset = 1;
375
                } else {
376
                    throw new IllegalArgumentException(root.toString());
377
                }
378
                return (offset + resource.length()) % modulus == 0;
379
            }
380
            public ClassPathImplementation getContent() {
381
                return null;
382
            }
383
            private PropertyChangeSupport pcs = new PropertyChangeSupport(this);
384
            public void addPropertyChangeListener(PropertyChangeListener listener) {
385
                pcs.addPropertyChangeListener(listener);
386
            }
387
            public void removePropertyChangeListener(PropertyChangeListener listener) {
388
                pcs.removePropertyChangeListener(listener);
389
            }
390
        }
391
        FPRI pr = new FPRI();
392
        TestClassPathImplementation impl = new TestClassPathImplementation();
393
        impl.addResource(pr);
394
        ClassPath cp = ClassPathFactory.createClassPath(impl);
395
        FileObject xx1 = u1fo.createData("xx");
396
        FileObject xxx1 = u1fo.createData("xxx");
397
        FileObject xy1 = FileUtil.createData(u1fo, "x/y");
398
        FileObject x_1 = u1fo.createData("x ");
399
        String cau = "\u010Dau";
400
        FileObject cau1 = u1fo.createData(cau);
401
        FileObject folder = u1fo.createFolder("folder");
402
        FileObject foldr = u1fo.createFolder("foldr");
403
        FileObject xx2 = u2fo.createData("xx");
404
        FileObject xxx2 = u2fo.createData("xxx");
405
        FileObject xy2 = FileUtil.createData(u2fo, "x/y");
406
        FileObject x_2 = u2fo.createData("x ");
407
        FileObject cau2 = u2fo.createData(cau);
408
        assertEquals(Arrays.asList(u1fo, u2fo), Arrays.asList(cp.getRoots()));
409
        assertTrue(cp.contains(xx1));
410
        assertTrue(cp.contains(x_1));
411
        assertFalse(cp.contains(xxx1));
412
        assertFalse(cp.contains(cau1));
413
        assertFalse(cp.contains(xy1));
414
        assertFalse(cp.contains(xx2));
415
        assertFalse(cp.contains(x_2));
416
        assertTrue(cp.contains(xxx2));
417
        assertTrue(cp.contains(cau2));
418
        assertTrue(cp.contains(xy2));
419
        assertFalse(cp.contains(folder));
420
        assertTrue(cp.contains(foldr));
421
        assertEquals(xx1, cp.findResource("xx"));
422
        assertEquals(x_1, cp.findResource("x "));
423
        assertEquals(xxx2, cp.findResource("xxx"));
424
        assertEquals(cau2, cp.findResource(cau));
425
        assertEquals(xy2, cp.findResource("x/y"));
426
        assertEquals(null, cp.findResource("folder"));
427
        assertEquals(foldr, cp.findResource("foldr"));
428
        assertEquals(Collections.singletonList(xx1), cp.findAllResources("xx"));
429
        assertEquals(Collections.singletonList(x_1), cp.findAllResources("x "));
430
        assertEquals(Collections.singletonList(xxx2), cp.findAllResources("xxx"));
431
        assertEquals(Collections.singletonList(cau2), cp.findAllResources(cau));
432
        assertEquals(Collections.singletonList(xy2), cp.findAllResources("x/y"));
433
        assertEquals(Collections.emptyList(), cp.findAllResources("folder"));
434
        assertEquals(Collections.singletonList(foldr), cp.findAllResources("foldr"));
435
        assertEquals("xx", cp.getResourceName(xx1));
436
        assertEquals("x ", cp.getResourceName(x_1));
437
        assertEquals("xxx", cp.getResourceName(xxx1));
438
        assertEquals(cau, cp.getResourceName(cau1));
439
        assertEquals("x/y", cp.getResourceName(xy1));
440
        assertEquals("folder", cp.getResourceName(folder));
441
        assertEquals("foldr", cp.getResourceName(foldr));
442
        assertEquals(u1fo, cp.findOwnerRoot(xx1));
443
        assertEquals(u1fo, cp.findOwnerRoot(x_1));
444
        assertEquals(u1fo, cp.findOwnerRoot(xxx1));
445
        assertEquals(u1fo, cp.findOwnerRoot(cau1));
446
        assertEquals(u1fo, cp.findOwnerRoot(xy1));
447
        assertEquals(u1fo, cp.findOwnerRoot(folder));
448
        assertEquals(u1fo, cp.findOwnerRoot(foldr));
449
        assertTrue(cp.isResourceVisible(xx1));
450
        assertTrue(cp.isResourceVisible(x_1));
451
        assertFalse(cp.isResourceVisible(xxx1));
452
        assertFalse(cp.isResourceVisible(cau1));
453
        assertFalse(cp.isResourceVisible(xy1));
454
        assertFalse(cp.isResourceVisible(folder));
455
        assertTrue(cp.isResourceVisible(foldr));
456
        ClassPath.Entry e1 = cp.entries().get(0);
457
        assertTrue(e1.includes("xx"));
458
        assertTrue(e1.includes("x "));
459
        assertFalse(e1.includes("xxx"));
460
        assertFalse(e1.includes(cau));
461
        assertFalse(e1.includes("x/y"));
462
        assertFalse(e1.includes("folder/"));
463
        assertTrue(e1.includes("foldr/"));
464
        assertTrue(e1.includes(xx1));
465
        assertTrue(e1.includes(x_1));
466
        assertFalse(e1.includes(xxx1));
467
        assertFalse(e1.includes(cau1));
468
        assertFalse(e1.includes(xy1));
469
        assertFalse(e1.includes(folder));
470
        assertTrue(e1.includes(foldr));
471
        try {
472
            e1.includes(xx2);
473
            fail();
474
        } catch (IllegalArgumentException iae) {}
475
        assertTrue(e1.includes(xx1.getURL()));
476
        assertTrue(e1.includes(x_1.getURL()));
477
        assertFalse(e1.includes(xxx1.getURL()));
478
        assertFalse(e1.includes(cau1.getURL()));
479
        assertFalse(e1.includes(xy1.getURL()));
480
        assertFalse(e1.includes(folder.getURL()));
481
        assertTrue(e1.includes(foldr.getURL()));
482
        try {
483
            e1.includes(xx2.getURL());
484
            fail();
485
        } catch (IllegalArgumentException iae) {}
486
        cp.addPropertyChangeListener(impl);
487
        pr.changeIncludes(3);
488
        impl.assertEvents(ClassPath.PROP_INCLUDES);
489
        assertFalse(cp.contains(xx1));
490
        assertFalse(cp.contains(x_1));
491
        assertTrue(cp.contains(xxx1));
492
        assertTrue(cp.contains(cau1));
493
        assertTrue(cp.contains(xy1));
494
        assertTrue(cp.contains(xx2));
495
        assertTrue(cp.contains(x_2));
496
        assertFalse(cp.contains(xxx2));
497
        assertFalse(cp.contains(cau2));
498
        assertFalse(cp.contains(xy2));
499
        assertEquals(xx2, cp.findResource("xx"));
500
        assertEquals(x_2, cp.findResource("x "));
501
        assertEquals(xxx1, cp.findResource("xxx"));
502
        assertEquals(cau1, cp.findResource(cau));
503
        assertEquals(xy1, cp.findResource("x/y"));
504
        e1 = cp.entries().get(0);
505
        assertFalse(e1.includes("xx"));
506
        assertFalse(e1.includes("x "));
507
        assertTrue(e1.includes("xxx"));
508
        assertTrue(e1.includes(cau));
509
        assertTrue(e1.includes("x/y"));
510
        assertFalse(e1.includes(xx1));
511
        assertFalse(e1.includes(x_1));
512
        assertTrue(e1.includes(xxx1));
513
        assertTrue(e1.includes(cau1));
514
        assertTrue(e1.includes(xy1));
515
        assertFalse(e1.includes(xx1.getURL()));
516
        assertFalse(e1.includes(x_1.getURL()));
517
        assertTrue(e1.includes(xxx1.getURL()));
518
        assertTrue(e1.includes(cau1.getURL()));
519
        assertTrue(e1.includes(xy1.getURL()));
520
    }
521
522
    public void testFpriChangeFiring() throws Exception {
523
        class FPRI implements FilteringPathResourceImplementation {
524
            URL root;
525
            PropertyChangeSupport pcs = new PropertyChangeSupport(this);
526
            FPRI(URL root) {
527
                this.root = root;
528
            }
529
            public boolean includes(URL root, String resource) {
530
                return true;
531
            }
532
            public URL[] getRoots() {
533
                return new URL[] {root};
534
            }
535
            public ClassPathImplementation getContent() {
536
                return null;
537
            }
538
            public void addPropertyChangeListener(PropertyChangeListener listener) {
539
                pcs.addPropertyChangeListener(listener);
540
            }
541
            public void removePropertyChangeListener(PropertyChangeListener listener) {
542
                pcs.removePropertyChangeListener(listener);
543
            }
544
            void fire(Object propid) {
545
                PropertyChangeEvent e = new PropertyChangeEvent(this, FilteringPathResourceImplementation.PROP_INCLUDES, null, null);
546
                e.setPropagationId(propid);
547
                pcs.firePropertyChange(e);
548
            }
549
        }
550
        FPRI fpri1 = new FPRI(new File(getWorkDir(), "src1").toURI().toURL());
551
        FPRI fpri2 = new FPRI(new File(getWorkDir(), "src2").toURI().toURL());
552
        class L implements PropertyChangeListener {
553
            int cnt;
554
            public void propertyChange(PropertyChangeEvent e) {
555
                if (ClassPath.PROP_INCLUDES.equals(e.getPropertyName())) {
556
                    cnt++;
557
                }
558
            }
559
        }
560
        ClassPath cp = ClassPathSupport.createClassPath(Arrays.asList(fpri1, fpri2));
561
        L l = new L();
562
        cp.addPropertyChangeListener(l);        
563
        //No events fired before cp.entries() called
564
        fpri1.fire(null);
565
        assertEquals(0, l.cnt);
566
        cp.entries();
567
        fpri1.fire(null);
568
        assertEquals(1, l.cnt);
569
        fpri2.fire(null);
570
        assertEquals(2, l.cnt);
571
        fpri1.fire("hello");
572
        assertEquals(3, l.cnt);
573
        fpri2.fire("goodbye");
574
        assertEquals(4, l.cnt);
575
        fpri1.fire("fixed");
576
        assertEquals(5, l.cnt);
577
        fpri2.fire("fixed");
578
        assertEquals(5, l.cnt);
579
        fpri1.fire("new");
580
        assertEquals(6, l.cnt);
581
    }
582
583
    public void testLeakingClassPath() throws Exception {
584
        ClassPath cp = ClassPathSupport.createClassPath(new URL("file:///a/"), new URL("file:///b/"));
585
        ClassPath proxyCP = ClassPathSupport.createProxyClassPath(cp);
586
        Reference<ClassPath> proxy = new WeakReference<ClassPath>(proxyCP);
587
        
588
        proxyCP.entries();
589
        
590
        proxyCP = null;
591
        
592
        assertGC("the proxy classpath needs to GCable", proxy);
593
    }
594
    
595
    public void testGetClassLoaderPerf () throws Exception {
596
        final String bootPathProp = System.getProperty("sun.boot.class.path");  //NOI18N
597
        List<URL> roots = new ArrayList<URL> ();
598
        StringTokenizer tk = new StringTokenizer (bootPathProp,File.pathSeparator);
599
        if (tk.hasMoreTokens()) {
600
            final String path = tk.nextToken();
601
            final File f = FileUtil.normalizeFile(new File (path));
602
            if (f.canRead()) {
603
                roots.add(f.toURI().toURL());
604
            }
605
        }
606
        final ClassLoader bootLoader = new URLClassLoader(roots.toArray(new URL[roots.size()]), null);
607
        
608
        final String classPathProp = System.getProperty("java.class.path");     //NOI18N
609
        roots = new ArrayList<URL> ();
610
        List<URL> roots2 = new ArrayList<URL>();
611
        tk = new StringTokenizer (classPathProp,File.pathSeparator);
612
        while (tk.hasMoreTokens()) {
613
            final String path = tk.nextToken();
614
            final File f = FileUtil.normalizeFile(new File (path));
615
            if (!f.canRead()) {
616
                continue;
617
            }
618
            URL url = f.toURI().toURL();
619
            roots2.add(url);
620
            if (FileUtil.isArchiveFile(url)) {
621
                url = FileUtil.getArchiveRoot(url);
622
            }
623
            roots.add(url);
624
        }
625
        
626
        final ClassPath cp = ClassPathSupport.createClassPath(roots.toArray(new URL[roots.size()]));
627
//        final ClassLoader loader = ClassLoaderSupport.create(cp,bootLoader);
628
//        final ClassLoader loader = new URLClassLoader(roots.toArray(new URL[roots.size()]),bootLoader);
629
        final ClassLoader loader = new URLClassLoader(roots2.toArray(new URL[roots2.size()]),bootLoader);
630
        
631
        final Set<String> classNames = getClassNames (cp);
632
        int noLoaded = 0;
633
        int noFailed = 0;
634
        long st = System.currentTimeMillis();
635
        for (String className : classNames) {
636
            try {
637
                final Class<?> c = loader.loadClass(className);
638
                noLoaded++;
639
            } catch (ClassNotFoundException e) {
640
                noFailed++;
641
            }
642
            catch (NoClassDefFoundError e) {
643
                noFailed++;
644
            }
645
        }
646
        long et = System.currentTimeMillis();
647
        System.out.println("Loaded: " + noLoaded + " in: " + (et-st)+"ms");
648
    }
649
    
650
    private Set<String> getClassNames (final ClassPath cp) {
651
        Set<String> classNames = new HashSet<String> ();
652
        for (FileObject root : cp.getRoots()) {
653
            Enumeration<? extends FileObject> fos = root.getChildren(true);
654
            while (fos.hasMoreElements()) {
655
                FileObject fo = fos.nextElement();
656
                if (isImportant (fo)) {
657
                    classNames.add(cp.getResourceName(fo, '.', false));
658
                }
659
            }
660
        }
661
        return classNames;
662
    }
663
    
664
    private boolean isImportant (final FileObject fo) {
665
        if (fo.isFolder()) {
666
            return false;
667
        }
668
        if (!"class".equals(fo.getExt())) {      //NOI18N
669
            return false;
670
        }
671
        return !fo.getName().contains("$");     //NOI18N
672
                
673
    }
674
675
    public void testJVMPathConversion() throws Exception {
676
        String root = getWorkDir().toURI().toString();
677
        ClassPath cp = ClassPathSupport.createClassPath(
678
                new URL(root + "folder/"),
679
                new URL("jar:" + root + "file.zip!/"),
680
                new URL("jar:" + root + "file.zip!/subdir/"));
681
        assertEquals(massagePath("<root>/folder:<root>/file.zip"), cp.toString(ClassPath.PathConversionMode.SKIP));
682
        assertEquals(massagePath("<root>/folder:<root>/file.zip:") + "jar:" + root + "file.zip!/subdir/", cp.toString(ClassPath.PathConversionMode.PRINT));
683
        try {
684
            cp.toString(ClassPath.PathConversionMode.FAIL);
685
            fail();
686
        } catch (IllegalArgumentException x) {/* OK */}
687
        CharSequence warnings = Log.enable(ClassPath.class.getName(), Level.WARNING);
688
        assertEquals(massagePath("<root>/folder:<root>/file.zip"), cp.toString(ClassPath.PathConversionMode.WARN));
689
        assertTrue(warnings.toString(), warnings.toString().contains("subdir"));
690
691
        cp = ClassPathSupport.createClassPath(
692
                new URL(root + "folder/"),
693
                new URL("jar:" + root + "file.zip!/"));
694
        assertEquals(cp.toString(), ClassPathSupport.createClassPath(cp.toString()).toString());
695
        // XXX could also test IAE (tricky - need to have a URLMapper in Lookup, etc.)
696
    }
697
    private String massagePath(String path) throws Exception {
698
        return path.replace('/', File.separatorChar).replace(':', File.pathSeparatorChar).replace("<root>", getWorkDir().getAbsolutePath());
699
    }
700
701
}
(-)a/api.java/test/unit/src/org/netbeans/api/java/classpath/GlobalPathRegistryTest.java (-381 lines)
Lines 1-381 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * Contributor(s):
25
 *
26
 * The Original Software is NetBeans. The Initial Developer of the Original
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
 * Microsystems, Inc. All Rights Reserved.
29
 *
30
 * If you wish your version of this file to be governed by only the CDDL
31
 * or only the GPL Version 2, indicate your decision by adding
32
 * "[Contributor] elects to include this software in this distribution
33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
34
 * single choice of license, a recipient has the option to distribute
35
 * your version of this file under either the CDDL, the GPL Version 2 or
36
 * to extend the choice of license to its licensees as provided above.
37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
38
 * Version 2 license, then the option applies only if the new code is
39
 * made subject to such option by the copyright holder.
40
 */
41
42
package org.netbeans.api.java.classpath;
43
44
import java.net.URL;
45
import java.util.ArrayList;
46
import java.util.Arrays;
47
import java.util.Collections;
48
import java.util.HashMap;
49
import java.util.HashSet;
50
import java.util.Iterator;
51
import java.util.Set;
52
import java.util.Map;
53
import javax.swing.event.ChangeEvent;
54
import javax.swing.event.ChangeListener;
55
import org.netbeans.api.java.queries.SourceForBinaryQuery;
56
import org.netbeans.junit.MockServices;
57
import org.netbeans.junit.NbTestCase;
58
import org.netbeans.spi.java.classpath.support.ClassPathSupport;
59
import org.netbeans.spi.java.queries.SourceForBinaryQueryImplementation;
60
import org.openide.filesystems.FileObject;
61
import org.netbeans.spi.java.classpath.ClassPathFactory;
62
import org.netbeans.spi.java.classpath.ClassPathImplementation;
63
import org.netbeans.spi.java.classpath.FilteringPathResourceImplementation;
64
import org.netbeans.spi.java.classpath.support.PathResourceBase;
65
import org.openide.filesystems.FileStateInvalidException;
66
import org.openide.filesystems.FileUtil;
67
import org.openide.util.ChangeSupport;
68
import org.openide.util.Lookup;
69
70
/**
71
 * Test functionality of GlobalPathRegistry.
72
 * @author Jesse Glick
73
 */
74
public class GlobalPathRegistryTest extends NbTestCase {
75
    
76
    public GlobalPathRegistryTest(String name) {
77
        super(name);
78
        MockServices.setServices(SFBQImpl.class, DeadLockSFBQImpl.class);
79
    }
80
    
81
    private GlobalPathRegistry r;
82
    private FileObject root;
83
    private ClassPath cp1, cp2, cp3, cp4, cp5;
84
    protected void setUp() throws Exception {
85
        super.setUp();
86
        r = GlobalPathRegistry.getDefault();
87
        r.clear();
88
        clearWorkDir();
89
        root = FileUtil.toFileObject(getWorkDir());
90
        cp1 = ClassPathSupport.createClassPath(new FileObject[] {root.createFolder("1")});
91
        cp2 = ClassPathSupport.createClassPath(new FileObject[] {root.createFolder("2")});
92
        cp3 = ClassPathSupport.createClassPath(new FileObject[] {root.createFolder("3")});
93
        cp4 = ClassPathSupport.createClassPath(new FileObject[] {root.createFolder("4")});
94
        cp5 = ClassPathSupport.createClassPath(new FileObject[] {root.createFolder("5")});
95
    }
96
    
97
    public void testBasicOperation() throws Exception {
98
        assertEquals("initially no paths of type a", Collections.<ClassPath>emptySet(), r.getPaths("a"));
99
        r.register("a", new ClassPath[] {cp1, cp2});
100
        assertEquals("added some paths of type a", new HashSet<ClassPath>(Arrays.asList(new ClassPath[] {cp1, cp2})), r.getPaths("a"));
101
        r.register("a", new ClassPath[0]);
102
        assertEquals("did not add any new paths to a", new HashSet<ClassPath>(Arrays.asList(new ClassPath[] {cp1, cp2})), r.getPaths("a"));
103
        assertEquals("initially no paths of type b", Collections.<ClassPath>emptySet(), r.getPaths("b"));
104
        r.register("b", new ClassPath[] {cp3, cp4, cp5});
105
        assertEquals("added some paths of type b", new HashSet<ClassPath>(Arrays.asList(new ClassPath[] {cp3, cp4, cp5})), r.getPaths("b"));
106
        r.unregister("a", new ClassPath[] {cp1});
107
        assertEquals("only one path left of type a", Collections.<ClassPath>singleton(cp2), r.getPaths("a"));
108
        r.register("a", new ClassPath[] {cp2, cp3});
109
        assertEquals("only one new path added of type a", new HashSet<ClassPath>(Arrays.asList(new ClassPath[] {cp2, cp3})), r.getPaths("a"));
110
        r.unregister("a", new ClassPath[] {cp2});
111
        assertEquals("still have extra cp2 in a", new HashSet<ClassPath>(Arrays.asList(new ClassPath[] {cp2, cp3})), r.getPaths("a"));
112
        r.unregister("a", new ClassPath[] {cp2});
113
        assertEquals("last cp2 removed from a", Collections.<ClassPath>singleton(cp3), r.getPaths("a"));
114
        r.unregister("a", new ClassPath[] {cp3});
115
        assertEquals("a now empty", Collections.<ClassPath>emptySet(), r.getPaths("a"));
116
        r.unregister("a", new ClassPath[0]);
117
        assertEquals("a still empty", Collections.<ClassPath>emptySet(), r.getPaths("a"));
118
        try {
119
            r.unregister("a", new ClassPath[] {cp3});
120
            fail("should not have been permitted to unregister a nonexistent entry");
121
        } catch (IllegalArgumentException x) {
122
            // Good.
123
        }
124
    }
125
    
126
    public void testListening() throws Exception {
127
        assertEquals("initially no paths of type b", Collections.<ClassPath>emptySet(), r.getPaths("b"));
128
        L l = new L();
129
        r.addGlobalPathRegistryListener(l);
130
        r.register("b", new ClassPath[] {cp1, cp2});
131
        GlobalPathRegistryEvent e = l.event();
132
        assertNotNull("got an event", e);
133
        assertTrue("was an addition", l.added());
134
        assertEquals("right registry", r, e.getRegistry());
135
        assertEquals("right ID", "b", e.getId());
136
        assertEquals("right changed paths", new HashSet<ClassPath>(Arrays.asList(new ClassPath[] {cp1, cp2})), e.getChangedPaths());
137
        r.register("b", new ClassPath[] {cp2, cp3});
138
        e = l.event();
139
        assertNotNull("got an event", e);
140
        assertTrue("was an addition", l.added());
141
        assertEquals("right changed paths", Collections.<ClassPath>singleton(cp3), e.getChangedPaths());
142
        r.register("b", new ClassPath[] {cp3});
143
        e = l.event();
144
        assertNull("no event for adding a dupe", e);
145
        r.unregister("b", new ClassPath[] {cp1, cp3, cp3});
146
        e = l.event();
147
        assertNotNull("got an event", e);
148
        assertFalse("was a removal", l.added());
149
        assertEquals("right changed paths", new HashSet<ClassPath>(Arrays.asList(new ClassPath[] {cp1, cp3})), e.getChangedPaths());
150
        r.unregister("b", new ClassPath[] {cp2});
151
        e = l.event();
152
        assertNull("no event for removing an extra", e);
153
        r.unregister("b", new ClassPath[] {cp2});
154
        e = l.event();
155
        assertNotNull("now an event for removing the last copy", e);
156
        assertFalse("was a removal", l.added());
157
        assertEquals("right changed paths", Collections.<ClassPath>singleton(cp2), e.getChangedPaths());
158
    }
159
    
160
    
161
    public void testGetSourceRoots () throws Exception {
162
        SFBQImpl query = Lookup.getDefault().lookup(SFBQImpl.class);
163
        assertNotNull ("SourceForBinaryQueryImplementation not found in lookup",query);                
164
        query.addPair(cp3.getRoots()[0].getURL(),new FileObject[0]);
165
        ClassPathTest.TestClassPathImplementation cpChangingImpl = new ClassPathTest.TestClassPathImplementation();
166
        ClassPath cpChanging = ClassPathFactory.createClassPath(cpChangingImpl);
167
        assertEquals("cpChangingImpl is empty", 0, cpChanging.getRoots().length);
168
        r.register(ClassPath.SOURCE, new ClassPath[] {cp1, cp2, cpChanging});
169
        r.register (ClassPath.COMPILE, new ClassPath[] {cp3});
170
        Set<FileObject> result = r.getSourceRoots();
171
        assertEquals ("Wrong number of source roots",result.size(),cp1.getRoots().length + cp2.getRoots().length);
172
        assertTrue ("Missing roots from cp1",result.containsAll (Arrays.asList(cp1.getRoots())));
173
        assertTrue ("Missing roots from cp2",result.containsAll (Arrays.asList(cp2.getRoots())));                
174
        // simulate classpath change:
175
        URL u = cp5.entries().get(0).getURL();
176
        cpChangingImpl.addResource(u);
177
        assertEquals("cpChangingImpl is not empty", 1, cpChanging.getRoots().length);
178
        result = r.getSourceRoots();
179
        assertEquals ("Wrong number of source roots",result.size(),cp1.getRoots().length + cp2.getRoots().length + cpChanging.getRoots().length);
180
        assertTrue ("Missing roots from cp1",result.containsAll (Arrays.asList(cp1.getRoots())));
181
        assertTrue ("Missing roots from cp2",result.containsAll (Arrays.asList(cp2.getRoots())));                
182
        cpChangingImpl.removeResource(u);
183
        
184
        query.addPair(cp3.getRoots()[0].getURL(),cp4.getRoots());       
185
        result = r.getSourceRoots();
186
        assertEquals ("Wrong number of source roots",result.size(),cp1.getRoots().length + cp2.getRoots().length+cp4.getRoots().length);
187
        assertTrue ("Missing roots from cp1",result.containsAll (Arrays.asList(cp1.getRoots())));
188
        assertTrue ("Missing roots from cp2",result.containsAll (Arrays.asList(cp2.getRoots())));
189
        assertTrue ("Missing roots from cp4",result.containsAll (Arrays.asList(cp4.getRoots())));
190
    }
191
    
192
    /**
193
     * Tests issue: #60976:Deadlock between JavaFastOpen$Evaluator and AntProjectHelper$something
194
     */
195
    public void testGetSourceRootsDeadLock () throws Exception {        
196
        DeadLockSFBQImpl query = Lookup.getDefault().lookup(DeadLockSFBQImpl.class);
197
        assertNotNull ("SourceForBinaryQueryImplementation not found in lookup",query);        
198
        r.register (ClassPath.COMPILE, new ClassPath[] {cp1});
199
        try {            
200
            query.setSynchronizedJob (
201
                new Runnable () {
202
                    public void run () {
203
                        r.register(ClassPath.COMPILE, new ClassPath[] {cp2});
204
                    }
205
                }
206
            );
207
            r.getSourceRoots();
208
        } finally {
209
            query.setSynchronizedJob (null);
210
        }
211
    }
212
213
    public void testFindResource() throws Exception {
214
        final FileObject src1 = root.createFolder("src1");
215
        FileObject src1included = FileUtil.createData(src1, "included/file");
216
        FileUtil.createData(src1, "excluded/file1");
217
        FileUtil.createData(src1, "excluded/file2");
218
        FileObject src2 = root.createFolder("src2");
219
        FileObject src2included = FileUtil.createData(src2, "included/file");
220
        FileObject src2excluded1 = FileUtil.createData(src2, "excluded/file1");
221
        class PRI extends PathResourceBase implements FilteringPathResourceImplementation {
222
            public URL[] getRoots() {
223
                try {
224
                    return new URL[] {src1.getURL()};
225
                } catch (FileStateInvalidException x) {
226
                    throw new AssertionError(x);
227
                }
228
            }
229
            public boolean includes(URL root, String resource) {
230
                return resource.startsWith("incl");
231
            }
232
            public ClassPathImplementation getContent() {
233
                return null;
234
            }
235
        }
236
        r.register(ClassPath.SOURCE, new ClassPath[] {
237
            ClassPathSupport.createClassPath(Collections.singletonList(new PRI())),
238
            ClassPathSupport.createClassPath(new FileObject[] {src2})
239
        });
240
        assertTrue(Arrays.asList(src1included, src2included).contains(r.findResource("included/file")));
241
        assertEquals(src2excluded1, r.findResource("excluded/file1"));
242
        assertEquals(null, r.findResource("excluded/file2"));
243
        assertEquals(null, r.findResource("nonexistent"));
244
    }
245
    
246
    public void testMemoryLeak124055 () throws Exception {
247
        final GlobalPathRegistry reg = GlobalPathRegistry.getDefault();
248
        final Set<? extends ClassPath> src = reg.getPaths(ClassPath.SOURCE);
249
        final Set<? extends ClassPath> boot = reg.getPaths(ClassPath.BOOT);
250
        final Set<? extends ClassPath> compile = reg.getPaths(ClassPath.COMPILE);
251
        assertTrue(src.isEmpty());
252
        assertTrue(boot.isEmpty());
253
        assertTrue(compile.isEmpty());
254
        assertTrue(reg.getSourceRoots().isEmpty());
255
        r.register(ClassPath.COMPILE, new ClassPath[] {cp3});
256
        SFBQImpl query = Lookup.getDefault().lookup(SFBQImpl.class);
257
        query.addPair(cp3.getRoots()[0].getURL(),cp4.getRoots());       
258
        //There should be one translated source root
259
        assertEquals(1, reg.getSourceRoots().size());
260
        assertEquals(1, reg.getResults().size());
261
        r.unregister(ClassPath.COMPILE, new ClassPath[] {cp3});
262
        //There shouldn't be registered source root
263
        assertTrue(reg.getSourceRoots().isEmpty());
264
        assertTrue(reg.getResults().isEmpty());
265
    }
266
    
267
    private static final class L implements GlobalPathRegistryListener {
268
        
269
        private GlobalPathRegistryEvent e;
270
        private boolean added;
271
        
272
        public L() {}
273
        
274
        public synchronized GlobalPathRegistryEvent event() {
275
            GlobalPathRegistryEvent _e = e;
276
            e = null;
277
            return _e;
278
        }
279
        
280
        public boolean added() {
281
            return added;
282
        }
283
        
284
        public synchronized void pathsAdded(GlobalPathRegistryEvent e) {
285
            assertNull("checked for last event", this.e);
286
            this.e = e;
287
            added = true;
288
        }
289
        
290
        public synchronized void pathsRemoved(GlobalPathRegistryEvent e) {
291
            assertNull("checked for last event", this.e);
292
            this.e = e;
293
            added = false;
294
        }
295
        
296
    }
297
    
298
    
299
    public static class SFBQImpl implements SourceForBinaryQueryImplementation {
300
        
301
        private Map<URL,SourceForBinaryQuery.Result> pairs = new HashMap<URL,SourceForBinaryQuery.Result> ();
302
        
303
        void addPair (URL binaryRoot, FileObject[] sourceRoots) {
304
            assert binaryRoot != null && sourceRoots != null;
305
            Result r = (Result) this.pairs.get (binaryRoot);
306
            if (r == null) {
307
                r = new Result (sourceRoots);
308
                this.pairs.put (binaryRoot, r);
309
            }
310
            else {
311
                r.setSources(sourceRoots);
312
            }
313
        }
314
                        
315
        public SourceForBinaryQuery.Result findSourceRoots(URL binaryRoot) {
316
            Result result = (Result) this.pairs.get (binaryRoot);
317
            return result;
318
        }
319
        
320
        
321
        private static class Result implements SourceForBinaryQuery.Result {
322
            
323
            private FileObject[] sources;                        
324
            private final ChangeSupport changeSupport = new ChangeSupport(this);
325
            
326
            public Result (FileObject[] sources) {
327
                this.sources = sources;
328
            }
329
            
330
            
331
            void setSources (FileObject[] sources) {
332
                this.sources = sources;
333
                this.changeSupport.fireChange ();
334
            }
335
                        
336
            public void addChangeListener(javax.swing.event.ChangeListener l) {
337
                changeSupport.addChangeListener (l);
338
            }            
339
            
340
            public FileObject[] getRoots() {
341
                return this.sources;
342
            }
343
            
344
            public void removeChangeListener(javax.swing.event.ChangeListener l) {
345
                changeSupport.removeChangeListener (l);
346
            }
347
            
348
        }
349
        
350
    }
351
    
352
    public static class DeadLockSFBQImpl extends Thread implements SourceForBinaryQueryImplementation {
353
        
354
        private Runnable r;
355
        
356
        public SourceForBinaryQuery.Result findSourceRoots(URL binaryRoot) {
357
            if (this.r != null) {                
358
                synchronized (this) {
359
                    this.start();
360
                    try {
361
                        this.wait ();
362
                    } catch (InterruptedException ie) {
363
                        ie.printStackTrace();
364
                    }
365
                }
366
            }
367
            return null;
368
        }
369
        
370
        public synchronized void run () {
371
            r.run();
372
            this.notify();
373
        }
374
        
375
        public void setSynchronizedJob (Runnable r) {
376
            this.r = r;
377
        }
378
        
379
    }
380
    
381
}
(-)a/api.java/test/unit/src/org/netbeans/modules/java/classpath/ProxyClassPathImplementationTest.java (-138 lines)
Lines 1-138 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * Contributor(s):
25
 *
26
 * The Original Software is NetBeans. The Initial Developer of the Original
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
 * Microsystems, Inc. All Rights Reserved.
29
 *
30
 * If you wish your version of this file to be governed by only the CDDL
31
 * or only the GPL Version 2, indicate your decision by adding
32
 * "[Contributor] elects to include this software in this distribution
33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
34
 * single choice of license, a recipient has the option to distribute
35
 * your version of this file under either the CDDL, the GPL Version 2 or
36
 * to extend the choice of license to its licensees as provided above.
37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
38
 * Version 2 license, then the option applies only if the new code is
39
 * made subject to such option by the copyright holder.
40
 */
41
package org.netbeans.modules.java.classpath;
42
43
44
import java.net.URL;
45
import java.util.concurrent.CountDownLatch;
46
import java.util.concurrent.ExecutorService;
47
import java.util.concurrent.Executors;
48
import java.util.concurrent.locks.ReentrantLock;
49
import junit.framework.TestCase;
50
import junit.framework.*;
51
import org.netbeans.api.java.classpath.ClassPath;
52
import org.netbeans.junit.NbTestCase;
53
import org.netbeans.spi.java.classpath.ClassPathFactory;
54
import org.netbeans.spi.java.classpath.ClassPathImplementation;
55
import org.netbeans.spi.java.classpath.PathResourceImplementation;
56
import java.util.List;
57
import java.util.ArrayList;
58
import java.util.Iterator;
59
import java.util.Collections;
60
import java.beans.PropertyChangeListener;
61
import java.beans.PropertyChangeEvent;
62
import org.netbeans.spi.java.classpath.support.ClassPathSupport;
63
import org.openide.util.WeakListeners;
64
65
/**
66
 *
67
 * @author tom
68
 */
69
public class ProxyClassPathImplementationTest extends NbTestCase {
70
    
71
    public ProxyClassPathImplementationTest(String testName) {
72
        super(testName);
73
    }
74
    
75
    public void testResources () throws Exception {
76
        final URL url1 = new URL ("file:///tmp/a/");
77
        final URL url2 = new URL ("file:///tmp/b/");
78
        final URL url3 = new URL ("file:///tmp/b/");
79
        
80
        final ClassPath cp1 = ClassPathSupport.createClassPath(new URL[] {url1, url2});
81
        final ClassPath cp2 = ClassPathSupport.createClassPath(new URL[] {url3});
82
        final ClassPath prxCp = ClassPathSupport.createProxyClassPath(new ClassPath[] {cp1,cp2});
83
        List<ClassPath.Entry> entries = prxCp.entries();
84
        assertEquals(3,entries.size());
85
        assertEquals(url1,entries.get(0).getURL());
86
        assertEquals(url2,entries.get(1).getURL());
87
        assertEquals(url3,entries.get(2).getURL());
88
    }
89
90
    public void testDeadLock() throws Exception{
91
        List<PathResourceImplementation> resources = Collections.<PathResourceImplementation>emptyList();
92
        final ReentrantLock lock = new ReentrantLock (false);
93
        final CountDownLatch signal = new CountDownLatch (1);
94
        final ClassPath cp = ClassPathFactory.createClassPath(ClassPathSupport.createProxyClassPathImplementation(new ClassPathImplementation[] {new LockClassPathImplementation (resources,lock, signal)}));
95
        lock.lock();
96
        final ExecutorService es = Executors.newSingleThreadExecutor();        
97
        try {
98
            es.submit(new Runnable () {
99
                public void run () {
100
                    cp.entries();
101
                }
102
            });
103
            signal.await();
104
            cp.entries();
105
        } finally {
106
            es.shutdownNow();
107
        }
108
    }  
109
    
110
    
111
    private class LockClassPathImplementation implements ClassPathImplementation {
112
        
113
        private List<? extends PathResourceImplementation> resources;
114
        private ReentrantLock lock;
115
        private CountDownLatch signal;
116
        
117
        public LockClassPathImplementation (final List<? extends PathResourceImplementation> resources, final ReentrantLock lock, final CountDownLatch signal) {
118
            this.resources = resources;
119
            this.lock = lock;
120
            this.signal = signal;
121
        }
122
        
123
        public List<? extends PathResourceImplementation> getResources() {
124
            this.signal.countDown();
125
            this.lock.lock();
126
            return this.resources;
127
        }
128
129
        public void addPropertyChangeListener(PropertyChangeListener listener) {
130
        }
131
132
        public void removePropertyChangeListener(PropertyChangeListener listener) {
133
        }
134
        
135
    }
136
    
137
    
138
}
(-)a/nbbuild/cluster.properties (+1 lines)
Lines 228-233 Link Here
228
nb.cluster.ide.depends=nb.cluster.platform
228
nb.cluster.ide.depends=nb.cluster.platform
229
nb.cluster.ide=\
229
nb.cluster.ide=\
230
        api.debugger,\
230
        api.debugger,\
231
        api.java.classpath,\
231
        api.xml,\
232
        api.xml,\
232
        classfile,\
233
        classfile,\
233
        core.ide,\
234
        core.ide,\
(-)a/nbbuild/javadoctools/links.xml (+1 lines)
Lines 165-167 Link Here
165
<link href="${javadoc.docs.org-netbeans-modules-websvc-serviceapi}" offline="true" packagelistloc="${netbeans.javadoc.dir}/org-netbeans-modules-websvc-serviceapi"/>
165
<link href="${javadoc.docs.org-netbeans-modules-websvc-serviceapi}" offline="true" packagelistloc="${netbeans.javadoc.dir}/org-netbeans-modules-websvc-serviceapi"/>
166
<link href="${javadoc.docs.org-netbeans-modules-java-api-common}" offline="true" packagelistloc="${netbeans.javadoc.dir}/org-netbeans-modules-java-api-common"/>
166
<link href="${javadoc.docs.org-netbeans-modules-java-api-common}" offline="true" packagelistloc="${netbeans.javadoc.dir}/org-netbeans-modules-java-api-common"/>
167
<link href="${javadoc.docs.org-netbeans-modules-java-sourceui}" offline="true" packagelistloc="${netbeans.javadoc.dir}/org-netbeans-modules-java-sourceui"/>
167
<link href="${javadoc.docs.org-netbeans-modules-java-sourceui}" offline="true" packagelistloc="${netbeans.javadoc.dir}/org-netbeans-modules-java-sourceui"/>
168
<link href="${javadoc.docs.org-netbeans-api-java-classpath}" offline="true" packagelistloc="${netbeans.javadoc.dir}/org-netbeans-api-java-classpath"/>
(-)a/nbbuild/javadoctools/properties.xml (+1 lines)
Lines 163-165 Link Here
163
<property name="javadoc.docs.org-netbeans-modules-websvc-serviceapi" value="${javadoc.web.root}/org-netbeans-modules-websvc-serviceapi"/>
163
<property name="javadoc.docs.org-netbeans-modules-websvc-serviceapi" value="${javadoc.web.root}/org-netbeans-modules-websvc-serviceapi"/>
164
<property name="javadoc.docs.org-netbeans-modules-java-api-common" value="${javadoc.web.root}/org-netbeans-modules-java-api-common"/>
164
<property name="javadoc.docs.org-netbeans-modules-java-api-common" value="${javadoc.web.root}/org-netbeans-modules-java-api-common"/>
165
<property name="javadoc.docs.org-netbeans-modules-java-sourceui" value="${javadoc.web.root}/org-netbeans-modules-java-sourceui"/>
165
<property name="javadoc.docs.org-netbeans-modules-java-sourceui" value="${javadoc.web.root}/org-netbeans-modules-java-sourceui"/>
166
<property name="javadoc.docs.org-netbeans-api-java-classpath" value="${javadoc.web.root}/org-netbeans-api-java-classpath"/>
(-)a/nbbuild/javadoctools/replaces.xml (+1 lines)
Lines 163-165 Link Here
163
<replacefilter token="@org-netbeans-modules-websvc-serviceapi@" value="${javadoc.docs.org-netbeans-modules-websvc-serviceapi}"/>
163
<replacefilter token="@org-netbeans-modules-websvc-serviceapi@" value="${javadoc.docs.org-netbeans-modules-websvc-serviceapi}"/>
164
<replacefilter token="@org-netbeans-modules-java-api-common@" value="${javadoc.docs.org-netbeans-modules-java-api-common}"/>
164
<replacefilter token="@org-netbeans-modules-java-api-common@" value="${javadoc.docs.org-netbeans-modules-java-api-common}"/>
165
<replacefilter token="@org-netbeans-modules-java-sourceui@" value="${javadoc.docs.org-netbeans-modules-java-sourceui}"/>
165
<replacefilter token="@org-netbeans-modules-java-sourceui@" value="${javadoc.docs.org-netbeans-modules-java-sourceui}"/>
166
<replacefilter token="@org-netbeans-api-java-classpath@" value="${javadoc.docs.org-netbeans-api-java-classpath}"/>

Return to bug 136169