OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libjava/] [classpath/] [java/] [beans/] [EventSetDescriptor.java] - Blame information for rev 14

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jlechner
/* java.beans.EventSetDescriptor
2
   Copyright (C) 1998 Free Software Foundation, Inc.
3
 
4
This file is part of GNU Classpath.
5
 
6
GNU Classpath is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2, or (at your option)
9
any later version.
10
 
11
GNU Classpath is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GNU Classpath; see the file COPYING.  If not, write to the
18
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
02110-1301 USA.
20
 
21
Linking this library statically or dynamically with other modules is
22
making a combined work based on this library.  Thus, the terms and
23
conditions of the GNU General Public License cover the whole
24
combination.
25
 
26
As a special exception, the copyright holders of this library give you
27
permission to link this library with independent modules to produce an
28
executable, regardless of the license terms of these independent
29
modules, and to copy and distribute the resulting executable under
30
terms of your choice, provided that you also meet, for each linked
31
independent module, the terms and conditions of the license of that
32
module.  An independent module is a module which is not derived from
33
or based on this library.  If you modify this library, you may extend
34
this exception to your version of the library, but you are not
35
obligated to do so.  If you do not wish to do so, delete this
36
exception statement from your version. */
37
 
38
 
39
package java.beans;
40
 
41
import gnu.java.lang.ClassHelper;
42
 
43
import java.lang.reflect.Method;
44
import java.lang.reflect.Modifier;
45
import java.util.Vector;
46
 
47
/**
48
 ** EventSetDescriptor describes the hookup between an event source
49
 ** class and an event listener class.
50
 **
51
 ** EventSets have several attributes: the listener class, the events
52
 ** that can be fired to the listener (methods in the listener class), and
53
 ** an add and remove listener method from the event firer's class.<P>
54
 **
55
 ** The methods have these constraints on them:<P>
56
 ** <UL>
57
 ** <LI>event firing methods: must have <CODE>void</CODE> return value.  Any
58
 ** parameters and exceptions are allowed.  May be public, protected or
59
 ** package-protected. (Don't ask me why that is, I'm just following the spec.
60
 ** The only place it is even mentioned is in the Java Beans white paper, and
61
 ** there it is only implied.)</LI>
62
 ** <LI>add listener method: must have <CODE>void</CODE> return value.  Must
63
 ** take exactly one argument, of the listener class's type.  May fire either
64
 ** zero exceptions, or one exception of type <CODE>java.util.TooManyListenersException</CODE>.
65
 ** Must be public.</LI>
66
 ** <LI>remove listener method: must have <CODE>void</CODE> return value.
67
 ** Must take exactly one argument, of the listener class's type.  May not
68
 ** fire any exceptions.  Must be public.</LI>
69
 ** </UL>
70
 **
71
 ** A final constraint is that event listener classes must extend from EventListener.<P>
72
 **
73
 ** There are also various design patterns associated with some of the methods
74
 ** of construction. Those are explained in more detail in the appropriate
75
 ** constructors.<P>
76
 **
77
 ** <STRONG>Documentation Convention:</STRONG> for proper
78
 ** Internalization of Beans inside an RAD tool, sometimes there
79
 ** are two names for a property or method: a programmatic, or
80
 ** locale-independent name, which can be used anywhere, and a
81
 ** localized, display name, for ease of use.  In the
82
 ** documentation I will specify different String values as
83
 ** either <EM>programmatic</EM> or <EM>localized</EM> to
84
 ** make this distinction clear.
85
 **
86
 ** @author John Keiser
87
 ** @since JDK1.1
88
 ** @version 1.1.0, 31 May 1998
89
 **/
90
 
