1 32 33 34 35 40 41 45 46 package org.openlaszlo.xml.internal; 47 48 import java.io.*; 49 import java.util.*; 50 51 import org.jdom.Attribute; 52 import org.jdom.Comment; 53 import org.jdom.Document; 54 import org.jdom.Element; 55 import org.jdom.JDOMException; 56 import org.jdom.input.SAXBuilder; 57 import org.jdom.output.*; 58 59 60 import org.openlaszlo.iv.flash.util.*; 61 import org.openlaszlo.iv.flash.api.action.*; 62 import org.openlaszlo.iv.flash.api.*; 63 import org.openlaszlo.compiler.CompilationError; 64 import org.openlaszlo.utils.ChainedException; 65 import org.openlaszlo.utils.FileUtils; 66 import org.openlaszlo.utils.HashIntTable; 67 68 import org.xmlpull.v1.XmlPullParser; 69 import org.xmlpull.v1.XmlPullParserException; 70 import org.xmlpull.v1.XmlPullParserFactory; 71 72 import org.apache.log4j.*; 73 74 75 82 public class DataCompiler extends DataCommon { 83 84 private static Logger mLogger = Logger.getLogger(DataCompiler.class); 85 private static XmlPullParserFactory factory = null; 86 87 88 static int MISC_BUFSIZ = 4096; 89 static String STRINGBUF_VAR = "__dcstrbuf__"; 90 91 92 private static XmlPullParserFactory getXPPFactory () { 93 if (factory == null) { 94 try { 96 String sys = null; 97 try { 98 sys = System.getProperty(XmlPullParserFactory.PROPERTY_NAME); 99 } catch (SecurityException se) { 100 } 101 factory = XmlPullParserFactory.newInstance(sys, null); 102 factory.setNamespaceAware(true); 103 } catch (XmlPullParserException e) { 104 throw new RuntimeException (e.getMessage()); 105 } 106 } 107 return factory; 108 } 109 110 public DataCompiler () { } 111 112 113 public static InputStream compile(String x, String headers, 115 int flashVersion, 116 boolean addwrapper, 117 boolean trimWhitespace 118 ) throws IOException, DataCompilerException { 119 return compile(x, headers, flashVersion, addwrapper, trimWhitespace, false); 120 } 121 122 123 133 134 public static InputStream compile(String x, String headers, 136 int flashVersion, 137 boolean addwrapper, 138 boolean trimWhitespace, 139 boolean compress 140 ) throws IOException, DataCompilerException { 141 try { 142 XmlPullParser xppbody = getXPPFactory().newPullParser(); 144 xppbody.setInput( new StringReader(x) ); 145 146 XmlPullParser xppheaders = getXPPFactory().newPullParser(); 148 if (addwrapper) { 149 xppheaders.setInput( new StringReader(headers) ); 150 } 151 mLogger.debug("compile x="+x+"\nheaders="+headers); 152 return getSWF(xppbody, xppheaders, x.length(), flashVersion, addwrapper, trimWhitespace, compress); 153 } catch (XmlPullParserException ex) { 154 throw new DataCompilerException("Parsing XML: " + ex.getMessage()); 155 } 156 } 157 158 public static InputStream compile(String x, int flashVersion) throws IOException, DataCompilerException { 159 try { 160 XmlPullParser xppbody = getXPPFactory().newPullParser(); 162 xppbody.setInput( new StringReader(x) ); 163 164 return getSWF(xppbody, null, x.length(), flashVersion, false); 165 } catch (XmlPullParserException ex) { 166 throw new DataCompilerException("Parsing XML: " + ex.getMessage()); 167 } 168 } 169 170 171 private static DataContext makeDataContext(int flashVersion) { 172 DataContext dc = new DataContext(flashVersion); 173 if (flashVersion == 5) { 174 dc.setEncoding("Cp1252"); 175 } else { 176 dc.setEncoding("UTF-8"); 177 } 178 return dc; 179 } 180 181 185 static void splitPushString (String text, Program prog) { 186 int index = 0; 189 int len = 0; 190 int nchunks = 0; 191 while (index < text.length()) { 192 if ((text.length() - index) > 10000) { 193 len = 10000; 194 } else { 195 len = text.length() - index; 196 } 197 String chunk = text.substring(index, index+len); 198 index += len; 199 200 prog.push(chunk); 201 nchunks++; 202 } 203 204 while (nchunks > 1) { 206 prog.addString(); 207 nchunks--; 208 } 209 } 210 211 212 213 static int MAXFRAME_SIZE = 20000; 214 215 static int FB_INIT_SIZE = MAXFRAME_SIZE * 2 + 128000; 217 218 219 private static byte constructor_idx = 0; 220 private static byte textnode_idx = 1; 221 222 231 232 233 263 264 private static final DataContext writeXMLData(XmlPullParser xpp, int flashVersion, 265 boolean splitframes, Vector programs, 266 DataContext dc, 267 boolean trimWhitespace, int stackdepth) 268 throws IOException, XmlPullParserException { 269 270 Program bodyp = (Program) programs.lastElement(); 272 FlashBuffer body = bodyp.body(); 273 274 int eventType = xpp.getEventType(); 275 while (eventType != xpp.END_DOCUMENT) { 276 if(eventType == xpp.START_DOCUMENT) { 277 } else if(eventType == xpp.START_TAG) { 278 body._writeByte(Actions.PushDuplicate); 282 283 284 int nattrs = xpp.getAttributeCount(); 287 String eltname = xpp.getName(); 288 289 int datasize = 0; 292 for (int i = 0; i < nattrs; i++) { 293 String attrname = xpp.getAttributeName(i); 294 datasize += getByteLength(attrname, dc.encoding) + 2; 295 String attrval = xpp.getAttributeValue(i); 296 datasize += getByteLength(attrval, dc.encoding) + 2; 297 } 298 299 if (datasize > 65500) { 301 bodyp.push(eltname); 302 303 for (int i = 0; i < nattrs; i++) { 304 String attrname = xpp.getAttributeName(i); 305 bodyp.push(attrname); 307 308 String attrval = xpp.getAttributeValue(i); 309 splitPushString(attrval, bodyp); 310 } 311 312 bodyp.push(nattrs); 313 body._writeByte(Actions.InitObject); 314 } else { 315 316 body._writeByte(Actions.PushData); 322 int push_bufferpos = body.getPos(); 325 body._writeWord(0); 327 _pushMergedStringDataSymbol(eltname, body, dc); 329 330 for (int i = 0; i < nattrs; i++) { 332 String attrname = xpp.getAttributeName(i); 333 _pushMergedStringDataSymbol(attrname, body, dc); 335 336 String attrval = xpp.getAttributeValue(i); 337 _pushMergedStringData(attrval, body, dc); 339 } 340 body._writeByte(0x07); body._writeDWord(nattrs); 343 344 int total_size = body.getPos() - (push_bufferpos + 2); 346 body.writeWordAt(total_size, push_bufferpos); 348 349 body._writeByte(Actions.InitObject); 350 } 351 352 body._writeByte(Actions.PushData); 357 body._writeWord(7); 358 body._writeByte(0x07); body._writeDWord(3); body._writeByte(0x08); body._writeByte(constructor_idx); body._writeByte(Actions.CallFunction); 363 364 365 stackdepth++; 369 } else if (eventType == xpp.END_TAG) { 370 body._writeByte(Actions.Pop); 372 stackdepth--; 373 374 376 body.setSize(body.getPos()); 381 382 if (splitframes && body.getSize() > MAXFRAME_SIZE) { 385 387 bodyp.push(stackdepth); 390 body.writeByte(Actions.InitArray); 391 bodyp.push("__dcns"); 392 body.writeByte(Actions.StackSwap); 393 bodyp.setVar(); 394 395 396 Program withpool = appendStringPool(dc, body); 398 programs.setElementAt(withpool, programs.size() -1); 400 401 body = new FlashBuffer(FB_INIT_SIZE); 402 bodyp = new Program(body); 403 programs.add(bodyp); 404 405 dc = makeDataContext(flashVersion); 406 addStringConstant(NODE_INSTANTIATOR_FN, dc); 410 addStringConstant(TEXT_INSTANTIATOR_FN, dc); 411 412 bodyp.push(0); bodyp.push("__dcns"); bodyp.getVar(); bodyp.push("length"); bodyp.getMember(); bodyp.lessThan(); bodyp.logicalNot(); 433 bodyp.jumpIfTrue(34); 436 bodyp.push(0); bodyp.push("__dcns"); bodyp.getVar(); bodyp.push("pop"); bodyp.callMethod(); bodyp.jump(- (34 + 34 + 5)); } 450 451 } else if(eventType == xpp.TEXT) { 452 if (trimWhitespace && xpp.isWhitespace()) { 453 } else { 456 String text = xpp.getText(); 457 if (trimWhitespace) { 458 text = text.trim(); 459 } 460 461 body._writeByte(Actions.PushDuplicate); 464 465 467 if (getByteLength(text, dc.encoding) > 64000) { 468 splitPushString (text, bodyp); 469 470 bodyp.push(2); 471 bodyp.push(TEXT_INSTANTIATOR_FN); 472 bodyp.callFunction(); 473 body._writeByte(Actions.Pop); 475 476 } else { 477 body._writeByte(Actions.PushData); 478 int push_bufferpos = body.getPos(); 481 body._writeWord(0); 483 _pushMergedStringData(text, body, dc); 484 body._writeByte(0x07); body._writeDWord(2); body._writeByte(0x08); body._writeByte(textnode_idx); 491 492 int total_size = body.getPos() - (push_bufferpos + 2); 494 body.writeWordAt(total_size, push_bufferpos); 495 body._writeByte(Actions.CallFunction); 496 body._writeByte(Actions.Pop); 498 } 499 500 } 501 } 502 eventType = xpp.next(); 503 } 505 506 return dc; 508 } 509 510 514 private static Program appendStringPool (DataContext dc, FlashBuffer body) { 515 byte pooldata[] = makeStringPool(dc); 517 518 body.setSize(body.getPos()); 520 521 FlashBuffer out = new FlashBuffer(body.getSize() + pooldata.length + MISC_BUFSIZ); 523 out._writeByte( Actions.ConstantPool ); 525 out._writeWord( pooldata.length + 2 ); out._writeWord( dc.cpool.size() ); out.writeArray( pooldata, 0, pooldata.length); 529 out.writeArray(body.getBuf(), 0, body.getSize()); 531 Program prog = new Program(out); 533 return prog; 534 } 535 536 537 public static Program makeProgram(Element data, int flashVersion) throws CompilationError { 538 return makeProgram(data, flashVersion, true, false); 539 } 540 541 544 public static Program makeProgram(Element data, int flashVersion, boolean trimWhitespace, boolean localdata) throws CompilationError { 545 XMLOutputter outputter = new XMLOutputter(); 546 StringWriter sout = new StringWriter(); 547 try { 548 outputter.output(data, sout); 549 } 550 catch (IOException ex) { 551 throw new RuntimeException ("DataCompiler makeProgram parsing XML: " + ex.getMessage()); 552 } 553 String x = sout.toString(); 554 try { 556 XmlPullParser xpp = getXPPFactory().newPullParser(); 557 xpp.setInput( new StringReader(x) ); 558 Vector progs = makeProgram(xpp, null, x.length(), flashVersion, false, false, trimWhitespace, localdata); 559 return ((Program) progs.firstElement()); 560 } catch (XmlPullParserException ex) { 561 throw new CompilationError("DataCompiler makeProgram parsing XML: " + ex.getMessage()); 562 } catch (IOException ex) { 563 throw new RuntimeException ("DataCompiler makeProgram parsing XML: " + ex.getMessage()); 564 } 565 } 566 567 568 569 580 public static Vector makeProgram(XmlPullParser xpp, XmlPullParser xpheaders, 581 int xmlsize, int flashVersion, 582 boolean splitframes, 583 boolean addwrapper, 584 boolean trimWhitespace, 585 boolean localdata) 586 throws IOException, XmlPullParserException { 587 Vector programs = new Vector(); 588 589 FlashBuffer body = new FlashBuffer(splitframes ? FB_INIT_SIZE : (xmlsize * 3) + 128000); 592 Program bodyp = new Program(body); 593 programs.add(bodyp); 594 595 bodyp.push(new Object []{"_m", "_level0"}); 598 bodyp.getVar(); 599 bodyp.push("_m"); 600 bodyp.getMember(); 601 bodyp.setVar(); 602 603 bodyp.push(new Object []{"_t", "_level0"}); 605 bodyp.getVar(); 606 bodyp.push("_t"); 607 bodyp.getMember(); 608 bodyp.setVar(); 609 610 bodyp.push(0); bodyp.push("_level0"); 614 bodyp.getVar(); 615 bodyp.push(ROOT_NODE_INSTANTIATOR_FN); 616 bodyp.callMethod(); 617 619 if (addwrapper) { 620 body.writeByte(Actions.PushDuplicate); 622 bodyp.push("resultset"); 624 bodyp.push(0); 625 body._writeByte(Actions.InitObject); 626 bodyp.push(3); bodyp.push(NODE_INSTANTIATOR_FN); 628 bodyp.callFunction(); 629 631 632 body.writeByte(Actions.PushDuplicate); 634 bodyp.push("body"); 635 bodyp.push(0); 636 body._writeByte(Actions.InitObject); bodyp.push(3); bodyp.push(NODE_INSTANTIATOR_FN); 639 bodyp.callFunction(); } 641 642 DataContext dc = makeDataContext(flashVersion); 644 addStringConstant(NODE_INSTANTIATOR_FN, dc); 647 addStringConstant(TEXT_INSTANTIATOR_FN, dc); 648 650 int stackdepth = (addwrapper ? 3 : 1); 652 dc = writeXMLData(xpp, flashVersion, splitframes, programs, dc, trimWhitespace, stackdepth); 653 bodyp = (Program) programs.lastElement(); 656 body = bodyp.body(); 657 658 if (addwrapper) { 660 bodyp.pop(); 662 dc = writeXMLData(xpheaders, flashVersion, false, programs, dc, trimWhitespace, stackdepth); 666 bodyp = (Program) programs.lastElement(); 667 body = bodyp.body(); 668 bodyp.pop(); } 670 671 bodyp.push(1); 673 bodyp.push("_level0"); 674 bodyp.getVar(); 675 bodyp.push(ROOT_NODE_FINAL_FN); 676 bodyp.callMethod(); 677 678 680 body.writeByte(Actions.PushDuplicate); 683 bodyp.push("__lzdataroot"); 684 body.writeByte(Actions.StackSwap); 685 bodyp.setVar(); 686 687 688 if (!localdata) { 691 bodyp.push("_parent"); 693 bodyp.getVar(); 694 bodyp.push(2); 695 bodyp.push("_parent"); 696 bodyp.getVar(); 697 bodyp.push("loader"); 698 bodyp.getMember(); 699 bodyp.push("returnData"); 700 bodyp.callMethod(); 701 bodyp.pop(); 702 703 if (splitframes) { 704 bodyp.stop(); 706 } 707 } 708 709 Program withpool = appendStringPool(dc, body); 711 programs.setElementAt(withpool, programs.size()-1); 713 714 return programs; 715 } 716 717 718 724 private static FlashFile makeSWF(XmlPullParser xpp, XmlPullParser xpheaders, int xmlsize, 725 int flashVersion, boolean addwrapper, boolean trimWhitespace) 726 throws IOException, XmlPullParserException { 727 mLogger.debug("makeSWF: addwrapper="+addwrapper+" xpp = "+xpp+" xpheaders="+xpheaders+" xmlsize="+xmlsize); 728 FlashFile file = FlashFile.newFlashFile(); 730 Script s = new Script(1); 731 file.setMainScript(s); 732 file.setVersion(flashVersion); 733 Vector progs = makeProgram(xpp, xpheaders, xmlsize, flashVersion, true, addwrapper, trimWhitespace, false); 734 735 while (progs.size() > 0) { 737 Program prog = (Program) progs.firstElement(); 738 progs.removeElementAt(0); Frame frame = s.newFrame(); 740 frame.addFlashObject(new DoAction(prog)); 741 } 742 743 return file; 744 } 745 746 747 public static InputStream getSWF(XmlPullParser xpp, XmlPullParser xpheaders, int xmlsize, 748 int flashVersion, boolean addwrapper) 749 throws IOException, XmlPullParserException { 750 return getSWF(xpp, xpheaders, xmlsize, flashVersion, addwrapper, true, false); 751 } 752 753 754 764 public static InputStream getSWF(XmlPullParser xpp, XmlPullParser xpheaders, int xmlsize, 765 int flashVersion, boolean addwrapper, boolean trimWhitespace, 766 boolean compress) 767 throws IOException, XmlPullParserException { 768 InputStream input; 770 int i = 0; 771 try { 772 FlashFile file = makeSWF(xpp, xpheaders, xmlsize, flashVersion, addwrapper, trimWhitespace); 773 if (flashVersion > 5) { 774 if (compress) { 775 file.setCompressed(true); 776 } 777 } 778 return file.generate().getInputStream(); 779 } catch (IVException ex) { 780 throw new ChainedException(ex); 781 } catch (IOException e) { 782 mLogger.error("io error getting SWF: " + e.getMessage()); 783 throw e; 784 } 785 } 786 787 } 788 789 | Popular Tags |