Source Code Cross Referenced for XMLStreamWriterImpl.java in  » 6.0-JDK-Modules » sjsxp » com » sun » xml » stream » writers » 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 » 6.0 JDK Modules » sjsxp » com.sun.xml.stream.writers 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * The contents of this file are subject to the terms
0003:         * of the Common Development and Distribution License
0004:         * (the License).  You may not use this file except in
0005:         * compliance with the License.
0006:         * 
0007:         * You can obtain a copy of the license at
0008:         * https://glassfish.dev.java.net/public/CDDLv1.0.html.
0009:         * See the License for the specific language governing
0010:         * permissions and limitations under the License.
0011:         * 
0012:         * When distributing Covered Code, include this CDDL
0013:         * Header Notice in each file and include the License file
0014:         * at https://glassfish.dev.java.net/public/CDDLv1.0.html.
0015:         * If applicable, add the following below the CDDL Header,
0016:         * with the fields enclosed by brackets [] replaced by
0017:         * you own identifying information:
0018:         * "Portions Copyrighted [year] [name of copyright owner]"
0019:         * 
0020:         * [Name of File] [ver.__] [Date]
0021:         * 
0022:         * Copyright 2006 Sun Microsystems Inc. All Rights Reserved
0023:         */
0024:
0025:        /*
0026:         * XMLWriter.java
0027:         *
0028:         * <code>XMLWriter</code> is not thread safe.
0029:         *
0030:         * For efficiency this writer buffers the input. Use <code>flush()</code> function
0031:         * to explicitly write the data to underlying stream.
0032:         *
0033:         * This writer is designed in such a way that it atleast buffers the input to the 
0034:         * <code>size</code> specified. Unless <code>flush</code> is called, it guarantees that
0035:         * data in chunks of size equal to or more than <code>size</code> specified will be written.
0036:         *
0037:         *
0038:         * <code>XMLWriter</code> instance can be reused. <code>setWriter()</code> internally clears the
0039:         * buffer and stores the reference to newly supplied <code>Writer</code> instance.
0040:         *
0041:         */
0042:
0043:        package com.sun.xml.stream.writers;
0044:
0045:        import java.io.FileOutputStream;
0046:        import java.io.IOException;
0047:        import java.io.OutputStream;
0048:        import java.io.OutputStreamWriter;
0049:        import java.io.Writer;
0050:        import java.nio.charset.Charset;
0051:        import java.nio.charset.CharsetEncoder;
0052:        import java.util.AbstractMap;
0053:        import java.util.ArrayList;
0054:        import java.util.Iterator;
0055:        import java.util.Random;
0056:        import java.util.Vector;
0057:        import java.util.Set;
0058:
0059:        import javax.xml.XMLConstants;
0060:        import javax.xml.namespace.NamespaceContext;
0061:        import javax.xml.stream.XMLOutputFactory;
0062:        import javax.xml.stream.XMLStreamException;
0063:        import javax.xml.stream.XMLStreamWriter;
0064:        import javax.xml.transform.stream.StreamResult;
0065:
0066:        import com.sun.xml.stream.Constants;
0067:        import com.sun.xml.stream.PropertyManager;
0068:        import com.sun.xml.stream.util.ReadOnlyIterator;
0069:
0070:        import com.sun.xml.stream.xerces.util.NamespaceSupport;
0071:        import com.sun.xml.stream.xerces.util.SymbolTable;
0072:        import com.sun.xml.stream.xerces.xni.QName;
0073:
0074:        /**
0075:         * This class implements a StAX XMLStreamWriter. It extends 
0076:         * <code>AbstractMap</code> in order to support a getter for 
0077:         * implementation-specific properties. For example, you can get 
0078:         * the underlying <code>OutputStream</code> by casting an instance 
0079:         * of this class to <code>Map</code> and calling 
0080:         * <code>getProperty(OUTPUTSTREAM_PROPERTY)</code>. 
0081:         *
0082:         * @author Neeraj Bajaj
0083:         * @author K.Venugopal
0084:         * @author Santiago.Pericas-Geertsen@sun.com
0085:         * @author Sunitha.Reddy@sun.com
0086:         */
0087:        public final class XMLStreamWriterImpl extends AbstractMap implements 
0088:                XMLStreamWriter {
0089:
0090:            public static final String START_COMMENT = "<!--";
0091:            public static final String END_COMMENT = "-->";
0092:            public static final String DEFAULT_ENCODING = " encoding=\"utf-8\"";
0093:            public static final String DEFAULT_XMLDECL = "<?xml version=\"1.0\" ?>";
0094:            public static final String DEFAULT_XML_VERSION = "1.0";
0095:            public static final char CLOSE_START_TAG = '>';
0096:            public static final char OPEN_START_TAG = '<';
0097:            public static final String OPEN_END_TAG = "</";
0098:            public static final char CLOSE_END_TAG = '>';
0099:            public static final String START_CDATA = "<![CDATA[";
0100:            public static final String END_CDATA = "]]>";
0101:            public static final String CLOSE_EMPTY_ELEMENT = "/>";
0102:            public static final String SPACE = " ";
0103:            public static final String UTF_8 = "UTF-8";
0104:
0105:            public static final String OUTPUTSTREAM_PROPERTY = "sjsxp-"
0106:                    + Constants.OUTPUTSTREAM;
0107:
0108:            /**
0109:             * This flag can be used to turn escaping off for content. It does
0110:             * not apply to attribute content.
0111:             */
0112:            boolean fEscapeCharacters = true;
0113:
0114:            /**
0115:             * Flag for the value of repairNamespace property 
0116:             */
0117:            private boolean fIsRepairingNamespace = false;
0118:
0119:            /**
0120:             * Underlying Writer to which characters are written.
0121:             */
0122:            private Writer fWriter;
0123:
0124:            /**
0125:             * Underlying OutputStream to which <code>fWriter</code>
0126:             * writes to. May be null if unknown.
0127:             */
0128:            private OutputStream fOutputStream = null;
0129:
0130:            /**
0131:             * Collects attributes when the writer is in reparing mode.
0132:             */
0133:            private ArrayList fAttributeCache;
0134:
0135:            /**
0136:             * Collects namespace declarations when the writer is in reparing mode.
0137:             */
0138:            private ArrayList fNamespaceDecls;
0139:
0140:            /** 
0141:             * Namespace context encapsulating user specified context
0142:             * and context built by the writer  
0143:             */
0144:            private NamespaceContextImpl fNamespaceContext = null;
0145:
0146:            private NamespaceSupport fInternalNamespaceContext = null;
0147:
0148:            private Random fPrefixGen = null;
0149:
0150:            /** 
0151:             * Reference to PropertyManager 
0152:             */
0153:            private PropertyManager fPropertyManager = null;
0154:
0155:            /** 
0156:             * Flag to track if start tag is opened 
0157:             */
0158:            private boolean fStartTagOpened = false;
0159:
0160:            /**
0161:             * Boolean flag  to indicate, if instance can be reused 
0162:             */
0163:            private boolean fReuse;
0164:
0165:            private SymbolTable fSymbolTable = new SymbolTable();
0166:
0167:            private ElementStack fElementStack = new ElementStack(); //Change this .-Venu
0168:
0169:            final private String DEFAULT_PREFIX = fSymbolTable.addSymbol("");
0170:
0171:            private final ReadOnlyIterator fReadOnlyIterator = new ReadOnlyIterator();
0172:
0173:            /**
0174:             * In some cases, this charset encoder is used to determine if a char is
0175:             * encodable by underlying writer. For example, an 8-bit char from the
0176:             * extended ASCII set is not encodable by 7-bit ASCII encoder. Unencodable
0177:             * chars are escaped using XML numeric entities.
0178:             */
0179:            private CharsetEncoder fEncoder = null;
0180:
0181:            /**
0182:             * Creates a new instance of XMLStreamWriterImpl. Uses platform's default
0183:             * encoding.
0184:             *
0185:             * @param outputStream Underlying stream to write the bytes to
0186:             * @param props        Properties used by this writer
0187:             */
0188:            public XMLStreamWriterImpl(OutputStream outputStream,
0189:                    PropertyManager props) throws IOException {
0190:
0191:                // cannot call this(outputStream, null, props); for constructor,
0192:                // OutputStreamWriter charsetName cannot be null
0193:
0194:                // use default encoding
0195:                this (new OutputStreamWriter(outputStream), props);
0196:            }
0197:
0198:            /**
0199:             * Creates a new instance of XMLStreamWriterImpl.
0200:             *
0201:             * @param outputStream Underlying stream to write the bytes
0202:             * @param encoding     Encoding used to convert chars into bytes
0203:             * @param props        Properties used by this writer
0204:             */
0205:            public XMLStreamWriterImpl(OutputStream outputStream,
0206:                    String encoding, PropertyManager props)
0207:                    throws java.io.IOException {
0208:                this (new StreamResult(outputStream), encoding, props);
0209:            }
0210:
0211:            /**
0212:             * Creates a new instance of XMLStreamWriterImpl using a Writer.
0213:             *
0214:             * @param writer  Underlying writer to which chars are written
0215:             * @param props   Properties used by this writer
0216:             */
0217:            public XMLStreamWriterImpl(Writer writer, PropertyManager props)
0218:                    throws java.io.IOException {
0219:                this (new StreamResult(writer), null, props);
0220:            }
0221:
0222:            /**
0223:             * Creates a new instance of XMLStreamWriterImpl using a StreamResult.
0224:             * A StreamResult encasupates an OutputStream, a Writer or a SystemId.
0225:             *
0226:             * @param writer  Underlying writer to which chars are written
0227:             * @param props   Properties used by this writer
0228:             */
0229:            public XMLStreamWriterImpl(StreamResult sr, String encoding,
0230:                    PropertyManager props) throws java.io.IOException {
0231:                setOutput(sr, encoding);
0232:                fPropertyManager = props;
0233:                init();
0234:            }
0235:
0236:            /**
0237:             * Initialize an instance of this XMLStreamWriter. Allocate new instances
0238:             * for all the data structures. Set internal flags based on property values.
0239:             */
0240:            private void init() {
0241:                fReuse = false;
0242:                fNamespaceDecls = new ArrayList();
0243:                fPrefixGen = new Random();
0244:                fAttributeCache = new ArrayList();
0245:                fInternalNamespaceContext = new NamespaceSupport();
0246:                fNamespaceContext = new NamespaceContextImpl();
0247:                fNamespaceContext.internalContext = fInternalNamespaceContext;
0248:
0249:                // Set internal state based on property values
0250:                Boolean ob = (Boolean) fPropertyManager
0251:                        .getProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES);
0252:                fIsRepairingNamespace = ob.booleanValue();
0253:                ob = (Boolean) fPropertyManager
0254:                        .getProperty(Constants.ESCAPE_CHARACTERS);
0255:                setEscapeCharacters(ob.booleanValue());
0256:            }
0257:
0258:            /**
0259:             * Reset this instance so that it can be re-used. Do not read properties
0260:             * again. The method <code>setOutput(StreamResult, encoding)</code> must
0261:             * be called after this one.
0262:             */
0263:            public void reset() {
0264:                reset(false);
0265:            }
0266:
0267:            /**
0268:             * Reset this instance so that it can be re-used. Clears but does not
0269:             * re-allocate internal data structures.
0270:             *
0271:             * @param resetProperties Indicates if properties should be read again
0272:             */
0273:            void reset(boolean resetProperties) {
0274:                if (!fReuse) {
0275:                    throw new java.lang.IllegalStateException(
0276:                            "close() Must be called before calling reset()");
0277:                }
0278:
0279:                fReuse = false;
0280:                fNamespaceDecls.clear();
0281:                fAttributeCache.clear();
0282:
0283:                // reset Element/NamespaceContext stacks
0284:                fElementStack.clear();
0285:                fInternalNamespaceContext.reset();
0286:
0287:                fStartTagOpened = false;
0288:                fNamespaceContext.userContext = null;
0289:
0290:                if (resetProperties) {
0291:                    Boolean ob = (Boolean) fPropertyManager
0292:                            .getProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES);
0293:                    fIsRepairingNamespace = ob.booleanValue();
0294:                    ob = (Boolean) fPropertyManager
0295:                            .getProperty(Constants.ESCAPE_CHARACTERS);
0296:                    setEscapeCharacters(ob.booleanValue());
0297:                }
0298:            }
0299:
0300:            /**
0301:             * Use a StreamResult to initialize the output for this XMLStreamWriter. Check
0302:             * for OutputStream, Writer and then systemId, in that order.
0303:             *
0304:             * @param sr        StreamResult encapsulating output information
0305:             * @param encoding  Encoding to be used except when a Writer is available
0306:             */
0307:            public void setOutput(StreamResult sr, String encoding)
0308:                    throws IOException {
0309:
0310:                if (sr.getOutputStream() != null) {
0311:                    setOutputUsingStream(sr.getOutputStream(), encoding);
0312:                } else if (sr.getWriter() != null) {
0313:                    setOutputUsingWriter(sr.getWriter());
0314:                } else if (sr.getSystemId() != null) {
0315:                    setOutputUsingStream(
0316:                            new FileOutputStream(sr.getSystemId()), encoding);
0317:                }
0318:            }
0319:
0320:            private void setOutputUsingWriter(Writer writer) throws IOException {
0321:                fWriter = writer;
0322:
0323:                if (writer instanceof  OutputStreamWriter) {
0324:                    String charset = ((OutputStreamWriter) writer)
0325:                            .getEncoding();
0326:                    if (charset != null && !charset.equalsIgnoreCase("utf-8")) {
0327:                        fEncoder = Charset.forName(charset).newEncoder();
0328:                    }
0329:                }
0330:            }
0331:
0332:            /**
0333:             * Utility method to create a writer when passed an OutputStream. Make
0334:             * sure to wrap an <code>OutputStreamWriter</code> using an 
0335:             * <code>XMLWriter</code> for performance reasons.
0336:             *
0337:             * @param os        Underlying OutputStream
0338:             * @param encoding  Encoding used to convert chars into bytes
0339:             */
0340:            private void setOutputUsingStream(OutputStream os, String encoding)
0341:                    throws IOException {
0342:                fOutputStream = os;
0343:
0344:                if (encoding != null) {
0345:                    if (encoding.equalsIgnoreCase("utf-8")) {
0346:                        fWriter = new UTF8OutputStreamWriter(os);
0347:                    } else {
0348:                        fWriter = new XMLWriter(new OutputStreamWriter(os,
0349:                                encoding));
0350:                        fEncoder = Charset.forName(encoding).newEncoder();
0351:                    }
0352:                } else {
0353:                    encoding = System.getProperty("file.encoding");
0354:                    if (encoding != null && encoding.equalsIgnoreCase("utf-8")) {
0355:                        fWriter = new UTF8OutputStreamWriter(os);
0356:                    } else {
0357:                        fWriter = new XMLWriter(new OutputStreamWriter(os));
0358:                    }
0359:                }
0360:            }
0361:
0362:            /** Can this instance be reused
0363:             *
0364:             * @return boolean boolean value to indicate if this instance can be reused or not
0365:             */
0366:            public boolean canReuse() {
0367:                return fReuse;
0368:            }
0369:
0370:            public void setEscapeCharacters(boolean escape) {
0371:                fEscapeCharacters = escape;
0372:            }
0373:
0374:            public boolean getEscapeCharacters() {
0375:                return fEscapeCharacters;
0376:            }
0377:
0378:            /**
0379:             * Close this XMLStreamWriter by closing underlying writer.
0380:             */
0381:            public void close() throws XMLStreamException {
0382:                if (fWriter != null) {
0383:                    try {
0384:                        //fWriter.close();
0385:                        fWriter.flush();
0386:                    } catch (IOException e) {
0387:                        throw new XMLStreamException(e);
0388:                    }
0389:                }
0390:                fWriter = null;
0391:                fOutputStream = null;
0392:                fNamespaceDecls.clear();
0393:                fAttributeCache.clear();
0394:                fElementStack.clear();
0395:                fInternalNamespaceContext.reset();
0396:                fReuse = true;
0397:            }
0398:
0399:            /**
0400:             * Flush this XMLStreamWriter by flushin underlying writer.
0401:             */
0402:            public void flush() throws XMLStreamException {
0403:                try {
0404:                    fWriter.flush();
0405:                } catch (IOException e) {
0406:                    throw new XMLStreamException(e);
0407:                }
0408:            }
0409:
0410:            /**
0411:             * Return <code>NamespaceContext</code> being used by the writer.
0412:             *
0413:             * @return NamespaceContext
0414:             */
0415:            public NamespaceContext getNamespaceContext() {
0416:                return fNamespaceContext;
0417:            }
0418:
0419:            /**
0420:             * Return a prefix associated with specified uri, or null if the
0421:             * uri is unknown.
0422:             *
0423:             * @param  uri The namespace uri
0424:             * @throws XMLStreamException if uri specified is "" or null
0425:             */
0426:            public String getPrefix(String uri) throws XMLStreamException {
0427:                return fNamespaceContext.getPrefix(uri);
0428:            }
0429:
0430:            /**
0431:             * Returns value associated with the specified property name.
0432:             *
0433:             * @param  str Property name
0434:             * @throws IllegalArgumentException if the specified property is not supported
0435:             * @return value associated with the specified property.
0436:             */
0437:            public Object getProperty(String str)
0438:                    throws IllegalArgumentException {
0439:                if (str == null) {
0440:                    throw new NullPointerException();
0441:                }
0442:
0443:                if (!fPropertyManager.containsProperty(str)) {
0444:                    throw new IllegalArgumentException("Property '" + str
0445:                            + "' is not supported");
0446:                }
0447:                if (str.equals(Constants.ZEPHYR_PROPERTY_PREFIX
0448:                        + Constants.OUTPUTSTREAM)) {
0449:                    return fOutputStream;
0450:                }
0451:                return fPropertyManager.getProperty(str);
0452:            }
0453:
0454:            /**
0455:             * Set the specified URI as default namespace in the current namespace context.
0456:             *
0457:             * @param uri Namespace URI
0458:             */
0459:            public void setDefaultNamespace(String uri)
0460:                    throws XMLStreamException {
0461:                if (uri != null) {
0462:                    uri = fSymbolTable.addSymbol(uri);
0463:                }
0464:
0465:                if (fIsRepairingNamespace) {
0466:                    if (isDefaultNamespace(uri)) {
0467:                        return;
0468:                    }
0469:
0470:                    QName qname = new QName();
0471:                    qname.setValues(DEFAULT_PREFIX, "xmlns", null, uri);
0472:                    fNamespaceDecls.add(qname);
0473:                } else {
0474:                    fInternalNamespaceContext
0475:                            .declarePrefix(DEFAULT_PREFIX, uri);
0476:                }
0477:            }
0478:
0479:            /**
0480:             * Sets the current <code>NamespaceContext</code> for prefix and uri bindings.
0481:             * This context becomes the root namespace context for writing and
0482:             * will replace the current root namespace context. Subsequent calls
0483:             * to setPrefix and setDefaultNamespace will bind namespaces using
0484:             * the context passed to the method as the root context for resolving
0485:             * namespaces. This method may only be called once at the start of the
0486:             * document. It does not cause the namespaces to be declared. If a
0487:             * namespace URI to prefix mapping is found in the namespace context
0488:             * it is treated as declared and the prefix may be used by the
0489:             * <code>XMLStreamWriter</code>.
0490:             *
0491:             * @param namespaceContext the namespace context to use for this writer, may not be null
0492:             * @throws XMLStreamException
0493:             */
0494:            public void setNamespaceContext(NamespaceContext namespaceContext)
0495:                    throws XMLStreamException {
0496:                fNamespaceContext.userContext = namespaceContext;
0497:            }
0498:
0499:            /**
0500:             * Sets the prefix the uri is bound to. This prefix is bound in the scope of
0501:             * the current START_ELEMENT / END_ELEMENT pair. If this method is called before
0502:             * a START_ELEMENT has been written the prefix is bound in the root scope.
0503:             *
0504:             * @param prefix
0505:             * @param uri
0506:             * @throws XMLStreamException
0507:             */
0508:            public void setPrefix(String prefix, String uri)
0509:                    throws XMLStreamException {
0510:
0511:                if (prefix == null) {
0512:                    throw new XMLStreamException("Prefix cannot be null");
0513:                }
0514:
0515:                if (uri == null) {
0516:                    throw new XMLStreamException("URI cannot be null");
0517:                }
0518:
0519:                prefix = fSymbolTable.addSymbol(prefix);
0520:                uri = fSymbolTable.addSymbol(uri);
0521:
0522:                if (fIsRepairingNamespace) {
0523:                    String tmpURI = fInternalNamespaceContext.getURI(prefix);
0524:
0525:                    if ((tmpURI != null) && (tmpURI == uri)) {
0526:                        return;
0527:                    }
0528:
0529:                    if (checkUserNamespaceContext(prefix, uri))
0530:                        return;
0531:                    QName qname = new QName();
0532:                    qname.setValues(prefix, XMLConstants.XMLNS_ATTRIBUTE, null,
0533:                            uri);
0534:                    fNamespaceDecls.add(qname);
0535:
0536:                    return;
0537:                }
0538:
0539:                fInternalNamespaceContext.declarePrefix(prefix, uri);
0540:            }
0541:
0542:            public void writeAttribute(String localName, String value)
0543:                    throws XMLStreamException {
0544:                try {
0545:                    if (!fStartTagOpened) {
0546:                        throw new XMLStreamException(
0547:                                "Attribute not associated with any element");
0548:                    }
0549:
0550:                    if (fIsRepairingNamespace) {
0551:                        Attribute attr = new Attribute(value); // Revisit:Dont create new one's. Reuse.-Venu
0552:                        attr.setValues(null, localName, null, null);
0553:                        fAttributeCache.add(attr);
0554:
0555:                        return;
0556:                    }
0557:
0558:                    fWriter.write(" ");
0559:                    fWriter.write(localName);
0560:                    fWriter.write("=\"");
0561:                    writeXMLContent(value, true, // true = escapeChars
0562:                            true); // true = escapeDoubleQuotes
0563:                    fWriter.write("\"");
0564:                } catch (IOException e) {
0565:                    throw new XMLStreamException(e);
0566:                }
0567:            }
0568:
0569:            public void writeAttribute(String namespaceURI, String localName,
0570:                    String value) throws XMLStreamException {
0571:                try {
0572:                    if (!fStartTagOpened) {
0573:                        throw new XMLStreamException(
0574:                                "Attribute not associated with any element");
0575:                    }
0576:
0577:                    if (namespaceURI == null) {
0578:                        throw new XMLStreamException(
0579:                                "NamespaceURI cannot be null");
0580:                    }
0581:
0582:                    namespaceURI = fSymbolTable.addSymbol(namespaceURI);
0583:
0584:                    String prefix = fInternalNamespaceContext
0585:                            .getPrefix(namespaceURI);
0586:
0587:                    if (!fIsRepairingNamespace) {
0588:                        if (prefix == null) {
0589:                            throw new XMLStreamException(
0590:                                    "Prefix cannot be null");
0591:                        }
0592:
0593:                        writeAttributeWithPrefix(prefix, localName, value);
0594:                    } else {
0595:                        Attribute attr = new Attribute(value);
0596:                        attr.setValues(null, localName, null, namespaceURI);
0597:                        fAttributeCache.add(attr);
0598:                    }
0599:                } catch (IOException e) {
0600:                    throw new XMLStreamException(e);
0601:                }
0602:            }
0603:
0604:            private void writeAttributeWithPrefix(String prefix,
0605:                    String localName, String value) throws IOException {
0606:                fWriter.write(SPACE);
0607:
0608:                if ((prefix != null)
0609:                        && (prefix != XMLConstants.DEFAULT_NS_PREFIX)) {
0610:                    fWriter.write(prefix);
0611:                    fWriter.write(":");
0612:                }
0613:
0614:                fWriter.write(localName);
0615:                fWriter.write("=\"");
0616:                writeXMLContent(value, true, // true = escapeChars
0617:                        true); // true = escapeDoubleQuotes
0618:                fWriter.write("\"");
0619:            }
0620:
0621:            public void writeAttribute(String prefix, String namespaceURI,
0622:                    String localName, String value) throws XMLStreamException {
0623:                try {
0624:                    if (!fStartTagOpened) {
0625:                        throw new XMLStreamException(
0626:                                "Attribute not associated with any element");
0627:                    }
0628:
0629:                    if (namespaceURI == null) {
0630:                        throw new XMLStreamException(
0631:                                "NamespaceURI cannot be null");
0632:                    }
0633:
0634:                    if (localName == null) {
0635:                        throw new XMLStreamException(
0636:                                "Local name cannot be null");
0637:                    }
0638:
0639:                    if (!fIsRepairingNamespace) {
0640:                        if (prefix == null || prefix.equals("")) {
0641:                            if (!namespaceURI.equals("")) {
0642:                                throw new XMLStreamException(
0643:                                        "prefix cannot be null or empty");
0644:                            } else {
0645:                                writeAttributeWithPrefix(null, localName, value);
0646:                                return;
0647:                            }
0648:                        }
0649:
0650:                        if (!prefix.equals(XMLConstants.XML_NS_PREFIX)
0651:                                || !namespaceURI
0652:                                        .equals(XMLConstants.XML_NS_URI)) {
0653:
0654:                            prefix = fSymbolTable.addSymbol(prefix);
0655:                            namespaceURI = fSymbolTable.addSymbol(namespaceURI);
0656:
0657:                            if (fInternalNamespaceContext
0658:                                    .containsPrefixInCurrentContext(prefix)) {
0659:
0660:                                String tmpURI = fInternalNamespaceContext
0661:                                        .getURI(prefix);
0662:
0663:                                if (tmpURI != null && tmpURI != namespaceURI) {
0664:                                    throw new XMLStreamException("Prefix "
0665:                                            + prefix + " is "
0666:                                            + "already bound to " + tmpURI
0667:                                            + ". Trying to rebind it to "
0668:                                            + namespaceURI + " is an error.");
0669:                                }
0670:                            }
0671:                            fInternalNamespaceContext.declarePrefix(prefix,
0672:                                    namespaceURI);
0673:                        }
0674:                        writeAttributeWithPrefix(prefix, localName, value);
0675:                    } else {
0676:                        if (prefix != null) {
0677:                            prefix = fSymbolTable.addSymbol(prefix);
0678:                        }
0679:
0680:                        namespaceURI = fSymbolTable.addSymbol(namespaceURI);
0681:
0682:                        Attribute attr = new Attribute(value);
0683:                        attr.setValues(prefix, localName, null, namespaceURI);
0684:                        fAttributeCache.add(attr);
0685:                    }
0686:                } catch (IOException e) {
0687:                    throw new XMLStreamException(e);
0688:                }
0689:            }
0690:
0691:            public void writeCData(String cdata) throws XMLStreamException {
0692:                try {
0693:                    if (cdata == null) {
0694:                        throw new XMLStreamException("cdata cannot be null");
0695:                    }
0696:
0697:                    if (fStartTagOpened) {
0698:                        closeStartTag();
0699:                    }
0700:
0701:                    fWriter.write(START_CDATA);
0702:                    fWriter.write(cdata);
0703:                    fWriter.write(END_CDATA);
0704:                } catch (IOException e) {
0705:                    throw new XMLStreamException(e);
0706:                }
0707:            }
0708:
0709:            public void writeCharacters(String data) throws XMLStreamException {
0710:                try {
0711:                    if (fStartTagOpened) {
0712:                        closeStartTag();
0713:                    }
0714:
0715:                    writeXMLContent(data);
0716:                } catch (IOException e) {
0717:                    throw new XMLStreamException(e);
0718:                }
0719:            }
0720:
0721:            public void writeCharacters(char[] data, int start, int len)
0722:                    throws XMLStreamException {
0723:                try {
0724:                    if (fStartTagOpened) {
0725:                        closeStartTag();
0726:                    }
0727:
0728:                    writeXMLContent(data, start, len, fEscapeCharacters);
0729:                } catch (IOException e) {
0730:                    throw new XMLStreamException(e);
0731:                }
0732:            }
0733:
0734:            public void writeComment(String comment) throws XMLStreamException {
0735:                try {
0736:                    if (fStartTagOpened) {
0737:                        closeStartTag();
0738:                    }
0739:
0740:                    fWriter.write(START_COMMENT);
0741:
0742:                    if (comment != null) {
0743:                        fWriter.write(comment);
0744:                    }
0745:
0746:                    fWriter.write(END_COMMENT);
0747:                } catch (IOException e) {
0748:                    throw new XMLStreamException(e);
0749:                }
0750:            }
0751:
0752:            public void writeDTD(String dtd) throws XMLStreamException {
0753:                try {
0754:                    if (fStartTagOpened) {
0755:                        closeStartTag();
0756:                    }
0757:
0758:                    fWriter.write(dtd);
0759:                } catch (IOException e) {
0760:                    throw new XMLStreamException(e);
0761:                }
0762:            }
0763:
0764:            /*
0765:             * Write default Namespace.
0766:             *
0767:             * If namespaceURI == null,
0768:             * then it is assumed to be equivilent to {@link XMLConstants.NULL_NS_URI},
0769:             * i.e. there is no Namespace.
0770:             *
0771:             * @param namespaceURI NamespaceURI to declare.
0772:             *
0773:             * @throws XMLStreamException
0774:             *
0775:             * @see <a href="http://www.w3.org/TR/REC-xml-names/#defaulting">
0776:             *   Namespaces in XML, 5.2 Namespace Defaulting</a>
0777:             */
0778:            public void writeDefaultNamespace(String namespaceURI)
0779:                    throws XMLStreamException {
0780:
0781:                // normalize namespaceURI
0782:                String namespaceURINormalized = null;
0783:                if (namespaceURI == null) {
0784:                    namespaceURINormalized = ""; // XMLConstants.NULL_NS_URI
0785:                } else {
0786:                    namespaceURINormalized = namespaceURI;
0787:                }
0788:
0789:                try {
0790:                    if (!fStartTagOpened) {
0791:                        throw new IllegalStateException(
0792:                                "Namespace Attribute not associated with any element");
0793:                    }
0794:
0795:                    if (fIsRepairingNamespace) {
0796:                        QName qname = new QName();
0797:                        qname.setValues(XMLConstants.DEFAULT_NS_PREFIX,
0798:                                XMLConstants.XMLNS_ATTRIBUTE, null,
0799:                                namespaceURINormalized);
0800:                        fNamespaceDecls.add(qname);
0801:
0802:                        return;
0803:                    }
0804:
0805:                    namespaceURINormalized = fSymbolTable
0806:                            .addSymbol(namespaceURINormalized);
0807:
0808:                    if (fInternalNamespaceContext
0809:                            .containsPrefixInCurrentContext("")) {
0810:
0811:                        String tmp = fInternalNamespaceContext.getURI("");
0812:
0813:                        if (tmp != null && tmp != namespaceURINormalized) {
0814:                            throw new XMLStreamException(
0815:                                    "xmlns has been already bound to " + tmp
0816:                                            + ". Rebinding it to "
0817:                                            + namespaceURINormalized
0818:                                            + " is an error");
0819:                        }
0820:                    }
0821:                    fInternalNamespaceContext.declarePrefix("",
0822:                            namespaceURINormalized);
0823:
0824:                    // use common namespace code with a prefix == null for xmlns="..."
0825:                    writenamespace(null, namespaceURINormalized);
0826:                } catch (IOException e) {
0827:                    throw new XMLStreamException(e);
0828:                }
0829:            }
0830:
0831:            public void writeEmptyElement(String localName)
0832:                    throws XMLStreamException {
0833:                try {
0834:                    if (fStartTagOpened) {
0835:                        closeStartTag();
0836:                    }
0837:
0838:                    openStartTag();
0839:                    fElementStack.push(null, localName, null, null, true);
0840:                    fInternalNamespaceContext.pushContext();
0841:
0842:                    if (!fIsRepairingNamespace) {
0843:                        fWriter.write(localName);
0844:                    }
0845:                } catch (IOException e) {
0846:                    throw new XMLStreamException(e);
0847:                }
0848:            }
0849:
0850:            public void writeEmptyElement(String namespaceURI, String localName)
0851:                    throws XMLStreamException {
0852:                if (namespaceURI == null) {
0853:                    throw new XMLStreamException("NamespaceURI cannot be null");
0854:                }
0855:
0856:                namespaceURI = fSymbolTable.addSymbol(namespaceURI);
0857:
0858:                String prefix = fNamespaceContext.getPrefix(namespaceURI);
0859:                writeEmptyElement(prefix, localName, namespaceURI);
0860:            }
0861:
0862:            public void writeEmptyElement(String prefix, String localName,
0863:                    String namespaceURI) throws XMLStreamException {
0864:                try {
0865:                    if (localName == null) {
0866:                        throw new XMLStreamException(
0867:                                "Local Name cannot be null");
0868:                    }
0869:
0870:                    if (namespaceURI == null) {
0871:                        throw new XMLStreamException(
0872:                                "NamespaceURI cannot be null");
0873:                    }
0874:
0875:                    if (prefix != null) {
0876:                        prefix = fSymbolTable.addSymbol(prefix);
0877:                    }
0878:
0879:                    namespaceURI = fSymbolTable.addSymbol(namespaceURI);
0880:
0881:                    if (fStartTagOpened) {
0882:                        closeStartTag();
0883:                    }
0884:
0885:                    openStartTag();
0886:
0887:                    fElementStack.push(prefix, localName, null, namespaceURI,
0888:                            true);
0889:                    fInternalNamespaceContext.pushContext();
0890:
0891:                    if (!fIsRepairingNamespace) {
0892:                        if (prefix == null) {
0893:                            throw new XMLStreamException("NamespaceURI "
0894:                                    + namespaceURI
0895:                                    + " has not been bound to any prefix");
0896:                        }
0897:                    } else {
0898:                        return;
0899:                    }
0900:
0901:                    if ((prefix != null)
0902:                            && (prefix != XMLConstants.DEFAULT_NS_PREFIX)) {
0903:                        fWriter.write(prefix);
0904:                        fWriter.write(":");
0905:                    }
0906:
0907:                    fWriter.write(localName);
0908:                } catch (IOException e) {
0909:                    throw new XMLStreamException(e);
0910:                }
0911:            }
0912:
0913:            public void writeEndDocument() throws XMLStreamException {
0914:                try {
0915:                    if (fStartTagOpened) {
0916:                        closeStartTag();
0917:                    }
0918:
0919:                    ElementState elem = null;
0920:
0921:                    while (!fElementStack.empty()) {
0922:                        elem = (ElementState) fElementStack.pop();
0923:                        fInternalNamespaceContext.popContext();
0924:
0925:                        if (elem.isEmpty) {
0926:                            //fWriter.write(CLOSE_EMPTY_ELEMENT);
0927:                        } else {
0928:                            fWriter.write(OPEN_END_TAG);
0929:
0930:                            if ((elem.prefix != null)
0931:                                    && !(elem.prefix).equals("")) {
0932:                                fWriter.write(elem.prefix);
0933:                                fWriter.write(":");
0934:                            }
0935:
0936:                            fWriter.write(elem.localpart);
0937:                            fWriter.write(CLOSE_END_TAG);
0938:                        }
0939:                    }
0940:                } catch (IOException e) {
0941:                    throw new XMLStreamException(e);
0942:                } catch (ArrayIndexOutOfBoundsException e) {
0943:                    throw new XMLStreamException("No more elements to write");
0944:                }
0945:            }
0946:
0947:            public void writeEndElement() throws XMLStreamException {
0948:                try {
0949:                    if (fStartTagOpened) {
0950:                        closeStartTag();
0951:                    }
0952:
0953:                    ElementState currentElement = (ElementState) fElementStack
0954:                            .pop();
0955:
0956:                    if (currentElement == null) {
0957:                        throw new XMLStreamException(
0958:                                "No element was found to write");
0959:                    }
0960:
0961:                    if (currentElement.isEmpty) {
0962:                        //fWriter.write(CLOSE_EMPTY_ELEMENT);
0963:                        return;
0964:                    }
0965:
0966:                    fWriter.write(OPEN_END_TAG);
0967:
0968:                    if ((currentElement.prefix != null)
0969:                            && !(currentElement.prefix).equals("")) {
0970:                        fWriter.write(currentElement.prefix);
0971:                        fWriter.write(":");
0972:                    }
0973:
0974:                    fWriter.write(currentElement.localpart);
0975:                    fWriter.write(CLOSE_END_TAG);
0976:                    fInternalNamespaceContext.popContext();
0977:                } catch (IOException e) {
0978:                    throw new XMLStreamException(e);
0979:                } catch (ArrayIndexOutOfBoundsException e) {
0980:                    throw new XMLStreamException(
0981:                            "No element was found to write: " + e.toString(), e);
0982:                }
0983:            }
0984:
0985:            public void writeEntityRef(String refName)
0986:                    throws XMLStreamException {
0987:                try {
0988:                    if (fStartTagOpened) {
0989:                        closeStartTag();
0990:                    }
0991:
0992:                    fWriter.write('&');
0993:                    fWriter.write(refName);
0994:                    fWriter.write(';');
0995:                } catch (IOException e) {
0996:                    throw new XMLStreamException(e);
0997:                }
0998:            }
0999:
1000:            /**
1001:             * Write a Namespace declaration.
1002:             *
1003:             * If namespaceURI == null,
1004:             * then it is assumed to be equivilent to {@link XMLConstants.NULL_NS_URI},
1005:             * i.e. there is no Namespace.
1006:             *
1007:             * @param prefix Prefix to bind.
1008:             * @param namespaceURI NamespaceURI to declare.
1009:             *
1010:             * @throws XMLStreamException
1011:             *
1012:             * @see <a href="http://www.w3.org/TR/REC-xml-names/#defaulting">
1013:             *   Namespaces in XML, 5.2 Namespace Defaulting</a>
1014:             */
1015:            public void writeNamespace(String prefix, String namespaceURI)
1016:                    throws XMLStreamException {
1017:
1018:                // normalize namespaceURI
1019:                String namespaceURINormalized = null;
1020:                if (namespaceURI == null) {
1021:                    namespaceURINormalized = ""; // XMLConstants.NULL_NS_URI
1022:                } else {
1023:                    namespaceURINormalized = namespaceURI;
1024:                }
1025:
1026:                try {
1027:                    QName qname = null;
1028:
1029:                    if (!fStartTagOpened) {
1030:                        throw new IllegalStateException(
1031:                                "Invalid state: start tag is not opened at writeNamespace("
1032:                                        + prefix + ", "
1033:                                        + namespaceURINormalized + ")");
1034:                    }
1035:
1036:                    // is this the default Namespace?
1037:                    if (prefix == null
1038:                            || prefix.equals(XMLConstants.DEFAULT_NS_PREFIX)
1039:                            || prefix.equals(XMLConstants.XMLNS_ATTRIBUTE)) {
1040:                        writeDefaultNamespace(namespaceURINormalized);
1041:                        return;
1042:                    }
1043:
1044:                    if (prefix.equals(XMLConstants.XML_NS_PREFIX)
1045:                            && namespaceURINormalized
1046:                                    .equals(XMLConstants.XML_NS_URI))
1047:                        return;
1048:
1049:                    prefix = fSymbolTable.addSymbol(prefix);
1050:                    namespaceURINormalized = fSymbolTable
1051:                            .addSymbol(namespaceURINormalized);
1052:
1053:                    if (fIsRepairingNamespace) {
1054:                        String tmpURI = fInternalNamespaceContext
1055:                                .getURI(prefix);
1056:
1057:                        if ((tmpURI != null)
1058:                                && (tmpURI == namespaceURINormalized)) {
1059:                            return;
1060:                        }
1061:
1062:                        qname = new QName();
1063:                        qname.setValues(prefix, XMLConstants.XMLNS_ATTRIBUTE,
1064:                                null, namespaceURINormalized);
1065:                        fNamespaceDecls.add(qname);
1066:
1067:                        return;
1068:                    }
1069:
1070:                    if (fInternalNamespaceContext
1071:                            .containsPrefixInCurrentContext(prefix)) {
1072:
1073:                        String tmp = fInternalNamespaceContext.getURI(prefix);
1074:
1075:                        if (tmp != null && tmp != namespaceURINormalized) {
1076:
1077:                            throw new XMLStreamException("prefix " + prefix
1078:                                    + " has been already bound to " + tmp
1079:                                    + ". Rebinding it to "
1080:                                    + namespaceURINormalized + " is an error");
1081:                        }
1082:                    }
1083:
1084:                    fInternalNamespaceContext.declarePrefix(prefix,
1085:                            namespaceURINormalized);
1086:                    writenamespace(prefix, namespaceURINormalized);
1087:
1088:                } catch (IOException e) {
1089:                    throw new XMLStreamException(e);
1090:                }
1091:            }
1092:
1093:            private void writenamespace(String prefix, String namespaceURI)
1094:                    throws IOException {
1095:                fWriter.write(" xmlns");
1096:
1097:                if ((prefix != null)
1098:                        && (prefix != XMLConstants.DEFAULT_NS_PREFIX)) {
1099:                    fWriter.write(":");
1100:                    fWriter.write(prefix);
1101:                }
1102:
1103:                fWriter.write("=\"");
1104:                writeXMLContent(namespaceURI, true, // true = escapeChars
1105:                        true); // true = escapeDoubleQuotes
1106:                fWriter.write("\"");
1107:            }
1108:
1109:            public void writeProcessingInstruction(String target)
1110:                    throws XMLStreamException {
1111:                try {
1112:                    if (fStartTagOpened) {
1113:                        closeStartTag();
1114:                    }
1115:
1116:                    if (target != null) {
1117:                        fWriter.write("<?");
1118:                        fWriter.write(target);
1119:                        fWriter.write("?>");
1120:
1121:                        return;
1122:                    }
1123:                } catch (IOException e) {
1124:                    throw new XMLStreamException(e);
1125:                }
1126:
1127:                throw new XMLStreamException("PI target cannot be null");
1128:            }
1129:
1130:            /**
1131:             * @param target
1132:             * @param data
1133:             * @throws XMLStreamException
1134:             */
1135:            public void writeProcessingInstruction(String target, String data)
1136:                    throws XMLStreamException {
1137:                try {
1138:                    if (fStartTagOpened) {
1139:                        closeStartTag();
1140:                    }
1141:
1142:                    if ((target == null) || (data == null)) {
1143:                        throw new XMLStreamException("PI target cannot be null");
1144:                    }
1145:
1146:                    fWriter.write("<?");
1147:                    fWriter.write(target);
1148:                    fWriter.write(SPACE);
1149:                    fWriter.write(data);
1150:                    fWriter.write("?>");
1151:                } catch (IOException e) {
1152:                    throw new XMLStreamException(e);
1153:                }
1154:            }
1155:
1156:            /**
1157:             * @throws XMLStreamException
1158:             */
1159:            public void writeStartDocument() throws XMLStreamException {
1160:                try {
1161:                    fWriter.write(DEFAULT_XMLDECL);
1162:                } catch (IOException ex) {
1163:                    throw new XMLStreamException(ex);
1164:                }
1165:            }
1166:
1167:            /**
1168:             * @param version
1169:             * @throws XMLStreamException
1170:             */
1171:            public void writeStartDocument(String version)
1172:                    throws XMLStreamException {
1173:                try {
1174:                    if ((version == null) || version.equals("")) {
1175:                        writeStartDocument();
1176:
1177:                        return;
1178:                    }
1179:
1180:                    fWriter.write("<?xml version=\"");
1181:                    fWriter.write(version);
1182:                    fWriter.write("\"");
1183:
1184:                    //fWriter.write(DEFAULT_ENCODING);
1185:                    fWriter.write("?>");
1186:                } catch (IOException ex) {
1187:                    throw new XMLStreamException(ex);
1188:                }
1189:            }
1190:
1191:            /**
1192:             * @param encoding
1193:             * @param version
1194:             * @throws XMLStreamException
1195:             */
1196:            public void writeStartDocument(String encoding, String version)
1197:                    throws XMLStreamException {
1198:                //Revisit : What about standalone ?
1199:                try {
1200:                    if ((encoding == null) && (version == null)) {
1201:                        writeStartDocument();
1202:
1203:                        return;
1204:                    }
1205:
1206:                    if (encoding == null) {
1207:                        writeStartDocument(version);
1208:
1209:                        return;
1210:                    }
1211:
1212:                    String streamEncoding = null;
1213:                    if (fWriter instanceof  OutputStreamWriter) {
1214:                        streamEncoding = ((OutputStreamWriter) fWriter)
1215:                                .getEncoding();
1216:                    } else if (fWriter instanceof  UTF8OutputStreamWriter) {
1217:                        streamEncoding = ((UTF8OutputStreamWriter) fWriter)
1218:                                .getEncoding();
1219:                    } else if (fWriter instanceof  XMLWriter) {
1220:                        streamEncoding = ((OutputStreamWriter) ((XMLWriter) fWriter)
1221:                                .getWriter()).getEncoding();
1222:                    }
1223:
1224:                    if (streamEncoding != null
1225:                            && !streamEncoding.equalsIgnoreCase(encoding)) {
1226:                        // If the equality check failed, check for charset encoding aliases
1227:                        boolean foundAlias = false;
1228:                        Set aliases = Charset.forName(encoding).aliases();
1229:                        for (Iterator it = aliases.iterator(); !foundAlias
1230:                                && it.hasNext();) {
1231:                            if (streamEncoding.equalsIgnoreCase((String) it
1232:                                    .next())) {
1233:                                foundAlias = true;
1234:                            }
1235:                        }
1236:                        // If no alias matches the encoding name, then report error
1237:                        if (!foundAlias) {
1238:                            throw new XMLStreamException(
1239:                                    "Underlying stream encoding '"
1240:                                            + streamEncoding
1241:                                            + "' and input paramter for writeStartDocument() method '"
1242:                                            + encoding + "' do not match.");
1243:                        }
1244:                    }
1245:
1246:                    fWriter.write("<?xml version=\"");
1247:
1248:                    if ((version == null) || version.equals("")) {
1249:                        fWriter.write(DEFAULT_XML_VERSION);
1250:                    } else {
1251:                        fWriter.write(version);
1252:                    }
1253:
1254:                    if (!encoding.equals("")) {
1255:                        fWriter.write("\" encoding=\"");
1256:                        fWriter.write(encoding);
1257:                    }
1258:
1259:                    fWriter.write("\"?>");
1260:                } catch (IOException ex) {
1261:                    throw new XMLStreamException(ex);
1262:                }
1263:            }
1264:
1265:            /**
1266:             * @param localName
1267:             * @throws XMLStreamException
1268:             */
1269:            public void writeStartElement(String localName)
1270:                    throws XMLStreamException {
1271:                try {
1272:                    if (localName == null) {
1273:                        throw new XMLStreamException(
1274:                                "Local Name cannot be null");
1275:                    }
1276:
1277:                    if (fStartTagOpened) {
1278:                        closeStartTag();
1279:                    }
1280:
1281:                    openStartTag();
1282:                    fElementStack.push(null, localName, null, null, false);
1283:                    fInternalNamespaceContext.pushContext();
1284:
1285:                    if (fIsRepairingNamespace) {
1286:                        return;
1287:                    }
1288:
1289:                    fWriter.write(localName);
1290:                } catch (IOException ex) {
1291:                    throw new XMLStreamException(ex);
1292:                }
1293:            }
1294:
1295:            /**
1296:             * @param namespaceURI
1297:             * @param localName
1298:             * @throws XMLStreamException
1299:             */
1300:            public void writeStartElement(String namespaceURI, String localName)
1301:                    throws XMLStreamException {
1302:                if (localName == null) {
1303:                    throw new XMLStreamException("Local Name cannot be null");
1304:                }
1305:
1306:                if (namespaceURI == null) {
1307:                    throw new XMLStreamException("NamespaceURI cannot be null");
1308:                }
1309:
1310:                namespaceURI = fSymbolTable.addSymbol(namespaceURI);
1311:
1312:                String prefix = null;
1313:
1314:                if (!fIsRepairingNamespace) {
1315:                    prefix = fNamespaceContext.getPrefix(namespaceURI);
1316:
1317:                    if (prefix != null) {
1318:                        prefix = fSymbolTable.addSymbol(prefix);
1319:                    }
1320:                }
1321:
1322:                writeStartElement(prefix, localName, namespaceURI);
1323:            }
1324:
1325:            /**
1326:             * @param prefix
1327:             * @param localName
1328:             * @param namespaceURI
1329:             * @throws XMLStreamException
1330:             */
1331:            public void writeStartElement(String prefix, String localName,
1332:                    String namespaceURI) throws XMLStreamException {
1333:                try {
1334:                    if (localName == null) {
1335:                        throw new XMLStreamException(
1336:                                "Local Name cannot be null");
1337:                    }
1338:
1339:                    if (namespaceURI == null) {
1340:                        throw new XMLStreamException(
1341:                                "NamespaceURI cannot be null");
1342:                    }
1343:
1344:                    if (!fIsRepairingNamespace) {
1345:                        if (prefix == null) {
1346:                            throw new XMLStreamException(
1347:                                    "Prefix cannot be null");
1348:                        }
1349:                    }
1350:
1351:                    if (fStartTagOpened) {
1352:                        closeStartTag();
1353:                    }
1354:
1355:                    openStartTag();
1356:                    namespaceURI = fSymbolTable.addSymbol(namespaceURI);
1357:
1358:                    if (prefix != null) {
1359:                        prefix = fSymbolTable.addSymbol(prefix);
1360:                    }
1361:
1362:                    fElementStack.push(prefix, localName, null, namespaceURI,
1363:                            false);
1364:                    fInternalNamespaceContext.pushContext();
1365:
1366:                    String tmpPrefix = fNamespaceContext
1367:                            .getPrefix(namespaceURI);
1368:
1369:                    if ((prefix != null)
1370:                            && ((tmpPrefix == null) || !prefix
1371:                                    .equals(tmpPrefix))) {
1372:                        fInternalNamespaceContext.declarePrefix(prefix,
1373:                                namespaceURI);
1374:
1375:                    }
1376:
1377:                    if (fIsRepairingNamespace) {
1378:                        if ((prefix == null)
1379:                                || ((tmpPrefix != null) && prefix
1380:                                        .equals(tmpPrefix))) {
1381:                            return;
1382:                        }
1383:
1384:                        QName qname = new QName();
1385:                        qname.setValues(prefix, XMLConstants.XMLNS_ATTRIBUTE,
1386:                                null, namespaceURI);
1387:                        fNamespaceDecls.add(qname);
1388:
1389:                        return;
1390:                    }
1391:
1392:                    if ((prefix != null)
1393:                            && (prefix != XMLConstants.DEFAULT_NS_PREFIX)) {
1394:                        fWriter.write(prefix);
1395:                        fWriter.write(":");
1396:                    }
1397:
1398:                    fWriter.write(localName);
1399:
1400:                } catch (IOException ex) {
1401:                    throw new XMLStreamException(ex);
1402:                }
1403:            }
1404:
1405:            /**
1406:             * Writes XML content to underlying writer. Escapes characters unless
1407:             * escaping character feature is turned off.
1408:             */
1409:            private void writeXMLContent(char[] content, int start, int length,
1410:                    boolean escapeChars) throws IOException {
1411:                if (!escapeChars) {
1412:                    fWriter.write(content, start, length);
1413:
1414:                    return;
1415:                }
1416:
1417:                // Index of the next char to be written
1418:                int startWritePos = start;
1419:
1420:                final int end = start + length;
1421:
1422:                for (int index = start; index < end; index++) {
1423:                    char ch = content[index];
1424:
1425:                    if (fEncoder != null && !fEncoder.canEncode(ch)) {
1426:                        fWriter.write(content, startWritePos, index
1427:                                - startWritePos);
1428:
1429:                        // Escape this char as underlying encoder cannot handle it
1430:                        fWriter.write("&#x");
1431:                        fWriter.write(Integer.toHexString(ch));
1432:                        fWriter.write(';');
1433:                        startWritePos = index + 1;
1434:                        continue;
1435:                    }
1436:
1437:                    switch (ch) {
1438:                    case '<':
1439:                        fWriter.write(content, startWritePos, index
1440:                                - startWritePos);
1441:                        fWriter.write("&lt;");
1442:                        startWritePos = index + 1;
1443:
1444:                        break;
1445:
1446:                    case '&':
1447:                        fWriter.write(content, startWritePos, index
1448:                                - startWritePos);
1449:                        fWriter.write("&amp;");
1450:                        startWritePos = index + 1;
1451:
1452:                        break;
1453:
1454:                    case '>':
1455:                        fWriter.write(content, startWritePos, index
1456:                                - startWritePos);
1457:                        fWriter.write("&gt;");
1458:                        startWritePos = index + 1;
1459:
1460:                        break;
1461:                    }
1462:                }
1463:
1464:                // Write any pending data
1465:                fWriter.write(content, startWritePos, end - startWritePos);
1466:            }
1467:
1468:            private void writeXMLContent(String content) throws IOException {
1469:                if ((content != null) && (content.length() > 0)) {
1470:                    writeXMLContent(content, fEscapeCharacters, // boolean = escapeChars
1471:                            false); // false = escapeDoubleQuotes
1472:                }
1473:            }
1474:
1475:            /**
1476:             * Writes XML content to underlying writer. Escapes characters unless
1477:             * escaping character feature is turned off.
1478:             */
1479:            private void writeXMLContent(String content, boolean escapeChars,
1480:                    boolean escapeDoubleQuotes) throws IOException {
1481:
1482:                if (!escapeChars) {
1483:                    fWriter.write(content);
1484:
1485:                    return;
1486:                }
1487:
1488:                // Index of the next char to be written
1489:                int startWritePos = 0;
1490:
1491:                final int end = content.length();
1492:
1493:                for (int index = 0; index < end; index++) {
1494:                    char ch = content.charAt(index);
1495:
1496:                    if (fEncoder != null && !fEncoder.canEncode(ch)) {
1497:                        fWriter.write(content, startWritePos, index
1498:                                - startWritePos);
1499:
1500:                        // Escape this char as underlying encoder cannot handle it
1501:                        fWriter.write("&#x");
1502:                        fWriter.write(Integer.toHexString(ch));
1503:                        fWriter.write(';');
1504:                        startWritePos = index + 1;
1505:                        continue;
1506:                    }
1507:
1508:                    switch (ch) {
1509:                    case '<':
1510:                        fWriter.write(content, startWritePos, index
1511:                                - startWritePos);
1512:                        fWriter.write("&lt;");
1513:                        startWritePos = index + 1;
1514:
1515:                        break;
1516:
1517:                    case '&':
1518:                        fWriter.write(content, startWritePos, index
1519:                                - startWritePos);
1520:                        fWriter.write("&amp;");
1521:                        startWritePos = index + 1;
1522:
1523:                        break;
1524:
1525:                    case '>':
1526:                        fWriter.write(content, startWritePos, index
1527:                                - startWritePos);
1528:                        fWriter.write("&gt;");
1529:                        startWritePos = index + 1;
1530:
1531:                        break;
1532:
1533:                    case '"':
1534:                        fWriter.write(content, startWritePos, index
1535:                                - startWritePos);
1536:                        if (escapeDoubleQuotes) {
1537:                            fWriter.write("&quot;");
1538:                        } else {
1539:                            fWriter.write('"');
1540:                        }
1541:                        startWritePos = index + 1;
1542:
1543:                        break;
1544:                    }
1545:                }
1546:
1547:                // Write any pending data
1548:                fWriter.write(content, startWritePos, end - startWritePos);
1549:            }
1550:
1551:            /**
1552:             * marks close of start tag and writes the same into the writer.
1553:             */
1554:            private void closeStartTag() throws XMLStreamException {
1555:                try {
1556:                    ElementState currentElement = fElementStack.peek();
1557:
1558:                    if (fIsRepairingNamespace) {
1559:                        repair();
1560:                        correctPrefix(currentElement);
1561:
1562:                        if ((currentElement.prefix != null)
1563:                                && (currentElement.prefix != XMLConstants.DEFAULT_NS_PREFIX)) {
1564:                            fWriter.write(currentElement.prefix);
1565:                            fWriter.write(":");
1566:                        }
1567:
1568:                        fWriter.write(currentElement.localpart);
1569:
1570:                        int len = fNamespaceDecls.size();
1571:                        QName qname = null;
1572:
1573:                        for (int i = 0; i < len; i++) {
1574:                            qname = (QName) fNamespaceDecls.get(i);
1575:
1576:                            if (qname != null) {
1577:                                if (fInternalNamespaceContext.declarePrefix(
1578:                                        qname.prefix, qname.uri)) {
1579:                                    writenamespace(qname.prefix, qname.uri);
1580:                                }
1581:                            }
1582:                        }
1583:
1584:                        fNamespaceDecls.clear();
1585:
1586:                        Attribute attr = null;
1587:
1588:                        for (int j = 0; j < fAttributeCache.size(); j++) {
1589:                            attr = (Attribute) fAttributeCache.get(j);
1590:
1591:                            if ((attr.prefix != null) && (attr.uri != null)) {
1592:                                if (!attr.prefix.equals("")
1593:                                        && !attr.uri.equals("")) {
1594:                                    String tmp = fInternalNamespaceContext
1595:                                            .getPrefix(attr.uri);
1596:
1597:                                    if ((tmp == null) || (tmp != attr.prefix)) {
1598:                                        if (fInternalNamespaceContext
1599:                                                .declarePrefix(attr.prefix,
1600:                                                        attr.uri)) {
1601:                                            writenamespace(attr.prefix,
1602:                                                    attr.uri);
1603:                                        }
1604:                                    }
1605:                                }
1606:                            }
1607:
1608:                            writeAttributeWithPrefix(attr.prefix,
1609:                                    attr.localpart, attr.value);
1610:                        }
1611:
1612:                        fAttributeCache.clear();
1613:                    }
1614:
1615:                    if (currentElement.isEmpty) {
1616:                        fElementStack.pop();
1617:                        fInternalNamespaceContext.popContext();
1618:                        fWriter.write(CLOSE_EMPTY_ELEMENT);
1619:                    } else {
1620:                        fWriter.write(CLOSE_START_TAG);
1621:                    }
1622:
1623:                    fStartTagOpened = false;
1624:                } catch (IOException ex) {
1625:                    fStartTagOpened = false;
1626:                    throw new XMLStreamException(ex);
1627:                }
1628:            }
1629:
1630:            /**
1631:             * marks open of start tag and writes the same into the writer.
1632:             */
1633:            private void openStartTag() throws IOException {
1634:                fStartTagOpened = true;
1635:                fWriter.write(OPEN_START_TAG);
1636:            }
1637:
1638:            /**
1639:             *
1640:             * @param uri
1641:             * @return
1642:             */
1643:            private void correctPrefix(QName attr) {
1644:                String tmpPrefix = null;
1645:                String prefix;
1646:                String uri;
1647:                prefix = attr.prefix;
1648:                uri = attr.uri;
1649:
1650:                if (prefix == null || prefix.equals("")) {
1651:                    if (uri == null) {
1652:                        return;
1653:                    }
1654:
1655:                    if (prefix == XMLConstants.DEFAULT_NS_PREFIX
1656:                            && uri == XMLConstants.DEFAULT_NS_PREFIX)
1657:                        return;
1658:
1659:                    uri = fSymbolTable.addSymbol(uri);
1660:
1661:                    QName decl = null;
1662:
1663:                    for (int i = 0; i < fNamespaceDecls.size(); i++) {
1664:                        decl = (QName) fNamespaceDecls.get(i);
1665:
1666:                        if ((decl != null) && (decl.uri == attr.uri)) {
1667:                            attr.prefix = decl.prefix;
1668:
1669:                            return;
1670:                        }
1671:                    }
1672:
1673:                    tmpPrefix = fNamespaceContext.getPrefix(uri);
1674:
1675:                    if (tmpPrefix == XMLConstants.DEFAULT_NS_PREFIX) {
1676:                        return;
1677:                    }
1678:
1679:                    if (tmpPrefix == null) {
1680:                        StringBuffer genPrefix = new StringBuffer("zdef");
1681:
1682:                        for (int i = 0; i < 1; i++) {
1683:                            genPrefix.append(fPrefixGen.nextInt());
1684:                        }
1685:
1686:                        prefix = genPrefix.toString();
1687:                        prefix = fSymbolTable.addSymbol(prefix);
1688:                    } else {
1689:                        prefix = fSymbolTable.addSymbol(tmpPrefix);
1690:                    }
1691:
1692:                    if (tmpPrefix == null) {
1693:                        QName qname = new QName();
1694:                        qname.setValues(prefix, XMLConstants.XMLNS_ATTRIBUTE,
1695:                                null, uri);
1696:                        fNamespaceDecls.add(qname);
1697:                        fInternalNamespaceContext.declarePrefix(fSymbolTable
1698:                                .addSymbol(prefix), uri);
1699:                    }
1700:                }
1701:
1702:                attr.prefix = prefix;
1703:            }
1704:
1705:            /**
1706:             * @param uri
1707:             * @return
1708:             */
1709:            private boolean isDefaultNamespace(String uri) {
1710:                String defaultNamespace = fInternalNamespaceContext
1711:                        .getURI(DEFAULT_PREFIX);
1712:
1713:                if (uri == defaultNamespace) {
1714:                    return true;
1715:                }
1716:
1717:                return false;
1718:            }
1719:
1720:            /**
1721:             * @param prefix
1722:             * @param uri
1723:             * @return
1724:             */
1725:            private boolean checkUserNamespaceContext(String prefix, String uri) {
1726:                if (fNamespaceContext.userContext != null) {
1727:                    String tmpURI = fNamespaceContext.userContext
1728:                            .getNamespaceURI(prefix);
1729:
1730:                    if ((tmpURI != null) && tmpURI.equals(uri)) {
1731:                        return true;
1732:                    }
1733:                }
1734:
1735:                return false;
1736:            }
1737:
1738:            /**
1739:             * Correct's namespaces  as per requirements of isReparisingNamespace property.
1740:             */
1741:            protected void repair() {
1742:                Attribute attr = null;
1743:                Attribute attr2 = null;
1744:                ElementState currentElement = fElementStack.peek();
1745:                removeDuplicateDecls();
1746:
1747:                for (int i = 0; i < fAttributeCache.size(); i++) {
1748:                    attr = (Attribute) fAttributeCache.get(i);
1749:                    if ((attr.prefix != null && !attr.prefix.equals(""))
1750:                            || (attr.uri != null && !attr.uri.equals(""))) {
1751:                        correctPrefix(currentElement, attr);
1752:                    }
1753:                }
1754:
1755:                if (!isDeclared(currentElement)) {
1756:                    if ((currentElement.prefix != null)
1757:                            && (currentElement.uri != null)) {
1758:                        if ((!currentElement.prefix.equals(""))
1759:                                && (!currentElement.uri.equals(""))) {
1760:                            fNamespaceDecls.add(currentElement);
1761:                        }
1762:                    }
1763:                }
1764:
1765:                for (int i = 0; i < fAttributeCache.size(); i++) {
1766:                    attr = (Attribute) fAttributeCache.get(i);
1767:                    for (int j = i + 1; j < fAttributeCache.size(); j++) {
1768:                        attr2 = (Attribute) fAttributeCache.get(j);
1769:                        if (!"".equals(attr.prefix) && !"".equals(attr2.prefix)) {
1770:                            correctPrefix(attr, attr2);
1771:                        }
1772:                    }
1773:                }
1774:
1775:                repairNamespaceDecl(currentElement);
1776:
1777:                int i = 0;
1778:
1779:                for (i = 0; i < fAttributeCache.size(); i++) {
1780:                    attr = (Attribute) fAttributeCache.get(i);
1781:                    /* If 'attr' is an attribute and it is in no namespace(which means that prefix="", uri=""), attr's 
1782:                       namespace should not be redinded. See [http://www.w3.org/TR/REC-xml-names/#defaulting].
1783:                     */
1784:                    if (attr.prefix != null && attr.prefix.equals("")
1785:                            && attr.uri != null && attr.uri.equals("")) {
1786:                        repairNamespaceDecl(attr);
1787:                    }
1788:                }
1789:
1790:                QName qname = null;
1791:
1792:                for (i = 0; i < fNamespaceDecls.size(); i++) {
1793:                    qname = (QName) fNamespaceDecls.get(i);
1794:
1795:                    if (qname != null) {
1796:                        fInternalNamespaceContext.declarePrefix(qname.prefix,
1797:                                qname.uri);
1798:                    }
1799:                }
1800:
1801:                for (i = 0; i < fAttributeCache.size(); i++) {
1802:                    attr = (Attribute) fAttributeCache.get(i);
1803:                    correctPrefix(attr);
1804:                }
1805:            }
1806:
1807:            /*
1808:             *If element and/or attribute names in the same start or empty-element tag
1809:             *are bound to different namespace URIs and are using the same prefix then
1810:             *the element or the first occurring attribute retains the original prefix
1811:             *and the following attributes have their prefixes replaced with a new prefix
1812:             *that is bound to the namespace URIs of those attributes.
1813:             */
1814:            void correctPrefix(QName attr1, QName attr2) {
1815:                String tmpPrefix = null;
1816:                QName decl = null;
1817:                boolean done = false;
1818:
1819:                checkForNull(attr1);
1820:                checkForNull(attr2);
1821:
1822:                if (attr1.prefix.equals(attr2.prefix)
1823:                        && !(attr1.uri.equals(attr2.uri))) {
1824:
1825:                    tmpPrefix = fNamespaceContext.getPrefix(attr2.uri);
1826:
1827:                    if (tmpPrefix != null) {
1828:                        attr2.prefix = fSymbolTable.addSymbol(tmpPrefix);
1829:                    } else {
1830:                        decl = null;
1831:                        for (int n = 0; n < fNamespaceDecls.size(); n++) {
1832:                            decl = (QName) fNamespaceDecls.get(n);
1833:                            if (decl != null && (decl.uri == attr2.uri)) {
1834:                                attr2.prefix = decl.prefix;
1835:
1836:                                return;
1837:                            }
1838:                        }
1839:
1840:                        //No namespace mapping found , so declare prefix.
1841:                        StringBuffer genPrefix = new StringBuffer("zdef");
1842:
1843:                        for (int k = 0; k < 1; k++) {
1844:                            genPrefix.append(fPrefixGen.nextInt());
1845:                        }
1846:
1847:                        tmpPrefix = genPrefix.toString();
1848:                        tmpPrefix = fSymbolTable.addSymbol(tmpPrefix);
1849:                        attr2.prefix = tmpPrefix;
1850:
1851:                        QName qname = new QName();
1852:                        qname.setValues(tmpPrefix,
1853:                                XMLConstants.XMLNS_ATTRIBUTE, null, attr2.uri);
1854:                        fNamespaceDecls.add(qname);
1855:                    }
1856:                }
1857:            }
1858:
1859:            void checkForNull(QName attr) {
1860:                if (attr.prefix == null)
1861:                    attr.prefix = XMLConstants.DEFAULT_NS_PREFIX;
1862:                if (attr.uri == null)
1863:                    attr.uri = XMLConstants.DEFAULT_NS_PREFIX;
1864:            }
1865:
1866:            void removeDuplicateDecls() {
1867:                QName decl1, decl2;
1868:                for (int i = 0; i < fNamespaceDecls.size(); i++) {
1869:                    decl1 = (QName) fNamespaceDecls.get(i);
1870:                    if (decl1 != null) {
1871:                        for (int j = i + 1; j < fNamespaceDecls.size(); j++) {
1872:                            decl2 = (QName) fNamespaceDecls.get(j);
1873:                            // QName.equals relies on identity equality, so we can't use it,
1874:                            // because prefixes aren't interned
1875:                            if (decl2 != null
1876:                                    && decl1.prefix.equals(decl2.prefix)
1877:                                    && decl1.uri.equals(decl2.uri))
1878:                                fNamespaceDecls.remove(j);
1879:                        }
1880:                    }
1881:                }
1882:            }
1883:
1884:            /*
1885:             *If an element or attribute name is bound to a prefix and there is a namespace
1886:             *declaration that binds that prefix to a different URI then that namespace declaration
1887:             *is either removed if the correct mapping is inherited from the parent context of that element,
1888:             *or changed to the namespace URI of the element or attribute using that prefix.
1889:             *
1890:             */
1891:            void repairNamespaceDecl(QName attr) {
1892:                QName decl = null;
1893:                String tmpURI;
1894:
1895:                //check for null prefix.
1896:                for (int j = 0; j < fNamespaceDecls.size(); j++) {
1897:                    decl = (QName) fNamespaceDecls.get(j);
1898:
1899:                    if (decl != null) {
1900:                        if ((attr.prefix != null)
1901:                                && (attr.prefix.equals(decl.prefix) && !(attr.uri
1902:                                        .equals(decl.uri)))) {
1903:                            tmpURI = fNamespaceContext
1904:                                    .getNamespaceURI(attr.prefix);
1905:
1906:                            //see if you need to add to symbole table.
1907:                            if (tmpURI != null) {
1908:                                if (tmpURI.equals(attr.uri)) {
1909:                                    fNamespaceDecls.set(j, null);
1910:                                } else {
1911:                                    decl.uri = attr.uri;
1912:                                }
1913:                            }
1914:                        }
1915:                    }
1916:                }
1917:            }
1918:
1919:            boolean isDeclared(QName attr) {
1920:                QName decl = null;
1921:
1922:                for (int n = 0; n < fNamespaceDecls.size(); n++) {
1923:                    decl = (QName) fNamespaceDecls.get(n);
1924:
1925:                    if ((attr.prefix != null)
1926:                            && ((attr.prefix == decl.prefix) && (decl.uri == attr.uri))) {
1927:                        return true;
1928:                    }
1929:                }
1930:
1931:                if (attr.uri != null) {
1932:                    if (fNamespaceContext.getPrefix(attr.uri) != null) {
1933:                        return true;
1934:                    }
1935:                }
1936:
1937:                return false;
1938:            }
1939:
1940:            /*
1941:             * Start of Internal classes.
1942:             *
1943:             */
1944:            protected class ElementStack {
1945:                /** The stack data. */
1946:                protected ElementState[] fElements;
1947:
1948:                /** The size of the stack. */
1949:                protected short fDepth;
1950:
1951:                /** Default constructor. */
1952:                public ElementStack() {
1953:                    fElements = new ElementState[10];
1954:
1955:                    for (int i = 0; i < fElements.length; i++) {
1956:                        fElements[i] = new ElementState();
1957:                    }
1958:                }
1959:
1960:                /**
1961:                 * Pushes an element on the stack.
1962:                 * <p>
1963:                 * <strong>Note:</strong> The QName values are copied into the
1964:                 * stack. In other words, the caller does <em>not</em> orphan
1965:                 * the element to the stack. Also, the QName object returned
1966:                 * is <em>not</em> orphaned to the caller. It should be
1967:                 * considered read-only.
1968:                 *
1969:                 * @param element The element to push onto the stack.
1970:                 *
1971:                 * @return Returns the actual QName object that stores the
1972:                 */
1973:                public ElementState push(ElementState element) {
1974:                    if (fDepth == fElements.length) {
1975:                        ElementState[] array = new ElementState[fElements.length * 2];
1976:                        System.arraycopy(fElements, 0, array, 0, fDepth);
1977:                        fElements = array;
1978:
1979:                        for (int i = fDepth; i < fElements.length; i++) {
1980:                            fElements[i] = new ElementState();
1981:                        }
1982:                    }
1983:
1984:                    fElements[fDepth].setValues(element);
1985:
1986:                    return fElements[fDepth++];
1987:                }
1988:
1989:                /**
1990:                 *
1991:                 * @param prefix
1992:                 * @param localpart
1993:                 * @param rawname
1994:                 * @param uri
1995:                 * @param isEmpty
1996:                 * @return
1997:                 */
1998:                public ElementState push(String prefix, String localpart,
1999:                        String rawname, String uri, boolean isEmpty) {
2000:                    if (fDepth == fElements.length) {
2001:                        ElementState[] array = new ElementState[fElements.length * 2];
2002:                        System.arraycopy(fElements, 0, array, 0, fDepth);
2003:                        fElements = array;
2004:
2005:                        for (int i = fDepth; i < fElements.length; i++) {
2006:                            fElements[i] = new ElementState();
2007:                        }
2008:                    }
2009:
2010:                    fElements[fDepth].setValues(prefix, localpart, rawname,
2011:                            uri, isEmpty);
2012:
2013:                    return fElements[fDepth++];
2014:                }
2015:
2016:                /**
2017:                 * Pops an element off of the stack by setting the values of
2018:                 * the specified QName.
2019:                 * <p>
2020:                 * <strong>Note:</strong> The object returned is <em>not</em>
2021:                 * orphaned to the caller. Therefore, the caller should consider
2022:                 * the object to be read-only.
2023:                 */
2024:                public ElementState pop() {
2025:                    return fElements[--fDepth];
2026:                }
2027:
2028:                /** Clears the stack without throwing away existing QName objects. */
2029:                public void clear() {
2030:                    fDepth = 0;
2031:                }
2032:
2033:                /**
2034:                 * This function is as a result of optimization done for endElement --
2035:                 * we dont need to set the value for every end element we encouter.
2036:                 * For Well formedness checks we can have the same QName object that was pushed.
2037:                 * the values will be set only if application need to know about the endElement
2038:                 * -- neeraj.bajaj@sun.com
2039:                 */
2040:                public ElementState peek() {
2041:                    return fElements[fDepth - 1];
2042:                }
2043:
2044:                /**
2045:                 *
2046:                 * @return
2047:                 */
2048:                public boolean empty() {
2049:                    return (fDepth > 0) ? false : true;
2050:                }
2051:            }
2052:
2053:            /**
2054:             * Maintains element state . localName for now.
2055:             */
2056:            class ElementState extends QName {
2057:                public boolean isEmpty = false;
2058:
2059:                public ElementState() {
2060:                }
2061:
2062:                public ElementState(String prefix, String localpart,
2063:                        String rawname, String uri) {
2064:                    super (prefix, localpart, rawname, uri);
2065:                }
2066:
2067:                public void setValues(String prefix, String localpart,
2068:                        String rawname, String uri, boolean isEmpty) {
2069:                    super .setValues(prefix, localpart, rawname, uri);
2070:                    this .isEmpty = isEmpty;
2071:                }
2072:            }
2073:
2074:            /**
2075:             * Attributes
2076:             */
2077:            class Attribute extends QName {
2078:                String value;
2079:
2080:                Attribute(String value) {
2081:                    super ();
2082:                    this .value = value;
2083:                }
2084:            }
2085:
2086:            /**
2087:             * Implementation of NamespaceContext .
2088:             *
2089:             */
2090:            class NamespaceContextImpl implements  NamespaceContext {
2091:                //root namespace context set by user.
2092:                NamespaceContext userContext = null;
2093:
2094:                //context built by the writer.
2095:                NamespaceSupport internalContext = null;
2096:
2097:                public String getNamespaceURI(String prefix) {
2098:                    String uri = null;
2099:
2100:                    if (prefix != null) {
2101:                        prefix = fSymbolTable.addSymbol(prefix);
2102:                    }
2103:
2104:                    if (internalContext != null) {
2105:                        uri = internalContext.getURI(prefix);
2106:
2107:                        if (uri != null) {
2108:                            return uri;
2109:                        }
2110:                    }
2111:
2112:                    if (userContext != null) {
2113:                        uri = userContext.getNamespaceURI(prefix);
2114:
2115:                        return uri;
2116:                    }
2117:
2118:                    return null;
2119:                }
2120:
2121:                public String getPrefix(String uri) {
2122:                    String prefix = null;
2123:
2124:                    if (uri != null) {
2125:                        uri = fSymbolTable.addSymbol(uri);
2126:                    }
2127:
2128:                    if (internalContext != null) {
2129:                        prefix = internalContext.getPrefix(uri);
2130:
2131:                        if (prefix != null) {
2132:                            return prefix;
2133:                        }
2134:                    }
2135:
2136:                    if (userContext != null) {
2137:                        return userContext.getPrefix(uri);
2138:                    }
2139:
2140:                    return null;
2141:                }
2142:
2143:                public java.util.Iterator getPrefixes(String uri) {
2144:                    Vector prefixes = null;
2145:                    Iterator itr = null;
2146:
2147:                    if (uri != null) {
2148:                        uri = fSymbolTable.addSymbol(uri);
2149:                    }
2150:
2151:                    if (userContext != null) {
2152:                        itr = userContext.getPrefixes(uri);
2153:                    }
2154:
2155:                    if (internalContext != null) {
2156:                        prefixes = internalContext.getPrefixes(uri);
2157:                    }
2158:
2159:                    if ((prefixes == null) && (itr != null)) {
2160:                        return itr;
2161:                    } else if ((prefixes != null) && (itr == null)) {
2162:                        return new ReadOnlyIterator(prefixes.iterator());
2163:                    } else if ((prefixes != null) && (itr != null)) {
2164:                        String ob = null;
2165:
2166:                        while (itr.hasNext()) {
2167:                            ob = (String) itr.next();
2168:
2169:                            if (ob != null) {
2170:                                ob = fSymbolTable.addSymbol(ob);
2171:                            }
2172:
2173:                            if (!prefixes.contains(ob)) {
2174:                                prefixes.add(ob);
2175:                            }
2176:                        }
2177:
2178:                        return new ReadOnlyIterator(prefixes.iterator());
2179:                    }
2180:
2181:                    return fReadOnlyIterator;
2182:                }
2183:            }
2184:
2185:            // -- Map Interface --------------------------------------------------
2186:
2187:            public int size() {
2188:                return 1;
2189:            }
2190:
2191:            public boolean isEmpty() {
2192:                return false;
2193:            }
2194:
2195:            public boolean containsKey(Object key) {
2196:                return key.equals(OUTPUTSTREAM_PROPERTY);
2197:            }
2198:
2199:            /**
2200:             * Returns the value associated to an implementation-specific
2201:             * property. 
2202:             */
2203:            public Object get(Object key) {
2204:                if (key.equals(OUTPUTSTREAM_PROPERTY)) {
2205:                    return fOutputStream;
2206:                }
2207:                return null;
2208:            }
2209:
2210:            public java.util.Set entrySet() {
2211:                throw new UnsupportedOperationException();
2212:            }
2213:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.