History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/java/beans/EventSetDescriptor.java (1 of 18352 files). Show all

Unified · Split

java/pkg/java/beans/EventSetDescriptor.java+536−0
@@ -0,0 +1,536 @@
1/*
2 * Copyright (c) 1996, 2010, 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
26package java.beans;
27
28import java.lang.ref.Reference;
29import java.lang.reflect.Method;
30import 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 */
40public 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<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;
281 setAddListenerMethod(addListenerMethod);
282 setRemoveListenerMethod(removeListenerMethod);
283 setListenerType(listenerType);
284 }
285
286 /**
287 * Gets the <TT>Class</TT> object for the target interface.
288 *
289 * @return The Class object for the target interface that will
290 * get invoked when the event is fired.
291 */
292 public Class<?> getListenerType() {
293 return (this.listenerTypeRef != null)
294 ? this.listenerTypeRef.get()
295 : null;
296 }
297
298 private void setListenerType(Class cls) {
299 this.listenerTypeRef = getWeakReference(cls);
300 }
301
302 /**
303 * Gets the methods of the target listener interface.
304 *
305 * @return An array of <TT>Method</TT> objects for the target methods
306 * within the target listener interface that will get called when
307 * events are fired.
308 */
309 public synchronized Method[] getListenerMethods() {
310 Method[] methods = getListenerMethods0();
311 if (methods == null) {
312 if (listenerMethodDescriptors != null) {
313 methods = new Method[listenerMethodDescriptors.length];
314 for (int i = 0; i < methods.length; i++) {
315 methods[i] = listenerMethodDescriptors[i].getMethod();
316 }
317 }
318 setListenerMethods(methods);
319 }
320 return methods;
321 }
322
323 private void setListenerMethods(Method[] methods) {
324 if (methods == null) {
325 return;
326 }
327 if (listenerMethodDescriptors == null) {
328 listenerMethodDescriptors = new MethodDescriptor[methods.length];
329 for (int i = 0; i < methods.length; i++) {
330 listenerMethodDescriptors[i] = new MethodDescriptor(methods[i]);
331 }
332 }
333 this.listenerMethodsRef = getSoftReference(methods);
334 }
335
336 private Method[] getListenerMethods0() {
337 return (this.listenerMethodsRef != null)
338 ? this.listenerMethodsRef.get()
339 : null;
340 }
341
342 /**
343 * Gets the <code>MethodDescriptor</code>s of the target listener interface.
344 *
345 * @return An array of <code>MethodDescriptor</code> objects for the target methods
346 * within the target listener interface that will get called when
347 * events are fired.
348 */
349 public synchronized MethodDescriptor[] getListenerMethodDescriptors() {
350 return listenerMethodDescriptors;
351 }
352
353 /**
354 * Gets the method used to add event listeners.
355 *
356 * @return The method used to register a listener at the event source.
357 */
358 public synchronized Method getAddListenerMethod() {
359 return getMethod(this.addMethodDescriptor);
360 }
361
362 private synchronized void setAddListenerMethod(Method method) {
363 if (method == null) {
364 return;
365 }
366 if (getClass0() == null) {
367 setClass0(method.getDeclaringClass());
368 }
369 addMethodDescriptor = new MethodDescriptor(method);
370 setTransient(method.getAnnotation(Transient.class));
371 }
372
373 /**
374 * Gets the method used to remove event listeners.
375 *
376 * @return The method used to remove a listener at the event source.
377 */
378 public synchronized Method getRemoveListenerMethod() {
379 return getMethod(this.removeMethodDescriptor);
380 }
381
382 private synchronized void setRemoveListenerMethod(Method method) {
383 if (method == null) {
384 return;
385 }
386 if (getClass0() == null) {
387 setClass0(method.getDeclaringClass());
388 }
389 removeMethodDescriptor = new MethodDescriptor(method);
390 setTransient(method.getAnnotation(Transient.class));
391 }
392
393 /**
394 * Gets the method used to access the registered event listeners.
395 *
396 * @return The method used to access the array of listeners at the event
397 * source or null if it doesn't exist.
398 * @since 1.4
399 */
400 public synchronized Method getGetListenerMethod() {
401 return getMethod(this.getMethodDescriptor);
402 }
403
404 private synchronized void setGetListenerMethod(Method method) {
405 if (method == null) {
406 return;
407 }
408 if (getClass0() == null) {
409 setClass0(method.getDeclaringClass());
410 }
411 getMethodDescriptor = new MethodDescriptor(method);
412 setTransient(method.getAnnotation(Transient.class));
413 }
414
415 /**
416 * Mark an event set as unicast (or not).
417 *
418 * @param unicast True if the event set is unicast.
419 */
420 public void setUnicast(boolean unicast) {
421 this.unicast = unicast;
422 }
423
424 /**
425 * Normally event sources are multicast. However there are some
426 * exceptions that are strictly unicast.
427 *
428 * @return <TT>true</TT> if the event set is unicast.
429 * Defaults to <TT>false</TT>.
430 */
431 public boolean isUnicast() {
432 return unicast;
433 }
434
435 /**
436 * Marks an event set as being in the &quot;default&quot; set (or not).
437 * By default this is <TT>true</TT>.
438 *
439 * @param inDefaultEventSet <code>true</code> if the event set is in
440 * the &quot;default&quot; set,
441 * <code>false</code> if not
442 */
443 public void setInDefaultEventSet(boolean inDefaultEventSet) {
444 this.inDefaultEventSet = inDefaultEventSet;
445 }
446
447 /**
448 * Reports if an event set is in the &quot;default&quot; set.
449 *
450 * @return <TT>true</TT> if the event set is in
451 * the &quot;default&quot; set. Defaults to <TT>true</TT>.
452 */
453 public boolean isInDefaultEventSet() {
454 return inDefaultEventSet;
455 }
456
457 /*
458 * Package-private constructor
459 * Merge two event set descriptors. Where they conflict, give the
460 * second argument (y) priority over the first argument (x).
461 *
462 * @param x The first (lower priority) EventSetDescriptor
463 * @param y The second (higher priority) EventSetDescriptor
464 */
465 EventSetDescriptor(EventSetDescriptor x, EventSetDescriptor y) {
466 super(x,y);
467 listenerMethodDescriptors = x.listenerMethodDescriptors;
468 if (y.listenerMethodDescriptors != null) {
469 listenerMethodDescriptors = y.listenerMethodDescriptors;
470 }
471
472 listenerTypeRef = x.listenerTypeRef;
473 if (y.listenerTypeRef != null) {
474 listenerTypeRef = y.listenerTypeRef;
475 }
476
477 addMethodDescriptor = x.addMethodDescriptor;
478 if (y.addMethodDescriptor != null) {
479 addMethodDescriptor = y.addMethodDescriptor;
480 }
481
482 removeMethodDescriptor = x.removeMethodDescriptor;
483 if (y.removeMethodDescriptor != null) {
484 removeMethodDescriptor = y.removeMethodDescriptor;
485 }
486
487 getMethodDescriptor = x.getMethodDescriptor;
488 if (y.getMethodDescriptor != null) {
489 getMethodDescriptor = y.getMethodDescriptor;
490 }
491
492 unicast = y.unicast;
493 if (!x.inDefaultEventSet || !y.inDefaultEventSet) {
494 inDefaultEventSet = false;
495 }
496 }
497
498 /*
499 * Package-private dup constructor
500 * This must isolate the new object from any changes to the old object.
501 */
502 EventSetDescriptor(EventSetDescriptor old) {
503 super(old);
504 if (old.listenerMethodDescriptors != null) {
505 int len = old.listenerMethodDescriptors.length;
506 listenerMethodDescriptors = new MethodDescriptor[len];
507 for (int i = 0; i < len; i++) {
508 listenerMethodDescriptors[i] = new MethodDescriptor(
509 old.listenerMethodDescriptors[i]);
510 }
511 }
512 listenerTypeRef = old.listenerTypeRef;
513
514 addMethodDescriptor = old.addMethodDescriptor;
515 removeMethodDescriptor = old.removeMethodDescriptor;
516 getMethodDescriptor = old.getMethodDescriptor;
517
518 unicast = old.unicast;
519 inDefaultEventSet = old.inDefaultEventSet;
520 }
521
522 void appendTo(StringBuilder sb) {
523 appendTo(sb, "unicast", this.unicast);
524 appendTo(sb, "inDefaultEventSet", this.inDefaultEventSet);
525 appendTo(sb, "listenerType", this.listenerTypeRef);
526 appendTo(sb, "getListenerMethod", getMethod(this.getMethodDescriptor));
527 appendTo(sb, "addListenerMethod", getMethod(this.addMethodDescriptor));
528 appendTo(sb, "removeListenerMethod", getMethod(this.removeMethodDescriptor));
529 }
530
531 private static Method getMethod(MethodDescriptor descriptor) {
532 return (descriptor != null)
533 ? descriptor.getMethod()
534 : null;
535 }
536}