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