Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/java/beans/beancontext/BeanContextSupport.java
38918 views
1
/*
2
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package java.beans.beancontext;
27
28
import java.awt.Component;
29
import java.awt.Container;
30
31
import java.beans.Beans;
32
import java.beans.AppletInitializer;
33
34
import java.beans.DesignMode;
35
36
import java.beans.PropertyChangeEvent;
37
import java.beans.PropertyChangeListener;
38
import java.beans.PropertyChangeSupport;
39
40
import java.beans.VetoableChangeListener;
41
import java.beans.VetoableChangeSupport;
42
import java.beans.PropertyVetoException;
43
44
import java.beans.Visibility;
45
46
import java.io.IOException;
47
import java.io.InputStream;
48
import java.io.ObjectInputStream;
49
import java.io.ObjectOutputStream;
50
import java.io.Serializable;
51
52
import java.net.URL;
53
54
import java.util.ArrayList;
55
import java.util.Collection;
56
import java.util.HashMap;
57
import java.util.Iterator;
58
import java.util.Locale;
59
import java.util.Map;
60
61
62
/**
63
* This helper class provides a utility implementation of the
64
* java.beans.beancontext.BeanContext interface.
65
* <p>
66
* Since this class directly implements the BeanContext interface, the class
67
* can, and is intended to be used either by subclassing this implementation,
68
* or via ad-hoc delegation of an instance of this class from another.
69
* </p>
70
*
71
* @author Laurence P. G. Cable
72
* @since 1.2
73
*/
74
public class BeanContextSupport extends BeanContextChildSupport
75
implements BeanContext,
76
Serializable,
77
PropertyChangeListener,
78
VetoableChangeListener {
79
80
// Fix for bug 4282900 to pass JCK regression test
81
static final long serialVersionUID = -4879613978649577204L;
82
83
/**
84
*
85
* Construct a BeanContextSupport instance
86
*
87
*
88
* @param peer The peer <tt>BeanContext</tt> we are
89
* supplying an implementation for,
90
* or <tt>null</tt>
91
* if this object is its own peer
92
* @param lcle The current Locale for this BeanContext. If
93
* <tt>lcle</tt> is <tt>null</tt>, the default locale
94
* is assigned to the <tt>BeanContext</tt> instance.
95
* @param dTime The initial state,
96
* <tt>true</tt> if in design mode,
97
* <tt>false</tt> if runtime.
98
* @param visible The initial visibility.
99
* @see java.util.Locale#getDefault()
100
* @see java.util.Locale#setDefault(java.util.Locale)
101
*/
102
public BeanContextSupport(BeanContext peer, Locale lcle, boolean dTime, boolean visible) {
103
super(peer);
104
105
locale = lcle != null ? lcle : Locale.getDefault();
106
designTime = dTime;
107
okToUseGui = visible;
108
109
initialize();
110
}
111
112
/**
113
* Create an instance using the specified Locale and design mode.
114
*
115
* @param peer The peer <tt>BeanContext</tt> we
116
* are supplying an implementation for,
117
* or <tt>null</tt> if this object is its own peer
118
* @param lcle The current Locale for this <tt>BeanContext</tt>. If
119
* <tt>lcle</tt> is <tt>null</tt>, the default locale
120
* is assigned to the <tt>BeanContext</tt> instance.
121
* @param dtime The initial state, <tt>true</tt>
122
* if in design mode,
123
* <tt>false</tt> if runtime.
124
* @see java.util.Locale#getDefault()
125
* @see java.util.Locale#setDefault(java.util.Locale)
126
*/
127
public BeanContextSupport(BeanContext peer, Locale lcle, boolean dtime) {
128
this (peer, lcle, dtime, true);
129
}
130
131
/**
132
* Create an instance using the specified locale
133
*
134
* @param peer The peer BeanContext we are
135
* supplying an implementation for,
136
* or <tt>null</tt> if this object
137
* is its own peer
138
* @param lcle The current Locale for this
139
* <tt>BeanContext</tt>. If
140
* <tt>lcle</tt> is <tt>null</tt>,
141
* the default locale
142
* is assigned to the <tt>BeanContext</tt>
143
* instance.
144
* @see java.util.Locale#getDefault()
145
* @see java.util.Locale#setDefault(java.util.Locale)
146
*/
147
public BeanContextSupport(BeanContext peer, Locale lcle) {
148
this (peer, lcle, false, true);
149
}
150
151
/**
152
* Create an instance using with a default locale
153
*
154
* @param peer The peer <tt>BeanContext</tt> we are
155
* supplying an implementation for,
156
* or <tt>null</tt> if this object
157
* is its own peer
158
*/
159
public BeanContextSupport(BeanContext peer) {
160
this (peer, null, false, true);
161
}
162
163
/**
164
* Create an instance that is not a delegate of another object
165
*/
166
167
public BeanContextSupport() {
168
this (null, null, false, true);
169
}
170
171
/**
172
* Gets the instance of <tt>BeanContext</tt> that
173
* this object is providing the implementation for.
174
* @return the BeanContext instance
175
*/
176
public BeanContext getBeanContextPeer() { return (BeanContext)getBeanContextChildPeer(); }
177
178
/**
179
* <p>
180
* The instantiateChild method is a convenience hook
181
* in BeanContext to simplify
182
* the task of instantiating a Bean, nested,
183
* into a <tt>BeanContext</tt>.
184
* </p>
185
* <p>
186
* The semantics of the beanName parameter are defined by java.beans.Beans.instantiate.
187
* </p>
188
*
189
* @param beanName the name of the Bean to instantiate within this BeanContext
190
* @throws IOException if there is an I/O error when the bean is being deserialized
191
* @throws ClassNotFoundException if the class
192
* identified by the beanName parameter is not found
193
* @return the new object
194
*/
195
public Object instantiateChild(String beanName)
196
throws IOException, ClassNotFoundException {
197
BeanContext bc = getBeanContextPeer();
198
199
return Beans.instantiate(bc.getClass().getClassLoader(), beanName, bc);
200
}
201
202
/**
203
* Gets the number of children currently nested in
204
* this BeanContext.
205
*
206
* @return number of children
207
*/
208
public int size() {
209
synchronized(children) {
210
return children.size();
211
}
212
}
213
214
/**
215
* Reports whether or not this
216
* <tt>BeanContext</tt> is empty.
217
* A <tt>BeanContext</tt> is considered
218
* empty when it contains zero
219
* nested children.
220
* @return if there are not children
221
*/
222
public boolean isEmpty() {
223
synchronized(children) {
224
return children.isEmpty();
225
}
226
}
227
228
/**
229
* Determines whether or not the specified object
230
* is currently a child of this <tt>BeanContext</tt>.
231
* @param o the Object in question
232
* @return if this object is a child
233
*/
234
public boolean contains(Object o) {
235
synchronized(children) {
236
return children.containsKey(o);
237
}
238
}
239
240
/**
241
* Determines whether or not the specified object
242
* is currently a child of this <tt>BeanContext</tt>.
243
* @param o the Object in question
244
* @return if this object is a child
245
*/
246
public boolean containsKey(Object o) {
247
synchronized(children) {
248
return children.containsKey(o);
249
}
250
}
251
252
/**
253
* Gets all JavaBean or <tt>BeanContext</tt> instances
254
* currently nested in this <tt>BeanContext</tt>.
255
* @return an <tt>Iterator</tt> of the nested children
256
*/
257
public Iterator iterator() {
258
synchronized(children) {
259
return new BCSIterator(children.keySet().iterator());
260
}
261
}
262
263
/**
264
* Gets all JavaBean or <tt>BeanContext</tt>
265
* instances currently nested in this BeanContext.
266
*/
267
public Object[] toArray() {
268
synchronized(children) {
269
return children.keySet().toArray();
270
}
271
}
272
273
/**
274
* Gets an array containing all children of
275
* this <tt>BeanContext</tt> that match
276
* the types contained in arry.
277
* @param arry The array of object
278
* types that are of interest.
279
* @return an array of children
280
*/
281
public Object[] toArray(Object[] arry) {
282
synchronized(children) {
283
return children.keySet().toArray(arry);
284
}
285
}
286
287
288
/************************************************************************/
289
290
/**
291
* protected final subclass that encapsulates an iterator but implements
292
* a noop remove() method.
293
*/
294
295
protected static final class BCSIterator implements Iterator {
296
BCSIterator(Iterator i) { super(); src = i; }
297
298
public boolean hasNext() { return src.hasNext(); }
299
public Object next() { return src.next(); }
300
public void remove() { /* do nothing */ }
301
302
private Iterator src;
303
}
304
305
/************************************************************************/
306
307
/*
308
* protected nested class containing per child information, an instance
309
* of which is associated with each child in the "children" hashtable.
310
* subclasses can extend this class to include their own per-child state.
311
*
312
* Note that this 'value' is serialized with the corresponding child 'key'
313
* when the BeanContextSupport is serialized.
314
*/
315
316
protected class BCSChild implements Serializable {
317
318
private static final long serialVersionUID = -5815286101609939109L;
319
320
BCSChild(Object bcc, Object peer) {
321
super();
322
323
child = bcc;
324
proxyPeer = peer;
325
}
326
327
Object getChild() { return child; }
328
329
void setRemovePending(boolean v) { removePending = v; }
330
331
boolean isRemovePending() { return removePending; }
332
333
boolean isProxyPeer() { return proxyPeer != null; }
334
335
Object getProxyPeer() { return proxyPeer; }
336
/*
337
* fields
338
*/
339
340
341
private Object child;
342
private Object proxyPeer;
343
344
private transient boolean removePending;
345
}
346
347
/**
348
* <p>
349
* Subclasses can override this method to insert their own subclass
350
* of Child without having to override add() or the other Collection
351
* methods that add children to the set.
352
* </p>
353
* @param targetChild the child to create the Child on behalf of
354
* @param peer the peer if the tragetChild and the peer are related by an implementation of BeanContextProxy * @return Subtype-specific subclass of Child without overriding collection methods
355
*/
356
357
protected BCSChild createBCSChild(Object targetChild, Object peer) {
358
return new BCSChild(targetChild, peer);
359
}
360
361
/************************************************************************/
362
363
/**
364
* Adds/nests a child within this <tt>BeanContext</tt>.
365
* <p>
366
* Invoked as a side effect of java.beans.Beans.instantiate().
367
* If the child object is not valid for adding then this method
368
* throws an IllegalStateException.
369
* </p>
370
*
371
*
372
* @param targetChild The child objects to nest
373
* within this <tt>BeanContext</tt>
374
* @return true if the child was added successfully.
375
* @see #validatePendingAdd
376
*/
377
public boolean add(Object targetChild) {
378
379
if (targetChild == null) throw new IllegalArgumentException();
380
381
// The specification requires that we do nothing if the child
382
// is already nested herein.
383
384
if (children.containsKey(targetChild)) return false; // test before locking
385
386
synchronized(BeanContext.globalHierarchyLock) {
387
if (children.containsKey(targetChild)) return false; // check again
388
389
if (!validatePendingAdd(targetChild)) {
390
throw new IllegalStateException();
391
}
392
393
394
// The specification requires that we invoke setBeanContext() on the
395
// newly added child if it implements the java.beans.beancontext.BeanContextChild interface
396
397
BeanContextChild cbcc = getChildBeanContextChild(targetChild);
398
BeanContextChild bccp = null;
399
400
synchronized(targetChild) {
401
402
if (targetChild instanceof BeanContextProxy) {
403
bccp = ((BeanContextProxy)targetChild).getBeanContextProxy();
404
405
if (bccp == null) throw new NullPointerException("BeanContextPeer.getBeanContextProxy()");
406
}
407
408
BCSChild bcsc = createBCSChild(targetChild, bccp);
409
BCSChild pbcsc = null;
410
411
synchronized (children) {
412
children.put(targetChild, bcsc);
413
414
if (bccp != null) children.put(bccp, pbcsc = createBCSChild(bccp, targetChild));
415
}
416
417
if (cbcc != null) synchronized(cbcc) {
418
try {
419
cbcc.setBeanContext(getBeanContextPeer());
420
} catch (PropertyVetoException pve) {
421
422
synchronized (children) {
423
children.remove(targetChild);
424
425
if (bccp != null) children.remove(bccp);
426
}
427
428
throw new IllegalStateException();
429
}
430
431
cbcc.addPropertyChangeListener("beanContext", childPCL);
432
cbcc.addVetoableChangeListener("beanContext", childVCL);
433
}
434
435
Visibility v = getChildVisibility(targetChild);
436
437
if (v != null) {
438
if (okToUseGui)
439
v.okToUseGui();
440
else
441
v.dontUseGui();
442
}
443
444
if (getChildSerializable(targetChild) != null) serializable++;
445
446
childJustAddedHook(targetChild, bcsc);
447
448
if (bccp != null) {
449
v = getChildVisibility(bccp);
450
451
if (v != null) {
452
if (okToUseGui)
453
v.okToUseGui();
454
else
455
v.dontUseGui();
456
}
457
458
if (getChildSerializable(bccp) != null) serializable++;
459
460
childJustAddedHook(bccp, pbcsc);
461
}
462
463
464
}
465
466
// The specification requires that we fire a notification of the change
467
468
fireChildrenAdded(new BeanContextMembershipEvent(getBeanContextPeer(), bccp == null ? new Object[] { targetChild } : new Object[] { targetChild, bccp } ));
469
470
}
471
472
return true;
473
}
474
475
/**
476
* Removes a child from this BeanContext. If the child object is not
477
* for adding then this method throws an IllegalStateException.
478
* @param targetChild The child objects to remove
479
* @see #validatePendingRemove
480
*/
481
public boolean remove(Object targetChild) {
482
return remove(targetChild, true);
483
}
484
485
/**
486
* internal remove used when removal caused by
487
* unexpected <tt>setBeanContext</tt> or
488
* by <tt>remove()</tt> invocation.
489
* @param targetChild the JavaBean, BeanContext, or Object to be removed
490
* @param callChildSetBC used to indicate that
491
* the child should be notified that it is no
492
* longer nested in this <tt>BeanContext</tt>.
493
* @return whether or not was present before being removed
494
*/
495
protected boolean remove(Object targetChild, boolean callChildSetBC) {
496
497
if (targetChild == null) throw new IllegalArgumentException();
498
499
synchronized(BeanContext.globalHierarchyLock) {
500
if (!containsKey(targetChild)) return false;
501
502
if (!validatePendingRemove(targetChild)) {
503
throw new IllegalStateException();
504
}
505
506
BCSChild bcsc = (BCSChild)children.get(targetChild);
507
BCSChild pbcsc = null;
508
Object peer = null;
509
510
// we are required to notify the child that it is no longer nested here if
511
// it implements java.beans.beancontext.BeanContextChild
512
513
synchronized(targetChild) {
514
if (callChildSetBC) {
515
BeanContextChild cbcc = getChildBeanContextChild(targetChild);
516
if (cbcc != null) synchronized(cbcc) {
517
cbcc.removePropertyChangeListener("beanContext", childPCL);
518
cbcc.removeVetoableChangeListener("beanContext", childVCL);
519
520
try {
521
cbcc.setBeanContext(null);
522
} catch (PropertyVetoException pve1) {
523
cbcc.addPropertyChangeListener("beanContext", childPCL);
524
cbcc.addVetoableChangeListener("beanContext", childVCL);
525
throw new IllegalStateException();
526
}
527
528
}
529
}
530
531
synchronized (children) {
532
children.remove(targetChild);
533
534
if (bcsc.isProxyPeer()) {
535
pbcsc = (BCSChild)children.get(peer = bcsc.getProxyPeer());
536
children.remove(peer);
537
}
538
}
539
540
if (getChildSerializable(targetChild) != null) serializable--;
541
542
childJustRemovedHook(targetChild, bcsc);
543
544
if (peer != null) {
545
if (getChildSerializable(peer) != null) serializable--;
546
547
childJustRemovedHook(peer, pbcsc);
548
}
549
}
550
551
fireChildrenRemoved(new BeanContextMembershipEvent(getBeanContextPeer(), peer == null ? new Object[] { targetChild } : new Object[] { targetChild, peer } ));
552
553
}
554
555
return true;
556
}
557
558
/**
559
* Tests to see if all objects in the
560
* specified <tt>Collection</tt> are children of
561
* this <tt>BeanContext</tt>.
562
* @param c the specified <tt>Collection</tt>
563
*
564
* @return <tt>true</tt> if all objects
565
* in the collection are children of
566
* this <tt>BeanContext</tt>, false if not.
567
*/
568
public boolean containsAll(Collection c) {
569
synchronized(children) {
570
Iterator i = c.iterator();
571
while (i.hasNext())
572
if(!contains(i.next()))
573
return false;
574
575
return true;
576
}
577
}
578
579
/**
580
* add Collection to set of Children (Unsupported)
581
* implementations must synchronized on the hierarchy lock and "children" protected field
582
* @throws UnsupportedOperationException thrown unconditionally by this implementation
583
* @return this implementation unconditionally throws {@code UnsupportedOperationException}
584
*/
585
public boolean addAll(Collection c) {
586
throw new UnsupportedOperationException();
587
}
588
589
/**
590
* remove all specified children (Unsupported)
591
* implementations must synchronized on the hierarchy lock and "children" protected field
592
* @throws UnsupportedOperationException thrown unconditionally by this implementation
593
* @return this implementation unconditionally throws {@code UnsupportedOperationException}
594
595
*/
596
public boolean removeAll(Collection c) {
597
throw new UnsupportedOperationException();
598
}
599
600
601
/**
602
* retain only specified children (Unsupported)
603
* implementations must synchronized on the hierarchy lock and "children" protected field
604
* @throws UnsupportedOperationException thrown unconditionally by this implementation
605
* @return this implementation unconditionally throws {@code UnsupportedOperationException}
606
*/
607
public boolean retainAll(Collection c) {
608
throw new UnsupportedOperationException();
609
}
610
611
/**
612
* clear the children (Unsupported)
613
* implementations must synchronized on the hierarchy lock and "children" protected field
614
* @throws UnsupportedOperationException thrown unconditionally by this implementation
615
*/
616
public void clear() {
617
throw new UnsupportedOperationException();
618
}
619
620
/**
621
* Adds a BeanContextMembershipListener
622
*
623
* @param bcml the BeanContextMembershipListener to add
624
* @throws NullPointerException if the argument is null
625
*/
626
627
public void addBeanContextMembershipListener(BeanContextMembershipListener bcml) {
628
if (bcml == null) throw new NullPointerException("listener");
629
630
synchronized(bcmListeners) {
631
if (bcmListeners.contains(bcml))
632
return;
633
else
634
bcmListeners.add(bcml);
635
}
636
}
637
638
/**
639
* Removes a BeanContextMembershipListener
640
*
641
* @param bcml the BeanContextMembershipListener to remove
642
* @throws NullPointerException if the argument is null
643
*/
644
645
public void removeBeanContextMembershipListener(BeanContextMembershipListener bcml) {
646
if (bcml == null) throw new NullPointerException("listener");
647
648
synchronized(bcmListeners) {
649
if (!bcmListeners.contains(bcml))
650
return;
651
else
652
bcmListeners.remove(bcml);
653
}
654
}
655
656
/**
657
* @param name the name of the resource requested.
658
* @param bcc the child object making the request.
659
*
660
* @return the requested resource as an InputStream
661
* @throws NullPointerException if the argument is null
662
*/
663
664
public InputStream getResourceAsStream(String name, BeanContextChild bcc) {
665
if (name == null) throw new NullPointerException("name");
666
if (bcc == null) throw new NullPointerException("bcc");
667
668
if (containsKey(bcc)) {
669
ClassLoader cl = bcc.getClass().getClassLoader();
670
671
return cl != null ? cl.getResourceAsStream(name)
672
: ClassLoader.getSystemResourceAsStream(name);
673
} else throw new IllegalArgumentException("Not a valid child");
674
}
675
676
/**
677
* @param name the name of the resource requested.
678
* @param bcc the child object making the request.
679
*
680
* @return the requested resource as an InputStream
681
*/
682
683
public URL getResource(String name, BeanContextChild bcc) {
684
if (name == null) throw new NullPointerException("name");
685
if (bcc == null) throw new NullPointerException("bcc");
686
687
if (containsKey(bcc)) {
688
ClassLoader cl = bcc.getClass().getClassLoader();
689
690
return cl != null ? cl.getResource(name)
691
: ClassLoader.getSystemResource(name);
692
} else throw new IllegalArgumentException("Not a valid child");
693
}
694
695
/**
696
* Sets the new design time value for this <tt>BeanContext</tt>.
697
* @param dTime the new designTime value
698
*/
699
public synchronized void setDesignTime(boolean dTime) {
700
if (designTime != dTime) {
701
designTime = dTime;
702
703
firePropertyChange("designMode", Boolean.valueOf(!dTime), Boolean.valueOf(dTime));
704
}
705
}
706
707
708
/**
709
* Reports whether or not this object is in
710
* currently in design time mode.
711
* @return <tt>true</tt> if in design time mode,
712
* <tt>false</tt> if not
713
*/
714
public synchronized boolean isDesignTime() { return designTime; }
715
716
/**
717
* Sets the locale of this BeanContext.
718
* @param newLocale the new locale. This method call will have
719
* no effect if newLocale is <CODE>null</CODE>.
720
* @throws PropertyVetoException if the new value is rejected
721
*/
722
public synchronized void setLocale(Locale newLocale) throws PropertyVetoException {
723
724
if ((locale != null && !locale.equals(newLocale)) && newLocale != null) {
725
Locale old = locale;
726
727
fireVetoableChange("locale", old, newLocale); // throws
728
729
locale = newLocale;
730
731
firePropertyChange("locale", old, newLocale);
732
}
733
}
734
735
/**
736
* Gets the locale for this <tt>BeanContext</tt>.
737
*
738
* @return the current Locale of the <tt>BeanContext</tt>
739
*/
740
public synchronized Locale getLocale() { return locale; }
741
742
/**
743
* <p>
744
* This method is typically called from the environment in order to determine
745
* if the implementor "needs" a GUI.
746
* </p>
747
* <p>
748
* The algorithm used herein tests the BeanContextPeer, and its current children
749
* to determine if they are either Containers, Components, or if they implement
750
* Visibility and return needsGui() == true.
751
* </p>
752
* @return <tt>true</tt> if the implementor needs a GUI
753
*/
754
public synchronized boolean needsGui() {
755
BeanContext bc = getBeanContextPeer();
756
757
if (bc != this) {
758
if (bc instanceof Visibility) return ((Visibility)bc).needsGui();
759
760
if (bc instanceof Container || bc instanceof Component)
761
return true;
762
}
763
764
synchronized(children) {
765
for (Iterator i = children.keySet().iterator(); i.hasNext();) {
766
Object c = i.next();
767
768
try {
769
return ((Visibility)c).needsGui();
770
} catch (ClassCastException cce) {
771
// do nothing ...
772
}
773
774
if (c instanceof Container || c instanceof Component)
775
return true;
776
}
777
}
778
779
return false;
780
}
781
782
/**
783
* notify this instance that it may no longer render a GUI.
784
*/
785
786
public synchronized void dontUseGui() {
787
if (okToUseGui) {
788
okToUseGui = false;
789
790
// lets also tell the Children that can that they may not use their GUI's
791
synchronized(children) {
792
for (Iterator i = children.keySet().iterator(); i.hasNext();) {
793
Visibility v = getChildVisibility(i.next());
794
795
if (v != null) v.dontUseGui();
796
}
797
}
798
}
799
}
800
801
/**
802
* Notify this instance that it may now render a GUI
803
*/
804
805
public synchronized void okToUseGui() {
806
if (!okToUseGui) {
807
okToUseGui = true;
808
809
// lets also tell the Children that can that they may use their GUI's
810
synchronized(children) {
811
for (Iterator i = children.keySet().iterator(); i.hasNext();) {
812
Visibility v = getChildVisibility(i.next());
813
814
if (v != null) v.okToUseGui();
815
}
816
}
817
}
818
}
819
820
/**
821
* Used to determine if the <tt>BeanContext</tt>
822
* child is avoiding using its GUI.
823
* @return is this instance avoiding using its GUI?
824
* @see Visibility
825
*/
826
public boolean avoidingGui() {
827
return !okToUseGui && needsGui();
828
}
829
830
/**
831
* Is this <tt>BeanContext</tt> in the
832
* process of being serialized?
833
* @return if this <tt>BeanContext</tt> is
834
* currently being serialized
835
*/
836
public boolean isSerializing() { return serializing; }
837
838
/**
839
* Returns an iterator of all children
840
* of this <tt>BeanContext</tt>.
841
* @return an iterator for all the current BCSChild values
842
*/
843
protected Iterator bcsChildren() { synchronized(children) { return children.values().iterator(); } }
844
845
/**
846
* called by writeObject after defaultWriteObject() but prior to
847
* serialization of currently serializable children.
848
*
849
* This method may be overridden by subclasses to perform custom
850
* serialization of their state prior to this superclass serializing
851
* the children.
852
*
853
* This method should not however be used by subclasses to replace their
854
* own implementation (if any) of writeObject().
855
* @param oos the {@code ObjectOutputStream} to use during serialization
856
* @throws IOException if serialization failed
857
*/
858
859
protected void bcsPreSerializationHook(ObjectOutputStream oos) throws IOException {
860
}
861
862
/**
863
* called by readObject after defaultReadObject() but prior to
864
* deserialization of any children.
865
*
866
* This method may be overridden by subclasses to perform custom
867
* deserialization of their state prior to this superclass deserializing
868
* the children.
869
*
870
* This method should not however be used by subclasses to replace their
871
* own implementation (if any) of readObject().
872
* @param ois the {@code ObjectInputStream} to use during deserialization
873
* @throws IOException if deserialization failed
874
* @throws ClassNotFoundException if needed classes are not found
875
*/
876
877
protected void bcsPreDeserializationHook(ObjectInputStream ois) throws IOException, ClassNotFoundException {
878
}
879
880
/**
881
* Called by readObject with the newly deserialized child and BCSChild.
882
* @param child the newly deserialized child
883
* @param bcsc the newly deserialized BCSChild
884
*/
885
protected void childDeserializedHook(Object child, BCSChild bcsc) {
886
synchronized(children) {
887
children.put(child, bcsc);
888
}
889
}
890
891
/**
892
* Used by writeObject to serialize a Collection.
893
* @param oos the <tt>ObjectOutputStream</tt>
894
* to use during serialization
895
* @param coll the <tt>Collection</tt> to serialize
896
* @throws IOException if serialization failed
897
*/
898
protected final void serialize(ObjectOutputStream oos, Collection coll) throws IOException {
899
int count = 0;
900
Object[] objects = coll.toArray();
901
902
for (int i = 0; i < objects.length; i++) {
903
if (objects[i] instanceof Serializable)
904
count++;
905
else
906
objects[i] = null;
907
}
908
909
oos.writeInt(count); // number of subsequent objects
910
911
for (int i = 0; count > 0; i++) {
912
Object o = objects[i];
913
914
if (o != null) {
915
oos.writeObject(o);
916
count--;
917
}
918
}
919
}
920
921
/**
922
* used by readObject to deserialize a collection.
923
* @param ois the ObjectInputStream to use
924
* @param coll the Collection
925
* @throws IOException if deserialization failed
926
* @throws ClassNotFoundException if needed classes are not found
927
*/
928
protected final void deserialize(ObjectInputStream ois, Collection coll) throws IOException, ClassNotFoundException {
929
int count = 0;
930
931
count = ois.readInt();
932
933
while (count-- > 0) {
934
coll.add(ois.readObject());
935
}
936
}
937
938
/**
939
* Used to serialize all children of
940
* this <tt>BeanContext</tt>.
941
* @param oos the <tt>ObjectOutputStream</tt>
942
* to use during serialization
943
* @throws IOException if serialization failed
944
*/
945
public final void writeChildren(ObjectOutputStream oos) throws IOException {
946
if (serializable <= 0) return;
947
948
boolean prev = serializing;
949
950
serializing = true;
951
952
int count = 0;
953
954
synchronized(children) {
955
Iterator i = children.entrySet().iterator();
956
957
while (i.hasNext() && count < serializable) {
958
Map.Entry entry = (Map.Entry)i.next();
959
960
if (entry.getKey() instanceof Serializable) {
961
try {
962
oos.writeObject(entry.getKey()); // child
963
oos.writeObject(entry.getValue()); // BCSChild
964
} catch (IOException ioe) {
965
serializing = prev;
966
throw ioe;
967
}
968
count++;
969
}
970
}
971
}
972
973
serializing = prev;
974
975
if (count != serializable) {
976
throw new IOException("wrote different number of children than expected");
977
}
978
979
}
980
981
/**
982
* Serialize the BeanContextSupport, if this instance has a distinct
983
* peer (that is this object is acting as a delegate for another) then
984
* the children of this instance are not serialized here due to a
985
* 'chicken and egg' problem that occurs on deserialization of the
986
* children at the same time as this instance.
987
*
988
* Therefore in situations where there is a distinct peer to this instance
989
* it should always call writeObject() followed by writeChildren() and
990
* readObject() followed by readChildren().
991
*
992
* @param oos the ObjectOutputStream
993
*/
994
995
private synchronized void writeObject(ObjectOutputStream oos) throws IOException, ClassNotFoundException {
996
serializing = true;
997
998
synchronized (BeanContext.globalHierarchyLock) {
999
try {
1000
oos.defaultWriteObject(); // serialize the BeanContextSupport object
1001
1002
bcsPreSerializationHook(oos);
1003
1004
if (serializable > 0 && this.equals(getBeanContextPeer()))
1005
writeChildren(oos);
1006
1007
serialize(oos, (Collection)bcmListeners);
1008
} finally {
1009
serializing = false;
1010
}
1011
}
1012
}
1013
1014
/**
1015
* When an instance of this class is used as a delegate for the
1016
* implementation of the BeanContext protocols (and its subprotocols)
1017
* there exists a 'chicken and egg' problem during deserialization
1018
* @param ois the ObjectInputStream to use
1019
* @throws IOException if deserialization failed
1020
* @throws ClassNotFoundException if needed classes are not found
1021
*/
1022
1023
public final void readChildren(ObjectInputStream ois) throws IOException, ClassNotFoundException {
1024
int count = serializable;
1025
1026
while (count-- > 0) {
1027
Object child = ois.readObject();
1028
BCSChild bscc = (BCSChild) ois.readObject();
1029
1030
synchronized(child) {
1031
BeanContextChild bcc = null;
1032
1033
try {
1034
bcc = (BeanContextChild)child;
1035
} catch (ClassCastException cce) {
1036
// do nothing;
1037
}
1038
1039
if (bcc != null) {
1040
try {
1041
bcc.setBeanContext(getBeanContextPeer());
1042
1043
bcc.addPropertyChangeListener("beanContext", childPCL);
1044
bcc.addVetoableChangeListener("beanContext", childVCL);
1045
1046
} catch (PropertyVetoException pve) {
1047
continue;
1048
}
1049
}
1050
1051
childDeserializedHook(child, bscc);
1052
}
1053
}
1054
}
1055
1056
/**
1057
* deserialize contents ... if this instance has a distinct peer the
1058
* children are *not* serialized here, the peer's readObject() must call
1059
* readChildren() after deserializing this instance.
1060
*/
1061
1062
private synchronized void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
1063
1064
synchronized(BeanContext.globalHierarchyLock) {
1065
ois.defaultReadObject();
1066
1067
initialize();
1068
1069
bcsPreDeserializationHook(ois);
1070
1071
if (serializable > 0 && this.equals(getBeanContextPeer()))
1072
readChildren(ois);
1073
1074
deserialize(ois, bcmListeners = new ArrayList(1));
1075
}
1076
}
1077
1078
/**
1079
* subclasses may envelope to monitor veto child property changes.
1080
*/
1081
1082
public void vetoableChange(PropertyChangeEvent pce) throws PropertyVetoException {
1083
String propertyName = pce.getPropertyName();
1084
Object source = pce.getSource();
1085
1086
synchronized(children) {
1087
if ("beanContext".equals(propertyName) &&
1088
containsKey(source) &&
1089
!getBeanContextPeer().equals(pce.getNewValue())
1090
) {
1091
if (!validatePendingRemove(source)) {
1092
throw new PropertyVetoException("current BeanContext vetoes setBeanContext()", pce);
1093
} else ((BCSChild)children.get(source)).setRemovePending(true);
1094
}
1095
}
1096
}
1097
1098
/**
1099
* subclasses may envelope to monitor child property changes.
1100
*/
1101
1102
public void propertyChange(PropertyChangeEvent pce) {
1103
String propertyName = pce.getPropertyName();
1104
Object source = pce.getSource();
1105
1106
synchronized(children) {
1107
if ("beanContext".equals(propertyName) &&
1108
containsKey(source) &&
1109
((BCSChild)children.get(source)).isRemovePending()) {
1110
BeanContext bc = getBeanContextPeer();
1111
1112
if (bc.equals(pce.getOldValue()) && !bc.equals(pce.getNewValue())) {
1113
remove(source, false);
1114
} else {
1115
((BCSChild)children.get(source)).setRemovePending(false);
1116
}
1117
}
1118
}
1119
}
1120
1121
/**
1122
* <p>
1123
* Subclasses of this class may override, or envelope, this method to
1124
* add validation behavior for the BeanContext to examine child objects
1125
* immediately prior to their being added to the BeanContext.
1126
* </p>
1127
*
1128
* @param targetChild the child to create the Child on behalf of
1129
* @return true iff the child may be added to this BeanContext, otherwise false.
1130
*/
1131
1132
protected boolean validatePendingAdd(Object targetChild) {
1133
return true;
1134
}
1135
1136
/**
1137
* <p>
1138
* Subclasses of this class may override, or envelope, this method to
1139
* add validation behavior for the BeanContext to examine child objects
1140
* immediately prior to their being removed from the BeanContext.
1141
* </p>
1142
*
1143
* @param targetChild the child to create the Child on behalf of
1144
* @return true iff the child may be removed from this BeanContext, otherwise false.
1145
*/
1146
1147
protected boolean validatePendingRemove(Object targetChild) {
1148
return true;
1149
}
1150
1151
/**
1152
* subclasses may override this method to simply extend add() semantics
1153
* after the child has been added and before the event notification has
1154
* occurred. The method is called with the child synchronized.
1155
* @param child the child
1156
* @param bcsc the BCSChild
1157
*/
1158
1159
protected void childJustAddedHook(Object child, BCSChild bcsc) {
1160
}
1161
1162
/**
1163
* subclasses may override this method to simply extend remove() semantics
1164
* after the child has been removed and before the event notification has
1165
* occurred. The method is called with the child synchronized.
1166
* @param child the child
1167
* @param bcsc the BCSChild
1168
*/
1169
1170
protected void childJustRemovedHook(Object child, BCSChild bcsc) {
1171
}
1172
1173
/**
1174
* Gets the Component (if any) associated with the specified child.
1175
* @param child the specified child
1176
* @return the Component (if any) associated with the specified child.
1177
*/
1178
protected static final Visibility getChildVisibility(Object child) {
1179
try {
1180
return (Visibility)child;
1181
} catch (ClassCastException cce) {
1182
return null;
1183
}
1184
}
1185
1186
/**
1187
* Gets the Serializable (if any) associated with the specified Child
1188
* @param child the specified child
1189
* @return the Serializable (if any) associated with the specified Child
1190
*/
1191
protected static final Serializable getChildSerializable(Object child) {
1192
try {
1193
return (Serializable)child;
1194
} catch (ClassCastException cce) {
1195
return null;
1196
}
1197
}
1198
1199
/**
1200
* Gets the PropertyChangeListener
1201
* (if any) of the specified child
1202
* @param child the specified child
1203
* @return the PropertyChangeListener (if any) of the specified child
1204
*/
1205
protected static final PropertyChangeListener getChildPropertyChangeListener(Object child) {
1206
try {
1207
return (PropertyChangeListener)child;
1208
} catch (ClassCastException cce) {
1209
return null;
1210
}
1211
}
1212
1213
/**
1214
* Gets the VetoableChangeListener
1215
* (if any) of the specified child
1216
* @param child the specified child
1217
* @return the VetoableChangeListener (if any) of the specified child
1218
*/
1219
protected static final VetoableChangeListener getChildVetoableChangeListener(Object child) {
1220
try {
1221
return (VetoableChangeListener)child;
1222
} catch (ClassCastException cce) {
1223
return null;
1224
}
1225
}
1226
1227
/**
1228
* Gets the BeanContextMembershipListener
1229
* (if any) of the specified child
1230
* @param child the specified child
1231
* @return the BeanContextMembershipListener (if any) of the specified child
1232
*/
1233
protected static final BeanContextMembershipListener getChildBeanContextMembershipListener(Object child) {
1234
try {
1235
return (BeanContextMembershipListener)child;
1236
} catch (ClassCastException cce) {
1237
return null;
1238
}
1239
}
1240
1241
/**
1242
* Gets the BeanContextChild (if any) of the specified child
1243
* @param child the specified child
1244
* @return the BeanContextChild (if any) of the specified child
1245
* @throws IllegalArgumentException if child implements both BeanContextChild and BeanContextProxy
1246
*/
1247
protected static final BeanContextChild getChildBeanContextChild(Object child) {
1248
try {
1249
BeanContextChild bcc = (BeanContextChild)child;
1250
1251
if (child instanceof BeanContextChild && child instanceof BeanContextProxy)
1252
throw new IllegalArgumentException("child cannot implement both BeanContextChild and BeanContextProxy");
1253
else
1254
return bcc;
1255
} catch (ClassCastException cce) {
1256
try {
1257
return ((BeanContextProxy)child).getBeanContextProxy();
1258
} catch (ClassCastException cce1) {
1259
return null;
1260
}
1261
}
1262
}
1263
1264
/**
1265
* Fire a BeanContextshipEvent on the BeanContextMembershipListener interface
1266
* @param bcme the event to fire
1267
*/
1268
1269
protected final void fireChildrenAdded(BeanContextMembershipEvent bcme) {
1270
Object[] copy;
1271
1272
synchronized(bcmListeners) { copy = bcmListeners.toArray(); }
1273
1274
for (int i = 0; i < copy.length; i++)
1275
((BeanContextMembershipListener)copy[i]).childrenAdded(bcme);
1276
}
1277
1278
/**
1279
* Fire a BeanContextshipEvent on the BeanContextMembershipListener interface
1280
* @param bcme the event to fire
1281
*/
1282
1283
protected final void fireChildrenRemoved(BeanContextMembershipEvent bcme) {
1284
Object[] copy;
1285
1286
synchronized(bcmListeners) { copy = bcmListeners.toArray(); }
1287
1288
for (int i = 0; i < copy.length; i++)
1289
((BeanContextMembershipListener)copy[i]).childrenRemoved(bcme);
1290
}
1291
1292
/**
1293
* protected method called from constructor and readObject to initialize
1294
* transient state of BeanContextSupport instance.
1295
*
1296
* This class uses this method to instantiate inner class listeners used
1297
* to monitor PropertyChange and VetoableChange events on children.
1298
*
1299
* subclasses may envelope this method to add their own initialization
1300
* behavior
1301
*/
1302
1303
protected synchronized void initialize() {
1304
children = new HashMap(serializable + 1);
1305
bcmListeners = new ArrayList(1);
1306
1307
childPCL = new PropertyChangeListener() {
1308
1309
/*
1310
* this adaptor is used by the BeanContextSupport class to forward
1311
* property changes from a child to the BeanContext, avoiding
1312
* accidential serialization of the BeanContext by a badly
1313
* behaved Serializable child.
1314
*/
1315
1316
public void propertyChange(PropertyChangeEvent pce) {
1317
BeanContextSupport.this.propertyChange(pce);
1318
}
1319
};
1320
1321
childVCL = new VetoableChangeListener() {
1322
1323
/*
1324
* this adaptor is used by the BeanContextSupport class to forward
1325
* vetoable changes from a child to the BeanContext, avoiding
1326
* accidential serialization of the BeanContext by a badly
1327
* behaved Serializable child.
1328
*/
1329
1330
public void vetoableChange(PropertyChangeEvent pce) throws PropertyVetoException {
1331
BeanContextSupport.this.vetoableChange(pce);
1332
}
1333
};
1334
}
1335
1336
/**
1337
* Gets a copy of the this BeanContext's children.
1338
* @return a copy of the current nested children
1339
*/
1340
protected final Object[] copyChildren() {
1341
synchronized(children) { return children.keySet().toArray(); }
1342
}
1343
1344
/**
1345
* Tests to see if two class objects,
1346
* or their names are equal.
1347
* @param first the first object
1348
* @param second the second object
1349
* @return true if equal, false if not
1350
*/
1351
protected static final boolean classEquals(Class first, Class second) {
1352
return first.equals(second) || first.getName().equals(second.getName());
1353
}
1354
1355
1356
/*
1357
* fields
1358
*/
1359
1360
1361
/**
1362
* all accesses to the <code> protected HashMap children </code> field
1363
* shall be synchronized on that object.
1364
*/
1365
protected transient HashMap children;
1366
1367
private int serializable = 0; // children serializable
1368
1369
/**
1370
* all accesses to the <code> protected ArrayList bcmListeners </code> field
1371
* shall be synchronized on that object.
1372
*/
1373
protected transient ArrayList bcmListeners;
1374
1375
//
1376
1377
/**
1378
* The current locale of this BeanContext.
1379
*/
1380
protected Locale locale;
1381
1382
/**
1383
* A <tt>boolean</tt> indicating if this
1384
* instance may now render a GUI.
1385
*/
1386
protected boolean okToUseGui;
1387
1388
1389
/**
1390
* A <tt>boolean</tt> indicating whether or not
1391
* this object is currently in design time mode.
1392
*/
1393
protected boolean designTime;
1394
1395
/*
1396
* transient
1397
*/
1398
1399
private transient PropertyChangeListener childPCL;
1400
1401
private transient VetoableChangeListener childVCL;
1402
1403
private transient boolean serializing;
1404
}
1405
1406