reqClass = getExternalJavaClass(uri);
if (reqClass == null) {
return null;
}
} catch (Exception err) {
throw new StaticError("Cannot load external Java class", err);
}
if (debug) {
diag.println("Looking for method " + local + " in Java class " + reqClass);
diag.println("Number of actual arguments = " + staticArgs.length);
}
int numArgs = staticArgs.length;
int significantArgs;
Class theClass = reqClass;
// if the method name is "new", look for a matching constructor
if ("new".equals(local)) {
if (debug) {
diag.println("Looking for a constructor");
}
int mod = theClass.getModifiers();
if (Modifier.isAbstract(mod)) {
theException = new StaticError("Class " + theClass + " is abstract");
} else if (Modifier.isInterface(mod)) {
theException = new StaticError(theClass + " is an interface");
} else if (Modifier.isPrivate(mod)) {
theException = new StaticError("Class " + theClass + " is private");
} else if (Modifier.isProtected(mod)) {
theException = new StaticError("Class " + theClass + " is protected");
}
if (theException != null) {
if (debug) {
diag.println("Cannot construct an instance: " + theException.getMessage());
}
return null;
}
Constructor[] constructors = theClass.getConstructors();
for (int c = 0; c < constructors.length; c++) {
Constructor theConstructor = constructors[c];
if (debug) {
diag.println("Found a constructor with " + theConstructor.getParameterTypes().length + " arguments");
}
if (theConstructor.getParameterTypes().length == numArgs) {
candidateMethods.add(theConstructor);
}
}
if (candidateMethods.size() == 0) {
theException = new StaticError("No constructor with " + numArgs +
(numArgs == 1 ? " parameter" : " parameters") +
" found in class " + theClass.getName());
if (debug) {
diag.println(theException.getMessage());
}
return null;
}
} else {
// convert any hyphens in the name, camelCasing the following character
String name = toCamelCase(local, debug, diag);
// look through the methods of this class to find one that matches the local name
Method[] methods = theClass.getMethods();
boolean consistentReturnType = true;
for (int m = 0; m < methods.length; m++) {
Method theMethod = methods[m];
if (debug) {
if (theMethod.getName().equals(name)) {
diag.println("Trying method " + theMethod.getName() + ": name matches");
if (!Modifier.isPublic(theMethod.getModifiers())) {
diag.println(" -- but the method is not public");
}
} else {
diag.println("Trying method " + theMethod.getName() + ": name does not match");
}
}
if (theMethod.getName().equals(name) &&
Modifier.isPublic(theMethod.getModifiers())) {
if (consistentReturnType) {
if (resultClass == null) {
resultClass = theMethod.getReturnType();
} else {
consistentReturnType =
(theMethod.getReturnType() == resultClass);
}
}
Class[] theParameterTypes = theMethod.getParameterTypes();
boolean isStatic = Modifier.isStatic(theMethod.getModifiers());
// if the method is not static, the first supplied argument is the instance, so
// discount it
if (debug) {
diag.println("Method is " + (isStatic ? "" : "not ") + "static");
}
significantArgs = (isStatic ? numArgs : numArgs - 1);
if (significantArgs >= 0) {
if (debug) {
diag.println("Method has " + theParameterTypes.length + " argument" +
(theParameterTypes.length == 1 ? "" : "s") +
"; expecting " + significantArgs);
}
if (theParameterTypes.length == significantArgs &&
(significantArgs == 0 || theParameterTypes[0] != XPathContext.class)) {
if (debug) {
diag.println("Found a candidate method:");
diag.println(" " + theMethod);
}
candidateMethods.add(theMethod);
}
// we allow the method to have an extra parameter if the first parameter is XPathContext
if (theParameterTypes.length == significantArgs + 1 &&
theParameterTypes[0] == XPathContext.class) {
if (debug) {
diag.println("Method is a candidate because first argument is XPathContext");
}
candidateMethods.add(theMethod);
}
}
}
}
// Code added by GS -- start
// look through the fields of this class to find those that matches the local name
Field[] fields = theClass.getFields();
for (int m = 0; m < fields.length; m++) {
Field theField = fields[m];
if (debug) {
if (theField.getName().equals(name)) {
diag.println("Trying field " + theField.getName() + ": name matches");
if (!Modifier.isPublic(theField.getModifiers())) {
diag.println(" -- but the field is not public");
}
} else {
diag.println("Trying field " + theField.getName() + ": name does not match");
}
}
if (theField.getName().equals(name) &&
Modifier.isPublic(theField.getModifiers())) {
if (consistentReturnType) {
if (resultClass == null) {
resultClass = theField.getType();
} else {
consistentReturnType =
(theField.getType() == resultClass);
}
}
boolean isStatic = Modifier.isStatic(theField.getModifiers());
// if the field is not static, the first supplied argument is the instance, so
// discount it
if (debug) {
diag.println("Field is " + (isStatic ? "" : "not ") + "static");
}
significantArgs = (isStatic ? numArgs : numArgs - 1);
if (significantArgs == 0) {
if (debug) {
diag.println("Found a candidate field:");
diag.println(" " + theField);
}
candidateMethods.add(theField);
}
}
}
// End of code added by GS
// No method found?
if (candidateMethods.size() == 0) {
theException = new StaticError("No method or field matching " + name +
" with " + numArgs +
(numArgs == 1 ? " parameter" : " parameters") +
" found in class " + theClass.getName());
if (debug) {
diag.println(theException.getMessage());