Source Code Cross Referenced for BaseMarkupSerializer.java in  » Portal » uPortal_rel-2-6-1-GA » org » jasig » portal » serialize » 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 » Portal » uPortal_rel 2 6 1 GA » org.jasig.portal.serialize 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright 1999-2002,2004,2005 The Apache Software Foundation.
0003:         *
0004:         * Licensed under the Apache License, Version 2.0 (the "License");
0005:         * you may not use this file except in compliance with the License.
0006:         * You may obtain a copy of the License at
0007:         *
0008:         *      http://www.apache.org/licenses/LICENSE-2.0
0009:         *
0010:         * Unless required by applicable law or agreed to in writing, software
0011:         * distributed under the License is distributed on an "AS IS" BASIS,
0012:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013:         * See the License for the specific language governing permissions and
0014:         * limitations under the License.
0015:         */
0016:
0017:        // Sep 14, 2000:
0018:        //  Fixed comments to preserve whitespaces and add a line break
0019:        //  when indenting. Reported by Gervase Markham <gerv@gerv.net>
0020:        // Sep 14, 2000:
0021:        //  Fixed serializer to report IO exception directly, instead at
0022:        //  the end of document processing.
0023:        //  Reported by Patrick Higgins <phiggins@transzap.com>
0024:        // Sep 13, 2000:
0025:        //   CR in character data will print as &#0D;
0026:        // Aug 25, 2000:
0027:        //   Fixed processing instruction printing inside element content
0028:        //   to not escape content. Reported by Mikael Staldal
0029:        //   <d96-mst@d.kth.se>
0030:        // Aug 25, 2000:
0031:        //   Added ability to omit comments.
0032:        //   Contributed by Anupam Bagchi <abagchi@jtcsv.com>
0033:        // Aug 26, 2000:
0034:        //   Fixed bug in newline handling when preserving spaces.
0035:        //   Contributed by Mike Dusseault <mdusseault@home.com>
0036:        // Aug 29, 2000:
0037:        //   Fixed state.unescaped not being set to false when
0038:        //   entering element state.
0039:        //   Reported by Lowell Vaughn <lvaughn@agillion.com>
0040:
0041:        package org.jasig.portal.serialize;
0042:
0043:        import java.io.IOException;
0044:        import java.io.OutputStream;
0045:        import java.io.Writer;
0046:        import java.util.Hashtable;
0047:        import java.util.Vector;
0048:
0049:        import javax.xml.transform.Result;
0050:
0051:        import org.apache.xerces.dom.DOMErrorImpl;
0052:        import org.apache.xerces.dom.DOMLocatorImpl;
0053:        import org.apache.xerces.dom.DOMMessageFormatter;
0054:        import org.apache.xerces.util.XMLChar;
0055:        import org.apache.xml.serialize.DOMSerializerImpl;
0056:        import org.jasig.portal.IAnchoringSerializer;
0057:        import org.jasig.portal.properties.PropertiesManager;
0058:        import org.w3c.dom.DOMImplementation;
0059:        import org.w3c.dom.Document;
0060:        import org.w3c.dom.DocumentFragment;
0061:        import org.w3c.dom.DocumentType;
0062:        import org.w3c.dom.DOMError;
0063:        import org.w3c.dom.DOMErrorHandler;
0064:        import org.w3c.dom.Element;
0065:        import org.w3c.dom.Entity;
0066:        import org.w3c.dom.NamedNodeMap;
0067:        import org.w3c.dom.Node;
0068:        import org.w3c.dom.Notation;
0069:        import org.w3c.dom.ls.LSException;
0070:        import org.w3c.dom.ls.LSSerializerFilter;
0071:        import org.w3c.dom.traversal.NodeFilter;
0072:        import org.xml.sax.ContentHandler;
0073:        import org.xml.sax.DTDHandler;
0074:        import org.xml.sax.DocumentHandler;
0075:        import org.xml.sax.Locator;
0076:        import org.xml.sax.SAXException;
0077:        import org.xml.sax.ext.DeclHandler;
0078:        import org.xml.sax.ext.LexicalHandler;
0079:
0080:        /**
0081:         * Base class for a serializer supporting both DOM and SAX pretty
0082:         * serializing of XML/HTML/XHTML documents. Derives classes perform
0083:         * the method-specific serializing, this class provides the common
0084:         * serializing mechanisms.
0085:         * <p>
0086:         * The serializer must be initialized with the proper writer and
0087:         * output format before it can be used by calling {@link #setOutputCharStream}
0088:         * or {@link #setOutputByteStream} for the writer and {@link #setOutputFormat}
0089:         * for the output format.
0090:         * <p>
0091:         * The serializer can be reused any number of times, but cannot
0092:         * be used concurrently by two threads.
0093:         * <p>
0094:         * If an output stream is used, the encoding is taken from the
0095:         * output format (defaults to <tt>UTF-8</tt>). If a writer is
0096:         * used, make sure the writer uses the same encoding (if applies)
0097:         * as specified in the output format.
0098:         * <p>
0099:         * The serializer supports both DOM and SAX. DOM serializing is done
0100:         * by calling {@link #serialize(Document)} and SAX serializing is done by firing
0101:         * SAX events and using the serializer as a document handler.
0102:         * This also applies to derived class.
0103:         * <p>
0104:         * If an I/O exception occurs while serializing, the serializer
0105:         * will not throw an exception directly, but only throw it
0106:         * at the end of serializing (either DOM or SAX's {@link
0107:         * org.xml.sax.DocumentHandler#endDocument}.
0108:         * <p>
0109:         * For elements that are not specified as whitespace preserving,
0110:         * the serializer will potentially break long text lines at space
0111:         * boundaries, indent lines, and serialize elements on separate
0112:         * lines. Line terminators will be regarded as spaces, and
0113:         * spaces at beginning of line will be stripped.
0114:         * <p>
0115:         * When indenting, the serializer is capable of detecting seemingly
0116:         * element content, and serializing these elements indented on separate
0117:         * lines. An element is serialized indented when it is the first or
0118:         * last child of an element, or immediate following or preceding
0119:         * another element.
0120:         *
0121:         *
0122:         * @version $Revision: 36683 $ $Date: 2006-08-23 15:08:00 -0700 (Wed, 23 Aug 2006) $
0123:         * @author <a href="mailto:arkin@intalio.com">Assaf Arkin</a>
0124:         * @author <a href="mailto:rahul.srivastava@sun.com">Rahul Srivastava</a>
0125:         * @author Elena Litani, IBM
0126:         * @see Serializer
0127:         */
0128:        public abstract class BaseMarkupSerializer implements  ContentHandler,
0129:                DocumentHandler, LexicalHandler, DTDHandler, DeclHandler,
0130:                DOMSerializer, Serializer, IAnchoringSerializer {
0131:
0132:            // DOM L3 implementation
0133:            protected short features = 0xFFFFFFFF;
0134:            protected DOMErrorHandler fDOMErrorHandler;
0135:            protected final DOMErrorImpl fDOMError = new DOMErrorImpl();
0136:            protected LSSerializerFilter fDOMFilter;
0137:
0138:            protected EncodingInfo _encodingInfo;
0139:
0140:            /**
0141:             * Holds array of all element states that have been entered.
0142:             * The array is automatically resized. When leaving an element,
0143:             * it's state is not removed but reused when later returning
0144:             * to the same nesting level.
0145:             */
0146:            private ElementState[] _elementStates;
0147:
0148:            /**
0149:             * The index of the next state to place in the array,
0150:             * or one plus the index of the current state. When zero,
0151:             * we are in no state.
0152:             */
0153:            private int _elementStateCount;
0154:
0155:            /**
0156:             * Vector holding comments and PIs that come before the root
0157:             * element (even after it), see {@link #serializePreRoot}.
0158:             */
0159:            private Vector _preRoot;
0160:
0161:            /**
0162:             * If the document has been started (header serialized), this
0163:             * flag is set to true so it's not started twice.
0164:             */
0165:            protected boolean _started;
0166:
0167:            /**
0168:             * True if the serializer has been prepared. This flag is set
0169:             * to false when the serializer is reset prior to using it,
0170:             * and to true after it has been prepared for usage.
0171:             */
0172:            private boolean _prepared;
0173:
0174:            /**
0175:             * Association between namespace URIs (keys) and prefixes (values).
0176:             * Accumulated here prior to starting an element and placing this
0177:             * list in the element state.
0178:             */
0179:            protected Hashtable _prefixes;
0180:
0181:            /**
0182:             * The system identifier of the document type, if known.
0183:             */
0184:            protected String _docTypePublicId;
0185:
0186:            /**
0187:             * The system identifier of the document type, if known.
0188:             */
0189:            protected String _docTypeSystemId;
0190:
0191:            /**
0192:             * The output format associated with this serializer. This will never
0193:             * be a null reference. If no format was passed to the constructor,
0194:             * the default one for this document type will be used. The format
0195:             * object is never changed by the serializer.
0196:             */
0197:            protected OutputFormat _format;
0198:
0199:            /**
0200:             * The printer used for printing text parts.
0201:             */
0202:            protected Printer _printer;
0203:
0204:            /**
0205:             * True if indenting printer.
0206:             */
0207:            protected boolean _indenting;
0208:
0209:            /** Temporary buffer to store character data */
0210:            protected final StringBuffer fStrBuffer = new StringBuffer(40);
0211:
0212:            /**
0213:             * The underlying writer.
0214:             */
0215:            private Writer _writer;
0216:
0217:            /**
0218:             * The output stream.
0219:             */
0220:            private OutputStream _output;
0221:
0222:            /** Current node that is being processed  */
0223:            protected Node fCurrentNode = null;
0224:
0225:            //--------------------------------//
0226:            // Constructor and initialization //
0227:            //--------------------------------//
0228:
0229:            /**
0230:             * Protected constructor can only be used by derived class.
0231:             * Must initialize the serializer before serializing any document,
0232:             * by calling {@link #setOutputCharStream} or {@link #setOutputByteStream}
0233:             * first
0234:             */
0235:            protected BaseMarkupSerializer(OutputFormat format) {
0236:                int i;
0237:
0238:                _elementStates = new ElementState[10];
0239:                for (i = 0; i < _elementStates.length; ++i)
0240:                    _elementStates[i] = new ElementState();
0241:                _format = format;
0242:
0243:                try {
0244:                    _allowDisableOutputEscaping = PropertiesManager
0245:                            .getPropertyAsBoolean("org.jasig.portal.serialize.BaseMarkupSerializer.allow_disable_output_escaping");
0246:                } catch (Exception e) {
0247:                    _allowDisableOutputEscaping = false;
0248:                }
0249:            }
0250:
0251:            public DocumentHandler asDocumentHandler() throws IOException {
0252:                prepare();
0253:                return this ;
0254:            }
0255:
0256:            public ContentHandler asContentHandler() throws IOException {
0257:                prepare();
0258:                return this ;
0259:            }
0260:
0261:            public DOMSerializer asDOMSerializer() throws IOException {
0262:                prepare();
0263:                return this ;
0264:            }
0265:
0266:            public void setOutputByteStream(OutputStream output) {
0267:                if (output == null) {
0268:                    String msg = DOMMessageFormatter.formatMessage(
0269:                            DOMMessageFormatter.SERIALIZER_DOMAIN,
0270:                            "ArgumentIsNull", new Object[] { "output" });
0271:                    throw new NullPointerException(msg);
0272:                }
0273:                _output = output;
0274:                _writer = null;
0275:                reset();
0276:            }
0277:
0278:            public void setOutputCharStream(Writer writer) {
0279:                if (writer == null) {
0280:                    String msg = DOMMessageFormatter.formatMessage(
0281:                            DOMMessageFormatter.SERIALIZER_DOMAIN,
0282:                            "ArgumentIsNull", new Object[] { "writer" });
0283:                    throw new NullPointerException(msg);
0284:                }
0285:                _writer = writer;
0286:                _output = null;
0287:                reset();
0288:            }
0289:
0290:            public void setOutputFormat(OutputFormat format) {
0291:                if (format == null) {
0292:                    String msg = DOMMessageFormatter.formatMessage(
0293:                            DOMMessageFormatter.SERIALIZER_DOMAIN,
0294:                            "ArgumentIsNull", new Object[] { "format" });
0295:                    throw new NullPointerException(msg);
0296:                }
0297:                _format = format;
0298:                reset();
0299:            }
0300:
0301:            public boolean reset() {
0302:                if (_elementStateCount > 1) {
0303:                    String msg = DOMMessageFormatter.formatMessage(
0304:                            DOMMessageFormatter.SERIALIZER_DOMAIN,
0305:                            "ResetInMiddle", null);
0306:                    throw new IllegalStateException(msg);
0307:                }
0308:                _prepared = false;
0309:                fCurrentNode = null;
0310:                fStrBuffer.setLength(0);
0311:                return true;
0312:            }
0313:
0314:            protected void prepare() throws IOException {
0315:                if (_prepared)
0316:                    return;
0317:
0318:                if (_writer == null && _output == null) {
0319:                    String msg = DOMMessageFormatter.formatMessage(
0320:                            DOMMessageFormatter.SERIALIZER_DOMAIN,
0321:                            "NoWriterSupplied", null);
0322:                    throw new IOException(msg);
0323:                }
0324:                // If the output stream has been set, use it to construct
0325:                // the writer. It is possible that the serializer has been
0326:                // reused with the same output stream and different encoding.
0327:
0328:                _encodingInfo = _format.getEncodingInfo();
0329:
0330:                if (_output != null) {
0331:                    _writer = _encodingInfo.getWriter(_output);
0332:                }
0333:
0334:                if (_format.getIndenting()) {
0335:                    _indenting = true;
0336:                    _printer = new IndentPrinter(_writer, _format);
0337:                } else {
0338:                    _indenting = false;
0339:                    _printer = new Printer(_writer, _format);
0340:                }
0341:
0342:                ElementState state;
0343:
0344:                _elementStateCount = 0;
0345:                state = _elementStates[0];
0346:                state.namespaceURI = null;
0347:                state.localName = null;
0348:                state.rawName = null;
0349:                state.preserveSpace = _format.getPreserveSpace();
0350:                state.empty = true;
0351:                state.afterElement = false;
0352:                state.afterComment = false;
0353:                state.doCData = state.inCData = false;
0354:                state.prefixes = null;
0355:
0356:                _docTypePublicId = _format.getDoctypePublic();
0357:                _docTypeSystemId = _format.getDoctypeSystem();
0358:                _started = false;
0359:                _prepared = true;
0360:            }
0361:
0362:            //----------------------------------//
0363:            // DOM document serializing methods //
0364:            //----------------------------------//
0365:
0366:            /**
0367:             * Serializes the DOM element using the previously specified
0368:             * writer and output format. Throws an exception only if
0369:             * an I/O exception occured while serializing.
0370:             *
0371:             * @param elem The element to serialize
0372:             * @throws IOException An I/O exception occured while
0373:             *   serializing
0374:             */
0375:            public void serialize(Element elem) throws IOException {
0376:                reset();
0377:                prepare();
0378:                serializeNode(elem);
0379:                _printer.flush();
0380:                if (_printer.getException() != null)
0381:                    throw _printer.getException();
0382:            }
0383:
0384:            /**
0385:             * Serializes the DOM document fragmnt using the previously specified
0386:             * writer and output format. Throws an exception only if
0387:             * an I/O exception occured while serializing.
0388:             *
0389:             * @param frag The element to serialize
0390:             * @throws IOException An I/O exception occured while
0391:             *   serializing
0392:             */
0393:            public void serialize(DocumentFragment frag) throws IOException {
0394:                reset();
0395:                prepare();
0396:                serializeNode(frag);
0397:                _printer.flush();
0398:                if (_printer.getException() != null)
0399:                    throw _printer.getException();
0400:            }
0401:
0402:            /**
0403:             * Serializes the DOM document using the previously specified
0404:             * writer and output format. Throws an exception only if
0405:             * an I/O exception occured while serializing.
0406:             *
0407:             * @param doc The document to serialize
0408:             * @throws IOException An I/O exception occured while
0409:             *   serializing
0410:             */
0411:            public void serialize(Document doc) throws IOException {
0412:                reset();
0413:                prepare();
0414:                serializeNode(doc);
0415:                serializePreRoot();
0416:                _printer.flush();
0417:                if (_printer.getException() != null)
0418:                    throw _printer.getException();
0419:            }
0420:
0421:            //------------------------------------------//
0422:            // SAX document handler serializing methods //
0423:            //------------------------------------------//
0424:
0425:            public void startDocument() throws SAXException {
0426:                try {
0427:                    prepare();
0428:                } catch (IOException except) {
0429:                    throw new SAXException(except.toString());
0430:                }
0431:                // Nothing to do here. All the magic happens in startDocument(String)
0432:            }
0433:
0434:            public void characters(char[] chars, int start, int length)
0435:                    throws SAXException {
0436:                ElementState state;
0437:
0438:                try {
0439:                    state = content();
0440:
0441:                    // Check if text should be print as CDATA section or unescaped
0442:                    // based on elements listed in the output format (the element
0443:                    // state) or whether we are inside a CDATA section or entity.
0444:
0445:                    if (state.inCData || state.doCData) {
0446:                        int saveIndent;
0447:
0448:                        // Print a CDATA section. The text is not escaped, but ']]>'
0449:                        // appearing in the code must be identified and dealt with.
0450:                        // The contents of a text node is considered space preserving.
0451:                        if (!state.inCData) {
0452:                            if (html4compat && state.inScript) {
0453:                                _printer.printText("\n//<![CDATA[\n");
0454:                            } else {
0455:                                //                    _printer.printText( "\n<!--/*--><![CDATA[/*><!--*/\n" );
0456:                                _printer.printText("\n/*<![CDATA[*/\n");
0457:                                //                    _printer.printText( "<![CDATA[" );
0458:                            }
0459:                            state.inCData = true;
0460:                        }
0461:                        saveIndent = _printer.getNextIndent();
0462:                        _printer.setNextIndent(0);
0463:                        char ch;
0464:                        final int end = start + length;
0465:                        for (int index = start; index < end; ++index) {
0466:                            ch = chars[index];
0467:                            if (ch == ']' && index + 2 < end
0468:                                    && chars[index + 1] == ']'
0469:                                    && chars[index + 2] == '>') {
0470:                                _printer.printText("]]]]><![CDATA[>");
0471:                                index += 2;
0472:                                continue;
0473:                            }
0474:                            if (!XMLChar.isValid(ch)) {
0475:                                // check if it is surrogate
0476:                                if (++index < end) {
0477:                                    surrogates(ch, chars[index]);
0478:                                } else {
0479:                                    fatalError("The character '" + (char) ch
0480:                                            + "' is an invalid XML character");
0481:                                }
0482:                                continue;
0483:                            } else {
0484:                                if ((ch >= ' '
0485:                                        && _encodingInfo.isPrintable((char) ch) && ch != 0xF7)
0486:                                        || ch == '\n'
0487:                                        || ch == '\r'
0488:                                        || ch == '\t') {
0489:                                    _printer.printText((char) ch);
0490:                                } else {
0491:                                    // The character is not printable -- split CDATA section
0492:                                    _printer.printText("]]>&#x");
0493:                                    _printer.printText(Integer.toHexString(ch));
0494:                                    _printer.printText(";<![CDATA[");
0495:                                }
0496:                            }
0497:                        }
0498:                        _printer.setNextIndent(saveIndent);
0499:
0500:                    } else {
0501:
0502:                        int saveIndent;
0503:
0504:                        if (state.preserveSpace) {
0505:                            // If preserving space then hold of indentation so no
0506:                            // excessive spaces are printed at line breaks, escape
0507:                            // the text content without replacing spaces and print
0508:                            // the text breaking only at line breaks.
0509:                            saveIndent = _printer.getNextIndent();
0510:                            _printer.setNextIndent(0);
0511:                            printText(chars, start, length, true,
0512:                                    state.unescaped);
0513:                            _printer.setNextIndent(saveIndent);
0514:                        } else {
0515:                            printText(chars, start, length, false,
0516:                                    state.unescaped);
0517:                        }
0518:                    }
0519:                } catch (IOException except) {
0520:                    throw new SAXException(except);
0521:                }
0522:            }
0523:
0524:            public void ignorableWhitespace(char[] chars, int start, int length)
0525:                    throws SAXException {
0526:                int i;
0527:
0528:                try {
0529:                    content();
0530:
0531:                    // Print ignorable whitespaces only when indenting, after
0532:                    // all they are indentation. Cancel the indentation to
0533:                    // not indent twice.
0534:                    if (_indenting) {
0535:                        _printer.setThisIndent(0);
0536:                        for (i = start; length-- > 0; ++i)
0537:                            _printer.printText(chars[i]);
0538:                    }
0539:                } catch (IOException except) {
0540:                    throw new SAXException(except);
0541:                }
0542:            }
0543:
0544:            public final void processingInstruction(String target, String code)
0545:                    throws SAXException {
0546:                try {
0547:                    processingInstructionIO(target, code);
0548:                } catch (IOException except) {
0549:                    throw new SAXException(except);
0550:                }
0551:            }
0552:
0553:            public void processingInstructionIO(String target, String code)
0554:                    throws IOException {
0555:                int index;
0556:                ElementState state;
0557:
0558:                state = content();
0559:
0560:                // Create the processing instruction textual representation.
0561:                // Make sure we don't have '?>' inside either target or code.
0562:                index = target.indexOf("?>");
0563:                if (index >= 0)
0564:                    fStrBuffer.append("<?").append(target.substring(0, index));
0565:                else
0566:                    fStrBuffer.append("<?").append(target);
0567:                if (code != null) {
0568:                    fStrBuffer.append(' ');
0569:                    index = code.indexOf("?>");
0570:                    if (index >= 0)
0571:                        fStrBuffer.append(code.substring(0, index));
0572:                    else
0573:                        fStrBuffer.append(code);
0574:                }
0575:                fStrBuffer.append("?>");
0576:
0577:                // If before the root element (or after it), do not print
0578:                // the PI directly but place it in the pre-root vector.
0579:                if (isDocumentState()) {
0580:                    if (_preRoot == null)
0581:                        _preRoot = new Vector();
0582:                    _preRoot.addElement(fStrBuffer.toString());
0583:                } else {
0584:                    _printer.indent();
0585:                    printText(fStrBuffer.toString(), true, true);
0586:                    _printer.unindent();
0587:                    if (_indenting)
0588:                        state.afterElement = true;
0589:                }
0590:
0591:                fStrBuffer.setLength(0);
0592:
0593:                if (_allowDisableOutputEscaping) {
0594:                    if (target.equals(Result.PI_DISABLE_OUTPUT_ESCAPING))
0595:                        startNonEscaping();
0596:                    else if (target.equals(Result.PI_ENABLE_OUTPUT_ESCAPING))
0597:                        endNonEscaping();
0598:                }
0599:            }
0600:
0601:            public void comment(char[] chars, int start, int length)
0602:                    throws SAXException {
0603:                try {
0604:                    comment(new String(chars, start, length));
0605:                } catch (IOException except) {
0606:                    throw new SAXException(except);
0607:                }
0608:            }
0609:
0610:            public void comment(String text) throws IOException {
0611:                int index;
0612:                ElementState state;
0613:
0614:                if (_format.getOmitComments())
0615:                    return;
0616:
0617:                state = content();
0618:                // Create the processing comment textual representation.
0619:                // Make sure we don't have '-->' inside the comment.
0620:                index = text.indexOf("-->");
0621:                if (index >= 0)
0622:                    fStrBuffer.append("<!--").append(text.substring(0, index))
0623:                            .append("-->");
0624:                else
0625:                    fStrBuffer.append("<!--").append(text).append("-->");
0626:
0627:                // If before the root element (or after it), do not print
0628:                // the comment directly but place it in the pre-root vector.
0629:                if (isDocumentState()) {
0630:                    if (_preRoot == null)
0631:                        _preRoot = new Vector();
0632:                    _preRoot.addElement(fStrBuffer.toString());
0633:                } else {
0634:                    // Indent this element on a new line if the first
0635:                    // content of the parent element or immediately
0636:                    // following an element.
0637:                    if (_indenting && !state.preserveSpace)
0638:                        _printer.breakLine();
0639:                    _printer.indent();
0640:                    printText(fStrBuffer.toString(), true, true);
0641:                    _printer.unindent();
0642:                    if (_indenting)
0643:                        state.afterElement = true;
0644:                }
0645:
0646:                fStrBuffer.setLength(0);
0647:                state.afterComment = true;
0648:                state.afterElement = false;
0649:            }
0650:
0651:            public void startCDATA() {
0652:                ElementState state;
0653:
0654:                state = getElementState();
0655:                state.doCData = true;
0656:            }
0657:
0658:            public void endCDATA() {
0659:                ElementState state;
0660:
0661:                state = getElementState();
0662:                state.doCData = false;
0663:            }
0664:
0665:            public void startNonEscaping() {
0666:                ElementState state;
0667:
0668:                state = getElementState();
0669:                state.unescaped = true;
0670:            }
0671:
0672:            public void endNonEscaping() {
0673:                ElementState state;
0674:
0675:                state = getElementState();
0676:                state.unescaped = false;
0677:            }
0678:
0679:            public void startPreserving() {
0680:                ElementState state;
0681:
0682:                state = getElementState();
0683:                state.preserveSpace = true;
0684:            }
0685:
0686:            public void endPreserving() {
0687:                ElementState state;
0688:
0689:                state = getElementState();
0690:                state.preserveSpace = false;
0691:            }
0692:
0693:            /**
0694:             * Called at the end of the document to wrap it up.
0695:             * Will flush the output stream and throw an exception
0696:             * if any I/O error occured while serializing.
0697:             *
0698:             * @throws SAXException An I/O exception occured during
0699:             *  serializing
0700:             */
0701:            public void endDocument() throws SAXException {
0702:                try {
0703:                    // Print all the elements accumulated outside of
0704:                    // the root element.
0705:                    serializePreRoot();
0706:                    // Flush the output, this is necessary for fStrBuffered output.
0707:                    _printer.flush();
0708:                } catch (IOException except) {
0709:                    throw new SAXException(except);
0710:                }
0711:            }
0712:
0713:            public void startEntity(String name) {
0714:                // ???
0715:            }
0716:
0717:            public void endEntity(String name) {
0718:                // ???
0719:            }
0720:
0721:            public void setDocumentLocator(Locator locator) {
0722:                // Nothing to do
0723:            }
0724:
0725:            //-----------------------------------------//
0726:            // SAX content handler serializing methods //
0727:            //-----------------------------------------//
0728:
0729:            public void skippedEntity(String name) throws SAXException {
0730:                try {
0731:                    endCDATA();
0732:                    content();
0733:                    _printer.printText('&');
0734:                    _printer.printText(name);
0735:                    _printer.printText(';');
0736:                } catch (IOException except) {
0737:                    throw new SAXException(except);
0738:                }
0739:            }
0740:
0741:            public void startPrefixMapping(String prefix, String uri)
0742:                    throws SAXException {
0743:                if (_prefixes == null)
0744:                    _prefixes = new Hashtable();
0745:                _prefixes.put(uri, prefix == null ? "" : prefix);
0746:            }
0747:
0748:            public void endPrefixMapping(String prefix) throws SAXException {
0749:            }
0750:
0751:            //------------------------------------------//
0752:            // SAX DTD/Decl handler serializing methods //
0753:            //------------------------------------------//
0754:
0755:            public final void startDTD(String name, String publicId,
0756:                    String systemId) throws SAXException {
0757:                try {
0758:                    _printer.enterDTD();
0759:                    _docTypePublicId = publicId;
0760:                    _docTypeSystemId = systemId;
0761:                } catch (IOException except) {
0762:                    throw new SAXException(except);
0763:                }
0764:            }
0765:
0766:            public void endDTD() {
0767:                // Nothing to do here, all the magic occurs in startDocument(String).
0768:            }
0769:
0770:            public void elementDecl(String name, String model)
0771:                    throws SAXException {
0772:                try {
0773:                    _printer.enterDTD();
0774:                    _printer.printText("<!ELEMENT ");
0775:                    _printer.printText(name);
0776:                    _printer.printText(' ');
0777:                    _printer.printText(model);
0778:                    _printer.printText('>');
0779:                    if (_indenting)
0780:                        _printer.breakLine();
0781:                } catch (IOException except) {
0782:                    throw new SAXException(except);
0783:                }
0784:            }
0785:
0786:            public void attributeDecl(String eName, String aName, String type,
0787:                    String valueDefault, String value) throws SAXException {
0788:                try {
0789:                    _printer.enterDTD();
0790:                    _printer.printText("<!ATTLIST ");
0791:                    _printer.printText(eName);
0792:                    _printer.printText(' ');
0793:                    _printer.printText(aName);
0794:                    _printer.printText(' ');
0795:                    _printer.printText(type);
0796:                    if (valueDefault != null) {
0797:                        _printer.printText(' ');
0798:                        _printer.printText(valueDefault);
0799:                    }
0800:                    if (value != null) {
0801:                        _printer.printText(" \"");
0802:                        printEscaped(value);
0803:                        _printer.printText('"');
0804:                    }
0805:                    _printer.printText('>');
0806:                    if (_indenting)
0807:                        _printer.breakLine();
0808:                } catch (IOException except) {
0809:                    throw new SAXException(except);
0810:                }
0811:            }
0812:
0813:            public void internalEntityDecl(String name, String value)
0814:                    throws SAXException {
0815:                try {
0816:                    _printer.enterDTD();
0817:                    _printer.printText("<!ENTITY ");
0818:                    _printer.printText(name);
0819:                    _printer.printText(" \"");
0820:                    printEscaped(value);
0821:                    _printer.printText("\">");
0822:                    if (_indenting)
0823:                        _printer.breakLine();
0824:                } catch (IOException except) {
0825:                    throw new SAXException(except);
0826:                }
0827:            }
0828:
0829:            public void externalEntityDecl(String name, String publicId,
0830:                    String systemId) throws SAXException {
0831:                try {
0832:                    _printer.enterDTD();
0833:                    unparsedEntityDecl(name, publicId, systemId, null);
0834:                } catch (IOException except) {
0835:                    throw new SAXException(except);
0836:                }
0837:            }
0838:
0839:            public void unparsedEntityDecl(String name, String publicId,
0840:                    String systemId, String notationName) throws SAXException {
0841:                try {
0842:                    _printer.enterDTD();
0843:                    if (publicId == null) {
0844:                        _printer.printText("<!ENTITY ");
0845:                        _printer.printText(name);
0846:                        _printer.printText(" SYSTEM ");
0847:                        printDoctypeURL(systemId);
0848:                    } else {
0849:                        _printer.printText("<!ENTITY ");
0850:                        _printer.printText(name);
0851:                        _printer.printText(" PUBLIC ");
0852:                        printDoctypeURL(publicId);
0853:                        _printer.printText(' ');
0854:                        printDoctypeURL(systemId);
0855:                    }
0856:                    if (notationName != null) {
0857:                        _printer.printText(" NDATA ");
0858:                        _printer.printText(notationName);
0859:                    }
0860:                    _printer.printText('>');
0861:                    if (_indenting)
0862:                        _printer.breakLine();
0863:                } catch (IOException except) {
0864:                    throw new SAXException(except);
0865:                }
0866:            }
0867:
0868:            public void notationDecl(String name, String publicId,
0869:                    String systemId) throws SAXException {
0870:                try {
0871:                    _printer.enterDTD();
0872:                    if (publicId != null) {
0873:                        _printer.printText("<!NOTATION ");
0874:                        _printer.printText(name);
0875:                        _printer.printText(" PUBLIC ");
0876:                        printDoctypeURL(publicId);
0877:                        if (systemId != null) {
0878:                            _printer.printText(' ');
0879:                            printDoctypeURL(systemId);
0880:                        }
0881:                    } else {
0882:                        _printer.printText("<!NOTATION ");
0883:                        _printer.printText(name);
0884:                        _printer.printText(" SYSTEM ");
0885:                        printDoctypeURL(systemId);
0886:                    }
0887:                    _printer.printText('>');
0888:                    if (_indenting)
0889:                        _printer.breakLine();
0890:                } catch (IOException except) {
0891:                    throw new SAXException(except);
0892:                }
0893:            }
0894:
0895:            //------------------------------------------//
0896:            // Generic node serializing methods methods //
0897:            //------------------------------------------//
0898:
0899:            /**
0900:             * Serialize the DOM node. This method is shared across XML, HTML and XHTML
0901:             * serializers and the differences are masked out in a separate {@link
0902:             * #serializeElement}.
0903:             *
0904:             * @param node The node to serialize
0905:             * @see #serializeElement
0906:             * @throws IOException An I/O exception occured while
0907:             *   serializing
0908:             */
0909:            protected void serializeNode(Node node) throws IOException {
0910:                fCurrentNode = node;
0911:
0912:                // Based on the node type call the suitable SAX handler.
0913:                // Only comments entities and documents which are not
0914:                // handled by SAX are serialized directly.
0915:                switch (node.getNodeType()) {
0916:                case Node.TEXT_NODE: {
0917:                    String text;
0918:
0919:                    text = node.getNodeValue();
0920:                    if (text != null) {
0921:                        if (fDOMFilter != null
0922:                                && (fDOMFilter.getWhatToShow() & NodeFilter.SHOW_TEXT) != 0) {
0923:                            short code = fDOMFilter.acceptNode(node);
0924:                            switch (code) {
0925:                            case NodeFilter.FILTER_REJECT:
0926:                            case NodeFilter.FILTER_SKIP: {
0927:                                break;
0928:                            }
0929:                            default: {
0930:                                characters(text);
0931:                            }
0932:                            }
0933:                        } else if (!_indenting
0934:                                || getElementState().preserveSpace
0935:                                || (text.replace('\n', ' ').trim().length() != 0))
0936:                            characters(text);
0937:
0938:                    }
0939:                    break;
0940:                }
0941:
0942:                case Node.CDATA_SECTION_NODE: {
0943:                    String text = node.getNodeValue();
0944:                    if ((features & /*DOMSerializerImpl.CDATA*/0x1 << 3) != 0) {
0945:                        if (text != null) {
0946:                            if (fDOMFilter != null
0947:                                    && (fDOMFilter.getWhatToShow() & NodeFilter.SHOW_CDATA_SECTION) != 0) {
0948:                                short code = fDOMFilter.acceptNode(node);
0949:                                switch (code) {
0950:                                case NodeFilter.FILTER_REJECT:
0951:                                case NodeFilter.FILTER_SKIP: {
0952:                                    // skip the CDATA node
0953:                                    return;
0954:                                }
0955:                                default: {
0956:                                    //fall through..
0957:                                }
0958:                                }
0959:                            }
0960:                            startCDATA();
0961:                            characters(text);
0962:                            endCDATA();
0963:                        }
0964:                    } else {
0965:                        // transform into a text node
0966:                        characters(text);
0967:                    }
0968:                    break;
0969:                }
0970:                case Node.COMMENT_NODE: {
0971:                    String text;
0972:
0973:                    if (!_format.getOmitComments()) {
0974:                        text = node.getNodeValue();
0975:                        if (text != null) {
0976:
0977:                            if (fDOMFilter != null
0978:                                    && (fDOMFilter.getWhatToShow() & NodeFilter.SHOW_COMMENT) != 0) {
0979:                                short code = fDOMFilter.acceptNode(node);
0980:                                switch (code) {
0981:                                case NodeFilter.FILTER_REJECT:
0982:                                case NodeFilter.FILTER_SKIP: {
0983:                                    // skip the comment node
0984:                                    return;
0985:                                }
0986:                                default: {
0987:                                    // fall through
0988:                                }
0989:                                }
0990:                            }
0991:                            comment(text);
0992:                        }
0993:                    }
0994:                    break;
0995:                }
0996:
0997:                case Node.ENTITY_REFERENCE_NODE: {
0998:                    Node child;
0999:
1000:                    endCDATA();
1001:                    content();
1002:
1003:                    if (((features & /*DOMSerializerImpl.ENTITIES*/0x1 << 2) != 0)
1004:                            || (node.getFirstChild() == null)) {
1005:                        if (fDOMFilter != null
1006:                                && (fDOMFilter.getWhatToShow() & NodeFilter.SHOW_ENTITY_REFERENCE) != 0) {
1007:                            short code = fDOMFilter.acceptNode(node);
1008:                            switch (code) {
1009:                            case NodeFilter.FILTER_REJECT: {
1010:                                return; // remove the node
1011:                            }
1012:                            case NodeFilter.FILTER_SKIP: {
1013:                                child = node.getFirstChild();
1014:                                while (child != null) {
1015:                                    serializeNode(child);
1016:                                    child = child.getNextSibling();
1017:                                }
1018:                                return;
1019:                            }
1020:
1021:                            default: {
1022:                                // fall through
1023:                            }
1024:                            }
1025:                        }
1026:                        checkUnboundNamespacePrefixedNode(node);
1027:
1028:                        _printer.printText("&");
1029:                        _printer.printText(node.getNodeName());
1030:                        _printer.printText(";");
1031:                    } else {
1032:                        child = node.getFirstChild();
1033:                        while (child != null) {
1034:                            serializeNode(child);
1035:                            child = child.getNextSibling();
1036:                        }
1037:                    }
1038:
1039:                    break;
1040:                }
1041:
1042:                case Node.PROCESSING_INSTRUCTION_NODE: {
1043:
1044:                    if (fDOMFilter != null
1045:                            && (fDOMFilter.getWhatToShow() & NodeFilter.SHOW_PROCESSING_INSTRUCTION) != 0) {
1046:                        short code = fDOMFilter.acceptNode(node);
1047:                        switch (code) {
1048:                        case NodeFilter.FILTER_REJECT:
1049:                        case NodeFilter.FILTER_SKIP: {
1050:                            return; // skip this node
1051:                        }
1052:                        default: { // fall through
1053:                        }
1054:                        }
1055:                    }
1056:                    processingInstructionIO(node.getNodeName(), node
1057:                            .getNodeValue());
1058:                    break;
1059:                }
1060:                case Node.ELEMENT_NODE: {
1061:
1062:                    if (fDOMFilter != null
1063:                            && (fDOMFilter.getWhatToShow() & NodeFilter.SHOW_ELEMENT) != 0) {
1064:                        short code = fDOMFilter.acceptNode(node);
1065:                        switch (code) {
1066:                        case NodeFilter.FILTER_REJECT: {
1067:                            return;
1068:                        }
1069:                        case NodeFilter.FILTER_SKIP: {
1070:                            Node child = node.getFirstChild();
1071:                            while (child != null) {
1072:                                serializeNode(child);
1073:                                child = child.getNextSibling();
1074:                            }
1075:                            return; // skip this node
1076:                        }
1077:
1078:                        default: { // fall through
1079:                        }
1080:                        }
1081:                    }
1082:                    serializeElement((Element) node);
1083:                    break;
1084:                }
1085:                case Node.DOCUMENT_NODE: {
1086:                    DocumentType docType;
1087:                    DOMImplementation domImpl;
1088:                    NamedNodeMap map;
1089:                    Entity entity;
1090:                    Notation notation;
1091:                    int i;
1092:
1093:                    // If there is a document type, use the SAX events to
1094:                    // serialize it.
1095:                    docType = ((Document) node).getDoctype();
1096:                    if (docType != null) {
1097:                        // DOM Level 2 (or higher)
1098:                        domImpl = ((Document) node).getImplementation();
1099:                        try {
1100:                            String internal;
1101:
1102:                            _printer.enterDTD();
1103:                            _docTypePublicId = docType.getPublicId();
1104:                            _docTypeSystemId = docType.getSystemId();
1105:                            internal = docType.getInternalSubset();
1106:                            if (internal != null && internal.length() > 0)
1107:                                _printer.printText(internal);
1108:                            endDTD();
1109:                        }
1110:                        // DOM Level 1 -- does implementation have methods?
1111:                        catch (NoSuchMethodError nsme) {
1112:                            Class docTypeClass = docType.getClass();
1113:
1114:                            String docTypePublicId = null;
1115:                            String docTypeSystemId = null;
1116:                            try {
1117:                                java.lang.reflect.Method getPublicId = docTypeClass
1118:                                        .getMethod("getPublicId",
1119:                                                (Class[]) null);
1120:                                if (getPublicId.getReturnType().equals(
1121:                                        String.class)) {
1122:                                    docTypePublicId = (String) getPublicId
1123:                                            .invoke(docType, (Object[]) null);
1124:                                }
1125:                            } catch (Exception e) {
1126:                                // ignore
1127:                            }
1128:                            try {
1129:                                java.lang.reflect.Method getSystemId = docTypeClass
1130:                                        .getMethod("getSystemId",
1131:                                                (Class[]) null);
1132:                                if (getSystemId.getReturnType().equals(
1133:                                        String.class)) {
1134:                                    docTypeSystemId = (String) getSystemId
1135:                                            .invoke(docType, (Object[]) null);
1136:                                }
1137:                            } catch (Exception e) {
1138:                                // ignore
1139:                            }
1140:                            _printer.enterDTD();
1141:                            _docTypePublicId = docTypePublicId;
1142:                            _docTypeSystemId = docTypeSystemId;
1143:                            endDTD();
1144:                        }
1145:                    }
1146:                    // !! Fall through
1147:                }
1148:                case Node.DOCUMENT_FRAGMENT_NODE: {
1149:                    Node child;
1150:
1151:                    // By definition this will happen if the node is a document,
1152:                    // document fragment, etc. Just serialize its contents. It will
1153:                    // work well for other nodes that we do not know how to serialize.
1154:                    child = node.getFirstChild();
1155:                    while (child != null) {
1156:                        serializeNode(child);
1157:                        child = child.getNextSibling();
1158:                    }
1159:                    break;
1160:                }
1161:
1162:                default:
1163:                    break;
1164:                }
1165:            }
1166:
1167:            /**
1168:             * Must be called by a method about to print any type of content.
1169:             * If the element was just opened, the opening tag is closed and
1170:             * will be matched to a closing tag. Returns the current element
1171:             * state with <tt>empty</tt> and <tt>afterElement</tt> set to false.
1172:             *
1173:             * @return The current element state
1174:             * @throws IOException An I/O exception occured while
1175:             *   serializing
1176:             */
1177:            protected ElementState content() throws IOException {
1178:                ElementState state;
1179:
1180:                state = getElementState();
1181:                if (!isDocumentState()) {
1182:                    // Need to close CData section first
1183:                    if (state.inCData && !state.doCData) {
1184:                        _printer.printText("]]>");
1185:                        state.inCData = false;
1186:                    }
1187:                    // If this is the first content in the element,
1188:                    // change the state to not-empty and close the
1189:                    // opening element tag.
1190:                    if (state.empty) {
1191:                        _printer.printText('>');
1192:                        state.empty = false;
1193:                    }
1194:                    // Except for one content type, all of them
1195:                    // are not last element. That one content
1196:                    // type will take care of itself.
1197:                    state.afterElement = false;
1198:                    // Except for one content type, all of them
1199:                    // are not last comment. That one content
1200:                    // type will take care of itself.
1201:                    state.afterComment = false;
1202:                }
1203:                return state;
1204:            }
1205:
1206:            /**
1207:             * Called to print the text contents in the prevailing element format.
1208:             * Since this method is capable of printing text as CDATA, it is used
1209:             * for that purpose as well. White space handling is determined by the
1210:             * current element state. In addition, the output format can dictate
1211:             * whether the text is printed as CDATA or unescaped.
1212:             *
1213:             * @param text The text to print
1214:             * @param unescaped True is should print unescaped
1215:             * @throws IOException An I/O exception occured while
1216:             *   serializing
1217:             */
1218:            protected void characters(String text) throws IOException {
1219:                ElementState state;
1220:
1221:                state = content();
1222:                // Check if text should be print as CDATA section or unescaped
1223:                // based on elements listed in the output format (the element
1224:                // state) or whether we are inside a CDATA section or entity.
1225:
1226:                if (state.inCData || state.doCData) {
1227:                    int index;
1228:                    int saveIndent;
1229:
1230:                    // Print a CDATA section. The text is not escaped, but ']]>'
1231:                    // appearing in the code must be identified and dealt with.
1232:                    // The contents of a text node is considered space preserving.
1233:                    if (!state.inCData) {
1234:                        _printer.printText("<![CDATA[");
1235:                        state.inCData = true;
1236:                    }
1237:                    saveIndent = _printer.getNextIndent();
1238:                    _printer.setNextIndent(0);
1239:                    printCDATAText(text);
1240:                    _printer.setNextIndent(saveIndent);
1241:
1242:                } else {
1243:
1244:                    int saveIndent;
1245:
1246:                    if (state.preserveSpace) {
1247:                        // If preserving space then hold of indentation so no
1248:                        // excessive spaces are printed at line breaks, escape
1249:                        // the text content without replacing spaces and print
1250:                        // the text breaking only at line breaks.
1251:                        saveIndent = _printer.getNextIndent();
1252:                        _printer.setNextIndent(0);
1253:                        printText(text, true, state.unescaped);
1254:                        _printer.setNextIndent(saveIndent);
1255:                    } else {
1256:                        printText(text, false, state.unescaped);
1257:                    }
1258:                }
1259:            }
1260:
1261:            /**
1262:             * Returns the suitable entity reference for this character value,
1263:             * or null if no such entity exists. Calling this method with <tt>'&amp;'</tt>
1264:             * will return <tt>"&amp;amp;"</tt>.
1265:             *
1266:             * @param ch Character value
1267:             * @return Character entity name, or null
1268:             */
1269:            protected abstract String getEntityRef(int ch);
1270:
1271:            /**
1272:             * Called to serializee the DOM element. The element is serialized based on
1273:             * the serializer's method (XML, HTML, XHTML).
1274:             *
1275:             * @param elem The element to serialize
1276:             * @throws IOException An I/O exception occured while
1277:             *   serializing
1278:             */
1279:            protected abstract void serializeElement(Element elem)
1280:                    throws IOException;
1281:
1282:            /**
1283:             * Comments and PIs cannot be serialized before the root element,
1284:             * because the root element serializes the document type, which
1285:             * generally comes first. Instead such PIs and comments are
1286:             * accumulated inside a vector and serialized by calling this
1287:             * method. Will be called when the root element is serialized
1288:             * and when the document finished serializing.
1289:             *
1290:             * @throws IOException An I/O exception occured while
1291:             *   serializing
1292:             */
1293:            protected void serializePreRoot() throws IOException {
1294:                int i;
1295:
1296:                if (_preRoot != null) {
1297:                    for (i = 0; i < _preRoot.size(); ++i) {
1298:                        printText((String) _preRoot.elementAt(i), true, true);
1299:                        if (_indenting)
1300:                            _printer.breakLine();
1301:                    }
1302:                    _preRoot.removeAllElements();
1303:                }
1304:            }
1305:
1306:            //---------------------------------------------//
1307:            // Text pretty printing and formatting methods //
1308:            //---------------------------------------------//
1309:
1310:            protected void printCDATAText(String text) throws IOException {
1311:                int length = text.length();
1312:                char ch;
1313:
1314:                for (int index = 0; index < length; ++index) {
1315:                    ch = text.charAt(index);
1316:                    if (ch == ']' && index + 2 < length
1317:                            && text.charAt(index + 1) == ']'
1318:                            && text.charAt(index + 2) == '>') { // check for ']]>'
1319:                        if (fDOMErrorHandler != null) {
1320:                            // REVISIT: this means that if DOM Error handler is not registered we don't report any
1321:                            // fatal errors and might serialize not wellformed document
1322:                            if ((features & /*DOMSerializerImpl.SPLITCDATA*/0x1 << 4) == 0) {
1323:                                String msg = DOMMessageFormatter.formatMessage(
1324:                                        DOMMessageFormatter.SERIALIZER_DOMAIN,
1325:                                        "EndingCDATA", null);
1326:                                if ((features & /*DOMSerializerImpl.WELLFORMED*/0x1 << 1) != 0) {
1327:                                    // issue fatal error
1328:                                    modifyDOMError(msg,
1329:                                            DOMError.SEVERITY_FATAL_ERROR,
1330:                                            "wf-invalid-character",
1331:                                            fCurrentNode);
1332:                                    fDOMErrorHandler
1333:                                            .handleError((DOMError) fDOMError);
1334:                                    throw new LSException(
1335:                                            LSException.SERIALIZE_ERR, msg);
1336:                                } else {
1337:                                    // issue error
1338:                                    modifyDOMError(msg,
1339:                                            DOMError.SEVERITY_ERROR,
1340:                                            "cdata-section-not-splitted",
1341:                                            fCurrentNode);
1342:                                    if (!fDOMErrorHandler
1343:                                            .handleError((DOMError) fDOMError)) {
1344:                                        throw new LSException(
1345:                                                LSException.SERIALIZE_ERR, msg);
1346:                                    }
1347:                                }
1348:                            } else {
1349:                                // issue warning
1350:                                String msg = DOMMessageFormatter.formatMessage(
1351:                                        DOMMessageFormatter.SERIALIZER_DOMAIN,
1352:                                        "SplittingCDATA", null);
1353:                                modifyDOMError(msg, DOMError.SEVERITY_WARNING,
1354:                                        null, fCurrentNode);
1355:                                fDOMErrorHandler
1356:                                        .handleError((DOMError) fDOMError);
1357:                            }
1358:                        }
1359:                        // split CDATA section
1360:                        _printer.printText("]]]]><![CDATA[>");
1361:                        index += 2;
1362:                        continue;
1363:                    }
1364:
1365:                    if (!XMLChar.isValid(ch)) {
1366:                        // check if it is surrogate
1367:                        if (++index < length) {
1368:                            surrogates(ch, text.charAt(index));
1369:                        } else {
1370:                            fatalError("The character '" + (char) ch
1371:                                    + "' is an invalid XML character");
1372:                        }
1373:                        continue;
1374:                    } else {
1375:                        if ((ch >= ' ' && _encodingInfo.isPrintable((char) ch) && ch != 0xF7)
1376:                                || ch == '\n' || ch == '\r' || ch == '\t') {
1377:                            _printer.printText((char) ch);
1378:                        } else {
1379:
1380:                            // The character is not printable -- split CDATA section
1381:                            _printer.printText("]]>&#x");
1382:                            _printer.printText(Integer.toHexString(ch));
1383:                            _printer.printText(";<![CDATA[");
1384:                        }
1385:                    }
1386:                }
1387:            }
1388:
1389:            protected void surrogates(int high, int low) throws IOException {
1390:                if (XMLChar.isHighSurrogate(high)) {
1391:                    if (!XMLChar.isLowSurrogate(low)) {
1392:                        //Invalid XML
1393:                        fatalError("The character '" + (char) low
1394:                                + "' is an invalid XML character");
1395:                    } else {
1396:                        int supplemental = XMLChar.supplemental((char) high,
1397:                                (char) low);
1398:                        if (!XMLChar.isValid(supplemental)) {
1399:                            //Invalid XML
1400:                            fatalError("The character '" + (char) supplemental
1401:                                    + "' is an invalid XML character");
1402:                        } else {
1403:                            if (content().inCData) {
1404:                                _printer.printText("]]>&#x");
1405:                                _printer.printText(Integer
1406:                                        .toHexString(supplemental));
1407:                                _printer.printText(";<![CDATA[");
1408:                            } else {
1409:                                printHex(supplemental);
1410:                            }
1411:                        }
1412:                    }
1413:                } else {
1414:                    fatalError("The character '" + (char) high
1415:                            + "' is an invalid XML character");
1416:                }
1417:
1418:            }
1419:
1420:            /**
1421:             * Called to print additional text with whitespace handling.
1422:             * If spaces are preserved, the text is printed as if by calling
1423:             * {@link #printText(String,boolean,boolean)} with a call to {@link Printer#breakLine}
1424:             * for each new line. If spaces are not preserved, the text is
1425:             * broken at space boundaries if longer than the line width;
1426:             * Multiple spaces are printed as such, but spaces at beginning
1427:             * of line are removed.
1428:             *
1429:             * @param text The text to print
1430:             * @param preserveSpace Space preserving flag
1431:             * @param unescaped Print unescaped
1432:             */
1433:            protected void printText(char[] chars, int start, int length,
1434:                    boolean preserveSpace, boolean unescaped)
1435:                    throws IOException {
1436:                int index;
1437:                char ch;
1438:
1439:                if (preserveSpace) {
1440:                    // Preserving spaces: the text must print exactly as it is,
1441:                    // without breaking when spaces appear in the text and without
1442:                    // consolidating spaces. If a line terminator is used, a line
1443:                    // break will occur.
1444:                    while (length-- > 0) {
1445:                        ch = chars[start];
1446:                        ++start;
1447:                        if (ch == '\n' || ch == '\r' || unescaped)
1448:                            _printer.printText(ch);
1449:                        else
1450:                            printEscaped(ch);
1451:                    }
1452:                } else {
1453:                    // Not preserving spaces: print one part at a time, and
1454:                    // use spaces between parts to break them into different
1455:                    // lines. Spaces at beginning of line will be stripped
1456:                    // by printing mechanism. Line terminator is treated
1457:                    // no different than other text part.
1458:                    while (length-- > 0) {
1459:                        ch = chars[start];
1460:                        ++start;
1461:                        if (ch == ' ' || ch == '\f' || ch == '\t' || ch == '\n'
1462:                                || ch == '\r')
1463:                            _printer.printSpace();
1464:                        else if (unescaped)
1465:                            _printer.printText(ch);
1466:                        else
1467:                            printEscaped(ch);
1468:                    }
1469:                }
1470:            }
1471:
1472:            protected void printText(String text, boolean preserveSpace,
1473:                    boolean unescaped) throws IOException {
1474:                int index;
1475:                char ch;
1476:
1477:                if (preserveSpace) {
1478:                    // Preserving spaces: the text must print exactly as it is,
1479:                    // without breaking when spaces appear in the text and without
1480:                    // consolidating spaces. If a line terminator is used, a line
1481:                    // break will occur.
1482:                    for (index = 0; index < text.length(); ++index) {
1483:                        ch = text.charAt(index);
1484:                        if (ch == '\n' || ch == '\r' || unescaped)
1485:                            _printer.printText(ch);
1486:                        else
1487:                            printEscaped(ch);
1488:                    }
1489:                } else {
1490:                    // Not preserving spaces: print one part at a time, and
1491:                    // use spaces between parts to break them into different
1492:                    // lines. Spaces at beginning of line will be stripped
1493:                    // by printing mechanism. Line terminator is treated
1494:                    // no different than other text part.
1495:                    for (index = 0; index < text.length(); ++index) {
1496:                        ch = text.charAt(index);
1497:                        if (ch == ' ' || ch == '\f' || ch == '\t' || ch == '\n'
1498:                                || ch == '\r')
1499:                            _printer.printSpace();
1500:                        else if (unescaped)
1501:                            _printer.printText(ch);
1502:                        else
1503:                            printEscaped(ch);
1504:                    }
1505:                }
1506:            }
1507:
1508:            /**
1509:             * Print a document type public or system identifier URL.
1510:             * Encapsulates the URL in double quotes, escapes non-printing
1511:             * characters and print it equivalent to {@link #printText}.
1512:             *
1513:             * @param url The document type url to print
1514:             */
1515:            protected void printDoctypeURL(String url) throws IOException {
1516:                int i;
1517:
1518:                _printer.printText('"');
1519:                for (i = 0; i < url.length(); ++i) {
1520:                    if (url.charAt(i) == '"' || url.charAt(i) < 0x20
1521:                            || url.charAt(i) > 0x7F) {
1522:                        _printer.printText('%');
1523:                        _printer.printText(Integer.toHexString(url.charAt(i)));
1524:                    } else
1525:                        _printer.printText(url.charAt(i));
1526:                }
1527:                _printer.printText('"');
1528:            }
1529:
1530:            protected void printEscaped(int ch) throws IOException {
1531:                String charRef;
1532:                // If there is a suitable entity reference for this
1533:                // character, print it. The list of available entity
1534:                // references is almost but not identical between
1535:                // XML and HTML.
1536:                charRef = getEntityRef(ch);
1537:                if (charRef != null) {
1538:                    _printer.printText('&');
1539:                    _printer.printText(charRef);
1540:                    _printer.printText(';');
1541:                } else if ((ch >= ' ' && _encodingInfo.isPrintable((char) ch) && ch != 0xF7)
1542:                        || ch == '\n' || ch == '\r' || ch == '\t') {
1543:                    // Non printables are below ASCII space but not tab or line
1544:                    // terminator, ASCII delete, or above a certain Unicode threshold.
1545:                    if (ch < 0x10000) {
1546:                        _printer.printText((char) ch);
1547:                    } else {
1548:                        _printer
1549:                                .printText((char) (((ch - 0x10000) >> 10) + 0xd800));
1550:                        _printer
1551:                                .printText((char) (((ch - 0x10000) & 0x3ff) + 0xdc00));
1552:                    }
1553:                } else {
1554:                    printHex(ch);
1555:                }
1556:            }
1557:
1558:            /**
1559:             * Escapes chars
1560:             */
1561:            final void printHex(int ch) throws IOException {
1562:                _printer.printText("&#x");
1563:                _printer.printText(Integer.toHexString(ch));
1564:                _printer.printText(';');
1565:
1566:            }
1567:
1568:            /**
1569:             * Escapes a string so it may be printed as text content or attribute
1570:             * value. Non printable characters are escaped using character references.
1571:             * Where the format specifies a deault entity reference, that reference
1572:             * is used (e.g. <tt>&amp;lt;</tt>).
1573:             *
1574:             * @param source The string to escape
1575:             */
1576:            protected void printEscaped(String source) throws IOException {
1577:                for (int i = 0; i < source.length(); ++i) {
1578:                    int ch = source.charAt(i);
1579:                    if ((ch & 0xfc00) == 0xd800 && i + 1 < source.length()) {
1580:                        int lowch = source.charAt(i + 1);
1581:                        if ((lowch & 0xfc00) == 0xdc00) {
1582:                            ch = 0x10000 + ((ch - 0xd800) << 10) + lowch
1583:                                    - 0xdc00;
1584:                            i++;
1585:                        }
1586:                    }
1587:                    printEscaped(ch);
1588:                }
1589:            }
1590:
1591:            //--------------------------------//
1592:            // Element state handling methods //
1593:            //--------------------------------//
1594:
1595:            /**
1596:             * Return the state of the current element.
1597:             *
1598:             * @return Current element state
1599:             */
1600:            protected ElementState getElementState() {
1601:                return _elementStates[_elementStateCount];
1602:            }
1603:
1604:            /**
1605:             * Enter a new element state for the specified element.
1606:             * Tag name and space preserving is specified, element
1607:             * state is initially empty.
1608:             *
1609:             * @return Current element state, or null
1610:             */
1611:            protected ElementState enterElementState(String namespaceURI,
1612:                    String localName, String rawName, boolean preserveSpace) {
1613:                ElementState state;
1614:
1615:                if (_elementStateCount + 1 == _elementStates.length) {
1616:                    ElementState[] newStates;
1617:
1618:                    // Need to create a larger array of states. This does not happen
1619:                    // often, unless the document is really deep.
1620:                    newStates = new ElementState[_elementStates.length + 10];
1621:                    for (int i = 0; i < _elementStates.length; ++i)
1622:                        newStates[i] = _elementStates[i];
1623:                    for (int i = _elementStates.length; i < newStates.length; ++i)
1624:                        newStates[i] = new ElementState();
1625:                    _elementStates = newStates;
1626:                }
1627:
1628:                ++_elementStateCount;
1629:                state = _elementStates[_elementStateCount];
1630:                state.namespaceURI = namespaceURI;
1631:                state.localName = localName;
1632:                state.rawName = rawName;
1633:                state.preserveSpace = preserveSpace;
1634:                state.empty = true;
1635:                state.afterElement = false;
1636:                state.afterComment = false;
1637:                state.doCData = state.inCData = false;
1638:                state.unescaped = false;
1639:                state.prefixes = _prefixes;
1640:
1641:                _prefixes = null;
1642:                return state;
1643:            }
1644:
1645:            /**
1646:             * Leave the current element state and return to the
1647:             * state of the parent element. If this was the root
1648:             * element, return to the state of the document.
1649:             *
1650:             * @return Previous element state
1651:             */
1652:            protected ElementState leaveElementState() {
1653:                if (_elementStateCount > 0) {
1654:                    /*Corrected by David Blondeau (blondeau@intalio.com)*/
1655:                    _prefixes = null;
1656:                    //_prefixes = _elementStates[ _elementStateCount ].prefixes;
1657:                    --_elementStateCount;
1658:                    return _elementStates[_elementStateCount];
1659:                } else {
1660:                    String msg = DOMMessageFormatter.formatMessage(
1661:                            DOMMessageFormatter.SERIALIZER_DOMAIN, "Internal",
1662:                            null);
1663:                    throw new IllegalStateException(msg);
1664:                }
1665:            }
1666:
1667:            /**
1668:             * Returns true if in the state of the document.
1669:             * Returns true before entering any element and after
1670:             * leaving the root element.
1671:             *
1672:             * @return True if in the state of the document
1673:             */
1674:            protected boolean isDocumentState() {
1675:                return _elementStateCount == 0;
1676:            }
1677:
1678:            /**
1679:             * Returns the namespace prefix for the specified URI.
1680:             * If the URI has been mapped to a prefix, returns the
1681:             * prefix, otherwise returns null.
1682:             *
1683:             * @param namespaceURI The namespace URI
1684:             * @return The namespace prefix if known, or null
1685:             */
1686:            protected String getPrefix(String namespaceURI) {
1687:                String prefix;
1688:
1689:                if (_prefixes != null) {
1690:                    prefix = (String) _prefixes.get(namespaceURI);
1691:                    if (prefix != null)
1692:                        return prefix;
1693:                }
1694:                if (_elementStateCount == 0)
1695:                    return null;
1696:                else {
1697:                    for (int i = _elementStateCount; i > 0; --i) {
1698:                        if (_elementStates[i].prefixes != null) {
1699:                            prefix = (String) _elementStates[i].prefixes
1700:                                    .get(namespaceURI);
1701:                            if (prefix != null)
1702:                                return prefix;
1703:                        }
1704:                    }
1705:                }
1706:                return null;
1707:            }
1708:
1709:            /**
1710:             * The method modifies global DOM error object
1711:             *
1712:             * @param message
1713:             * @param severity
1714:             * @param type
1715:             * @return a DOMError
1716:             */
1717:            protected DOMError modifyDOMError(String message, short severity,
1718:                    String type, Node node) {
1719:                fDOMError.reset();
1720:                fDOMError.fMessage = message;
1721:                fDOMError.fType = type;
1722:                fDOMError.fSeverity = severity;
1723:                fDOMError.fLocator = new DOMLocatorImpl(-1, -1, -1, node, null);
1724:                return (DOMError) fDOMError;
1725:
1726:            }
1727:
1728:            protected void fatalError(String message) throws IOException {
1729:                if (fDOMErrorHandler != null) {
1730:                    modifyDOMError(message, DOMError.SEVERITY_FATAL_ERROR,
1731:                            null, fCurrentNode);
1732:                    fDOMErrorHandler.handleError((DOMError) fDOMError);
1733:                } else {
1734:                    throw new IOException(message);
1735:                }
1736:            }
1737:
1738:            /**
1739:             * DOM level 3:
1740:             * Check a node to determine if it contains unbound namespace prefixes.
1741:             *
1742:             * @param node The node to check for unbound namespace prefices
1743:             */
1744:            protected void checkUnboundNamespacePrefixedNode(Node node)
1745:                    throws IOException {
1746:
1747:            }
1748:
1749:            public void startAnchoring(String anchorId) {
1750:                this .anchorId = anchorId;
1751:            }
1752:
1753:            public void stopAnchoring() {
1754:                this .anchorId = null;
1755:            }
1756:
1757:            protected String appendAnchorIfNecessary(String elementName,
1758:                    String attributeName, String attributeValue) {
1759:                if (anchorId != null) {
1760:                    // looking for an <a> or <form> tag element
1761:                    if (elementName.equalsIgnoreCase("a")
1762:                            || elementName.equalsIgnoreCase("form")) {
1763:                        // found an <a> or <form>, let's peek at the attributes it contains
1764:                        // does it contain either an "href" or "action" attribute
1765:                        if (attributeName.equalsIgnoreCase("href")
1766:                                || attributeName.equalsIgnoreCase("action")) {
1767:                            // found the attribute, now lets make sure it points back to a channel
1768:                            if (attributeValue.indexOf(".render.") != -1
1769:                                    && attributeValue.indexOf("javascript:") == -1) {
1770:                                // this link points back to a channel, so let's
1771:                                // rewrite it and place back into the Attribute Object
1772:                                attributeValue += "#" + anchorId;
1773:                            }
1774:                        }
1775:                    }
1776:                }
1777:                return attributeValue;
1778:            }
1779:
1780:            /**
1781:             * A portal property indicating whether or not to allow the disabling
1782:             * of output escaping.  When allowed, XSLT stylesheets can request
1783:             * to disable output escaping, therefore enabling the direct pass-through
1784:             * of markup such as HTML.
1785:             */
1786:            private boolean _allowDisableOutputEscaping;
1787:
1788:            protected String anchorId = null;
1789:
1790:            boolean html4compat = true; // make script tags in an xhtml document compatable with html 4
1791:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.