1 16 package com.google.gwt.dev.util.xml; 17 18 import com.google.gwt.core.ext.TreeLogger; 19 import com.google.gwt.core.ext.UnableToCompleteException; 20 import com.google.gwt.util.tools.Utility; 21 22 import org.xml.sax.Attributes ; 23 import org.xml.sax.InputSource ; 24 import org.xml.sax.Locator ; 25 import org.xml.sax.SAXException ; 26 import org.xml.sax.XMLReader ; 27 import org.xml.sax.helpers.DefaultHandler ; 28 29 import java.io.IOException ; 30 import java.io.Reader ; 31 import java.util.Stack ; 32 33 import javax.xml.parsers.ParserConfigurationException ; 34 import javax.xml.parsers.SAXParser ; 35 import javax.xml.parsers.SAXParserFactory ; 36 37 46 public final class ReflectiveParser { 47 48 private static final class Impl extends DefaultHandler { 49 50 private Locator locator; 51 52 private Reader reader; 53 54 private Stack schemaLevels = new Stack (); 55 56 private Stack argStack = new Stack (); 57 58 private Schema defaultSchema; 59 60 public void characters(char[] ch, int start, int length) 61 throws SAXException { 62 int lineNumber = locator.getLineNumber(); 63 64 Schema schemaLevel = getTopSchemaLevel(); 67 68 Class slc = schemaLevel.getClass(); 71 HandlerClassInfo classInfo = HandlerClassInfo.getClassInfo(slc); 72 assert (classInfo != null); HandlerMethod method = classInfo.getTextMethod(); 74 if (method == null) { 75 return; 78 } 79 80 try { 83 final String text = String.valueOf(ch, start, length); 84 method.invokeText(lineNumber, text, schemaLevel); 85 } catch (UnableToCompleteException e) { 86 throw new SAXException (e); 87 } 88 } 89 90 public void endElement(String namespaceURI, String localName, String elem) 91 throws SAXException { 92 int lineNumber = locator.getLineNumber(); 93 94 Schema schemaLevel = popLevel(); 97 if (schemaLevel == null) { 98 return; 102 } 103 104 Class slc = schemaLevel.getClass(); 107 HandlerClassInfo classInfo = HandlerClassInfo.getClassInfo(slc); 108 assert (classInfo != null); HandlerMethod method = classInfo.getEndMethod(elem); 110 if (method == null) { 111 return; 114 } 115 116 Object [] args = getCurrentArgs(); 117 if (args != null) { 118 try { 122 method.invokeEnd(lineNumber, elem, schemaLevel, args); 123 } catch (UnableToCompleteException e) { 124 throw new SAXException (e); 125 } 126 } 127 } 128 129 public void setDocumentLocator(Locator locator) { 130 this.locator = locator; 131 } 132 133 public void startElement(String namespaceURI, String localName, 134 String elemName, Attributes atts) throws SAXException { 135 int lineNumber = locator.getLineNumber(); 136 137 Schema schemaLevel = getTopSchemaLevel(); 140 if (schemaLevel == null) { 141 Schema nextToTop = getNextToTopSchemaLevel(); 144 145 setArgsAndPushLevel(null, null); 148 149 try { 152 nextToTop.onUnexpectedChild(lineNumber, elemName); 153 } catch (UnableToCompleteException e) { 154 throw new SAXException (e); 155 } 156 157 return; 158 } 159 160 Class slc = schemaLevel.getClass(); 163 HandlerClassInfo classInfo = HandlerClassInfo.getClassInfo(slc); 164 HandlerMethod method = classInfo.getStartMethod(elemName); 165 166 if (method == null) { 167 try { 171 schemaLevel.onUnexpectedElement(lineNumber, elemName); 172 } catch (UnableToCompleteException e) { 173 throw new SAXException (e); 174 } 175 176 setArgsAndPushLevel(null, null); 180 181 return; 182 } 183 184 HandlerArgs args = method.createArgs(schemaLevel, lineNumber, elemName); 185 186 for (int i = 0, n = atts.getLength(); i < n; ++i) { 189 String attrName = atts.getQName(i); 190 String attrValue = atts.getValue(i); 191 192 if (!args.setArg(attrName, attrValue)) { 193 try { 196 schemaLevel.onUnexpectedAttribute(lineNumber, elemName, attrName, 197 attrValue); 198 } catch (UnableToCompleteException e) { 199 throw new SAXException (e); 200 } 201 } 202 } 203 204 int missingCount = 0; 207 for (int i = 0, n = args.getArgCount(); i < n; ++i) { 208 if (!args.isArgSet(i)) { 209 try { 213 schemaLevel.onMissingAttribute(lineNumber, elemName, 214 args.getArgName(i)); 215 } catch (UnableToCompleteException e) { 216 throw new SAXException (e); 217 } 218 219 ++missingCount; 220 } 221 } 222 223 if (missingCount > 0) { 224 227 setArgsAndPushLevel(null, null); 231 232 return; 233 } 234 235 Object [] invokeArgs = new Object [method.getParamCount()]; 240 Schema childSchemaLevel; 241 try { 242 childSchemaLevel = method.invokeBegin(lineNumber, elemName, 243 schemaLevel, args, invokeArgs); 244 } catch (UnableToCompleteException e) { 245 throw new SAXException (e); 246 } 247 248 setArgsAndPushLevel(invokeArgs, childSchemaLevel); 253 } 254 255 private Object [] getCurrentArgs() { 256 return (Object []) argStack.peek(); 257 } 258 259 private Schema getNextToTopSchemaLevel() { 260 return (Schema) schemaLevels.get(schemaLevels.size() - 2); 261 } 262 263 private Schema getTopSchemaLevel() { 264 return (Schema) schemaLevels.peek(); 265 } 266 267 private void parse(TreeLogger logger, Schema topSchema, Reader reader) 268 throws UnableToCompleteException { 269 defaultSchema = new DefaultSchema(logger); 273 274 topSchema.setParent(defaultSchema); 279 280 argStack.push(null); 283 284 setArgsAndPushLevel(null, topSchema); 287 288 Throwable caught = null; 289 try { 290 this.reader = reader; 291 SAXParser parser = SAXParserFactory.newInstance().newSAXParser(); 292 InputSource inputSource = new InputSource (this.reader); 293 XMLReader xmlReader = parser.getXMLReader(); 294 xmlReader.setContentHandler(this); 295 xmlReader.parse(inputSource); 296 } catch (SAXException e) { 297 caught = e; 301 302 Exception inner = e.getException(); 303 if (inner instanceof RuntimeException ) { 304 throw (RuntimeException ) inner; 305 } else if (inner != null) { 306 caught = inner; 307 } 308 309 } catch (ParserConfigurationException e) { 310 caught = e; 311 } catch (IOException e) { 312 caught = e; 313 } finally { 314 Utility.close(reader); 315 } 316 317 if (caught != null) { 318 Messages.XML_PARSE_FAILED.log(logger, caught); 319 throw new UnableToCompleteException(); 320 } 321 } 322 323 private Schema popLevel() { 324 argStack.pop(); 325 schemaLevels.pop(); 326 return getTopSchemaLevel(); 327 } 328 329 private void setArgsAndPushLevel(Object [] handlerArgs, Schema schemaLevel) { 330 argStack.set(argStack.size() - 1, handlerArgs); 332 argStack.push(null); 334 if (!schemaLevels.isEmpty()) { 335 Schema maybeParent = null; 338 for (int i = schemaLevels.size() - 1; i >= 0; --i) { 339 maybeParent = (Schema) schemaLevels.get(i); 340 if (maybeParent != null) { 341 break; 342 } 343 } 344 if (maybeParent == null) { 345 throw new IllegalStateException ("Cannot find any parent schema"); 346 } 347 if (schemaLevel != null) { 348 schemaLevel.setParent(maybeParent); 349 } 350 } 351 schemaLevels.push(schemaLevel); 353 } 354 } 355 356 public static void parse(TreeLogger logger, Schema schema, Reader reader) 357 throws UnableToCompleteException { 358 359 registerSchemaLevel(schema.getClass()); 362 363 Impl impl = new Impl(); 366 impl.parse(logger, schema, reader); 367 } 368 369 372 public static void registerSchemaLevel(Class schemaLevelClass) { 373 HandlerClassInfo.registerClass(schemaLevelClass); 374 375 Class [] nested = schemaLevelClass.getDeclaredClasses(); 378 for (int i = 0, n = nested.length; i < n; ++i) { 379 Class nestedClass = nested[i]; 380 if (Schema.class.isAssignableFrom(nestedClass)) { 381 registerSchemaLevel(nestedClass); 382 } 383 } 384 } 385 } 386 | Popular Tags |