1 16 package com.google.gwt.dev.util.xml; 17 18 import com.google.gwt.core.ext.UnableToCompleteException; 19 20 import java.lang.reflect.InvocationTargetException ; 21 import java.lang.reflect.Method ; 22 import java.util.ArrayList ; 23 import java.util.List ; 24 25 28 public final class HandlerMethod { 29 30 private static final HandlerParam[] EMPTY_HANDLERPARAMS = new HandlerParam[0]; 31 32 private static final Schema sArbitraryChildHandler = new Schema() { 34 35 public void onBadAttributeValue(int lineNumber, String elemName, 36 String attrName, String attrValue, Class paramType) { 37 } 39 40 public void onHandlerException(int lineNumber, String elemLocalName, 41 Method method, Throwable e) { 42 } 44 45 public void onMissingAttribute(int lineNumber, String elemName, 46 String argName) { 47 } 49 50 public void onUnexpectedAttribute(int lineNumber, String elemName, 51 String attrName, String attrValue) { 52 } 54 55 public void onUnexpectedChild(int lineNumber, String elemName) { 56 } 58 59 public void onUnexpectedElement(int lineNumber, String elemName) { 60 } 62 }; 63 64 private static final int TYPE_NONE = 0; 65 private static final int TYPE_BEGIN = 1; 66 private static final int TYPE_END = 2; 67 private static final int TYPE_TEXT = 3; 68 69 static { 70 ReflectiveParser.registerSchemaLevel(sArbitraryChildHandler.getClass()); 71 } 72 73 79 public static HandlerMethod tryCreate(Method method) { 80 String methodName = method.getName(); 81 String normalizedTagName = null; 82 try { 83 int type = TYPE_NONE; 84 85 if (methodName.startsWith("__")) { 86 if (methodName.endsWith("_begin")) { 87 type = TYPE_BEGIN; 88 normalizedTagName = methodName.substring(0, methodName.length() 89 - "_begin".length()); 90 } else if (methodName.endsWith("_end")) { 91 type = TYPE_END; 92 normalizedTagName = methodName.substring(0, methodName.length() 93 - "_end".length()); 94 } else if (methodName.equals("__text")) { 95 type = TYPE_TEXT; 96 } 97 } 98 99 if (type == TYPE_NONE) { 100 return null; 104 } 105 106 assert (type == TYPE_BEGIN || type == TYPE_END || type == TYPE_TEXT); 107 108 Class returnType = method.getReturnType(); 111 boolean arbitraryChildren = false; 112 if (type == TYPE_BEGIN) { 113 if (Schema.class.isAssignableFrom(returnType)) { 114 arbitraryChildren = false; 115 116 ReflectiveParser.registerSchemaLevel(returnType); 119 120 } else if (returnType.equals(Void.TYPE)) { 121 arbitraryChildren = true; 122 } else { 123 throw new IllegalArgumentException ( 124 "The return type of begin handlers must be 'void' or assignable to 'SchemaLevel'"); 125 } 126 } else if (!Void.TYPE.equals(returnType)) { 127 throw new IllegalArgumentException ( 128 "Only 'void' may be specified as a return type for 'end' and 'text' handlers"); 129 } 130 131 if (type == TYPE_TEXT) { 134 Class [] paramTypes = method.getParameterTypes(); 135 if (paramTypes.length != 1 || !String .class.equals(paramTypes[0])) { 136 throw new IllegalArgumentException ( 137 "__text handlers must have exactly one String parameter"); 138 } 139 140 return new HandlerMethod(method, type, false, EMPTY_HANDLERPARAMS); 144 } else { 145 Class [] paramTypes = method.getParameterTypes(); 146 List handlerParams = new ArrayList (); 147 for (int i = 0, n = paramTypes.length; i < n; ++i) { 148 HandlerParam handlerParam = HandlerParam.create(method, 149 normalizedTagName, i); 150 if (handlerParam != null) { 151 handlerParams.add(handlerParam); 152 } else { 153 throw new IllegalArgumentException ("In method '" + method.getName() 154 + "', parameter " + (i + 1) + " is an unsupported type"); 155 } 156 } 157 158 HandlerParam[] hpa = (HandlerParam[]) handlerParams.toArray(EMPTY_HANDLERPARAMS); 159 return new HandlerMethod(method, type, arbitraryChildren, hpa); 160 } 161 } catch (Exception e) { 162 throw new RuntimeException ("Unable to use method '" + methodName 163 + "' as a handler", e); 164 } 165 } 166 167 private final boolean arbitraryChildren; 168 169 private final HandlerParam[] handlerParams; 170 171 private final Method method; 172 173 private final int methodType; 174 175 private HandlerMethod(Method method, int type, boolean arbitraryChildren, 176 HandlerParam[] hpa) { 177 this.method = method; 178 this.methodType = type; 179 this.arbitraryChildren = arbitraryChildren; 180 this.handlerParams = (HandlerParam[]) hpa.clone(); 181 182 this.method.setAccessible(true); 183 } 184 185 public HandlerArgs createArgs(Schema schema, int lineNumber, String elemName) { 186 return new HandlerArgs(schema, lineNumber, elemName, handlerParams); 187 } 188 189 public String getNormalizedName() { 190 String name = method.getName(); 191 if (isStartMethod()) { 192 return name.substring(2, name.length() - "_begin".length()); 193 } else if (isEndMethod()) { 194 return name.substring(2, name.length() - "_end".length()); 195 } else { 196 throw new IllegalStateException ("Unexpected method name"); 197 } 198 } 199 200 public HandlerParam getParam(int i) { 201 return handlerParams[i]; 202 } 203 204 public int getParamCount() { 205 return handlerParams.length; 206 } 207 208 public Schema invokeBegin(int lineNumber, String elemLocalName, 209 Schema target, HandlerArgs args, Object [] outInvokeArgs) 210 throws UnableToCompleteException { 211 assert (outInvokeArgs.length == args.getArgCount()); 212 213 for (int i = 0, n = args.getArgCount(); i < n; ++i) { 214 Object invokeArg = args.convertToArg(i); 215 outInvokeArgs[i] = invokeArg; 216 } 217 218 Schema nextSchemaLevel = null; 219 220 Throwable caught = null; 221 try { 222 target.setLineNumber(lineNumber); 223 nextSchemaLevel = (Schema) method.invoke(target, outInvokeArgs); 224 } catch (IllegalArgumentException e) { 225 caught = e; 226 } catch (IllegalAccessException e) { 227 caught = e; 228 } catch (InvocationTargetException e) { 229 caught = e.getTargetException(); 230 } 231 232 if (caught != null) { 233 target.onHandlerException(lineNumber, elemLocalName, method, caught); 234 } 235 236 if (nextSchemaLevel != null) { 252 return nextSchemaLevel; 253 } else if (arbitraryChildren) { 254 return sArbitraryChildHandler; 255 } else { 256 return null; 257 } 258 } 259 260 public void invokeEnd(int lineNumber, String elem, Schema target, 261 Object [] args) throws UnableToCompleteException { 262 Throwable caught = null; 263 try { 264 target.setLineNumber(lineNumber); 265 method.invoke(target, args); 266 return; 267 } catch (IllegalArgumentException e) { 268 caught = e; 269 } catch (IllegalAccessException e) { 270 caught = e; 271 } catch (InvocationTargetException e) { 272 caught = e.getTargetException(); 273 } 274 target.onHandlerException(lineNumber, elem, method, caught); 275 } 276 277 public void invokeText(int lineNumber, String text, Schema target) 278 throws UnableToCompleteException { 279 Throwable caught = null; 280 try { 281 target.setLineNumber(lineNumber); 282 method.invoke(target, new Object [] {text}); 283 return; 284 } catch (IllegalArgumentException e) { 285 caught = e; 286 } catch (IllegalAccessException e) { 287 caught = e; 288 } catch (InvocationTargetException e) { 289 caught = e.getTargetException(); 290 } 291 target.onHandlerException(lineNumber, "#text", method, caught); 292 } 293 294 public boolean isEndMethod() { 295 return methodType == TYPE_END; 296 } 297 298 public boolean isStartMethod() { 299 return methodType == TYPE_BEGIN; 300 } 301 } 302 | Popular Tags |