1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
|
package com.jclark.xsl.sax;
import java.net.URL;
import java.lang.reflect.*;
import org.xml.sax.*;
import com.jclark.xsl.om.XSLException;
import com.jclark.xsl.om.Node;
import com.jclark.xsl.expr.ExtensionContext;
import com.jclark.xsl.tr.ExtensionHandler;
import com.jclark.xsl.tr.Result;
import com.jclark.xsl.tr.ResultFragmentVariant;
import com.jclark.xsl.tr.ResultFragmentVariantBase;
public class ExtensionHandlerImpl implements ExtensionHandler {
private static class ContextImpl implements ExtensionContext {
private final Class cls;
ContextImpl(Class cls) {
this.cls = cls;
}
public boolean available(String name) {
if (name.equals("new"))
return cls.getConstructors().length != 0;
name = camelCase(name);
Method[] methods = cls.getMethods();
for (int i = 0; i < methods.length; i++)
if (methods[i].getName().equals(name))
return true;
return false;
}
private Object callMethod(String name, Object[] args)
throws XSLException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
name = camelCase(name);
Method[] methods = cls.getMethods();
Method method = null;
boolean mustBeStatic = true;
if (args.length > 0 && cls.isInstance(args[0]))
mustBeStatic = false;
for (int i = 0; i < methods.length; i++) {
if (methods[i].getName().equals(name)
&& (Modifier.isStatic(methods[i].getModifiers())
? methods[i].getParameterTypes().length == args.length
: (!mustBeStatic
&& methods[i].getParameterTypes().length == args.length - 1))) {
if (method != null)
throw new XSLException(name + ": overloaded method");
method = methods[i];
}
}
if (method == null)
throw new XSLException(name + ": no method with " + args.length + " arguments");
Object result;
if (Modifier.isStatic(method.getModifiers()))
result = method.invoke(null, args);
else {
Object obj = args[0];
Object[] newArgs = new Object[args.length - 1];
System.arraycopy(args, 1, newArgs, 0, newArgs.length);
result = method.invoke(obj, newArgs);
}
if (result instanceof ResultTreeFragment)
return wrapResultTreeFragment((ResultTreeFragment)result);
return result;
}
private Object callConstructor(Object[] args)
throws XSLException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Constructor[] constructors = cls.getConstructors();
Constructor constructor = null;
for (int i = 0; i < constructors.length; i++) {
if (constructors[i].getParameterTypes().length == args.length) {
if (constructor != null)
throw new XSLException("overloaded constructor");
constructor = constructors[i];
}
}
if (constructor == null)
throw new XSLException("no constructor with " + args.length + " arguments");
return constructor.newInstance(args);
}
public Object call(String name, Node currentNode, Object[] args) throws XSLException {
try {
if (name.equals("new"))
return callConstructor(args);
else
return callMethod(name, args);
}
catch (IllegalAccessException e) {
throw new XSLException(name + ": illegal access");
}
catch (IllegalArgumentException e) {
throw new XSLException(name + ": illegal arguments");
}
catch (InstantiationException e) {
throw new XSLException("cannot instantiate class");
}
catch (InvocationTargetException e) {
Throwable t = e.getTargetException();
if (t instanceof RuntimeException)
throw (RuntimeException)t;
if (t instanceof Error)
throw (Error)t;
if (t instanceof Exception)
throw new XSLException((Exception)t);
throw new XSLException(e);
}
}
private String camelCase(String name) {
int i = name.indexOf('-');
if (i < 0 || i + 1 == name.length())
return name;
return (name.substring(0, i)
+ Character.toUpperCase(name.charAt(i + 1))
+ camelCase(name.substring(i + 2)));
}
}
static final private String JAVA_NS = "http://www.jclark.com/xt/java/";
public ExtensionContext createContext(String namespace) throws XSLException {
if (namespace.startsWith(JAVA_NS)) {
try {
return new ContextImpl(Class.forName(namespace.substring(JAVA_NS.length())));
}
catch (ClassNotFoundException e) { }
}
return null;
}
private static Object wrapResultTreeFragment(final ResultTreeFragment frag) {
return new ResultFragmentVariantBase() {
public Object convertToObject() {
return frag;
}
public void append(Result result) throws XSLException {
if (result instanceof ResultBase)
((ResultBase)result).resultTreeFragment(frag);
else {
// FIXME
throw new XSLException("weird result tree fragment usage not implemented");
}
}
};
}
public Object wrapResultFragmentVariant(final ResultFragmentVariant frag) {
return new ResultTreeFragment() {
public void emit(DocumentHandler handler) throws SAXException {
ResultBase result = new MultiNamespaceResult(handler, null);
try {
frag.append(result);
result.flush();
}
catch (XSLException e) {
throw new SAXException(e);
}
}
};
}
}
|