1 64 65 66 package com.jcorporate.expresso.ext.report; 67 68 69 import com.jcorporate.expresso.core.misc.StringUtil; 70 import com.jcorporate.expresso.kernel.exception.ExpressoRuntimeException; 71 import com.jcorporate.expresso.kernel.management.DOMWriter; 72 import com.jcorporate.expresso.kernel.util.FastStringBuffer; 73 import org.apache.log4j.Logger; 74 import org.w3c.dom.Attr ; 75 import org.w3c.dom.Document ; 76 import org.w3c.dom.DocumentType ; 77 import org.w3c.dom.Entity ; 78 import org.w3c.dom.NamedNodeMap ; 79 import org.w3c.dom.Node ; 80 import org.w3c.dom.NodeList ; 81 import org.xml.sax.ErrorHandler ; 82 import org.xml.sax.InputSource ; 83 import org.xml.sax.SAXException ; 84 import org.xml.sax.SAXParseException ; 85 86 import javax.xml.parsers.DocumentBuilder ; 87 import javax.xml.parsers.DocumentBuilderFactory ; 88 import java.io.BufferedWriter ; 89 import java.io.File ; 90 import java.io.FileWriter ; 91 import java.io.IOException ; 92 import java.io.OutputStream ; 93 import java.io.OutputStreamWriter ; 94 import java.io.StringWriter ; 95 import java.io.Writer ; 96 import java.util.StringTokenizer ; 97 98 99 104 105 public class XMLPrinter implements ErrorHandler , DOMWriter { 106 107 protected static Logger log; 108 public static final OutputStreamWriter SYSTEM_OUT = new OutputStreamWriter (System.out); 109 public static final String DEFAULT_INDENT = " "; 111 114 protected Writer _out = null; 115 116 119 protected String _indent = DEFAULT_INDENT; 120 121 124 protected char _indentChar = ' '; 125 126 129 protected int _indentLength = 0; 130 131 134 protected int _column = 0; 135 136 139 protected boolean _omitXmlDecl = false; 140 141 144 protected String _newline = System.getProperty("line.separator"); 145 146 public XMLPrinter() { 147 log = Logger.getLogger(XMLPrinter.class); 148 setWriter(SYSTEM_OUT); 149 } 150 151 159 public void saveDocument(OutputStream os, Document document) 160 throws ExpressoRuntimeException { 161 try { 162 setWriter(new OutputStreamWriter (os)); 163 outputDocument(document.getDocumentElement()); 164 getWriter().flush(); 165 } catch (IOException ioe) { 166 throw new ExpressoRuntimeException(ioe); 167 } 168 } 169 170 176 public String getRequiredClass() { 177 return "org.w3c.dom.Document"; 178 } 179 180 183 public void outputDocument(Node node) throws IOException { 184 if (!_omitXmlDecl && node.getNodeType() == Node.ELEMENT_NODE) { 185 println("<?xml version='1.0' ?>"); 186 println(""); 187 } 188 printTree(node); 189 } 190 191 194 public void setWriter(Writer out) { 195 this._out = out; 196 } 197 198 201 public Writer getWriter() { 202 return this._out; 203 } 204 205 209 public void setIndentSize(int indentSize) { 210 _indent = ""; 211 _indentLength = 0; 212 213 int inc; 214 if (_indentChar == '\t') { 215 inc = 4; 216 } else { 217 inc = 1; 218 } 219 220 for (int i = 0; i < indentSize; i++) { 221 _indent += _indentChar; 222 _indentLength += inc; 223 } 224 } 225 226 232 public void setIndent(char indentChar, int size) { 233 _indentChar = indentChar; 234 setIndentSize(size); 235 } 236 237 240 public void setOmitXmlDecl(boolean b) { 241 _omitXmlDecl = b; 242 } 243 244 248 public void closeWriter() { 249 try { 250 this._out.close(); 251 } catch (IOException ioe) { 252 } 254 } 255 256 260 public void setFile(File file) throws IOException { 261 File parentDirectory = file.getParentFile(); 262 263 if (parentDirectory != null && !parentDirectory.exists()) { 264 parentDirectory.mkdirs(); 265 } 266 267 setWriter(new BufferedWriter (new FileWriter (file))); 268 } 269 270 274 public void setFile(String filename) throws IOException { 275 setFile(new File (filename)); 276 } 277 278 283 public static String nodeToString(Node node) { 284 try { 285 XMLPrinter printer = new XMLPrinter(); 286 287 StringWriter writer = new StringWriter (); 288 289 printer.setWriter(writer); 290 291 printer.outputDocument(node); 292 293 return writer.getBuffer().toString(); 294 295 } catch (IOException e) { 296 return null; 297 } 298 } 299 300 306 public static String toXML(String html) { 307 return toXML(html, true); 308 } 309 310 317 public static String toXML(String html, boolean escapeAll) { 318 if (html == null) { 319 return ""; 320 } 321 322 FastStringBuffer parsedString = new FastStringBuffer(html.length()); 323 324 String delim; 325 delim = "&;><'\""; 326 327 StringTokenizer st; 328 st = new StringTokenizer (html, delim, true); 329 330 String token; 331 332 while (st.hasMoreTokens()) { 333 token = st.nextToken(); 334 335 if (token.equals("&")) { 337 token = "&"; 338 } else if (token.equals(">")) { 339 token = ">"; 340 } else if (token.equals("<")) { 341 token = "<"; 342 } else if (escapeAll) { 343 if (token.equals(";")) { 344 token = ";"; 345 } else if (token.equals("'")) { 346 token = "'"; 347 } else if (token.equals("\"")) { 348 token = """; 349 } 350 } 351 parsedString.append(token); 352 } 353 return parsedString.toString(); 354 } 355 356 362 public void print(String string, String indent) throws IOException { 363 print(indent); 364 if (string != null) { 365 print(string.trim()); 366 } 367 } 368 369 375 public void println(String string, String indent) throws IOException { 376 print(indent); 377 if (string != null) { 378 println(string.trim()); 379 } else { 380 println(""); 381 } 382 } 383 384 389 public void print(String string) throws IOException { 390 this._out.write(string); 391 } 392 393 398 public void println(String string) throws IOException { 399 print(string); 400 print(_newline); 401 } 402 403 408 protected String getIndent(int col) { 409 String indent = ""; 410 411 String indent2x = this._indent + this._indent; 413 for (int i = (col & 0x7ffffe); i > 0; i -= 2) { 414 indent += indent2x; 415 } 416 if ((col & 0x01) == 1) { 417 indent += this._indent; 418 } 419 420 return indent; 421 } 422 423 426 protected void printTree(Node node, int col) throws IOException { 427 int old = _column; 428 _column = col; 429 printTree(node); 430 _column = old; 431 } 432 433 436 protected void printTree(Node node) throws IOException { 437 int nodeType = -1; 438 439 if (node != null) { 440 nodeType = node.getNodeType(); 441 switch (nodeType) { 442 case Node.DOCUMENT_NODE: 443 { 444 NodeList nodes = node.getChildNodes(); 445 446 if (nodes != null) { 447 for (int i = 0; i < nodes.getLength(); i++) { 448 printTree(nodes.item(i)); 449 } 450 } 451 452 break; 453 } 454 455 case Node.ELEMENT_NODE: 456 { 457 String name = node.getNodeName(); 458 this.print("<" + name, getIndent(this._column)); 459 460 NamedNodeMap attributes = node.getAttributes(); 461 for (int i = 0; i < attributes.getLength(); i++) { 462 Attr current = (Attr ) attributes.item(i); 463 464 469 if (current.getSpecified() == true) { 470 this.print(" " + current.getNodeName() + "='" + current.getNodeValue() + "'"); 471 } 472 473 474 } 476 if (!node.hasChildNodes()) { 477 this.println(" />"); 479 } else { 480 this.print(">"); 482 483 NodeList children = node.getChildNodes(); 484 485 boolean hasChildElements = false; 488 if (children != null) { 489 int len = children.getLength(); 490 for (int i = 0; i < len; i++) { 491 if (children.item(i).getNodeType() != Node.TEXT_NODE) { 492 hasChildElements = true; 493 break; 494 } 495 } 496 } 497 498 if (hasChildElements) { 500 this.println(""); 501 } 502 503 this._column++; 504 505 for (int i = 0; i < children.getLength(); i++) { 506 printTree(children.item(i)); 507 } 508 this._column--; 509 510 if (hasChildElements) { 512 this.println("</" + name + ">", getIndent(this._column)); 513 } else { 514 this.println("</" + name + ">"); 515 } 516 } 517 518 break; 519 } 520 521 case Node.TEXT_NODE: 522 { 523 String nodeValue = node.getNodeValue().trim(); 524 if (!nodeValue.equals("")) { 525 this.print(toXML(nodeValue)); 527 } 528 break; 529 } 530 531 case Node.CDATA_SECTION_NODE: 532 { 533 this.print("<![CDATA[", getIndent(this._column)); 534 535 this.print(convertNewline(node.getNodeValue())); 536 this.println("]]>"); 537 break; 538 } 539 540 case Node.PROCESSING_INSTRUCTION_NODE: 541 { 542 if (node.getNodeName() != null) { 543 if (!_omitXmlDecl && (false == node.getNodeName().startsWith("xml")) && (false == node.getNodeName().startsWith( 544 "xsl"))) { 545 this.println("<?xml " + node.getNodeName() + "=\"" + node.getNodeValue() + "\"?>"); 547 } else { 548 if (!_omitXmlDecl || !"xml".equals(node.getNodeName())) { 550 this.println("<?" + node.getNodeName() + " " + node.getNodeValue() + " ?>"); 551 } 552 } 553 } 554 break; 555 } 556 557 case Node.ENTITY_REFERENCE_NODE: 558 { 559 this.println("&" + node.getNodeName() + ";"); 560 break; 561 } 562 563 case Node.DOCUMENT_TYPE_NODE: 564 { 565 DocumentType docType = (DocumentType ) node; 566 567 this.print("<!DOCTYPE " + docType.getName()); 570 if (docType.getPublicId() != null) { 571 this.print(" PUBLIC "); 572 } else if (docType.getSystemId() != null) { 573 this.print(" SYSTEM "); 574 } 575 577 if (docType.getPublicId() != null) { 578 579 this.print("\"" + docType.getPublicId() + "\" "); 580 } 581 if (docType.getSystemId() != null) { 582 this.print("\"" + docType.getSystemId() + "\" "); 583 } 584 585 NamedNodeMap nodes = docType.getEntities(); 587 588 for (int i = 0; i < nodes.getLength(); i++) { 589 this.println(""); 590 Entity entity = (Entity ) nodes.item(i); 591 this.print(" [<!ENTITY " + entity.getNodeName() + " "); 592 593 NodeList children = entity.getChildNodes(); 595 if (children != null && children.getLength() > 0) { 596 this.print("\"" + XMLPrinter.nodeToString(children.item(0)) + "\">]"); 597 } else { 598 this.print("\"" + entity.getNodeValue() + "\">]"); 599 } 600 } 601 602 this.println(""); 604 this.println(">"); 605 606 break; 607 } 608 } 609 610 } 611 612 this._out.flush(); 613 } 614 615 618 protected String convertNewline(String text) { 619 text = StringUtil.replace(text, "\r\n", "\n"); 621 text = StringUtil.replace(text, "\n", _newline); 623 624 return text; 625 } 626 627 628 public static int run(String [] args, XMLPrinter printer) { 629 String filename = null; 630 String outputname = null; 631 632 File tempOut = null; 633 634 try { 635 if (System.getProperty("log4j.configuration") == null || 636 System.getProperty("log4j.configuration").trim().length() == 0) { 637 System.err.println("ERROR: Logging will not work - 'log4j.configuration' must be defined."); 638 } else { 639 org.apache.log4j.PropertyConfigurator.configureAndWatch(System.getProperty("log4j.configuration")); 640 } 641 642 for (int i = 0; i < args.length; i++) { 643 if (args[i].toLowerCase().startsWith("-omitxml=")) { 644 printer.setOmitXmlDecl(StringUtil.toBoolean(args[i].substring(9))); 645 } else if (args[i].toLowerCase().equals("-out") && args.length > i + 1) { 646 outputname = args[++i]; 647 } else if (args[i].toLowerCase().equals("-in") && args.length > i + 1) { 648 filename = args[++i]; 649 } 650 } 651 652 if (filename == null) { 653 log.error("No input file specified."); 654 return (2); 655 } 656 657 File inputfile = new File (filename); 658 659 Document doc = null; 660 661 java.io.Reader inputReader = null; 662 try { 663 inputReader = new DocBookFilterReader(new java.io.FileReader (inputfile)); 664 InputSource inputSource = new InputSource (inputReader); 665 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 666 dbf.setNamespaceAware(true); 667 dbf.setValidating(false); 668 669 DocumentBuilder db = dbf.newDocumentBuilder(); 670 db.setErrorHandler(printer); 671 672 if (inputfile.getParentFile() != null) { 674 inputSource.setSystemId(inputfile.getParentFile().toURL().toString()); 675 } 676 677 doc = db.parse(inputSource); 678 } catch (Exception e) { 679 log.error("Error Parsing XML Document.", e); 680 return (1); 681 } finally { 682 try { 683 inputReader.close(); 684 } catch (Throwable t) { 685 } 686 } 687 688 690 File outputfile = null; 691 if (outputname != null) { 692 outputfile = new File (outputname); 693 } else { 694 outputfile = inputfile; 695 } 696 697 tempOut = File.createTempFile(outputfile.getName() + "-", ".xmlpp", outputfile.getParentFile()); 698 699 try { 700 Writer outfilewriter = new java.io.FileWriter (tempOut); 701 printer.setWriter(new DocBookFilterWriter(outfilewriter)); 702 703 printer.outputDocument(doc.getDocumentElement()); 705 } catch (Exception e) { 706 log.error("Error formatting XML Document.", e); 707 return (1); 708 } finally { 709 try { 710 printer.getWriter().close(); 711 } catch (Throwable t) { 712 } 713 } 714 715 if (outputname == null) { 717 File bak = new File (inputfile.getParentFile(), inputfile.getName() + ".bak"); 718 if (!inputfile.renameTo(bak) || inputfile.exists()) { 719 bak = File.createTempFile(inputfile.getName() + "-", ".xmlpp", inputfile.getParentFile()); 720 721 log.warn("Can't rename input to *.bak - trying copy to " + bak.getName()); 722 723 try { 724 copyFile(inputfile, bak); 725 log.info("input file backed up"); 726 } catch (IOException ioe) { 727 tempOut = null; 728 log.error("Unable to backup the input file. The output was left in " 729 + tempOut.getAbsolutePath(), ioe); 730 return 1; 731 } 732 } 733 } 734 735 try { 737 copyFile(tempOut, outputfile); 738 } catch (IOException ioe) { 739 log.error("Unable to overwrite output file " + outputfile.getAbsolutePath()); 740 return 1; 741 } 742 743 } catch (Exception e) { 744 log.error("Error prettying XML Document.", e); 745 return (1); 746 } finally { 747 if (tempOut != null) { 748 try { 749 if (tempOut.delete()) { 750 return 0; 751 } 752 } catch (Throwable t) { 753 } 754 try { 755 log.warn("A temporary file was left on disk - " + tempOut.getAbsolutePath()); 756 } catch (Throwable t) { 757 log.warn("A temporary file was left on disk - "); 758 } 759 } 760 } 761 return 0; 762 } 763 764 public static int run(String [] args) { 765 org.apache.log4j.BasicConfigurator.configure(); 766 767 XMLPrinter printer = new XMLPrinter(); 768 769 return run(args, printer); 770 } 771 772 public static void main(String [] args) { 773 System.exit(run(args)); 774 } 775 776 protected static void copyFile(File in, File out) throws IOException { 777 java.io.FileWriter filewriter = null; 778 java.io.FileReader filereader = null; 779 try { 780 filewriter = new java.io.FileWriter (out); 781 filereader = new java.io.FileReader (in); 782 783 char[] buf = new char[4096]; 784 int nread = filereader.read(buf, 0, 4096); 785 while (nread >= 0) { 786 filewriter.write(buf, 0, nread); 787 nread = filereader.read(buf, 0, 4096); 788 } 789 buf = null; 790 } finally { 791 try { 792 filereader.close(); 793 } catch (Throwable t) { 794 } 795 try { 796 filewriter.close(); 797 } catch (Throwable t) { 798 } 799 } 800 } 801 802 810 public void warning(SAXParseException ex) { 811 812 log.warn(getLocationString(ex) + ": " + ex.getMessage()); 813 } 814 815 820 public void error(SAXParseException ex) { 821 log.error(getLocationString(ex) + ": " + ex.getMessage()); 822 } 823 824 830 public void fatalError(SAXParseException ex) 831 throws SAXException { 832 log.error(getLocationString(ex) + ": " + ex.getMessage()); 833 throw ex; 834 } 835 836 842 private String getLocationString(SAXParseException ex) { 843 FastStringBuffer str = new FastStringBuffer(128); 844 String systemId = ex.getSystemId(); 845 846 if (systemId != null) { 847 int index = systemId.lastIndexOf('/'); 848 849 if (index != -1) { 850 systemId = systemId.substring(index + 1); 851 } 852 853 str.append(systemId); 854 } 855 856 str.append(':'); 857 str.append(ex.getLineNumber()); 858 str.append(':'); 859 str.append(ex.getColumnNumber()); 860 861 return str.toString(); 862 } } 864 | Popular Tags |