}
if ((explicit == null) && (_superBeanInfo != null))
{
// We have no explicit BeanInfo events. Check with our parent.
EventSetDescriptor supers[] = _superBeanInfo.getEventSetDescriptors();
for (int i = 0 ; i < supers.length; i++)
{
_addEvent(events, supers[i]);
}
int ix = _superBeanInfo.getDefaultEventIndex();
if ((ix >= 0) && (ix < supers.length))
{
_defaultEventName = supers[ix].getName();
}
}
for (int i = 0; i < _additionalBeanInfo.length; i++)
{
EventSetDescriptor additional[] =
_additionalBeanInfo[i].getEventSetDescriptors();
if (additional != null)
{
for (int j = 0 ; j < additional.length; j++)
{
_addEvent(events, additional[j]);
}
}
}
if (explicit != null)
{
// Add the explicit informant data to our results.
for (int i = 0 ; i < explicit.length; i++)
{
_addEvent(events, explicit[i]);
}
}
else
{
// Apply some reflection to the current class.
// Get an array of all the beans methods at this level
Method methodList[] = _getPublicMethods(_beanClass);
// Find all suitable "add" and "remove" methods.
// -= Simon Lessard =-
// TODO: Check if synchronization is really needed.
Hashtable<String, Method> adds = new Hashtable<String, Method>();
Hashtable<String, Method> removes = new Hashtable<String, Method>();
for (int i = 0; i < methodList.length; i++)
{
Method method = methodList[i];
//
// skip static methods.
//
if (Modifier.isStatic(method.getModifiers()))
{
continue;
}
String name = method.getName();
Class<?>[] argTypes = method.getParameterTypes();
Class<?> resultType = method.getReturnType();
if (name.startsWith("add") &&
(argTypes.length == 1) &&
(resultType == Void.TYPE))
{
String compound = name.substring(3) + ":" + argTypes[0];
adds.put(compound, method);
}
else if (name.startsWith("remove") &&
(argTypes.length == 1) &&
(resultType == Void.TYPE))
{
String compound = name.substring(6) + ":" + argTypes[0];
removes.put(compound, method);
}
}
// Now look for matching addFooListener+removeFooListener pairs.
Enumeration<String> keys = adds.keys();
while (keys.hasMoreElements())
{
String compound = keys.nextElement();
// Skip any "add" which doesn't have a matching "remove".
if (removes.get(compound) == null)
{
continue;
}
// Method name has to end in "Listener"
if (compound.indexOf("Listener:") <= 0)
{
continue;
}
String listenerName = compound.substring(0, compound.indexOf(':'));
String eventName = decapitalize(
listenerName.substring(0,
listenerName.length() - 8));
Method addMethod = adds.get(compound);
Method removeMethod = removes.get(compound);
Class<?> argType = addMethod.getParameterTypes()[0];
// Check if the argument type is a subtype of EventListener
if (!JavaIntrospector._isSubclass(argType, _EVENT_LISTENER_TYPE))
{
continue;
}
// generate a list of Method objects for each of the target methods:
Method allMethods[] = argType.getMethods();
int count = 0;
for (int i = 0; i < allMethods.length; i++)
{
if (_isEventHandler(allMethods[i]))
{
count++;
}
else
{
allMethods[i] = null;
}
}
Method methods[] = new Method[count];
int j = 0;
for (int i = 0; i < allMethods.length; i++)
{
if (allMethods[i] != null)
{
methods[j++] = allMethods[i];
}
}
EventSetDescriptor esd = new EventSetDescriptor(eventName,
argType,
methods,
addMethod,
removeMethod);
// If the adder method throws the TooManyListenersException then it
// is a Unicast event source.
if (_throwsException(addMethod,TooManyListenersException.class))
{
esd.setUnicast(true);
}
_addEvent(events, esd);
}
}