EventSetDescriptor.java [plain text]
package java.beans;
import java.util.*;
import java.lang.reflect.*;
import gnu.java.lang.*;
public class EventSetDescriptor extends FeatureDescriptor {
private Method addListenerMethod;
private Method removeListenerMethod;
private Class listenerType;
private MethodDescriptor[] listenerMethodDescriptors;
private Method[] listenerMethods;
private boolean unicast;
private boolean inDefaultEventSet = true;
public EventSetDescriptor(Class eventSourceClass,
String eventSetName,
Class listenerType,
String listenerMethodName) throws IntrospectionException {
setName(eventSetName);
if(!java.util.EventListener.class.isAssignableFrom(listenerType)) {
throw new IntrospectionException("Listener type is not an EventListener.");
}
String[] names = new String[1];
names[0] = listenerMethodName;
try {
eventSetName = Character.toUpperCase(eventSetName.charAt(0)) + eventSetName.substring(1);
} catch(StringIndexOutOfBoundsException e) {
eventSetName = "";
}
findMethods(eventSourceClass,listenerType,names,"add"+eventSetName+"Listener","remove"+eventSetName+"Listener",eventSetName+"Event");
this.listenerType = listenerType;
checkAddListenerUnicast();
if(this.removeListenerMethod.getExceptionTypes().length > 0) {
throw new IntrospectionException("Listener remove method throws exceptions.");
}
}
public EventSetDescriptor(Class eventSourceClass,
String eventSetName,
Class listenerType,
String[] listenerMethodNames,
String addListenerMethodName,
String removeListenerMethodName) throws IntrospectionException {
setName(eventSetName);
if(!java.util.EventListener.class.isAssignableFrom(listenerType)) {
throw new IntrospectionException("Listener type is not an EventListener.");
}
findMethods(eventSourceClass,listenerType,listenerMethodNames,addListenerMethodName,removeListenerMethodName,null);
this.listenerType = listenerType;
checkAddListenerUnicast();
if(this.removeListenerMethod.getExceptionTypes().length > 0) {
throw new IntrospectionException("Listener remove method throws exceptions.");
}
}
public EventSetDescriptor(String eventSetName,
Class listenerType,
Method[] listenerMethods,
Method addListenerMethod,
Method removeListenerMethod) throws IntrospectionException {
setName(eventSetName);
if(!java.util.EventListener.class.isAssignableFrom(listenerType)) {
throw new IntrospectionException("Listener type is not an EventListener.");
}
this.listenerMethods = listenerMethods;
this.addListenerMethod = addListenerMethod;
this.removeListenerMethod = removeListenerMethod;
this.listenerType = listenerType;
checkMethods();
checkAddListenerUnicast();
if(this.removeListenerMethod.getExceptionTypes().length > 0) {
throw new IntrospectionException("Listener remove method throws exceptions.");
}
}
public EventSetDescriptor(String eventSetName,
Class listenerType,
MethodDescriptor[] listenerMethodDescriptors,
Method addListenerMethod,
Method removeListenerMethod) throws IntrospectionException {
setName(eventSetName);
if(!java.util.EventListener.class.isAssignableFrom(listenerType)) {
throw new IntrospectionException("Listener type is not an EventListener.");
}
this.listenerMethodDescriptors = listenerMethodDescriptors;
this.listenerMethods = new Method[listenerMethodDescriptors.length];
for(int i=0;i<this.listenerMethodDescriptors.length;i++) {
this.listenerMethods[i] = this.listenerMethodDescriptors[i].getMethod();
}
this.addListenerMethod = addListenerMethod;
this.removeListenerMethod = removeListenerMethod;
this.listenerType = listenerType;
checkMethods();
checkAddListenerUnicast();
if(this.removeListenerMethod.getExceptionTypes().length > 0) {
throw new IntrospectionException("Listener remove method throws exceptions.");
}
}
public Class getListenerType() {
return listenerType;
}
public Method[] getListenerMethods() {
return listenerMethods;
}
public MethodDescriptor[] getListenerMethodDescriptors() {
if(listenerMethodDescriptors == null) {
listenerMethodDescriptors = new MethodDescriptor[listenerMethods.length];
for(int i=0;i<listenerMethods.length;i++) {
listenerMethodDescriptors[i] = new MethodDescriptor(listenerMethods[i]);
}
}
return listenerMethodDescriptors;
}
public Method getAddListenerMethod() {
return addListenerMethod;
}
public Method getRemoveListenerMethod() {
return removeListenerMethod;
}
public void setUnicast(boolean unicast) {
this.unicast = unicast;
}
public boolean isUnicast() {
return unicast;
}
public void setInDefaultEventSet(boolean inDefaultEventSet) {
this.inDefaultEventSet = inDefaultEventSet;
}
public boolean isInDefaultEventSet() {
return inDefaultEventSet;
}
private void checkAddListenerUnicast() throws IntrospectionException {
Class[] addListenerExceptions = this.addListenerMethod.getExceptionTypes();
if(addListenerExceptions.length > 1) {
throw new IntrospectionException("Listener add method throws too many exceptions.");
} else if(addListenerExceptions.length == 1
&& !java.util.TooManyListenersException.class.isAssignableFrom(addListenerExceptions[0])) {
throw new IntrospectionException("Listener add method throws too many exceptions.");
}
}
private void checkMethods() throws IntrospectionException {
if(!addListenerMethod.getDeclaringClass().isAssignableFrom(removeListenerMethod.getDeclaringClass())
&& !removeListenerMethod.getDeclaringClass().isAssignableFrom(addListenerMethod.getDeclaringClass())) {
throw new IntrospectionException("add and remove listener methods do not come from the same class. This is bad.");
}
if(!addListenerMethod.getReturnType().equals(java.lang.Void.TYPE)
|| addListenerMethod.getParameterTypes().length != 1
|| !listenerType.equals(addListenerMethod.getParameterTypes()[0])
|| !Modifier.isPublic(addListenerMethod.getModifiers())) {
throw new IntrospectionException("Add Listener Method invalid.");
}
if(!removeListenerMethod.getReturnType().equals(java.lang.Void.TYPE)
|| removeListenerMethod.getParameterTypes().length != 1
|| !listenerType.equals(removeListenerMethod.getParameterTypes()[0])
|| removeListenerMethod.getExceptionTypes().length > 0
|| !Modifier.isPublic(removeListenerMethod.getModifiers())) {
throw new IntrospectionException("Remove Listener Method invalid.");
}
for(int i=0;i<listenerMethods.length;i++) {
if(!listenerMethods[i].getReturnType().equals(java.lang.Void.TYPE)
|| Modifier.isPrivate(listenerMethods[i].getModifiers())) {
throw new IntrospectionException("Event Method " + listenerMethods[i].getName() + " non-void or private.");
}
if(!listenerMethods[i].getDeclaringClass().isAssignableFrom(listenerType)) {
throw new IntrospectionException("Event Method " + listenerMethods[i].getName() + " not from class " + listenerType.getName());
}
}
}
private void findMethods(Class eventSourceClass,
Class listenerType,
String listenerMethodNames[],
String addListenerMethodName,
String removeListenerMethodName,
String absurdEventClassCheckName) throws IntrospectionException {
Class[] listenerArgList = new Class[1];
listenerArgList[0] = listenerType;
try {
this.addListenerMethod = eventSourceClass.getMethod(addListenerMethodName,listenerArgList);
} catch(SecurityException E) {
throw new IntrospectionException("SecurityException trying to access method " + addListenerMethodName + ".");
} catch(NoSuchMethodException E) {
throw new IntrospectionException("Could not find method " + addListenerMethodName + ".");
}
if(this.addListenerMethod == null || !this.addListenerMethod.getReturnType().equals(java.lang.Void.TYPE)) {
throw new IntrospectionException("Add listener method does not exist, is not public, or is not void.");
}
try {
this.removeListenerMethod = eventSourceClass.getMethod(removeListenerMethodName,listenerArgList);
} catch(SecurityException E) {
throw new IntrospectionException("SecurityException trying to access method " + removeListenerMethodName + ".");
} catch(NoSuchMethodException E) {
throw new IntrospectionException("Could not find method " + removeListenerMethodName + ".");
}
if(this.removeListenerMethod == null || !this.removeListenerMethod.getReturnType().equals(java.lang.Void.TYPE)) {
throw new IntrospectionException("Remove listener method does not exist, is not public, or is not void.");
}
Method[] methods;
try {
methods = ClassHelper.getAllMethods(listenerType);
} catch(SecurityException E) {
throw new IntrospectionException("Security: You cannot access fields in this class.");
}
Vector chosenMethods = new Vector();
boolean[] listenerMethodFound = new boolean[listenerMethodNames.length];
for(int i=0;i<methods.length;i++) {
if(Modifier.isPrivate(methods[i].getModifiers())) {
continue;
}
Method currentMethod = methods[i];
Class retval = currentMethod.getReturnType();
if(retval.equals(java.lang.Void.TYPE)) {
for(int j=0;j<listenerMethodNames.length;j++) {
if(currentMethod.getName().equals(listenerMethodNames[j])
&& (absurdEventClassCheckName == null
|| (currentMethod.getParameterTypes().length == 1
&& ((currentMethod.getParameterTypes()[0]).getName().equals(absurdEventClassCheckName)
|| (currentMethod.getParameterTypes()[0]).getName().endsWith("."+absurdEventClassCheckName)
)
)
)
) {
chosenMethods.addElement(currentMethod);
listenerMethodFound[j] = true;
}
}
}
}
for(int i=0;i<listenerMethodFound.length;i++) {
if(!listenerMethodFound[i]) {
throw new IntrospectionException("Could not find event method " + listenerMethodNames[i]);
}
}
this.listenerMethods = new Method[chosenMethods.size()];
for(int i=0;i<chosenMethods.size();i++) {
this.listenerMethods[i] = (Method)chosenMethods.elementAt(i);
}
}
}