1 7 8 package org.dom4j.io; 9 10 import java.io.Externalizable ; 11 import java.io.IOException ; 12 import java.io.ObjectInput ; 13 import java.io.ObjectOutput ; 14 import java.util.ArrayList ; 15 import java.util.HashMap ; 16 import java.util.Iterator ; 17 import java.util.List ; 18 import java.util.Map ; 19 20 import org.dom4j.Namespace; 21 import org.dom4j.QName; 22 import org.xml.sax.Attributes ; 23 import org.xml.sax.ContentHandler ; 24 import org.xml.sax.DTDHandler ; 25 import org.xml.sax.SAXException ; 26 import org.xml.sax.ext.DeclHandler ; 27 import org.xml.sax.ext.LexicalHandler ; 28 import org.xml.sax.helpers.AttributesImpl ; 29 import org.xml.sax.helpers.DefaultHandler ; 30 31 60 public class SAXEventRecorder extends DefaultHandler implements LexicalHandler , 61 DeclHandler , DTDHandler , Externalizable { 62 public static final long serialVersionUID = 1; 63 64 private static final byte STRING = 0; 65 66 private static final byte OBJECT = 1; 67 68 private static final byte NULL = 2; 69 70 private List events = new ArrayList (); 71 72 private Map prefixMappings = new HashMap (); 73 74 private static final String XMLNS = "xmlns"; 75 76 private static final String EMPTY_STRING = ""; 77 78 public SAXEventRecorder() { 79 } 80 81 public void replay(ContentHandler handler) throws SAXException { 82 SAXEvent saxEvent; 83 Iterator itr = events.iterator(); 84 85 while (itr.hasNext()) { 86 saxEvent = (SAXEvent) itr.next(); 87 88 switch (saxEvent.event) { 89 case SAXEvent.PROCESSING_INSTRUCTION: 91 handler.processingInstruction((String ) saxEvent.getParm(0), 92 (String ) saxEvent.getParm(1)); 93 94 break; 95 96 case SAXEvent.START_PREFIX_MAPPING: 97 handler.startPrefixMapping((String ) saxEvent.getParm(0), 98 (String ) saxEvent.getParm(1)); 99 100 break; 101 102 case SAXEvent.END_PREFIX_MAPPING: 103 handler.endPrefixMapping((String ) saxEvent.getParm(0)); 104 105 break; 106 107 case SAXEvent.START_DOCUMENT: 108 handler.startDocument(); 109 110 break; 111 112 case SAXEvent.END_DOCUMENT: 113 handler.endDocument(); 114 115 break; 116 117 case SAXEvent.START_ELEMENT: 118 119 AttributesImpl attributes = new AttributesImpl (); 120 List attParmList = (List ) saxEvent.getParm(3); 121 122 if (attParmList != null) { 123 Iterator attsItr = attParmList.iterator(); 124 125 while (attsItr.hasNext()) { 126 String [] attParms = (String []) attsItr.next(); 127 attributes.addAttribute(attParms[0], attParms[1], 128 attParms[2], attParms[3], attParms[4]); 129 } 130 } 131 132 handler.startElement((String ) saxEvent.getParm(0), 133 (String ) saxEvent.getParm(1), (String ) saxEvent 134 .getParm(2), attributes); 135 136 break; 137 138 case SAXEvent.END_ELEMENT: 139 handler.endElement((String ) saxEvent.getParm(0), 140 (String ) saxEvent.getParm(1), (String ) saxEvent 141 .getParm(2)); 142 143 break; 144 145 case SAXEvent.CHARACTERS: 146 147 char[] chars = (char[]) saxEvent.getParm(0); 148 int start = ((Integer ) saxEvent.getParm(1)).intValue(); 149 int end = ((Integer ) saxEvent.getParm(2)).intValue(); 150 handler.characters(chars, start, end); 151 152 break; 153 154 case SAXEvent.START_DTD: 156 ((LexicalHandler ) handler).startDTD((String ) saxEvent 157 .getParm(0), (String ) saxEvent.getParm(1), 158 (String ) saxEvent.getParm(2)); 159 160 break; 161 162 case SAXEvent.END_DTD: 163 ((LexicalHandler ) handler).endDTD(); 164 165 break; 166 167 case SAXEvent.START_ENTITY: 168 ((LexicalHandler ) handler).startEntity((String ) saxEvent 169 .getParm(0)); 170 171 break; 172 173 case SAXEvent.END_ENTITY: 174 ((LexicalHandler ) handler).endEntity((String ) saxEvent 175 .getParm(0)); 176 177 break; 178 179 case SAXEvent.START_CDATA: 180 ((LexicalHandler ) handler).startCDATA(); 181 182 break; 183 184 case SAXEvent.END_CDATA: 185 ((LexicalHandler ) handler).endCDATA(); 186 187 break; 188 189 case SAXEvent.COMMENT: 190 191 char[] cchars = (char[]) saxEvent.getParm(0); 192 int cstart = ((Integer ) saxEvent.getParm(1)).intValue(); 193 int cend = ((Integer ) saxEvent.getParm(2)).intValue(); 194 ((LexicalHandler ) handler).comment(cchars, cstart, cend); 195 196 break; 197 198 case SAXEvent.ELEMENT_DECL: 200 ((DeclHandler ) handler).elementDecl((String ) saxEvent 201 .getParm(0), (String ) saxEvent.getParm(1)); 202 203 break; 204 205 case SAXEvent.ATTRIBUTE_DECL: 206 ((DeclHandler ) handler).attributeDecl((String ) saxEvent 207 .getParm(0), (String ) saxEvent.getParm(1), 208 (String ) saxEvent.getParm(2), (String ) saxEvent 209 .getParm(3), (String ) saxEvent.getParm(4)); 210 211 break; 212 213 case SAXEvent.INTERNAL_ENTITY_DECL: 214 ((DeclHandler ) handler).internalEntityDecl( 215 (String ) saxEvent.getParm(0), (String ) saxEvent 216 .getParm(1)); 217 218 break; 219 220 case SAXEvent.EXTERNAL_ENTITY_DECL: 221 ((DeclHandler ) handler).externalEntityDecl( 222 (String ) saxEvent.getParm(0), (String ) saxEvent 223 .getParm(1), (String ) saxEvent.getParm(2)); 224 225 break; 226 227 default: 228 throw new SAXException ("Unrecognized event: " 229 + saxEvent.event); 230 } 231 } 232 } 233 234 public void processingInstruction(String target, String data) 237 throws SAXException { 238 SAXEvent saxEvent = new SAXEvent(SAXEvent.PROCESSING_INSTRUCTION); 239 saxEvent.addParm(target); 240 saxEvent.addParm(data); 241 events.add(saxEvent); 242 } 243 244 public void startPrefixMapping(String prefix, String uri) 245 throws SAXException { 246 SAXEvent saxEvent = new SAXEvent(SAXEvent.START_PREFIX_MAPPING); 247 saxEvent.addParm(prefix); 248 saxEvent.addParm(uri); 249 events.add(saxEvent); 250 } 251 252 public void endPrefixMapping(String prefix) throws SAXException { 253 SAXEvent saxEvent = new SAXEvent(SAXEvent.END_PREFIX_MAPPING); 254 saxEvent.addParm(prefix); 255 events.add(saxEvent); 256 } 257 258 public void startDocument() throws SAXException { 259 SAXEvent saxEvent = new SAXEvent(SAXEvent.START_DOCUMENT); 260 events.add(saxEvent); 261 } 262 263 public void endDocument() throws SAXException { 264 SAXEvent saxEvent = new SAXEvent(SAXEvent.END_DOCUMENT); 265 events.add(saxEvent); 266 } 267 268 public void startElement(String namespaceURI, String localName, 269 String qualifiedName, Attributes attributes) throws SAXException { 270 SAXEvent saxEvent = new SAXEvent(SAXEvent.START_ELEMENT); 271 saxEvent.addParm(namespaceURI); 272 saxEvent.addParm(localName); 273 saxEvent.addParm(qualifiedName); 274 275 QName qName = null; 276 if (namespaceURI != null) { 277 qName = new QName(localName, Namespace.get(namespaceURI)); 278 } else { 279 qName = new QName(localName); 280 } 281 282 if ((attributes != null) && (attributes.getLength() > 0)) { 283 List attParmList = new ArrayList (attributes.getLength()); 284 String [] attParms = null; 285 286 for (int i = 0; i < attributes.getLength(); i++) { 287 288 String attLocalName = attributes.getLocalName(i); 289 290 if (attLocalName.startsWith(XMLNS)) { 291 292 String prefix = null; 296 if (attLocalName.length() > 5) { 297 prefix = attLocalName.substring(6); 298 } else { 299 prefix = EMPTY_STRING; 300 } 301 302 SAXEvent prefixEvent = new SAXEvent( 303 SAXEvent.START_PREFIX_MAPPING); 304 prefixEvent.addParm(prefix); 305 prefixEvent.addParm(attributes.getValue(i)); 306 events.add(prefixEvent); 307 308 List prefixes = (List ) prefixMappings.get(qName); 311 if (prefixes == null) { 312 prefixes = new ArrayList (); 313 prefixMappings.put(qName, prefixes); 314 } 315 prefixes.add(prefix); 316 317 } else { 318 319 attParms = new String [5]; 320 attParms[0] = attributes.getURI(i); 321 attParms[1] = attLocalName; 322 attParms[2] = attributes.getQName(i); 323 attParms[3] = attributes.getType(i); 324 attParms[4] = attributes.getValue(i); 325 attParmList.add(attParms); 326 327 } 328 329 } 330 331 saxEvent.addParm(attParmList); 332 } 333 334 events.add(saxEvent); 335 } 336 337 public void endElement(String namespaceURI, String localName, String qName) 338 throws SAXException { 339 340 SAXEvent saxEvent = new SAXEvent(SAXEvent.END_ELEMENT); 341 saxEvent.addParm(namespaceURI); 342 saxEvent.addParm(localName); 343 saxEvent.addParm(qName); 344 events.add(saxEvent); 345 346 349 QName elementName = null; 350 if (namespaceURI != null) { 351 elementName = new QName(localName, Namespace.get(namespaceURI)); 352 } else { 353 elementName = new QName(localName); 354 } 355 356 List prefixes = (List ) prefixMappings.get(elementName); 357 if (prefixes != null) { 358 Iterator itr = prefixes.iterator(); 359 while (itr.hasNext()) { 360 SAXEvent prefixEvent = 361 new SAXEvent(SAXEvent.END_PREFIX_MAPPING); 362 prefixEvent.addParm(itr.next()); 363 events.add(prefixEvent); 364 } 365 } 366 367 } 368 369 public void characters(char[] ch, int start, int end) throws SAXException { 370 SAXEvent saxEvent = new SAXEvent(SAXEvent.CHARACTERS); 371 saxEvent.addParm(ch); 372 saxEvent.addParm(new Integer (start)); 373 saxEvent.addParm(new Integer (end)); 374 events.add(saxEvent); 375 } 376 377 public void startDTD(String name, String publicId, String systemId) 380 throws SAXException { 381 SAXEvent saxEvent = new SAXEvent(SAXEvent.START_DTD); 382 saxEvent.addParm(name); 383 saxEvent.addParm(publicId); 384 saxEvent.addParm(systemId); 385 events.add(saxEvent); 386 } 387 388 public void endDTD() throws SAXException { 389 SAXEvent saxEvent = new SAXEvent(SAXEvent.END_DTD); 390 events.add(saxEvent); 391 } 392 393 public void startEntity(String name) throws SAXException { 394 SAXEvent saxEvent = new SAXEvent(SAXEvent.START_ENTITY); 395 saxEvent.addParm(name); 396 events.add(saxEvent); 397 } 398 399 public void endEntity(String name) throws SAXException { 400 SAXEvent saxEvent = new SAXEvent(SAXEvent.END_ENTITY); 401 saxEvent.addParm(name); 402 events.add(saxEvent); 403 } 404 405 public void startCDATA() throws SAXException { 406 SAXEvent saxEvent = new SAXEvent(SAXEvent.START_CDATA); 407 events.add(saxEvent); 408 } 409 410 public void endCDATA() throws SAXException { 411 SAXEvent saxEvent = new SAXEvent(SAXEvent.END_CDATA); 412 events.add(saxEvent); 413 } 414 415 public void comment(char[] ch, int start, int end) throws SAXException { 416 SAXEvent saxEvent = new SAXEvent(SAXEvent.COMMENT); 417 saxEvent.addParm(ch); 418 saxEvent.addParm(new Integer (start)); 419 saxEvent.addParm(new Integer (end)); 420 events.add(saxEvent); 421 } 422 423 public void elementDecl(String name, String model) throws SAXException { 426 SAXEvent saxEvent = new SAXEvent(SAXEvent.ELEMENT_DECL); 427 saxEvent.addParm(name); 428 saxEvent.addParm(model); 429 events.add(saxEvent); 430 } 431 432 public void attributeDecl(String eName, String aName, String type, 433 String valueDefault, String value) throws SAXException { 434 SAXEvent saxEvent = new SAXEvent(SAXEvent.ATTRIBUTE_DECL); 435 saxEvent.addParm(eName); 436 saxEvent.addParm(aName); 437 saxEvent.addParm(type); 438 saxEvent.addParm(valueDefault); 439 saxEvent.addParm(value); 440 events.add(saxEvent); 441 } 442 443 public void internalEntityDecl(String name, String value) 444 throws SAXException { 445 SAXEvent saxEvent = new SAXEvent(SAXEvent.INTERNAL_ENTITY_DECL); 446 saxEvent.addParm(name); 447 saxEvent.addParm(value); 448 events.add(saxEvent); 449 } 450 451 public void externalEntityDecl(String name, String publicId, String sysId) 452 throws SAXException { 453 SAXEvent saxEvent = new SAXEvent(SAXEvent.EXTERNAL_ENTITY_DECL); 454 saxEvent.addParm(name); 455 saxEvent.addParm(publicId); 456 saxEvent.addParm(sysId); 457 events.add(saxEvent); 458 } 459 460 public void writeExternal(ObjectOutput out) throws IOException { 461 if (events == null) { 462 out.writeByte(NULL); 463 } else { 464 out.writeByte(OBJECT); 465 out.writeObject(events); 466 } 467 } 468 469 public void readExternal(ObjectInput in) throws ClassNotFoundException , 470 IOException { 471 if (in.readByte() != NULL) { 472 events = (List ) in.readObject(); 473 } 474 } 475 476 static class SAXEvent implements Externalizable { 479 public static final long serialVersionUID = 1; 480 481 static final byte PROCESSING_INSTRUCTION = 1; 482 483 static final byte START_PREFIX_MAPPING = 2; 484 485 static final byte END_PREFIX_MAPPING = 3; 486 487 static final byte START_DOCUMENT = 4; 488 489 static final byte END_DOCUMENT = 5; 490 491 static final byte START_ELEMENT = 6; 492 493 static final byte END_ELEMENT = 7; 494 495 static final byte CHARACTERS = 8; 496 497 static final byte START_DTD = 9; 498 499 static final byte END_DTD = 10; 500 501 static final byte START_ENTITY = 11; 502 503 static final byte END_ENTITY = 12; 504 505 static final byte START_CDATA = 13; 506 507 static final byte END_CDATA = 14; 508 509 static final byte COMMENT = 15; 510 511 static final byte ELEMENT_DECL = 16; 512 513 static final byte ATTRIBUTE_DECL = 17; 514 515 static final byte INTERNAL_ENTITY_DECL = 18; 516 517 static final byte EXTERNAL_ENTITY_DECL = 19; 518 519 protected byte event; 520 521 protected List parms; 522 523 public SAXEvent() { 524 } 525 526 SAXEvent(byte event) { 527 this.event = event; 528 } 529 530 void addParm(Object parm) { 531 if (parms == null) { 532 parms = new ArrayList (3); 533 } 534 535 parms.add(parm); 536 } 537 538 Object getParm(int index) { 539 if ((parms != null) && (index < parms.size())) { 540 return parms.get(index); 541 } else { 542 return null; 543 } 544 } 545 546 public void writeExternal(ObjectOutput out) throws IOException { 547 out.writeByte(event); 548 549 if (parms == null) { 550 out.writeByte(NULL); 551 } else { 552 out.writeByte(OBJECT); 553 out.writeObject(parms); 554 } 555 } 556 557 public void readExternal(ObjectInput in) throws ClassNotFoundException , 558 IOException { 559 event = in.readByte(); 560 561 if (in.readByte() != NULL) { 562 parms = (List ) in.readObject(); 563 } 564 } 565 } 566 } 567 568 604 | Popular Tags |