91
public class EventSetDescriptor extends FeatureDescriptor {
92
        private Method addListenerMethod;
93
        private Method removeListenerMethod;
94
        private Class listenerType;
95
        private MethodDescriptor[] listenerMethodDescriptors;
96
        private Method[] listenerMethods;
97
 
98
        private boolean unicast;
99
        private boolean inDefaultEventSet = true;
100
 
101
        /** Create a new EventSetDescriptor.
102
         ** This version of the constructor enforces the rules imposed on the methods
103
         ** described at the top of this class, as well as searching for:<P>
104
         ** <OL>
105
         ** <LI>The event-firing method must be non-private with signature
106
         ** <CODE>void &lt;listenerMethodName&gt;(&lt;eventSetName&gt;Event)</CODE>
107
         ** (where <CODE>&lt;eventSetName&gt;</CODE> has its first character capitalized
108
         ** by the constructor and the Event is a descendant of
109
         ** <CODE>java.util.EventObject</CODE>) in class <CODE>listenerType</CODE>
110
         ** (any exceptions may be thrown).
111
         ** <B>Implementation note:</B> Note that there could conceivably be multiple
112
         ** methods with this type of signature (example: java.util.MouseEvent vs.
113
         ** my.very.own.MouseEvent).  In this implementation, all methods fitting the
114
         ** description will be put into the <CODE>EventSetDescriptor</CODE>, even
115
         ** though the spec says only one should be chosen (they probably weren't thinking as
116
         ** pathologically as I was).  I don't like arbitrarily choosing things.
117
         ** If your class has only one such signature, as most do, you'll have no problems.</LI>
118
         ** <LI>The add and remove methods must be public and named
119
         ** <CODE>void add&lt;eventSetName&gt;Listener(&lt;listenerType&gt;)</CODE> and
120
         ** <CODE>void remove&lt;eventSetName&gt;Listener(&lt;listenerType&gt;)</CODE> in
121
         ** in class <CODE>eventSourceClass</CODE>, where
122
         ** <CODE>&lt;eventSetName&gt;</CODE> will have its first letter capitalized.
123
         ** Standard exception rules (see class description) apply.</LI>
124
         ** </OL>
125
         ** @param eventSourceClass the class containing the add/remove listener methods.
126
         ** @param eventSetName the programmatic name of the event set, generally starting
127
         ** with a lowercase letter (i.e. fooManChu instead of FooManChu).  This will be used
128
         ** to generate the name of the event object as well as the names of the add and
129
         ** remove methods.
130
         ** @param listenerType the class containing the event firing method.
131
         ** @param listenerMethodName the name of the event firing method.
132
         ** @exception IntrospectionException if listenerType is not an EventListener,
133
         **                                   or if methods are not found or are invalid.
134
         **/
135
        public EventSetDescriptor(Class  eventSourceClass,
136
                                  String eventSetName,
137
                                  Class  listenerType,
138
                                  String listenerMethodName) throws IntrospectionException {
139
                setName(eventSetName);
140
                if(!java.util.EventListener.class.isAssignableFrom(listenerType)) {
141
                        throw new IntrospectionException("Listener type is not an EventListener.");
142
                }
143
 
144
                String[] names = new String[1];
145
                names[0] = listenerMethodName;
146
 
147
                try {
148
                        eventSetName = Character.toUpperCase(eventSetName.charAt(0)) + eventSetName.substring(1);
149
                } catch(StringIndexOutOfBoundsException e) {
150
                        eventSetName = "";
151
                }
152
 
153
                findMethods(eventSourceClass,listenerType,names,"add"+eventSetName+"Listener","remove"+eventSetName+"Listener",eventSetName+"Event");
154
                this.listenerType = listenerType;
155
                checkAddListenerUnicast();
156
                if(this.removeListenerMethod.getExceptionTypes().length > 0) {
157
                        throw new IntrospectionException("Listener remove method throws exceptions.");
158
                }
159
        }
160
 
161
        /** Create a new EventSetDescriptor.
162
         ** This form of the constructor allows you to specify the names of the methods and adds
163
         ** no new constraints on top of the rules already described at the top of the class.<P>
164
         **
165
         ** @param eventSourceClass the class containing the add and remove listener methods.
166
         ** @param eventSetName the programmatic name of the event set, generally starting
167
         ** with a lowercase letter (i.e. fooManChu instead of FooManChu).
168
         ** @param listenerType the class containing the event firing methods.
169
         ** @param listenerMethodNames the names of the even firing methods.
170
         ** @param addListenerMethodName the name of the add listener method.
171
         ** @param removeListenerMethodName the name of the remove listener method.
172
         ** @exception IntrospectionException if listenerType is not an EventListener
173
         **                                   or if methods are not found or are invalid.
174
         **/
175
        public EventSetDescriptor(Class eventSourceClass,
176
                                   String eventSetName,
177
                                   Class listenerType,
178
                                   String[] listenerMethodNames,
179
                                   String addListenerMethodName,
180
                                   String removeListenerMethodName) throws IntrospectionException {
181
                setName(eventSetName);
182
                if(!java.util.EventListener.class.isAssignableFrom(listenerType)) {
183
                        throw new IntrospectionException("Listener type is not an EventListener.");
184
                }
185
 
186
                findMethods(eventSourceClass,listenerType,listenerMethodNames,addListenerMethodName,removeListenerMethodName,null);
187
                this.listenerType = listenerType;
188
                checkAddListenerUnicast();
189
                if(this.removeListenerMethod.getExceptionTypes().length > 0) {
190
                        throw new IntrospectionException("Listener remove method throws exceptions.");
191
                }
192
        }
193
 
194
        /** Create a new EventSetDescriptor.
195
         ** This form of constructor allows you to explicitly say which methods do what, and
196
         ** no reflection is done by the EventSetDescriptor.  The methods are, however,
197
         ** checked to ensure that they follow the rules set forth at the top of the class.
198
         ** @param eventSetName the programmatic name of the event set, generally starting
199
         ** with a lowercase letter (i.e. fooManChu instead of FooManChu).
200
         ** @param listenerType the class containing the listenerMethods.
201
         ** @param listenerMethods the event firing methods.
202
         ** @param addListenerMethod the add listener method.
203
         ** @param removeListenerMethod the remove listener method.
204
         ** @exception IntrospectionException if the listenerType is not an EventListener,
205
         **                                   or any of the methods are invalid.
206
         **/
207
        public EventSetDescriptor(String eventSetName,
208
                                   Class listenerType,
209
                                   Method[] listenerMethods,
210
                                   Method addListenerMethod,
211
                                   Method removeListenerMethod) throws IntrospectionException {
212
                setName(eventSetName);
213
                if(!java.util.EventListener.class.isAssignableFrom(listenerType)) {
214
                        throw new IntrospectionException("Listener type is not an EventListener.");
215
                }
216
 
217
                this.listenerMethods = listenerMethods;
218
                this.addListenerMethod = addListenerMethod;
219
                this.removeListenerMethod = removeListenerMethod;
220
                this.listenerType = listenerType;
221
                checkMethods();
222
                checkAddListenerUnicast();
223
                if(this.removeListenerMethod.getExceptionTypes().length > 0) {
224
                        throw new IntrospectionException("Listener remove method throws exceptions.");
225
                }
226
        }
227
 
228
        /** Create a new EventSetDescriptor.
229
         ** This form of constructor allows you to explicitly say which methods do what, and
230
         ** no reflection is done by the EventSetDescriptor.  The methods are, however,
231
         ** checked to ensure that they follow the rules set forth at the top of the class.
232
         ** @param eventSetName the programmatic name of the event set, generally starting
233
         ** with a lowercase letter (i.e. fooManChu instead of FooManChu).
234
         ** @param listenerType the class containing the listenerMethods.
235
         ** @param listenerMethodDescriptors the event firing methods.
236
         ** @param addListenerMethod the add listener method.
237
         ** @param removeListenerMethod the remove listener method.
238
         ** @exception IntrospectionException if the listenerType is not an EventListener,
239
         **                                   or any of the methods are invalid.
240
         **/
241
        public EventSetDescriptor(String eventSetName,
242
                                   Class listenerType,
243
                                   MethodDescriptor[] listenerMethodDescriptors,
244
                                   Method addListenerMethod,
245
                                   Method removeListenerMethod) throws IntrospectionException {
246
                setName(eventSetName);
247
                if(!java.util.EventListener.class.isAssignableFrom(listenerType)) {
248
                        throw new IntrospectionException("Listener type is not an EventListener.");
249
                }
250
 
251
                this.listenerMethodDescriptors = listenerMethodDescriptors;
252
                this.listenerMethods = new Method[listenerMethodDescriptors.length];
253
                for(int i=0;i<this.listenerMethodDescriptors.length;i++) {
254
                        this.listenerMethods[i] = this.listenerMethodDescriptors[i].getMethod();
255
                }
256
 
257
                this.addListenerMethod = addListenerMethod;
258
                this.removeListenerMethod = removeListenerMethod;
259
                this.listenerType = listenerType;
260
                checkMethods();
261
                checkAddListenerUnicast();
262
                if(this.removeListenerMethod.getExceptionTypes().length > 0) {
263
                        throw new IntrospectionException("Listener remove method throws exceptions.");
264
                }
265
        }
266
 
267
        /** Get the class that contains the event firing methods. **/
268
        public Class getListenerType() {
269
                return listenerType;
270
        }
271
 
272
        /** Get the event firing methods. **/
273
        public Method[] getListenerMethods() {
274
                return listenerMethods;
275
        }
276
 
277
        /** Get the event firing methods as MethodDescriptors. **/
278
        public MethodDescriptor[] getListenerMethodDescriptors() {
279
                if(listenerMethodDescriptors == null) {
280
                        listenerMethodDescriptors = new MethodDescriptor[listenerMethods.length];
281
                        for(int i=0;i<listenerMethods.length;i++) {
282
                                listenerMethodDescriptors[i] = new MethodDescriptor(listenerMethods[i]);
283
                        }
284
                }
285
                return listenerMethodDescriptors;
286
        }
287
 
288
        /** Get the add listener method. **/
289
        public Method getAddListenerMethod() {
290
                return addListenerMethod;
291
        }
292
 
293
        /** Get the remove listener method. **/
294
        public Method getRemoveListenerMethod() {
295
                return removeListenerMethod;
296
        }
297
 
298
        /** Set whether or not multiple listeners may be added.
299
         ** @param unicast whether or not multiple listeners may be added.
300
         **/
301
        public void setUnicast(boolean unicast) {
302
                this.unicast = unicast;
303
        }
304
 
305
        /** Get whether or not multiple listeners may be added.  (Defaults to false.) **/
306
        public boolean isUnicast() {
307
                return unicast;
308
        }
309
 
310
        /** Set whether or not this is in the default event set.
311
         ** @param inDefaultEventSet whether this is in the default event set.
312
         **/
313
        public void setInDefaultEventSet(boolean inDefaultEventSet) {
314
                this.inDefaultEventSet = inDefaultEventSet;
315
        }
316
 
317
        /** Get whether or not this is in the default event set.  (Defaults to true.)**/
318
        public boolean isInDefaultEventSet() {
319
                return inDefaultEventSet;
320
        }
321
 
322
        private void checkAddListenerUnicast() throws IntrospectionException {
323
                Class[] addListenerExceptions = this.addListenerMethod.getExceptionTypes();
324
                if(addListenerExceptions.length > 1) {
325
                        throw new IntrospectionException("Listener add method throws too many exceptions.");
326
                } else if(addListenerExceptions.length == 1
327
                          && !java.util.TooManyListenersException.class.isAssignableFrom(addListenerExceptions[0])) {
328
                        throw new IntrospectionException("Listener add method throws too many exceptions.");
329
                }
330
        }
331
 
332
        private void checkMethods() throws IntrospectionException {
333
                if(!addListenerMethod.getDeclaringClass().isAssignableFrom(removeListenerMethod.getDeclaringClass())
334
                   && !removeListenerMethod.getDeclaringClass().isAssignableFrom(addListenerMethod.getDeclaringClass())) {
335
                        throw new IntrospectionException("add and remove listener methods do not come from the same class.  This is bad.");
336
                }
337
                if(!addListenerMethod.getReturnType().equals(java.lang.Void.TYPE)
338
                   || addListenerMethod.getParameterTypes().length != 1
339
                   || !listenerType.equals(addListenerMethod.getParameterTypes()[0])
340
                   || !Modifier.isPublic(addListenerMethod.getModifiers())) {
341
                        throw new IntrospectionException("Add Listener Method invalid.");
342
                }
343
                if(!removeListenerMethod.getReturnType().equals(java.lang.Void.TYPE)
344
                   || removeListenerMethod.getParameterTypes().length != 1
345
                   || !listenerType.equals(removeListenerMethod.getParameterTypes()[0])
346
                   || removeListenerMethod.getExceptionTypes().length > 0
347
                   || !Modifier.isPublic(removeListenerMethod.getModifiers())) {
348
                        throw new IntrospectionException("Remove Listener Method invalid.");
349
                }
350
 
351
                for(int i=0;i<listenerMethods.length;i++) {
352
                        if(!listenerMethods[i].getReturnType().equals(java.lang.Void.TYPE)
353
                           || Modifier.isPrivate(listenerMethods[i].getModifiers())) {
354
                                throw new IntrospectionException("Event Method " + listenerMethods[i].getName() + " non-void or private.");
355
                        }
356
                        if(!listenerMethods[i].getDeclaringClass().isAssignableFrom(listenerType)) {
357
                                throw new IntrospectionException("Event Method " + listenerMethods[i].getName() + " not from class " + listenerType.getName());
358
                        }
359
                }
360
        }
361
 
362
        private void findMethods(Class eventSourceClass,
363
                Class listenerType,
364
                String listenerMethodNames[],
365
                String addListenerMethodName,
366
                String removeListenerMethodName,
367
                String absurdEventClassCheckName) throws IntrospectionException {
368
 
369
                /* Find add listener method and remove listener method. */
370
                Class[] listenerArgList = new Class[1];
371
                listenerArgList[0] = listenerType;
372
                try {
373
                        this.addListenerMethod = eventSourceClass.getMethod(addListenerMethodName,listenerArgList);
374
                } catch(SecurityException E) {
375
                        throw new IntrospectionException("SecurityException trying to access method " + addListenerMethodName + ".");
376
                } catch(NoSuchMethodException E) {
377
                        throw new IntrospectionException("Could not find method " + addListenerMethodName + ".");
378
                }
379
 
380
                if(this.addListenerMethod == null || !this.addListenerMethod.getReturnType().equals(java.lang.Void.TYPE)) {
381
                        throw new IntrospectionException("Add listener method does not exist, is not public, or is not void.");
382
                }
383
 
384
                try {
385
                        this.removeListenerMethod = eventSourceClass.getMethod(removeListenerMethodName,listenerArgList);
386
                } catch(SecurityException E) {
387
                        throw new IntrospectionException("SecurityException trying to access method " + removeListenerMethodName + ".");
388
                } catch(NoSuchMethodException E) {
389
                        throw new IntrospectionException("Could not find method " + removeListenerMethodName + ".");
390
                }
391
                if(this.removeListenerMethod == null || !this.removeListenerMethod.getReturnType().equals(java.lang.Void.TYPE)) {
392
                        throw new IntrospectionException("Remove listener method does not exist, is not public, or is not void.");
393
                }
394
 
395
                /* Find the listener methods. */
396
                Method[] methods;
397
                try {
398
                        methods = ClassHelper.getAllMethods(listenerType);
399
                } catch(SecurityException E) {
400
                        throw new IntrospectionException("Security: You cannot access fields in this class.");
401
                }
402
 
403
                Vector chosenMethods = new Vector();
404
                boolean[] listenerMethodFound = new boolean[listenerMethodNames.length];
405
                for(int i=0;i<methods.length;i++) {
406
                        if(Modifier.isPrivate(methods[i].getModifiers())) {
407
                                continue;
408
                        }
409
                        Method currentMethod = methods[i];
410
                        Class retval = currentMethod.getReturnType();
411
                        if(retval.equals(java.lang.Void.TYPE)) {
412
                                for(int j=0;j<listenerMethodNames.length;j++) {
413
                                        if(currentMethod.getName().equals(listenerMethodNames[j])
414
                                           && (absurdEventClassCheckName == null
415
                                               || (currentMethod.getParameterTypes().length == 1
416
                                                   && ((currentMethod.getParameterTypes()[0]).getName().equals(absurdEventClassCheckName)
417
                                                       || (currentMethod.getParameterTypes()[0]).getName().endsWith("."+absurdEventClassCheckName)
418
                                                      )
419
                                                  )
420
                                              )
421
                                          ) {
422
                                                chosenMethods.addElement(currentMethod);
423
                                                listenerMethodFound[j] = true;
424
                                        }
425
                                }
426
                        }
427
                }
428
 
429
                /* Make sure we found all the methods we were looking for. */
430
                for(int i=0;i<listenerMethodFound.length;i++) {
431
                        if(!listenerMethodFound[i]) {
432
                                throw new IntrospectionException("Could not find event method " + listenerMethodNames[i]);
433
                        }
434
                }
435
 
436
                /* Now that we've chosen the listener methods we want, store them. */
437
                this.listenerMethods = new Method[chosenMethods.size()];
438
                for(int i=0;i<chosenMethods.size();i++) {
439
                        this.listenerMethods[i] = (Method)chosenMethods.elementAt(i);
440
                }
441
        }
442
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.