1 29 30 package com.caucho.xml.stream; 31 32 import com.caucho.vfs.WriteStream; 33 34 import javax.xml.namespace.NamespaceContext ; 35 import javax.xml.namespace.QName ; 36 import javax.xml.stream.XMLStreamException; 37 import javax.xml.stream.XMLStreamWriter; 38 import java.io.IOException ; 39 import java.util.ArrayList ; 40 import java.util.logging.Logger ; 41 42 public class XMLStreamWriterImpl implements XMLStreamWriter { 43 private static final Logger log 44 = Logger.getLogger(XMLStreamReaderImpl.class.getName()); 45 46 private WriteStream _ws; 47 private NamespaceWriterContext _tracker; 48 49 private QName _pendingTagName = null; 50 private boolean _shortTag = false; 51 private boolean _repair = false; 52 private ArrayList <QName > _pendingAttributeNames = new ArrayList <QName >(); 53 private ArrayList <String > _pendingAttributeValues = new ArrayList <String >(); 54 55 public XMLStreamWriterImpl(WriteStream ws) 56 { 57 this(ws, false); 58 } 59 60 public XMLStreamWriterImpl(WriteStream ws, boolean repair) 61 { 62 _ws = ws; 63 _repair = repair; 64 _tracker = new NamespaceWriterContext(repair); 65 } 66 67 public void close() throws XMLStreamException 68 { 69 try { 70 flushPending(); 71 _ws.close(); 72 } 73 catch (IOException e) { 74 throw new XMLStreamException(e); 75 } 76 } 77 78 public void flush() throws XMLStreamException 79 { 80 try { 81 _ws.flush(); 82 } 83 catch (IOException e) { 84 throw new XMLStreamException(e); 85 } 86 } 87 88 public NamespaceContext getNamespaceContext() 89 { 90 return _tracker; 91 } 92 93 public String getPrefix(String uri) 94 throws XMLStreamException 95 { 96 return _tracker.getPrefix(uri); 97 } 98 99 public Object getProperty(String name) 100 throws IllegalArgumentException 101 { 102 throw new PropertyNotSupportedException(name); 103 } 104 105 public void setDefaultNamespace(String uri) 106 throws XMLStreamException 107 { 108 _tracker.declare(null, uri, _repair); 109 } 110 111 public void setNamespaceContext(NamespaceContext context) 112 throws XMLStreamException 113 { 114 String message = "please do not set the NamespaceContext"; 115 throw new UnsupportedOperationException (message); 116 } 117 118 public void setPrefix(String prefix, String uri) 119 throws XMLStreamException 120 { 121 _tracker.declare(prefix, uri); 122 } 123 124 public void writeAttribute(String localName, String value) 125 throws XMLStreamException 126 { 127 _pendingAttributeNames.add(new QName (localName)); 128 _pendingAttributeValues.add(value); 129 } 130 131 public void writeAttribute(String namespaceURI, String localName, 132 String value) 133 throws XMLStreamException 134 { 135 if (_repair) { 136 String prefix = _tracker.declare(namespaceURI); 137 138 if (prefix == null) 139 _pendingAttributeNames.add(new QName (namespaceURI, localName)); 140 else 141 _pendingAttributeNames.add(new QName (namespaceURI, localName, prefix)); 142 } 143 else 144 _pendingAttributeNames.add(new QName (namespaceURI, localName)); 145 146 _pendingAttributeValues.add(value); 147 } 148 149 public void writeAttribute(String prefix, String namespaceURI, 150 String localName, String value) 151 throws XMLStreamException 152 { 153 if (_repair && _tracker.getPrefix(namespaceURI) == null) 154 _tracker.declare(prefix, namespaceURI, true); 155 else 156 _tracker.declare(prefix, namespaceURI); 157 158 _pendingAttributeNames.add(new QName (namespaceURI, localName, prefix)); 159 _pendingAttributeValues.add(value); 160 } 161 162 public void writeCData(String data) 163 throws XMLStreamException 164 { 165 flushPending(); 166 try { 167 _ws.print("<![CDATA["); 168 _ws.print(data); 169 _ws.print("]]>"); 170 } 171 catch (IOException e) { 172 throw new XMLStreamException(e); 173 } 174 } 175 176 public void writeCharacters(char[] text, int start, int len) 177 throws XMLStreamException 178 { 179 flushPending(); 180 try { 181 Escapifier.escape(text, start, len, _ws); 182 } 183 catch (IOException e) { 184 throw new XMLStreamException(e); 185 } 186 } 187 188 public void writeCharacters(String text) 189 throws XMLStreamException 190 { 191 flushPending(); 192 try { 193 Escapifier.escape(text, _ws); 194 } 195 catch (IOException e) { 196 throw new XMLStreamException(e); 197 } 198 } 199 200 public void writeComment(String data) 201 throws XMLStreamException 202 { 203 flushPending(); 204 try { 205 _ws.print("<!--"); 206 _ws.print(data); 207 _ws.print("-->"); 208 } 209 catch (IOException e) { 210 throw new XMLStreamException(e); 211 } 212 } 213 214 public void writeDefaultNamespace(String namespaceURI) 215 throws XMLStreamException 216 { 217 _tracker.declare("", namespaceURI, true); 218 } 219 220 public void writeDTD(String dtd) 221 throws XMLStreamException 222 { 223 throw new UnsupportedOperationException (); 224 } 225 226 public void writeEmptyElement(String localName) 227 throws XMLStreamException 228 { 229 flushPending(); 230 try { 231 QName qname = new QName (localName); 232 pushContext(qname); 233 _pendingTagName = qname; 234 _shortTag = true; 235 } 236 catch (IOException e) { 237 throw new XMLStreamException(e); 238 } 239 } 240 241 public void writeEmptyElement(String namespaceURI, String localName) 242 throws XMLStreamException 243 { 244 flushPending(); 245 246 try { 247 QName qname = null; 248 249 if (_repair) { 250 String prefix = _tracker.declare(namespaceURI); 251 252 if (prefix == null) 253 qname = new QName (namespaceURI, localName); 254 else 255 qname = new QName (namespaceURI, localName, prefix); 256 } 257 else 258 qname = new QName (namespaceURI, localName); 259 260 pushContext(qname); 261 _pendingTagName = qname; 262 _shortTag = true; 263 } 264 catch (IOException e) { 265 throw new XMLStreamException(e); 266 } 267 } 268 269 public void writeEmptyElement(String prefix, String localName, 270 String namespaceURI) 271 throws XMLStreamException 272 { 273 flushPending(); 274 try { 275 if (_repair && _tracker.getPrefix(namespaceURI) == null) 276 _tracker.declare(prefix, namespaceURI, true); 277 278 QName qname = new QName (namespaceURI, localName, prefix); 279 pushContext(qname); 280 _pendingTagName = qname; 281 _shortTag = true; 282 } 283 catch (IOException e) { 284 throw new XMLStreamException(e); 285 } 286 } 287 288 public void writeEndDocument() 289 throws XMLStreamException 290 { 291 } 292 293 public void writeEndElement() 294 throws XMLStreamException 295 { 296 flushPending(); 297 try { 298 QName name = popContext(); 299 _ws.print("</"); 300 _ws.print(printQName(name)); 301 _ws.print(">"); 302 } 303 catch (IOException e) { 304 throw new XMLStreamException(e); 305 } 306 } 307 308 private static String printQName(QName name) { 309 310 if (name.getPrefix() == null || name.getPrefix().equals("")) 311 return name.getLocalPart(); 312 313 return name.getPrefix() + ":" + name.getLocalPart(); 314 } 315 316 public void writeEntityRef(String name) 317 throws XMLStreamException 318 { 319 flushPending(); 320 try { 321 _ws.print("&"); 322 _ws.print(name); 323 _ws.print(";"); 324 } 325 catch (IOException e) { 326 throw new XMLStreamException(e); 327 } 328 } 329 330 public void writeNamespace(String prefix, String namespaceURI) 331 throws XMLStreamException 332 { 333 if (_pendingTagName == null) 334 throw new XMLStreamException("Namespace written before element"); 335 336 if (prefix == null || "".equals(prefix) || "xmlns".equals(prefix)) 337 writeDefaultNamespace(namespaceURI); 338 else 339 _tracker.declare(prefix, namespaceURI, true); 340 } 341 342 public void writeProcessingInstruction(String target) 343 throws XMLStreamException 344 { 345 flushPending(); 346 try { 347 _ws.print("<?"); 348 _ws.print(target); 349 _ws.print("?>"); 350 } 351 catch (IOException e) { 352 throw new XMLStreamException(e); 353 } 354 } 355 356 public void writeProcessingInstruction(String target, String data) 357 throws XMLStreamException 358 { 359 flushPending(); 360 try { 361 _ws.print("<?"); 362 _ws.print(target); 363 _ws.print(" "); 364 _ws.print(data); 365 _ws.print("?>"); 366 } 367 catch (IOException e) { 368 throw new XMLStreamException(e); 369 } 370 } 371 372 public void writeStartDocument() 373 throws XMLStreamException 374 { 375 writeStartDocument("1.0"); 376 } 377 378 public void writeStartDocument(String version) 379 throws XMLStreamException 380 { 381 writeStartDocument("utf-8", version); 382 } 383 384 public void writeStartDocument(String encoding, String version) 385 throws XMLStreamException 386 { 387 try { 388 _ws.print("<?xml version=\""+version+"\" encoding=\""+encoding+"\"?>"); 389 } 390 catch (IOException e) { 391 throw new XMLStreamException(e); 392 } 393 } 394 395 public void writeStartElement(String localName) 396 throws XMLStreamException 397 { 398 flushPending(); 399 try { 400 QName qname = new QName (localName); 401 pushContext(qname); 402 _pendingTagName = qname; 403 } 404 catch (IOException e) { 405 throw new XMLStreamException(e); 406 } 407 } 408 409 public void writeStartElement(String namespaceURI, String localName) 410 throws XMLStreamException 411 { 412 flushPending(); 413 try { 414 QName qname = null; 415 416 if (_repair) { 417 String prefix = _tracker.declare(namespaceURI); 418 419 if (prefix == null) 420 qname = new QName (namespaceURI, localName); 421 else 422 qname = new QName (namespaceURI, localName, prefix); 423 } 424 else 425 qname = new QName (namespaceURI, localName); 426 427 pushContext(qname); 428 _pendingTagName = qname; 429 } 430 catch (IOException e) { 431 throw new XMLStreamException(e); 432 } 433 } 434 435 public void writeStartElement(String prefix, String localName, 436 String namespaceURI) 437 throws XMLStreamException 438 { 439 flushPending(); 440 try { 441 if (_repair && _tracker.getPrefix(namespaceURI) == null) 442 _tracker.declare(prefix, namespaceURI, true); 443 444 QName qname = new QName (namespaceURI, localName, prefix); 445 pushContext(qname); 446 _pendingTagName = qname; 447 } 448 catch (IOException e) { 449 throw new XMLStreamException(e); 450 } 451 } 452 453 455 private boolean _flushed = true; 456 457 private void pushContext(QName elementName) 458 throws IOException 459 { 460 flushContext(); 461 _tracker.push(); 462 _tracker.setElementName(elementName); 463 _flushed = false; 464 } 465 466 private QName popContext() 467 throws IOException 468 { 469 flushContext(); 470 QName name = _tracker.getElementName(); 471 _tracker.pop(); 472 return name; 473 } 474 475 private void flushContext() 476 throws IOException 477 { 478 if (_flushed) return; 479 _tracker.emitDeclarations(_ws); 480 _flushed = true; 481 } 482 483 private void flushPending() 484 throws XMLStreamException 485 { 486 try { 487 if (_pendingTagName == null) return; 488 489 _ws.print("<"); 490 _ws.print(printQName(_pendingTagName)); 491 492 for(int i=0; i<_pendingAttributeNames.size(); i++) { 493 _ws.print(" "); 494 _ws.print(printQName(_pendingAttributeNames.get(i))); 495 _ws.print("=\""); 496 Escapifier.escape(_pendingAttributeValues.get(i), _ws); 497 _ws.print('"'); 498 } 499 flushContext(); 500 501 if (_shortTag) { 502 _ws.print("/>"); 503 popContext(); 504 } else { 505 _ws.print(">"); 506 } 507 508 _pendingTagName = null; 509 _pendingAttributeNames.clear(); 510 _pendingAttributeValues.clear(); 511 _shortTag = false; 512 } 513 catch (IOException e) { 514 throw new XMLStreamException(e); 515 } 516 } 517 } 518 | Popular Tags |