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/EventSetDescriptor.java
38829 views
1
/*
2
* Copyright (c) 1996, 2012, 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;
27
28
import java.lang.ref.Reference;
29
import java.lang.reflect.Method;
30
import java.lang.reflect.Modifier;
31
32
/**
33
* An EventSetDescriptor describes a group of events that a given Java
34
* bean fires.
35
* <P>
36
* The given group of events are all delivered as method calls on a single
37
* event listener interface, and an event listener object can be registered
38
* via a call on a registration method supplied by the event source.
39
*/
40
public class EventSetDescriptor extends FeatureDescriptor {
41
42
private MethodDescriptor[] listenerMethodDescriptors;
43
private MethodDescriptor addMethodDescriptor;
44
private MethodDescriptor removeMethodDescriptor;
45
private MethodDescriptor getMethodDescriptor;
46
47
private Reference<Method[]> listenerMethodsRef;
48
private Reference<? extends Class<?>> listenerTypeRef;
49
50
private boolean unicast;
51
private boolean inDefaultEventSet = true;
52
53
/**
54
* Creates an <TT>EventSetDescriptor</TT> assuming that you are
55
* following the most simple standard design pattern where a named
56
* event &quot;fred&quot; is (1) delivered as a call on the single method of
57
* interface FredListener, (2) has a single argument of type FredEvent,
58
* and (3) where the FredListener may be registered with a call on an
59
* addFredListener method of the source component and removed with a
60
* call on a removeFredListener method.
61
*
62
* @param sourceClass The class firing the event.
63
* @param eventSetName The programmatic name of the event. E.g. &quot;fred&quot;.
64
* Note that this should normally start with a lower-case character.
65
* @param listenerType The target interface that events
66
* will get delivered to.
67
* @param listenerMethodName The method that will get called when the event gets
68
* delivered to its target listener interface.
69
* @exception IntrospectionException if an exception occurs during
70
* introspection.
71
*/
72
public EventSetDescriptor(Class<?> sourceClass, String eventSetName,
73
Class<?> listenerType, String listenerMethodName)
74
throws IntrospectionException {
75
this(sourceClass, eventSetName, listenerType,
76
new String[] { listenerMethodName },
77
Introspector.ADD_PREFIX + getListenerClassName(listenerType),
78
Introspector.REMOVE_PREFIX + getListenerClassName(listenerType),
79
Introspector.GET_PREFIX + getListenerClassName(listenerType) + "s");
80
81
String eventName = NameGenerator.capitalize(eventSetName) + "Event";
82
Method[] listenerMethods = getListenerMethods();
83
if (listenerMethods.length > 0) {
84
Class[] args = getParameterTypes(getClass0(), listenerMethods[0]);
85
// Check for EventSet compliance. Special case for vetoableChange. See 4529996
86
if (!"vetoableChange".equals(eventSetName) && !args[0].getName().endsWith(eventName)) {
87
throw new IntrospectionException("Method \"" + listenerMethodName +
88
"\" should have argument \"" +
89
eventName + "\"");
90
}
91
}
92
}
93
94
private static String getListenerClassName(Class<?> cls) {
95
String className = cls.getName();
96
return className.substring(className.lastIndexOf('.') + 1);
97
}
98
99
/**
100
* Creates an <TT>EventSetDescriptor</TT> from scratch using
101
* string names.
102
*
103
* @param sourceClass The class firing the event.
104
* @param eventSetName The programmatic name of the event set.
105
* Note that this should normally start with a lower-case character.
106
* @param listenerType The Class of the target interface that events
107
* will get delivered to.
108
* @param listenerMethodNames The names of the methods that will get called
109
* when the event gets delivered to its target listener interface.
110
* @param addListenerMethodName The name of the method on the event source
111
* that can be used to register an event listener object.
112
* @param removeListenerMethodName The name of the method on the event source
113
* that can be used to de-register an event listener object.
114
* @exception IntrospectionException if an exception occurs during
115
* introspection.
116
*/
117
public EventSetDescriptor(Class<?> sourceClass,
118
String eventSetName,
119
Class<?> listenerType,
120
String listenerMethodNames[],
121
String addListenerMethodName,
122
String removeListenerMethodName)
123
throws IntrospectionException {
124
this(sourceClass, eventSetName, listenerType,
125
listenerMethodNames, addListenerMethodName,
126
removeListenerMethodName, null);
127
}
128
129
/**
130
* This constructor creates an EventSetDescriptor from scratch using
131
* string names.
132
*
133
* @param sourceClass The class firing the event.
134
* @param eventSetName The programmatic name of the event set.
135
* Note that this should normally start with a lower-case character.
136
* @param listenerType The Class of the target interface that events
137
* will get delivered to.
138
* @param listenerMethodNames The names of the methods that will get called
139
* when the event gets delivered to its target listener interface.
140
* @param addListenerMethodName The name of the method on the event source
141
* that can be used to register an event listener object.
142
* @param removeListenerMethodName The name of the method on the event source
143
* that can be used to de-register an event listener object.
144
* @param getListenerMethodName The method on the event source that
145
* can be used to access the array of event listener objects.
146
* @exception IntrospectionException if an exception occurs during
147
* introspection.
148
* @since 1.4
149
*/
150
public EventSetDescriptor(Class<?> sourceClass,
151
String eventSetName,
152
Class<?> listenerType,
153
String listenerMethodNames[],
154
String addListenerMethodName,
155
String removeListenerMethodName,
156
String getListenerMethodName)
157
throws IntrospectionException {
158
if (sourceClass == null || eventSetName == null || listenerType == null) {
159
throw new NullPointerException();
160
}
161
setName(eventSetName);
162
setClass0(sourceClass);
163
setListenerType(listenerType);
164
165
Method[] listenerMethods = new Method[listenerMethodNames.length];
166
for (int i = 0; i < listenerMethodNames.length; i++) {
167
// Check for null names
168
if (listenerMethodNames[i] == null) {
169
throw new NullPointerException();
170
}
171
listenerMethods[i] = getMethod(listenerType, listenerMethodNames[i], 1);
172
}
173
setListenerMethods(listenerMethods);
174
175
setAddListenerMethod(getMethod(sourceClass, addListenerMethodName, 1));
176
setRemoveListenerMethod(getMethod(sourceClass, removeListenerMethodName, 1));
177
178
// Be more forgiving of not finding the getListener method.
179
Method method = Introspector.findMethod(sourceClass, getListenerMethodName, 0);
180
if (method != null) {
181
setGetListenerMethod(method);
182
}
183
}
184
185
private static Method getMethod(Class<?> cls, String name, int args)
186
throws IntrospectionException {
187
if (name == null) {
188
return null;
189
}
190
Method method = Introspector.findMethod(cls, name, args);
191
if ((method == null) || Modifier.isStatic(method.getModifiers())) {
192
throw new IntrospectionException("Method not found: " + name +
193
" on class " + cls.getName());
194
}
195
return method;
196
}
197
198
/**
199
* Creates an <TT>EventSetDescriptor</TT> from scratch using
200
* <TT>java.lang.reflect.Method</TT> and <TT>java.lang.Class</TT> objects.
201
*
202
* @param eventSetName The programmatic name of the event set.
203
* @param listenerType The Class for the listener interface.
204
* @param listenerMethods An array of Method objects describing each
205
* of the event handling methods in the target listener.
206
* @param addListenerMethod The method on the event source
207
* that can be used to register an event listener object.
208
* @param removeListenerMethod The method on the event source
209
* that can be used to de-register an event listener object.
210
* @exception IntrospectionException if an exception occurs during
211
* introspection.
212
*/
213
public EventSetDescriptor(String eventSetName,
214
Class<?> listenerType,
215
Method listenerMethods[],
216
Method addListenerMethod,
217
Method removeListenerMethod)
218
throws IntrospectionException {
219
this(eventSetName, listenerType, listenerMethods,
220
addListenerMethod, removeListenerMethod, null);
221
}
222
223
/**
224
* This constructor creates an EventSetDescriptor from scratch using
225
* java.lang.reflect.Method and java.lang.Class objects.
226
*
227
* @param eventSetName The programmatic name of the event set.
228
* @param listenerType The Class for the listener interface.
229
* @param listenerMethods An array of Method objects describing each
230
* of the event handling methods in the target listener.
231
* @param addListenerMethod The method on the event source
232
* that can be used to register an event listener object.
233
* @param removeListenerMethod The method on the event source
234
* that can be used to de-register an event listener object.
235
* @param getListenerMethod The method on the event source
236
* that can be used to access the array of event listener objects.
237
* @exception IntrospectionException if an exception occurs during
238
* introspection.
239
* @since 1.4
240
*/
241
public EventSetDescriptor(String eventSetName,
242
Class<?> listenerType,
243
Method listenerMethods[],
244
Method addListenerMethod,
245
Method removeListenerMethod,
246
Method getListenerMethod)
247
throws IntrospectionException {
248
setName(eventSetName);
249
setListenerMethods(listenerMethods);
250
setAddListenerMethod(addListenerMethod);
251
setRemoveListenerMethod( removeListenerMethod);
252
setGetListenerMethod(getListenerMethod);
253
setListenerType(listenerType);
254
}
255
256
/**
257
* Creates an <TT>EventSetDescriptor</TT> from scratch using
258
* <TT>java.lang.reflect.MethodDescriptor</TT> and <TT>java.lang.Class</TT>
259
* objects.
260
*
261
* @param eventSetName The programmatic name of the event set.
262
* @param listenerType The Class for the listener interface.
263
* @param listenerMethodDescriptors An array of MethodDescriptor objects
264
* describing each of the event handling methods in the
265
* target listener.
266
* @param addListenerMethod The method on the event source
267
* that can be used to register an event listener object.
268
* @param removeListenerMethod The method on the event source
269
* that can be used to de-register an event listener object.
270
* @exception IntrospectionException if an exception occurs during
271
* introspection.
272
*/
273
public EventSetDescriptor(String eventSetName,
274
Class<?> listenerType,
275
MethodDescriptor listenerMethodDescriptors[],
276
Method addListenerMethod,
277
Method removeListenerMethod)
278
throws IntrospectionException {
279
setName(eventSetName);
280
this.listenerMethodDescriptors = (listenerMethodDescriptors != null)
281
? listenerMethodDescriptors.clone()
282
: null;
283
setAddListenerMethod(addListenerMethod);
284
setRemoveListenerMethod(removeListenerMethod);
285
setListenerType(listenerType);
286
}
287
288
/**
289
* Gets the <TT>Class</TT> object for the target interface.
290
*
291
* @return The Class object for the target interface that will
292
* get invoked when the event is fired.
293
*/
294
public Class<?> getListenerType() {
295
return (this.listenerTypeRef != null)
296
? this.listenerTypeRef.get()
297
: null;
298
}
299
300
private void setListenerType(Class<?> cls) {
301
this.listenerTypeRef = getWeakReference(cls);
302
}
303
304
/**
305
* Gets the methods of the target listener interface.
306
*
307
* @return An array of <TT>Method</TT> objects for the target methods
308
* within the target listener interface that will get called when
309
* events are fired.
310
*/
311
public synchronized Method[] getListenerMethods() {
312
Method[] methods = getListenerMethods0();
313
if (methods == null) {
314
if (listenerMethodDescriptors != null) {
315
methods = new Method[listenerMethodDescriptors.length];
316
for (int i = 0; i < methods.length; i++) {
317
methods[i] = listenerMethodDescriptors[i].getMethod();
318
}
319
}
320
setListenerMethods(methods);
321
}
322
return methods;
323
}
324
325
private void setListenerMethods(Method[] methods) {
326
if (methods == null) {
327
return;
328
}
329
if (listenerMethodDescriptors == null) {
330
listenerMethodDescriptors = new MethodDescriptor[methods.length];
331
for (int i = 0; i < methods.length; i++) {
332
listenerMethodDescriptors[i] = new MethodDescriptor(methods[i]);
333
}
334
}
335
this.listenerMethodsRef = getSoftReference(methods);
336
}
337
338
private Method[] getListenerMethods0() {
339
return (this.listenerMethodsRef != null)
340
? this.listenerMethodsRef.get()
341
: null;
342
}
343
344
/**
345
* Gets the <code>MethodDescriptor</code>s of the target listener interface.
346
*
347
* @return An array of <code>MethodDescriptor</code> objects for the target methods
348
* within the target listener interface that will get called when
349
* events are fired.
350
*/
351
public synchronized MethodDescriptor[] getListenerMethodDescriptors() {
352
return (this.listenerMethodDescriptors != null)
353
? this.listenerMethodDescriptors.clone()
354
: null;
355
}
356
357
/**
358
* Gets the method used to add event listeners.
359
*
360
* @return The method used to register a listener at the event source.
361
*/
362
public synchronized Method getAddListenerMethod() {
363
return getMethod(this.addMethodDescriptor);
364
}
365
366
private synchronized void setAddListenerMethod(Method method) {
367
if (method == null) {
368
return;
369
}
370
if (getClass0() == null) {
371
setClass0(method.getDeclaringClass());
372
}
373
addMethodDescriptor = new MethodDescriptor(method);
374
setTransient(method.getAnnotation(Transient.class));
375
}
376
377
/**
378
* Gets the method used to remove event listeners.
379
*
380
* @return The method used to remove a listener at the event source.
381
*/
382
public synchronized Method getRemoveListenerMethod() {
383
return getMethod(this.removeMethodDescriptor);
384
}
385
386
private synchronized void setRemoveListenerMethod(Method method) {
387
if (method == null) {
388
return;
389
}
390
if (getClass0() == null) {
391
setClass0(method.getDeclaringClass());
392
}
393
removeMethodDescriptor = new MethodDescriptor(method);
394
setTransient(method.getAnnotation(Transient.class));
395
}
396
397
/**
398
* Gets the method used to access the registered event listeners.
399
*
400
* @return The method used to access the array of listeners at the event
401
* source or null if it doesn't exist.
402
* @since 1.4
403
*/
404
public synchronized Method getGetListenerMethod() {
405
return getMethod(this.getMethodDescriptor);
406
}
407
408
private synchronized void setGetListenerMethod(Method method) {
409
if (method == null) {
410
return;
411
}
412
if (getClass0() == null) {
413
setClass0(method.getDeclaringClass());
414
}
415
getMethodDescriptor = new MethodDescriptor(method);
416
setTransient(method.getAnnotation(Transient.class));
417
}
418
419
/**
420
* Mark an event set as unicast (or not).
421
*
422
* @param unicast True if the event set is unicast.
423
*/
424
public void setUnicast(boolean unicast) {
425
this.unicast = unicast;
426
}
427
428
/**
429
* Normally event sources are multicast. However there are some
430
* exceptions that are strictly unicast.
431
*
432
* @return <TT>true</TT> if the event set is unicast.
433
* Defaults to <TT>false</TT>.
434
*/
435
public boolean isUnicast() {
436
return unicast;
437
}
438
439
/**
440
* Marks an event set as being in the &quot;default&quot; set (or not).
441
* By default this is <TT>true</TT>.
442
*
443
* @param inDefaultEventSet <code>true</code> if the event set is in
444
* the &quot;default&quot; set,
445
* <code>false</code> if not
446
*/
447
public void setInDefaultEventSet(boolean inDefaultEventSet) {
448
this.inDefaultEventSet = inDefaultEventSet;
449
}
450
451
/**
452
* Reports if an event set is in the &quot;default&quot; set.
453
*
454
* @return <TT>true</TT> if the event set is in
455
* the &quot;default&quot; set. Defaults to <TT>true</TT>.
456
*/
457
public boolean isInDefaultEventSet() {
458
return inDefaultEventSet;
459
}
460
461
/*
462
* Package-private constructor
463
* Merge two event set descriptors. Where they conflict, give the
464
* second argument (y) priority over the first argument (x).
465
*
466
* @param x The first (lower priority) EventSetDescriptor
467
* @param y The second (higher priority) EventSetDescriptor
468
*/
469
EventSetDescriptor(EventSetDescriptor x, EventSetDescriptor y) {
470
super(x,y);
471
listenerMethodDescriptors = x.listenerMethodDescriptors;
472
if (y.listenerMethodDescriptors != null) {
473
listenerMethodDescriptors = y.listenerMethodDescriptors;
474
}
475
476
listenerTypeRef = x.listenerTypeRef;
477
if (y.listenerTypeRef != null) {
478
listenerTypeRef = y.listenerTypeRef;
479
}
480
481
addMethodDescriptor = x.addMethodDescriptor;
482
if (y.addMethodDescriptor != null) {
483
addMethodDescriptor = y.addMethodDescriptor;
484
}
485
486
removeMethodDescriptor = x.removeMethodDescriptor;
487
if (y.removeMethodDescriptor != null) {
488
removeMethodDescriptor = y.removeMethodDescriptor;
489
}
490
491
getMethodDescriptor = x.getMethodDescriptor;
492
if (y.getMethodDescriptor != null) {
493
getMethodDescriptor = y.getMethodDescriptor;
494
}
495
496
unicast = y.unicast;
497
if (!x.inDefaultEventSet || !y.inDefaultEventSet) {
498
inDefaultEventSet = false;
499
}
500
}
501
502
/*
503
* Package-private dup constructor
504
* This must isolate the new object from any changes to the old object.
505
*/
506
EventSetDescriptor(EventSetDescriptor old) {
507
super(old);
508
if (old.listenerMethodDescriptors != null) {
509
int len = old.listenerMethodDescriptors.length;
510
listenerMethodDescriptors = new MethodDescriptor[len];
511
for (int i = 0; i < len; i++) {
512
listenerMethodDescriptors[i] = new MethodDescriptor(
513
old.listenerMethodDescriptors[i]);
514
}
515
}
516
listenerTypeRef = old.listenerTypeRef;
517
518
addMethodDescriptor = old.addMethodDescriptor;
519
removeMethodDescriptor = old.removeMethodDescriptor;
520
getMethodDescriptor = old.getMethodDescriptor;
521
522
unicast = old.unicast;
523
inDefaultEventSet = old.inDefaultEventSet;
524
}
525
526
void appendTo(StringBuilder sb) {
527
appendTo(sb, "unicast", this.unicast);
528
appendTo(sb, "inDefaultEventSet", this.inDefaultEventSet);
529
appendTo(sb, "listenerType", this.listenerTypeRef);
530
appendTo(sb, "getListenerMethod", getMethod(this.getMethodDescriptor));
531
appendTo(sb, "addListenerMethod", getMethod(this.addMethodDescriptor));
532
appendTo(sb, "removeListenerMethod", getMethod(this.removeMethodDescriptor));
533
}
534
535
private static Method getMethod(MethodDescriptor descriptor) {
536
return (descriptor != null)
537
? descriptor.getMethod()
538
: null;
539
}
540
}
541
542