Source Code Cross Referenced for DataCompiler.java in  » Ajax » Laszlo-4.0.10 » org » openlaszlo » xml » internal » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Ajax » Laszlo 4.0.10 » org.openlaszlo.xml.internal 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /* ****************************************************************************
002:         * DataCompiler.java
003:         *
004:         * Compile XML directly to SWF bytecodes.
005:         * ****************************************************************************/
006:
007:        /* J_LZ_COPYRIGHT_BEGIN *******************************************************
008:         * Copyright 2001-2006 Laszlo Systems, Inc.  All Rights Reserved.              *
009:         * Use is subject to license terms.                                            *
010:         * J_LZ_COPYRIGHT_END *********************************************************/
011:
012:        package org.openlaszlo.xml.internal;
013:
014:        import java.io.*;
015:        import java.util.*;
016:
017:        import org.jdom.Attribute;
018:        import org.jdom.Comment;
019:        import org.jdom.Document;
020:        import org.jdom.Element;
021:        import org.jdom.JDOMException;
022:        import org.jdom.input.SAXBuilder;
023:        import org.jdom.output.*;
024:
025:        import org.openlaszlo.iv.flash.util.*;
026:        import org.openlaszlo.iv.flash.api.action.*;
027:        import org.openlaszlo.iv.flash.api.*;
028:        import org.openlaszlo.compiler.CompilationError;
029:        import org.openlaszlo.utils.ChainedException;
030:        import org.openlaszlo.utils.FileUtils;
031:        import org.openlaszlo.utils.HashIntTable;
032:
033:        import org.xmlpull.v1.XmlPullParser;
034:        import org.xmlpull.v1.XmlPullParserException;
035:        import org.xmlpull.v1.XmlPullParserFactory;
036:
037:        import org.apache.log4j.*;
038:
039:        /**
040:         * Takes XML in various forms, and serializes it to isomorphic actionscript
041:         * bytecode.
042:         *
043:         * @author Max Carlson, Henry Minsky
044:         * @version 1.1
045:         */
046:        public class DataCompiler extends DataCommon {
047:            /* Logger */
048:            private static Logger mLogger = Logger
049:                    .getLogger(DataCompiler.class);
050:            private static XmlPullParserFactory factory = null;
051:
052:            /** global var to hold the image of the stack when splitting frames */
053:            static int MISC_BUFSIZ = 4096;
054:            static String STRINGBUF_VAR = "__dcstrbuf__";
055:
056:            private static XmlPullParserFactory getXPPFactory() {
057:                if (factory == null) {
058:                    // Set up the XML Parser factory
059:                    try {
060:                        String sys = null;
061:                        try {
062:                            sys = System
063:                                    .getProperty(XmlPullParserFactory.PROPERTY_NAME);
064:                        } catch (SecurityException se) {
065:                        }
066:                        factory = XmlPullParserFactory.newInstance(sys, null);
067:                        factory.setNamespaceAware(true);
068:                    } catch (XmlPullParserException e) {
069:                        throw new RuntimeException(e.getMessage());
070:                    }
071:                }
072:                return factory;
073:            }
074:
075:            public DataCompiler() {
076:            }
077:
078:            // compress = false, for back compatibility
079:            public static InputStream compile(String x, String headers,
080:                    int flashVersion, boolean addwrapper, boolean trimWhitespace)
081:                    throws IOException, DataCompilerException {
082:                return compile(x, headers, flashVersion, addwrapper,
083:                        trimWhitespace, false, false);
084:            }
085:
086:            public static InputStream compile(String x, String headers,
087:                    int flashVersion, boolean addwrapper,
088:                    boolean trimWhitespace, boolean compress)
089:                    throws IOException, DataCompilerException {
090:                return compile(x, headers, flashVersion, addwrapper,
091:                        trimWhitespace, compress, false);
092:            }
093:
094:            /**
095:             * Compile XML to SWF
096:             *
097:             * @param x XML string to compile
098:             * @return input stream
099:             *
100:             * The size of the input XML will always be greater than the
101:             * output .swf (possibly plus some factor, to be measured), so we can allocate a FlashBuffer
102:             * with that max size and be done.
103:             */
104:
105:            // Change input from String to Reader, for higher efficiency
106:            public static InputStream compile(String x, String headers,
107:                    int flashVersion, boolean addwrapper,
108:                    boolean trimWhitespace, boolean compress, boolean nsprefix)
109:                    throws IOException, DataCompilerException {
110:                try {
111:                    // XML Parser for the data body
112:                    XmlPullParser xppbody = getXPPFactory().newPullParser();
113:                    xppbody.setInput(new StringReader(x));
114:
115:                    // XML Parser for the headers
116:                    XmlPullParser xppheaders = getXPPFactory().newPullParser();
117:                    if (addwrapper) {
118:                        xppheaders.setInput(new StringReader(headers));
119:                    }
120:                    return getSWF(xppbody, xppheaders, x.length(),
121:                            flashVersion, addwrapper, trimWhitespace, compress,
122:                            nsprefix);
123:                } catch (XmlPullParserException ex) {
124:                    throw new DataCompilerException("Parsing XML: "
125:                            + ex.getMessage());
126:                }
127:            }
128:
129:            public static InputStream compile(String x, int flashVersion)
130:                    throws IOException, DataCompilerException {
131:                try {
132:
133:                    // XML Parser for the data body
134:                    XmlPullParser xppbody = getXPPFactory().newPullParser();
135:                    xppbody.setInput(new StringReader(x));
136:
137:                    return getSWF(xppbody, null, x.length(), flashVersion,
138:                            false);
139:                } catch (XmlPullParserException ex) {
140:                    throw new DataCompilerException("Parsing XML: "
141:                            + ex.getMessage());
142:                }
143:            }
144:
145:            public static InputStream compile(String x, int flashVersion,
146:                    boolean nsprefix) throws IOException, DataCompilerException {
147:                try {
148:                    // XML Parser for the data body
149:                    XmlPullParser xppbody = getXPPFactory().newPullParser();
150:                    xppbody.setInput(new StringReader(x));
151:
152:                    // defaults
153:                    // addwrapper = false
154:                    // compress = false
155:                    boolean trimWhitespace = false;
156:                    return getSWF(xppbody, null, x.length(), flashVersion,
157:                            false, trimWhitespace, false, nsprefix);
158:                } catch (XmlPullParserException ex) {
159:                    throw new DataCompilerException("Parsing XML: "
160:                            + ex.getMessage());
161:                }
162:            }
163:
164:            /** Create a new string pool buffer */
165:            private static DataContext makeDataContext(int flashVersion) {
166:                DataContext dc = new DataContext(flashVersion);
167:                return dc;
168:            }
169:
170:            /** Split string into PUSH chunks of less than 64k, and emit string concat
171:                instructions to re-assemble them. Leaves string value on stack.
172:                
173:             */
174:            static void splitPushString(String text, Program prog) {
175:                // break up into 64K chunks, append to local variable.
176:                // To account for multibyte chars, use 10000 to be safe.
177:                int index = 0;
178:                int len = 0;
179:                int nchunks = 0;
180:                while (index < text.length()) {
181:                    if ((text.length() - index) > 10000) {
182:                        len = 10000;
183:                    } else {
184:                        len = text.length() - index;
185:                    }
186:                    String chunk = text.substring(index, index + len);
187:                    index += len;
188:
189:                    prog.push(chunk);
190:                    nchunks++;
191:                }
192:
193:                // concatenate all the strings
194:                while (nchunks > 1) {
195:                    prog.addString();
196:                    nchunks--;
197:                }
198:            }
199:
200:            static int MAXFRAME_SIZE = 20000;
201:
202:            // Initial buffer size for program, with space for string constant pool (max 64k)
203:            static int FB_INIT_SIZE = MAXFRAME_SIZE * 2 + 128000;
204:
205:            /* These two hardcoded constants are always added first to string pool of a frame, in this order. */
206:            private static byte constructor_idx = 0;
207:            private static byte textnode_idx = 1;
208:
209:            static String getStackTrace(Throwable aThrowable) {
210:                final Writer result = new StringWriter();
211:                final PrintWriter printWriter = new PrintWriter(result);
212:                aThrowable.printStackTrace(printWriter);
213:                return result.toString();
214:            }
215:
216:            /**
217:             * Main loop which pulls XPP events and writes swf bytecodes to build the node structure.
218:             *
219:             * @param xpp XML parser pointing to data
220:             * @param programs a list of Flash Programs. Add to it as we create new frames. 
221:             * enter assuming that root node is on the stack
222:             *
223:             */
224:
225:            /*
226:
227:            >>> c("stackarray=['top','middle', 'root']",printInstructions=1)
228:              constants 'stackarray' 'middle' 'root' 'top'
229:              push 'stackarray' 'root' 'middle' 'top' '3'
230:              initArray
231:              setVariable
232:            >>>
233:
234:
235:            >>> c('while(a.length > 0) a.pop()' , printInstructions=1)
236:              constants 'a' 'length' 'pop'
237:            L1:
238:              push '0.0' 'a'
239:              getVariable
240:              push 'length'
241:              getMember
242:              lessThan
243:              not
244:              branchIfTrue 'L0'
245:              push '0' 'a'
246:              getVariable
247:              push 'pop'
248:              callMethod
249:              pop
250:              branch 'L1'
251:            L0:
252:            >>>
253:
254:             */
255:
256:            private static final DataContext writeXMLData(XmlPullParser xpp,
257:                    Vector programs, DataContext dc, int stackdepth,
258:                    DCOptions ioptions) throws IOException,
259:                    XmlPullParserException {
260:
261:                DCOptions options = (DCOptions) ioptions.clone();
262:
263:                int flashVersion = options.flashVersion;
264:                boolean splitframes = options.splitframes;
265:                boolean addwrapper = options.addwrapper;
266:                boolean trimWhitespace = options.trimWhitespace;
267:                boolean localdata = options.localdata;
268:                boolean nsprefix = options.nsprefix;
269:
270:                // Use the program we were passed in, it has the root node on top of stack.
271:                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:                        // makeNodeNoText = function (attrs, name, parent)
279:                        // dup pointer to PARENT (who is at top of stack)
280:                        // DUP
281:                        body._writeByte(Actions.PushDuplicate);
282:
283:                        // Fold all the attribute key/value pairs into a single PUSH
284:                        // Build ATTRIBUTE object
285:                        int nattrs = xpp.getAttributeCount();
286:                        String eltname = xpp.getName();
287:                        String eltprefix = xpp.getPrefix();
288:                        if (nsprefix && eltprefix != null) {
289:                            eltname = eltprefix + ":" + eltname;
290:                        }
291:
292:                        // Check if combined attr+data is > 64k, if so, use individual
293:                        // pushes with string breaking/merging, rather than compressed merging.
294:                        int datasize = 0;
295:                        for (int i = 0; i < nattrs; i++) {
296:                            String attrname = xpp.getAttributeName(i);
297:                            String attrprefix = xpp.getAttributePrefix(i);
298:                            if (nsprefix && attrprefix != null) {
299:                                attrname = attrprefix + ":" + attrname;
300:                            }
301:                            datasize += getByteLength(attrname, dc.encoding) + 2;
302:                            String attrval = xpp.getAttributeValue(i);
303:                            datasize += getByteLength(attrval, dc.encoding) + 2;
304:                        }
305:
306:                        // If if data is too large, use individual split pushses
307:                        if (datasize > 65500) {
308:                            bodyp.push(eltname);
309:
310:                            for (int i = 0; i < nattrs; i++) {
311:                                String attrname = xpp.getAttributeName(i);
312:                                String attrprefix = xpp.getAttributePrefix(i);
313:                                if (nsprefix && attrprefix != null) {
314:                                    attrname = attrprefix + ":" + attrname;
315:                                }
316:                                //System.out.print("Attr " + attrname);
317:                                bodyp.push(attrname);
318:
319:                                String attrval = xpp.getAttributeValue(i);
320:                                splitPushString(attrval, bodyp);
321:                            }
322:
323:                            bodyp.push(nattrs);
324:                            body._writeByte(Actions.InitObject);
325:                        } else {
326:
327:                            // We're really squeezing things down, so we are going to merge 
328:                            // the PUSH of the element name with the PUSH of the attribute key/value
329:                            // data and the attribute count. So the stack will look like
330:                            // [eltname attrname1 attrval1 attrname2 attrval2 ... ... nattrs]
331:                            // when we're done
332:                            body._writeByte(Actions.PushData);
333:                            // Leave a two byte space for the PUSH length
334:                            // Mark where we are, so we can rewrite this with correct length later.
335:                            int push_bufferpos = body.getPos();
336:                            body._writeWord(0); // placeholder 16-bit length field 
337:
338:                            // Push element NAME
339:                            _pushMergedStringDataSymbol(eltname, body, dc);
340:
341:                            // PUSH := {0x96, lenlo, lenhi, 0x00, char, char, char, ...0x00, }
342:                            for (int i = 0; i < nattrs; i++) {
343:                                String attrname = xpp.getAttributeName(i);
344:                                String attrprefix = xpp.getAttributePrefix(i);
345:                                if (nsprefix && attrprefix != null) {
346:                                    attrname = attrprefix + ":" + attrname;
347:                                }
348:                                //System.out.print("Attr " + attrname);
349:                                _pushMergedStringDataSymbol(attrname, body, dc);
350:
351:                                String attrval = xpp.getAttributeValue(i);
352:                                //System.out.println("= " + attrval);
353:                                _pushMergedStringData(attrval, body, dc);
354:                            }
355:                            // create the attrs object; push the attr count
356:                            body._writeByte(0x07); // INT type
357:                            body._writeDWord(nattrs);
358:
359:                            // Now go back and fix up the size arg to the PUSH instruction
360:                            int total_size = body.getPos()
361:                                    - (push_bufferpos + 2);
362:                            //System.out.println("pos="+body.getPos()+ " total_size = "+total_size+"  push_bufferpos="+push_bufferpos+" nattrs="+nattrs);
363:                            body.writeWordAt(total_size, push_bufferpos);
364:
365:                            body._writeByte(Actions.InitObject);
366:                        }
367:
368:                        // stack now has [parent, name, attrs]
369:                        // Push # of args and node-instantiator-function name
370:                        // PUSH 3, _mdn
371:                        // [PUSHDATA, 9, 0,  0x07, 03 00 00 00 0x08, "_m"]
372:                        body._writeByte(Actions.PushData);
373:                        body._writeWord(7);
374:                        body._writeByte(0x07); // INT type
375:                        body._writeDWord(3); // '3' integer constant , number of args to node constructor fn
376:                        body._writeByte(0x08); //  SHORT DICTIONARY LOOKUP type
377:                        body._writeByte(constructor_idx); // index of "_m" string constant
378:                        body._writeByte(Actions.CallFunction);
379:
380:                        // We push new node on the stack, so we can reference it as the parent 
381:                        // Stack => [parentnode newnode]
382:                        // increment the node stack depth
383:                        stackdepth++;
384:                    } else if (eventType == xpp.END_TAG) {
385:                        // Pop the node off the stack. 
386:                        body._writeByte(Actions.Pop);
387:                        stackdepth--;
388:
389:                        // Good place to check if this frame has gotten large enough to split.
390:
391:                        // IMPORTANT: recalculate buffer size to what it
392:                        // really is (since we've been using the fast
393:                        // _writeXXX functions which dont' update size
394:                        // automatically);
395:                        body.setSize(body.getPos());
396:
397:                        // When we end a frame, we call initArray (stackdepth) to unload to "__dcns".
398:                        // Then when we start the next frame, we loop to transfer array contents back to stack
399:                        if (splitframes && body.getSize() > MAXFRAME_SIZE) {
400:                            //mLogger.debug("splitting frame "+body.getSize());
401:
402:                            // dump the stack to a global variable
403:                            // XXXXX NEED TO COMPENSATE FOR HEADER WRAPPERS!!!!!!!
404:                            bodyp.push(stackdepth);
405:                            body.writeByte(Actions.InitArray);
406:                            bodyp.push("__dcns");
407:                            body.writeByte(Actions.StackSwap);
408:                            bodyp.setVar();
409:
410:                            // prepend the string pool to the program,and add it to the frame list
411:                            Program withpool = appendStringPool(dc, body);
412:                            // replace the last program with one that has a string pool.
413:                            programs
414:                                    .setElementAt(withpool, programs.size() - 1);
415:
416:                            body = new FlashBuffer(FB_INIT_SIZE);
417:                            bodyp = new Program(body);
418:                            programs.add(bodyp);
419:
420:                            dc = makeDataContext(flashVersion);
421:                            // Intern the node constructor function names in
422:                            // the string pool as first entries. Always use
423:                            // this ordering.
424:                            addStringConstant(NODE_INSTANTIATOR_FN, dc);
425:                            addStringConstant(TEXT_INSTANTIATOR_FN, dc);
426:
427:                            // The code below is basically this:
428:                            // while(__dcns.length > 0) { __dcns.pop() }
429:                            // But each pop() leaves the popped data on stack.
430:                            //L1:
431:                            //push '0.0' 'a'
432:                            // == 34
433:                            bodyp.push(0); // 8
434:                            bodyp.push("__dcns"); // 4 + 6 +1= 11
435:                            //getVariable
436:                            bodyp.getVar(); // 1
437:                            //push 'length'
438:                            bodyp.push("length"); // 4 + "length" +1 = 11
439:                            //getMember
440:                            bodyp.getMember(); // 1
441:                            //lessThan
442:                            bodyp.lessThan(); //1 
443:                            //not
444:                            bodyp.logicalNot(); // 1 
445:                            // total = (+ 8 11 1 11 1 1 1 ) = 34
446:                            //branchIfTrue 'L0'
447:
448:                            // == 5
449:                            bodyp.jumpIfTrue(34); // 5 bytes   //jump L0:
450:
451:                            // == 34
452:                            //push '0' 'a'
453:                            bodyp.push(0); // 4 + data length = 8
454:                            bodyp.push("__dcns"); // 4 + "__dcns" + 1 = 11
455:                            //getVariable
456:                            bodyp.getVar(); // 1
457:                            //push 'pop'
458:                            bodyp.push("pop"); // 4 + 1 + 'pop' = 8
459:                            //callMethod
460:                            bodyp.callMethod(); // 1
461:                            //branch 'L1'
462:                            bodyp.jump(-(34 + 34 + 5)); //5 bytes  // jump L1:
463:                            //L0:
464:                        }
465:
466:                    } else if (eventType == xpp.TEXT) {
467:                        if (xpp.isWhitespace()) {
468:                            // If the text is all whitespace, then don't create a node.
469:                        } else {
470:                            String text = xpp.getText();
471:                            if (trimWhitespace) {
472:                                text = text.trim();
473:                            }
474:
475:                            // dup pointer to parent (who is at top of stack)
476:                            // DUP
477:                            body._writeByte(Actions.PushDuplicate);
478:
479:                            // Push text
480:
481:                            if (getByteLength(text, dc.encoding) > 64000) {
482:                                splitPushString(text, bodyp);
483:
484:                                bodyp.push(2);
485:                                bodyp.push(TEXT_INSTANTIATOR_FN);
486:                                bodyp.callFunction();
487:                                // Pop the node, because there will be no end tag for it, and it has no children.
488:                                body._writeByte(Actions.Pop);
489:
490:                            } else {
491:                                body._writeByte(Actions.PushData);
492:                                // Leave a two byte space for the PUSH length
493:                                // Mark where we are, so we can rewrite this with correct length later.
494:                                int push_bufferpos = body.getPos();
495:                                body._writeWord(0); // placeholder 16-bit length field 
496:
497:                                _pushMergedStringData(text, body, dc);
498:                                // Set up argsnum and function name
499:                                // PUSH 2, _tdn
500:                                body._writeByte(0x07); // INT type
501:                                body._writeDWord(2); // '2' integer constant ; number of args to function
502:                                body._writeByte(0x08); //  SHORT DICTIONARY LOOKUP
503:                                body._writeByte(textnode_idx); // push function name: index of "_t" string constant
504:
505:                                // Now go back and fix up the size arg to the PUSH instruction
506:                                int total_size = body.getPos()
507:                                        - (push_bufferpos + 2);
508:                                body.writeWordAt(total_size, push_bufferpos);
509:                                body._writeByte(Actions.CallFunction);
510:                                // Pop the node, because there will be no end tag for it, and it has no children.
511:                                body._writeByte(Actions.Pop);
512:                            }
513:
514:                        }
515:                    }
516:                    eventType = xpp.next();
517:                    // invariant is that when we start a frame, stack contains parent node list
518:                }
519:
520:                // return the datacontext, the caller will use it to write the last string pool
521:                return dc;
522:            }
523:
524:            /** Takes the string hash table in DataContext dc, and prepends it to the
525:                program in FlashBuffer body. Returns a new program with the stringpool
526:                at the start.
527:             **/
528:            private static Program appendStringPool(DataContext dc,
529:                    FlashBuffer body) {
530:                // Collect the string dictionary data
531:                byte pooldata[] = makeStringPool(dc);
532:
533:                // sync up size with buffer
534:                body.setSize(body.getPos());
535:
536:                // 'out' is the main FlashBuffer for composing the output file
537:                FlashBuffer out = new FlashBuffer(body.getSize()
538:                        + pooldata.length + MISC_BUFSIZ);
539:                // Write out string constant pool
540:                out._writeByte(Actions.ConstantPool);
541:                out._writeWord(pooldata.length + 2); // number of bytes in pool data + int (# strings)
542:                out._writeWord(dc.cpool.size()); // number of strings in pool
543:                out.writeArray(pooldata, 0, pooldata.length); // copy the data
544:
545:                // Write out the code to build nodes
546:                out.writeArray(body.getBuf(), 0, body.getSize());
547:                // This is a program that contains the constant pool plus code
548:                Program prog = new Program(out);
549:                return prog;
550:            }
551:
552:            /** default trimWhitespace=false */
553:            public static Program makeProgram(Element data, int flashVersion)
554:                    throws CompilationError {
555:
556:                DCOptions options = new DCOptions();
557:                options.flashVersion = flashVersion;
558:                options.trimWhitespace = false;
559:                options.localdata = false;
560:
561:                return makeProgram(data, options);
562:            }
563:
564:            /**
565:               Called for compile-time data, don't do frame splitting, and don't add any resultset wrapper
566:             */
567:            public static Program makeProgram(Element data, int flashVersion,
568:                    boolean trimWhitespace, boolean localdata, boolean nsprefix)
569:                    throws CompilationError {
570:
571:                DCOptions options = new DCOptions();
572:                options.flashVersion = flashVersion;
573:                options.trimWhitespace = trimWhitespace;
574:                options.localdata = localdata;
575:                options.nsprefix = nsprefix;
576:                return makeProgram(data, options);
577:            }
578:
579:            /**
580:               Called for compile-time data, don't do frame splitting, and don't add any resultset wrapper
581:             */
582:            public static Program makeProgram(Element data, DCOptions ioptions)
583:                    throws CompilationError {
584:
585:                DCOptions options = (DCOptions) ioptions.clone();
586:                options.splitframes = false;
587:                options.addwrapper = false;
588:
589:                XMLOutputter outputter = new XMLOutputter();
590:                StringWriter sout = new StringWriter();
591:                try {
592:                    outputter.output(data, sout);
593:                } catch (IOException ex) {
594:                    throw new RuntimeException(
595:                            "DataCompiler makeProgram parsing XML: "
596:                                    + ex.getMessage());
597:                }
598:                String x = sout.toString();
599:                // [TODO 02-10-2003 hqm -- Do we need to catch character conversion errors -> ASCII like we did with JDOM?]
600:                try {
601:                    XmlPullParser xpp = getXPPFactory().newPullParser();
602:                    xpp.setInput(new StringReader(x));
603:                    Vector progs = makeProgram(xpp, null, x.length(), options);
604:                    return ((Program) progs.firstElement());
605:                } catch (XmlPullParserException ex) {
606:                    throw new CompilationError(
607:                            "DataCompiler makeProgram parsing XML: "
608:                                    + ex.getMessage());
609:                } catch (IOException ex) {
610:                    throw new RuntimeException(
611:                            "DataCompiler makeProgram parsing XML: "
612:                                    + ex.getMessage());
613:                }
614:            }
615:
616:            /** Bag to hold data compiler options */
617:            static class DCOptions implements  Cloneable {
618:                /** swf target runtime */
619:                int flashVersion = 6;
620:
621:                /** Split code for building data into multiple frames, to keep player from
622:                 * getting too sluggish or "player responding slowly" error */
623:                boolean splitframes = true;
624:
625:                /** add metadata headers info as XML wrapper */
626:                boolean addwrapper = false;
627:
628:                /** trim  whitespace in text content */
629:                boolean trimWhitespace = false;
630:
631:                /** data inlined at compile time */
632:                boolean localdata = false;
633:
634:                /** add namespace prefixes to tags and attribute names */
635:                boolean nsprefix = false;
636:
637:                DCOptions() {
638:                }
639:
640:                public Object clone() {
641:                    try {
642:                        return super .clone();
643:                    } catch (CloneNotSupportedException e) {
644:                        throw new RuntimeException(e);
645:                    }
646:                }
647:
648:                public String toString() {
649:                    return ("flashVersion=" + flashVersion + ", "
650:                            + "splitframes=" + splitframes + ", "
651:                            + "addwrapper=" + addwrapper + ", "
652:                            + "trimWhitespace=" + trimWhitespace + ", "
653:                            + "localdata=" + localdata + ", " + "nsprefix=" + nsprefix);
654:                }
655:
656:            }
657:
658:            /**
659:             * Produces a JGenerator Flash Program containing
660:             * executable SWF codes to build an XML datasource structure which
661:             * represents this XML stream.
662:             *
663:             * Splits execution across frames when program buffer becomes too large.
664:             *
665:             *
666:             * @param xpp XML XPP parser which is reading from the data content string
667:             * @return Vector of one or more (if frame splitting) Flash Programs */
668:            public static Vector makeProgram(XmlPullParser xpp,
669:                    XmlPullParser xpheaders, int xmlsize, DCOptions ioptions)
670:                    throws IOException, XmlPullParserException {
671:                Vector programs = new Vector();
672:
673:                DCOptions options = (DCOptions) ioptions.clone();
674:
675:                int flashVersion = options.flashVersion;
676:                boolean splitframes = options.splitframes;
677:                boolean addwrapper = options.addwrapper;
678:                boolean trimWhitespace = options.trimWhitespace;
679:                boolean localdata = options.localdata;
680:                boolean nsprefix = options.nsprefix;
681:
682:                // Allocate at least enough room to hold the data nodes and strings, ok to allocate too much;
683:                // If we are not splitting frames, allocate enough to hold the whole XML file.
684:                FlashBuffer body = new FlashBuffer(splitframes ? FB_INIT_SIZE
685:                        : (xmlsize * 3) + 128000);
686:                Program bodyp = new Program(body);
687:                programs.add(bodyp);
688:
689:                // Bind the node creation functions to some short local names:
690:                //  element nodes: _level0._m => _m
691:                bodyp.push(new Object[] { "_m", "_level0" });
692:                bodyp.getVar();
693:                bodyp.push("_m");
694:                bodyp.getMember();
695:                bodyp.setVar();
696:
697:                //  text nodes: _level0._t => _t
698:                bodyp.push(new Object[] { "_t", "_level0" });
699:                bodyp.getVar();
700:                bodyp.push("_t");
701:                bodyp.getMember();
702:                bodyp.setVar();
703:
704:                // Build a root node by calling the runtime's root node instantiator
705:                // The root node will have $n = 0, and whatever other initial conditions are needed.
706:                bodyp.push(0); // Root node creator function takes no args.
707:                bodyp.push("_level0");
708:                bodyp.getVar();
709:                bodyp.push(ROOT_NODE_INSTANTIATOR_FN);
710:                bodyp.callMethod();
711:                // The root node is now on the stack.
712:
713:                if (addwrapper) {
714:                    // dup root node
715:                    body.writeByte(Actions.PushDuplicate);
716:                    // Create and push <resultset> node on stack
717:                    bodyp.push("resultset");
718:                    bodyp.push(0);
719:                    body._writeByte(Actions.InitObject);
720:                    bodyp.push(3); // 3 args : makeElementNode(attrs, name, parent)
721:                    bodyp.push(NODE_INSTANTIATOR_FN);
722:                    bodyp.callFunction();
723:                    // stack = <root> <resultset>
724:
725:                    // Push <body> element
726:                    body.writeByte(Actions.PushDuplicate);
727:                    bodyp.push("body");
728:                    bodyp.push(0);
729:                    body._writeByte(Actions.InitObject); // {}
730:                    bodyp.push(3); // 3 args : makeElementNode(attrs, name, parent)
731:                    bodyp.push(NODE_INSTANTIATOR_FN);
732:                    bodyp.callFunction(); // stack = <root> <resultset> <body>
733:                }
734:
735:                // Build data, which will get stuck under <body> node
736:                DataContext dc = makeDataContext(flashVersion);
737:                // Always insert the node constructor function names as the
738:                // first entries in string pool in this order.
739:                addStringConstant(NODE_INSTANTIATOR_FN, dc);
740:                addStringConstant(TEXT_INSTANTIATOR_FN, dc);
741:                // If it's a big multiframe dataset, a new dc in a new frame may be returned.
742:
743:                // If we are adding a wrapper, the stack has two extra items on it already, <resultset> and <body>.
744:                int stackdepth = (addwrapper ? 3 : 1);
745:                dc = writeXMLData(xpp, programs, dc, stackdepth, options);
746:                // Multiple frames may have been created, so append
747:                // finalization code to the last program in the list.
748:                bodyp = (Program) programs.lastElement();
749:                body = bodyp.body();
750:
751:                // Finalization Phase
752:                if (addwrapper) {
753:                    // pop the <body> node
754:                    bodyp.pop();
755:                    // stack ==  <root> <resultset> 
756:                    // Add in <headers>, they will get the <resultset> node as parent,
757:                    // since it's on top of stack
758:                    options.splitframes = false;
759:                    dc = writeXMLData(xpheaders, programs, dc, stackdepth,
760:                            options);
761:                    bodyp = (Program) programs.lastElement();
762:                    body = bodyp.body();
763:                    bodyp.pop(); // stack == <root>
764:                }
765:
766:                // Call the node finalize function; takes one arg: the scaffolding root node
767:                bodyp.push(1);
768:                bodyp.push("_level0");
769:                bodyp.getVar();
770:                bodyp.push(ROOT_NODE_FINAL_FN);
771:                bodyp.callMethod();
772:
773:                // The <resultset> node is on the stack now
774:
775:                // This is used by the data compiler to compile inline
776:                // datasets into an app swf file.
777:                body.writeByte(Actions.PushDuplicate);
778:                bodyp.push("__lzdataroot");
779:                body.writeByte(Actions.StackSwap);
780:                bodyp.setVar();
781:
782:                // If we're runtime-loaded (non-local) data, we need to call
783:                // back to our parent movieclip data loader.
784:                if (!localdata) {
785:                    // Call to _parent.loader.returnData(_parent, data) 
786:                    bodyp.push("_parent");
787:                    bodyp.getVar();
788:                    bodyp.push(2);
789:                    bodyp.push("_parent");
790:                    bodyp.getVar();
791:                    bodyp.push("loader");
792:                    bodyp.getMember();
793:                    bodyp.push("returnData");
794:                    bodyp.callMethod();
795:                    bodyp.pop();
796:
797:                    if (splitframes) {
798:                        // add a STOP for multiframe programs, otherwise it loops
799:                        bodyp.stop();
800:                    }
801:                }
802:
803:                // prepend the string pool to the program,and add it to the frame list
804:                Program withpool = appendStringPool(dc, body);
805:                // add to the list of frame/programs
806:                programs.setElementAt(withpool, programs.size() - 1);
807:
808:                return programs;
809:            }
810:
811:            // default nsprefix to false
812:            private static FlashFile makeSWF(XmlPullParser xpp,
813:                    XmlPullParser xpheaders, int xmlsize, int flashVersion,
814:                    boolean addwrapper, boolean trimWhitespace)
815:                    throws IOException, XmlPullParserException {
816:                return makeSWF(xpp, xpheaders, xmlsize, flashVersion,
817:                        addwrapper, trimWhitespace, false);
818:            }
819:
820:            /**
821:             * Make SWF
822:             *
823:             * @param xpp parser which is pointing at XML data 
824:             * @return FlashFile containing entire SWF with header
825:             */
826:            private static FlashFile makeSWF(XmlPullParser xpp,
827:                    XmlPullParser xpheaders, int xmlsize, int flashVersion,
828:                    boolean addwrapper, boolean trimWhitespace, boolean nsprefix)
829:                    throws IOException, XmlPullParserException {
830:                DCOptions options = new DCOptions();
831:                options.flashVersion = flashVersion;
832:                options.trimWhitespace = trimWhitespace;
833:                options.localdata = false;
834:                options.splitframes = true;
835:                options.addwrapper = addwrapper;
836:                options.nsprefix = nsprefix;
837:
838:                // Create FlashFile object nd include action bytes
839:                FlashFile file = FlashFile.newFlashFile();
840:                Script s = new Script(1);
841:                file.setMainScript(s);
842:                file.setVersion(flashVersion);
843:                Vector progs = makeProgram(xpp, xpheaders, xmlsize, options);
844:
845:                // iterate making a frame for each program
846:                while (progs.size() > 0) {
847:                    Program prog = (Program) progs.firstElement();
848:                    progs.removeElementAt(0); // pop
849:                    Frame frame = s.newFrame();
850:                    frame.addFlashObject(new DoAction(prog));
851:                }
852:
853:                return file;
854:            }
855:
856:            /** default trimWhitespace to true, for back compatibility */
857:            public static InputStream getSWF(XmlPullParser xpp,
858:                    XmlPullParser xpheaders, int xmlsize, int flashVersion,
859:                    boolean addwrapper) throws IOException,
860:                    XmlPullParserException {
861:                return getSWF(xpp, xpheaders, xmlsize, flashVersion,
862:                        addwrapper, true, false, false);
863:            }
864:
865:            /**
866:             * Get XML to output stream SWF
867:             *
868:             * @param xpp an XPP XML parser which points to the XML data
869:             * @param xppheaders an XPP XML parser which points to HTTP or other header XML metadata
870:             * @param flashVersion 5 or greater
871:             * @param addwrapper Set to true if you pass in a separate HTTP headers string
872:             * @param trimWhitespace controls whether whitespace is trimmed in text content
873:             * @return swf input stream
874:             */
875:            public static InputStream getSWF(XmlPullParser xpp,
876:                    XmlPullParser xpheaders, int xmlsize, int flashVersion,
877:                    boolean addwrapper, boolean trimWhitespace,
878:                    boolean compress, boolean nsprefix) throws IOException,
879:                    XmlPullParserException {
880:                // Get inputstream and write to outputstream
881:                InputStream input;
882:                int i = 0;
883:                try {
884:                    FlashFile file = makeSWF(xpp, xpheaders, xmlsize,
885:                            flashVersion, addwrapper, trimWhitespace, nsprefix);
886:                    if (flashVersion > 5) {
887:                        if (compress) {
888:                            file.setCompressed(true);
889:                        }
890:                    }
891:                    return file.generate().getInputStream();
892:                } catch (IVException ex) {
893:                    throw new ChainedException(ex);
894:                } catch (IOException e) {
895:                    mLogger.error("io error getting SWF: " + e.getMessage());
896:                    throw e;
897:                }
898:            }
899:
900:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.