286N/A/*
286N/A * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
286N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
286N/A *
286N/A * This code is free software; you can redistribute it and/or modify it
286N/A * under the terms of the GNU General Public License version 2 only, as
286N/A * published by the Free Software Foundation. Oracle designates this
286N/A * particular file as subject to the "Classpath" exception as provided
286N/A * by Oracle in the LICENSE file that accompanied this code.
286N/A *
286N/A * This code is distributed in the hope that it will be useful, but WITHOUT
286N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
286N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
286N/A * version 2 for more details (a copy is included in the LICENSE file that
286N/A * accompanied this code).
286N/A *
286N/A * You should have received a copy of the GNU General Public License version
286N/A * 2 along with this work; if not, write to the Free Software Foundation,
286N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
286N/A *
286N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
286N/A * or visit www.oracle.com if you need additional information or have any
286N/A * questions.
286N/A */
286N/A
286N/Apackage com.sun.xml.internal.stream.writers;
286N/A
286N/Aimport java.io.FileOutputStream;
286N/Aimport java.io.IOException;
286N/Aimport java.io.OutputStream;
286N/Aimport java.io.OutputStreamWriter;
286N/Aimport java.io.Writer;
286N/Aimport java.nio.charset.Charset;
286N/Aimport java.nio.charset.CharsetEncoder;
286N/Aimport java.util.AbstractMap;
286N/Aimport java.util.ArrayList;
286N/Aimport java.util.HashMap;
286N/Aimport java.util.Iterator;
286N/Aimport java.util.Random;
286N/Aimport java.util.Vector;
286N/Aimport java.util.Set;
286N/Aimport java.util.Iterator;
286N/A
286N/Aimport javax.xml.XMLConstants;
286N/Aimport javax.xml.namespace.NamespaceContext;
286N/Aimport javax.xml.stream.XMLOutputFactory;
286N/Aimport javax.xml.stream.XMLStreamConstants;
286N/Aimport javax.xml.stream.XMLStreamException;
286N/Aimport javax.xml.stream.XMLStreamWriter;
286N/Aimport javax.xml.transform.stream.StreamResult;
286N/A
286N/Aimport com.sun.org.apache.xerces.internal.impl.Constants;
286N/Aimport com.sun.org.apache.xerces.internal.impl.PropertyManager;
286N/Aimport com.sun.org.apache.xerces.internal.util.NamespaceSupport;
286N/Aimport com.sun.org.apache.xerces.internal.util.SymbolTable;
524N/Aimport com.sun.org.apache.xerces.internal.utils.SecuritySupport;
286N/Aimport com.sun.org.apache.xerces.internal.xni.QName;
286N/A
286N/Aimport com.sun.xml.internal.stream.util.ReadOnlyIterator;
286N/A
286N/A/**
286N/A * This class implements a StAX XMLStreamWriter. It extends
286N/A * <code>AbstractMap</code> in order to support a getter for
286N/A * implementation-specific properties. For example, you can get
286N/A * the underlying <code>OutputStream</code> by casting an instance
286N/A * of this class to <code>Map</code> and calling
286N/A * <code>getProperty(OUTPUTSTREAM_PROPERTY)</code>.
286N/A *
286N/A * @author Neeraj Bajaj
286N/A * @author K.Venugopal
286N/A * @author Santiago.Pericas-Geertsen@sun.com
286N/A * @author Sunitha.Reddy@sun.com
286N/A */
286N/Apublic final class XMLStreamWriterImpl extends AbstractMap implements XMLStreamWriter {
286N/A
286N/A public static final String START_COMMENT = "<!--";
286N/A public static final String END_COMMENT = "-->";
286N/A public static final String DEFAULT_ENCODING = " encoding=\"utf-8\"";
286N/A public static final String DEFAULT_XMLDECL = "<?xml version=\"1.0\" ?>";
286N/A public static final String DEFAULT_XML_VERSION = "1.0";
286N/A public static final char CLOSE_START_TAG = '>';
286N/A public static final char OPEN_START_TAG = '<';
286N/A public static final String OPEN_END_TAG = "</";
286N/A public static final char CLOSE_END_TAG = '>';
286N/A public static final String START_CDATA = "<![CDATA[";
286N/A public static final String END_CDATA = "]]>";
286N/A public static final String CLOSE_EMPTY_ELEMENT = "/>";
286N/A public static final String SPACE = " ";
286N/A public static final String UTF_8 = "UTF-8";
286N/A
286N/A public static final String OUTPUTSTREAM_PROPERTY = "sjsxp-outputstream";
286N/A
286N/A /**
286N/A * This flag can be used to turn escaping off for content. It does
286N/A * not apply to attribute content.
286N/A */
286N/A boolean fEscapeCharacters = true;
286N/A
286N/A /**
286N/A * Flag for the value of repairNamespace property
286N/A */
286N/A private boolean fIsRepairingNamespace = false;
286N/A
286N/A /**
286N/A * Underlying Writer to which characters are written.
286N/A */
286N/A private Writer fWriter;
286N/A
286N/A /**
286N/A * Underlying OutputStream to which <code>fWriter</code>
286N/A * writes to. May be null if unknown.
286N/A */
286N/A private OutputStream fOutputStream = null;
286N/A
286N/A /**
286N/A * Collects attributes when the writer is in reparing mode.
286N/A */
286N/A private ArrayList fAttributeCache;
286N/A
286N/A /**
286N/A * Collects namespace declarations when the writer is in reparing mode.
286N/A */
286N/A private ArrayList fNamespaceDecls;
286N/A
286N/A /**
286N/A * Namespace context encapsulating user specified context
286N/A * and context built by the writer
286N/A */
286N/A private NamespaceContextImpl fNamespaceContext = null;
286N/A
286N/A private NamespaceSupport fInternalNamespaceContext = null;
286N/A
286N/A private Random fPrefixGen = null;
286N/A
286N/A /**
286N/A * Reference to PropertyManager
286N/A */
286N/A private PropertyManager fPropertyManager = null;
286N/A
286N/A /**
286N/A * Flag to track if start tag is opened
286N/A */
286N/A private boolean fStartTagOpened = false;
286N/A
286N/A /**
286N/A * Boolean flag to indicate, if instance can be reused
286N/A */
286N/A private boolean fReuse;
286N/A
286N/A private SymbolTable fSymbolTable = new SymbolTable();
286N/A
286N/A private ElementStack fElementStack = new ElementStack(); //Change this .-Venu
286N/A
286N/A final private String DEFAULT_PREFIX = fSymbolTable.addSymbol("");
286N/A
286N/A private final ReadOnlyIterator fReadOnlyIterator = new ReadOnlyIterator();
286N/A
286N/A /**
286N/A * In some cases, this charset encoder is used to determine if a char is
286N/A * encodable by underlying writer. For example, an 8-bit char from the
286N/A * extended ASCII set is not encodable by 7-bit ASCII encoder. Unencodable
286N/A * chars are escaped using XML numeric entities.
286N/A */
286N/A private CharsetEncoder fEncoder = null;
286N/A
286N/A /**
286N/A * This is used to hold the namespace for attributes which happen to have
286N/A * the same uri as the default namespace; It's added to avoid changing the
286N/A * current impl. which has many redundant code for the repair mode
286N/A */
286N/A HashMap fAttrNamespace = null;
286N/A
286N/A /**
286N/A * Creates a new instance of XMLStreamWriterImpl. Uses platform's default
286N/A * encoding.
286N/A *
286N/A * @param outputStream Underlying stream to write the bytes to
286N/A * @param props Properties used by this writer
286N/A */
286N/A public XMLStreamWriterImpl(OutputStream outputStream, PropertyManager props)
286N/A throws IOException {
286N/A
286N/A // cannot call this(outputStream, null, props); for constructor,
286N/A // OutputStreamWriter charsetName cannot be null
286N/A
286N/A // use default encoding
286N/A this(new OutputStreamWriter(outputStream), props);
286N/A }
286N/A
286N/A /**
286N/A * Creates a new instance of XMLStreamWriterImpl.
286N/A *
286N/A * @param outputStream Underlying stream to write the bytes
286N/A * @param encoding Encoding used to convert chars into bytes
286N/A * @param props Properties used by this writer
286N/A */
286N/A public XMLStreamWriterImpl(OutputStream outputStream, String encoding,
286N/A PropertyManager props) throws java.io.IOException {
286N/A this(new StreamResult(outputStream), encoding, props);
286N/A }
286N/A
286N/A /**
286N/A * Creates a new instance of XMLStreamWriterImpl using a Writer.
286N/A *
286N/A * @param writer Underlying writer to which chars are written
286N/A * @param props Properties used by this writer
286N/A */
286N/A public XMLStreamWriterImpl(Writer writer, PropertyManager props)
286N/A throws java.io.IOException {
286N/A this(new StreamResult(writer), null, props);
286N/A }
286N/A
286N/A /**
286N/A * Creates a new instance of XMLStreamWriterImpl using a StreamResult.
286N/A * A StreamResult encasupates an OutputStream, a Writer or a SystemId.
286N/A *
286N/A * @param writer Underlying writer to which chars are written
286N/A * @param props Properties used by this writer
286N/A */
286N/A public XMLStreamWriterImpl(StreamResult sr, String encoding,
286N/A PropertyManager props) throws java.io.IOException {
286N/A setOutput(sr, encoding);
286N/A fPropertyManager = props;
286N/A init();
286N/A }
286N/A
286N/A /**
286N/A * Initialize an instance of this XMLStreamWriter. Allocate new instances
286N/A * for all the data structures. Set internal flags based on property values.
286N/A */
286N/A private void init() {
286N/A fReuse = false;
286N/A fNamespaceDecls = new ArrayList();
286N/A fPrefixGen = new Random();
286N/A fAttributeCache = new ArrayList();
286N/A fInternalNamespaceContext = new NamespaceSupport();
286N/A fInternalNamespaceContext.reset();
286N/A fNamespaceContext = new NamespaceContextImpl();
286N/A fNamespaceContext.internalContext = fInternalNamespaceContext;
286N/A
286N/A // Set internal state based on property values
286N/A Boolean ob = (Boolean) fPropertyManager.getProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES);
286N/A fIsRepairingNamespace = ob.booleanValue();
286N/A ob = (Boolean) fPropertyManager.getProperty(Constants.ESCAPE_CHARACTERS);
286N/A setEscapeCharacters(ob.booleanValue());
286N/A }
286N/A
286N/A /**
286N/A * Reset this instance so that it can be re-used. Do not read properties
286N/A * again. The method <code>setOutput(StreamResult, encoding)</code> must
286N/A * be called after this one.
286N/A */
286N/A public void reset() {
286N/A reset(false);
286N/A }
286N/A
286N/A /**
286N/A * Reset this instance so that it can be re-used. Clears but does not
286N/A * re-allocate internal data structures.
286N/A *
286N/A * @param resetProperties Indicates if properties should be read again
286N/A */
286N/A void reset(boolean resetProperties) {
286N/A if (!fReuse) {
286N/A throw new java.lang.IllegalStateException(
286N/A "close() Must be called before calling reset()");
286N/A }
286N/A
286N/A fReuse = false;
286N/A fNamespaceDecls.clear();
286N/A fAttributeCache.clear();
286N/A
286N/A // reset Element/NamespaceContext stacks
286N/A fElementStack.clear();
286N/A fInternalNamespaceContext.reset();
286N/A
286N/A fStartTagOpened = false;
286N/A fNamespaceContext.userContext = null;
286N/A
286N/A if (resetProperties) {
286N/A Boolean ob = (Boolean) fPropertyManager.getProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES);
286N/A fIsRepairingNamespace = ob.booleanValue();
286N/A ob = (Boolean) fPropertyManager.getProperty(Constants.ESCAPE_CHARACTERS);
286N/A setEscapeCharacters(ob.booleanValue());
286N/A }
286N/A }
286N/A
286N/A /**
286N/A * Use a StreamResult to initialize the output for this XMLStreamWriter. Check
286N/A * for OutputStream, Writer and then systemId, in that order.
286N/A *
286N/A * @param sr StreamResult encapsulating output information
286N/A * @param encoding Encoding to be used except when a Writer is available
286N/A */
286N/A public void setOutput(StreamResult sr, String encoding)
286N/A throws IOException {
286N/A
286N/A if (sr.getOutputStream() != null) {
286N/A setOutputUsingStream(sr.getOutputStream(), encoding);
286N/A }
286N/A else if (sr.getWriter() != null) {
286N/A setOutputUsingWriter(sr.getWriter());
286N/A }
286N/A else if (sr.getSystemId() != null) {
286N/A setOutputUsingStream(new FileOutputStream(sr.getSystemId()),
286N/A encoding);
286N/A }
286N/A }
286N/A
286N/A private void setOutputUsingWriter(Writer writer)
286N/A throws IOException
286N/A {
286N/A fWriter = writer;
286N/A
286N/A if (writer instanceof OutputStreamWriter) {
286N/A String charset = ((OutputStreamWriter) writer).getEncoding();
286N/A if (charset != null && !charset.equalsIgnoreCase("utf-8")) {
286N/A fEncoder = Charset.forName(charset).newEncoder();
286N/A }
286N/A }
286N/A }
286N/A
286N/A /**
286N/A * Utility method to create a writer when passed an OutputStream. Make
286N/A * sure to wrap an <code>OutputStreamWriter</code> using an
286N/A * <code>XMLWriter</code> for performance reasons.
286N/A *
286N/A * @param os Underlying OutputStream
286N/A * @param encoding Encoding used to convert chars into bytes
286N/A */
286N/A private void setOutputUsingStream(OutputStream os, String encoding)
286N/A throws IOException {
286N/A fOutputStream = os;
286N/A
286N/A if (encoding != null) {
286N/A if (encoding.equalsIgnoreCase("utf-8")) {
286N/A fWriter = new UTF8OutputStreamWriter(os);
286N/A }
286N/A else {
286N/A fWriter = new XMLWriter(new OutputStreamWriter(os, encoding));
286N/A fEncoder = Charset.forName(encoding).newEncoder();
286N/A }
286N/A } else {
524N/A encoding = SecuritySupport.getSystemProperty("file.encoding");
286N/A if (encoding != null && encoding.equalsIgnoreCase("utf-8")) {
286N/A fWriter = new UTF8OutputStreamWriter(os);
286N/A } else {
286N/A fWriter = new XMLWriter(new OutputStreamWriter(os));
286N/A }
286N/A }
286N/A }
286N/A
286N/A /** Can this instance be reused
286N/A *
286N/A * @return boolean boolean value to indicate if this instance can be reused or not
286N/A */
286N/A public boolean canReuse() {
286N/A return fReuse;
286N/A }
286N/A
286N/A public void setEscapeCharacters(boolean escape) {
286N/A fEscapeCharacters = escape;
286N/A }
286N/A
286N/A public boolean getEscapeCharacters() {
286N/A return fEscapeCharacters;
286N/A }
286N/A
286N/A /**
286N/A * Close this XMLStreamWriter by closing underlying writer.
286N/A */
286N/A public void close() throws XMLStreamException {
286N/A if (fWriter != null) {
286N/A try {
286N/A //fWriter.close();
286N/A fWriter.flush();
286N/A } catch (IOException e) {
286N/A throw new XMLStreamException(e);
286N/A }
286N/A }
286N/A fWriter = null;
286N/A fOutputStream = null;
286N/A fNamespaceDecls.clear();
286N/A fAttributeCache.clear();
286N/A fElementStack.clear();
286N/A fInternalNamespaceContext.reset();
286N/A fReuse = true;
293N/A fStartTagOpened = false;
293N/A fNamespaceContext.userContext = null;
286N/A }
286N/A
286N/A /**
286N/A * Flush this XMLStreamWriter by flushin underlying writer.
286N/A */
286N/A public void flush() throws XMLStreamException {
286N/A try {
286N/A fWriter.flush();
286N/A } catch (IOException e) {
286N/A throw new XMLStreamException(e);
286N/A }
286N/A }
286N/A
286N/A /**
286N/A * Return <code>NamespaceContext</code> being used by the writer.
286N/A *
286N/A * @return NamespaceContext
286N/A */
286N/A public NamespaceContext getNamespaceContext() {
286N/A return fNamespaceContext;
286N/A }
286N/A
286N/A /**
286N/A * Return a prefix associated with specified uri, or null if the
286N/A * uri is unknown.
286N/A *
286N/A * @param uri The namespace uri
286N/A * @throws XMLStreamException if uri specified is "" or null
286N/A */
286N/A public String getPrefix(String uri) throws XMLStreamException {
286N/A return fNamespaceContext.getPrefix(uri);
286N/A }
286N/A
286N/A /**
286N/A * Returns value associated with the specified property name.
286N/A *
286N/A * @param str Property name
286N/A * @throws IllegalArgumentException if the specified property is not supported
286N/A * @return value associated with the specified property.
286N/A */
286N/A public Object getProperty(String str)
286N/A throws IllegalArgumentException {
286N/A if (str == null) {
286N/A throw new NullPointerException();
286N/A }
286N/A
286N/A if (!fPropertyManager.containsProperty(str)) {
286N/A throw new IllegalArgumentException("Property '" + str +
286N/A "' is not supported");
286N/A }
286N/A
286N/A return fPropertyManager.getProperty(str);
286N/A }
286N/A
286N/A /**
286N/A * Set the specified URI as default namespace in the current namespace context.
286N/A *
286N/A * @param uri Namespace URI
286N/A */
286N/A public void setDefaultNamespace(String uri) throws XMLStreamException {
286N/A if (uri != null) {
286N/A uri = fSymbolTable.addSymbol(uri);
286N/A }
286N/A
286N/A if (fIsRepairingNamespace) {
286N/A if (isDefaultNamespace(uri)) {
286N/A return;
286N/A }
286N/A
286N/A QName qname = new QName();
286N/A qname.setValues(DEFAULT_PREFIX, "xmlns", null, uri);
286N/A fNamespaceDecls.add(qname);
286N/A } else {
286N/A fInternalNamespaceContext.declarePrefix(DEFAULT_PREFIX, uri);
286N/A }
286N/A }
286N/A
286N/A /**
286N/A * Sets the current <code>NamespaceContext</code> for prefix and uri bindings.
286N/A * This context becomes the root namespace context for writing and
286N/A * will replace the current root namespace context. Subsequent calls
286N/A * to setPrefix and setDefaultNamespace will bind namespaces using
286N/A * the context passed to the method as the root context for resolving
286N/A * namespaces. This method may only be called once at the start of the
286N/A * document. It does not cause the namespaces to be declared. If a
286N/A * namespace URI to prefix mapping is found in the namespace context
286N/A * it is treated as declared and the prefix may be used by the
286N/A * <code>XMLStreamWriter</code>.
286N/A *
286N/A * @param namespaceContext the namespace context to use for this writer, may not be null
286N/A * @throws XMLStreamException
286N/A */
286N/A public void setNamespaceContext(NamespaceContext namespaceContext)
286N/A throws XMLStreamException {
286N/A fNamespaceContext.userContext = namespaceContext;
286N/A }
286N/A
286N/A /**
286N/A * Sets the prefix the uri is bound to. This prefix is bound in the scope of
286N/A * the current START_ELEMENT / END_ELEMENT pair. If this method is called before
286N/A * a START_ELEMENT has been written the prefix is bound in the root scope.
286N/A *
286N/A * @param prefix
286N/A * @param uri
286N/A * @throws XMLStreamException
286N/A */
286N/A public void setPrefix(String prefix, String uri) throws XMLStreamException {
286N/A
286N/A if (prefix == null) {
286N/A throw new XMLStreamException("Prefix cannot be null");
286N/A }
286N/A
286N/A if (uri == null) {
286N/A throw new XMLStreamException("URI cannot be null");
286N/A }
286N/A
286N/A prefix = fSymbolTable.addSymbol(prefix);
286N/A uri = fSymbolTable.addSymbol(uri);
286N/A
286N/A if (fIsRepairingNamespace) {
286N/A String tmpURI = fInternalNamespaceContext.getURI(prefix);
286N/A
286N/A if ((tmpURI != null) && (tmpURI == uri)) {
286N/A return;
286N/A }
286N/A
286N/A if(checkUserNamespaceContext(prefix,uri))
286N/A return;
286N/A QName qname = new QName();
286N/A qname.setValues(prefix,XMLConstants.XMLNS_ATTRIBUTE, null,uri);
286N/A fNamespaceDecls.add(qname);
286N/A
286N/A return;
286N/A }
286N/A
286N/A fInternalNamespaceContext.declarePrefix(prefix, uri);
286N/A }
286N/A
286N/A public void writeAttribute(String localName, String value)
286N/A throws XMLStreamException {
286N/A try {
286N/A if (!fStartTagOpened) {
286N/A throw new XMLStreamException(
286N/A "Attribute not associated with any element");
286N/A }
286N/A
286N/A if (fIsRepairingNamespace) {
286N/A Attribute attr = new Attribute(value); // Revisit:Dont create new one's. Reuse.-Venu
286N/A attr.setValues(null, localName, null, null);
286N/A fAttributeCache.add(attr);
286N/A
286N/A return;
286N/A }
286N/A
286N/A fWriter.write(" ");
286N/A fWriter.write(localName);
286N/A fWriter.write("=\"");
286N/A writeXMLContent(
286N/A value,
286N/A true, // true = escapeChars
286N/A true); // true = escapeDoubleQuotes
286N/A fWriter.write("\"");
286N/A } catch (IOException e) {
286N/A throw new XMLStreamException(e);
286N/A }
286N/A }
286N/A
286N/A public void writeAttribute(String namespaceURI, String localName,
286N/A String value) throws XMLStreamException {
286N/A try {
286N/A if (!fStartTagOpened) {
286N/A throw new XMLStreamException(
286N/A "Attribute not associated with any element");
286N/A }
286N/A
286N/A if (namespaceURI == null) {
286N/A throw new XMLStreamException("NamespaceURI cannot be null");
286N/A }
286N/A
286N/A namespaceURI = fSymbolTable.addSymbol(namespaceURI);
286N/A
286N/A String prefix = fInternalNamespaceContext.getPrefix(namespaceURI);
286N/A
286N/A if (!fIsRepairingNamespace) {
286N/A if (prefix == null) {
286N/A throw new XMLStreamException("Prefix cannot be null");
286N/A }
286N/A
286N/A writeAttributeWithPrefix(prefix, localName, value);
286N/A } else {
286N/A Attribute attr = new Attribute(value);
286N/A attr.setValues(null, localName, null, namespaceURI);
286N/A fAttributeCache.add(attr);
286N/A }
286N/A } catch (IOException e) {
286N/A throw new XMLStreamException(e);
286N/A }
286N/A }
286N/A
286N/A private void writeAttributeWithPrefix(String prefix, String localName,
286N/A String value) throws IOException {
286N/A fWriter.write(SPACE);
286N/A
286N/A if ((prefix != null) && (prefix != XMLConstants.DEFAULT_NS_PREFIX)) {
286N/A fWriter.write(prefix);
286N/A fWriter.write(":");
286N/A }
286N/A
286N/A fWriter.write(localName);
286N/A fWriter.write("=\"");
286N/A writeXMLContent(value,
286N/A true, // true = escapeChars
286N/A true); // true = escapeDoubleQuotes
286N/A fWriter.write("\"");
286N/A }
286N/A
286N/A public void writeAttribute(String prefix, String namespaceURI,
286N/A String localName, String value) throws XMLStreamException {
286N/A try {
286N/A if (!fStartTagOpened) {
286N/A throw new XMLStreamException(
286N/A "Attribute not associated with any element");
286N/A }
286N/A
286N/A if (namespaceURI == null) {
286N/A throw new XMLStreamException("NamespaceURI cannot be null");
286N/A }
286N/A
286N/A if (localName == null) {
286N/A throw new XMLStreamException("Local name cannot be null");
286N/A }
286N/A
286N/A if (!fIsRepairingNamespace) {
286N/A if (prefix == null || prefix.equals("")){
286N/A if (!namespaceURI.equals("")) {
286N/A throw new XMLStreamException("prefix cannot be null or empty");
286N/A } else {
286N/A writeAttributeWithPrefix(null, localName, value);
286N/A return;
286N/A }
286N/A }
286N/A
286N/A if (!prefix.equals(XMLConstants.XML_NS_PREFIX) || !namespaceURI.equals(XMLConstants.XML_NS_URI)) {
286N/A
286N/A prefix = fSymbolTable.addSymbol(prefix);
286N/A namespaceURI = fSymbolTable.addSymbol(namespaceURI);
286N/A
286N/A if (fInternalNamespaceContext.containsPrefixInCurrentContext(prefix)){
286N/A
286N/A String tmpURI = fInternalNamespaceContext.getURI(prefix);
286N/A
286N/A if (tmpURI != null && tmpURI != namespaceURI){
286N/A throw new XMLStreamException("Prefix "+prefix+" is " +
286N/A "already bound to "+tmpURI+
286N/A ". Trying to rebind it to "+namespaceURI+" is an error.");
286N/A }
286N/A }
286N/A fInternalNamespaceContext.declarePrefix(prefix, namespaceURI);
286N/A }
286N/A writeAttributeWithPrefix(prefix, localName, value);
286N/A } else {
286N/A if (prefix != null) {
286N/A prefix = fSymbolTable.addSymbol(prefix);
286N/A }
286N/A
286N/A namespaceURI = fSymbolTable.addSymbol(namespaceURI);
286N/A
286N/A Attribute attr = new Attribute(value);
286N/A attr.setValues(prefix, localName, null, namespaceURI);
286N/A fAttributeCache.add(attr);
286N/A }
286N/A } catch (IOException e) {
286N/A throw new XMLStreamException(e);
286N/A }
286N/A }
286N/A
286N/A public void writeCData(String cdata) throws XMLStreamException {
286N/A try {
286N/A if (cdata == null) {
286N/A throw new XMLStreamException("cdata cannot be null");
286N/A }
286N/A
286N/A if (fStartTagOpened) {
286N/A closeStartTag();
286N/A }
286N/A
286N/A fWriter.write(START_CDATA);
286N/A fWriter.write(cdata);
286N/A fWriter.write(END_CDATA);
286N/A } catch (IOException e) {
286N/A throw new XMLStreamException(e);
286N/A }
286N/A }
286N/A
286N/A public void writeCharacters(String data) throws XMLStreamException {
286N/A try {
286N/A if (fStartTagOpened) {
286N/A closeStartTag();
286N/A }
286N/A
286N/A writeXMLContent(data);
286N/A } catch (IOException e) {
286N/A throw new XMLStreamException(e);
286N/A }
286N/A }
286N/A
286N/A public void writeCharacters(char[] data, int start, int len)
286N/A throws XMLStreamException {
286N/A try {
286N/A if (fStartTagOpened) {
286N/A closeStartTag();
286N/A }
286N/A
286N/A writeXMLContent(data, start, len, fEscapeCharacters);
286N/A } catch (IOException e) {
286N/A throw new XMLStreamException(e);
286N/A }
286N/A }
286N/A
286N/A public void writeComment(String comment) throws XMLStreamException {
286N/A try {
286N/A if (fStartTagOpened) {
286N/A closeStartTag();
286N/A }
286N/A
286N/A fWriter.write(START_COMMENT);
286N/A
286N/A if (comment != null) {
286N/A fWriter.write(comment);
286N/A }
286N/A
286N/A fWriter.write(END_COMMENT);
286N/A } catch (IOException e) {
286N/A throw new XMLStreamException(e);
286N/A }
286N/A }
286N/A
286N/A public void writeDTD(String dtd) throws XMLStreamException {
286N/A try {
286N/A if (fStartTagOpened) {
286N/A closeStartTag();
286N/A }
286N/A
286N/A fWriter.write(dtd);
286N/A } catch (IOException e) {
286N/A throw new XMLStreamException(e);
286N/A }
286N/A }
286N/A
286N/A /*
286N/A * Write default Namespace.
286N/A *
286N/A * If namespaceURI == null,
286N/A * then it is assumed to be equivilent to {@link XMLConstants.NULL_NS_URI},
286N/A * i.e. there is no Namespace.
286N/A *
286N/A * @param namespaceURI NamespaceURI to declare.
286N/A *
286N/A * @throws XMLStreamException
286N/A *
286N/A * @see <a href="http://www.w3.org/TR/REC-xml-names/#defaulting">
286N/A * Namespaces in XML, 5.2 Namespace Defaulting</a>
286N/A */
286N/A public void writeDefaultNamespace(String namespaceURI)
286N/A throws XMLStreamException {
286N/A
286N/A // normalize namespaceURI
286N/A String namespaceURINormalized = null;
286N/A if (namespaceURI == null) {
286N/A namespaceURINormalized = ""; // XMLConstants.NULL_NS_URI
286N/A } else {
286N/A namespaceURINormalized = namespaceURI;
286N/A }
286N/A
286N/A try {
286N/A if (!fStartTagOpened) {
286N/A throw new IllegalStateException(
286N/A "Namespace Attribute not associated with any element");
286N/A }
286N/A
286N/A if (fIsRepairingNamespace) {
286N/A QName qname = new QName();
286N/A qname.setValues(XMLConstants.DEFAULT_NS_PREFIX,
286N/A XMLConstants.XMLNS_ATTRIBUTE, null, namespaceURINormalized);
286N/A fNamespaceDecls.add(qname);
286N/A
286N/A return;
286N/A }
286N/A
286N/A namespaceURINormalized = fSymbolTable.addSymbol(namespaceURINormalized);
286N/A
286N/A if (fInternalNamespaceContext.containsPrefixInCurrentContext("")){
286N/A
286N/A String tmp = fInternalNamespaceContext.getURI("");
286N/A
286N/A if (tmp != null && tmp != namespaceURINormalized) {
286N/A throw new XMLStreamException(
286N/A "xmlns has been already bound to " +tmp +
286N/A ". Rebinding it to "+ namespaceURINormalized +
286N/A " is an error");
286N/A }
286N/A }
286N/A fInternalNamespaceContext.declarePrefix("", namespaceURINormalized);
286N/A
286N/A // use common namespace code with a prefix == null for xmlns="..."
286N/A writenamespace(null, namespaceURINormalized);
286N/A } catch (IOException e) {
286N/A throw new XMLStreamException(e);
286N/A }
286N/A }
286N/A
286N/A public void writeEmptyElement(String localName) throws XMLStreamException {
286N/A try {
286N/A if (fStartTagOpened) {
286N/A closeStartTag();
286N/A }
286N/A
286N/A openStartTag();
286N/A fElementStack.push(null, localName, null, null, true);
286N/A fInternalNamespaceContext.pushContext();
286N/A
286N/A if (!fIsRepairingNamespace) {
286N/A fWriter.write(localName);
286N/A }
286N/A } catch (IOException e) {
286N/A throw new XMLStreamException(e);
286N/A }
286N/A }
286N/A
286N/A public void writeEmptyElement(String namespaceURI, String localName)
286N/A throws XMLStreamException {
286N/A if (namespaceURI == null) {
286N/A throw new XMLStreamException("NamespaceURI cannot be null");
286N/A }
286N/A
286N/A namespaceURI = fSymbolTable.addSymbol(namespaceURI);
286N/A
286N/A String prefix = fNamespaceContext.getPrefix(namespaceURI);
286N/A writeEmptyElement(prefix, localName, namespaceURI);
286N/A }
286N/A
286N/A public void writeEmptyElement(String prefix, String localName,
286N/A String namespaceURI) throws XMLStreamException {
286N/A try {
286N/A if (localName == null) {
286N/A throw new XMLStreamException("Local Name cannot be null");
286N/A }
286N/A
286N/A if (namespaceURI == null) {
286N/A throw new XMLStreamException("NamespaceURI cannot be null");
286N/A }
286N/A
286N/A if (prefix != null) {
286N/A prefix = fSymbolTable.addSymbol(prefix);
286N/A }
286N/A
286N/A namespaceURI = fSymbolTable.addSymbol(namespaceURI);
286N/A
286N/A if (fStartTagOpened) {
286N/A closeStartTag();
286N/A }
286N/A
286N/A openStartTag();
286N/A
286N/A fElementStack.push(prefix, localName, null, namespaceURI, true);
286N/A fInternalNamespaceContext.pushContext();
286N/A
286N/A if (!fIsRepairingNamespace) {
286N/A if (prefix == null) {
286N/A throw new XMLStreamException("NamespaceURI " +
286N/A namespaceURI + " has not been bound to any prefix");
286N/A }
286N/A } else {
286N/A return;
286N/A }
286N/A
286N/A if ((prefix != null) && (prefix != XMLConstants.DEFAULT_NS_PREFIX)) {
286N/A fWriter.write(prefix);
286N/A fWriter.write(":");
286N/A }
286N/A
286N/A fWriter.write(localName);
286N/A } catch (IOException e) {
286N/A throw new XMLStreamException(e);
286N/A }
286N/A }
286N/A
286N/A public void writeEndDocument() throws XMLStreamException {
286N/A try {
286N/A if (fStartTagOpened) {
286N/A closeStartTag();
286N/A }
286N/A
286N/A ElementState elem = null;
286N/A
286N/A while (!fElementStack.empty()) {
286N/A elem = (ElementState) fElementStack.pop();
286N/A fInternalNamespaceContext.popContext();
286N/A
286N/A if (elem.isEmpty) {
286N/A //fWriter.write(CLOSE_EMPTY_ELEMENT);
286N/A } else {
286N/A fWriter.write(OPEN_END_TAG);
286N/A
286N/A if ((elem.prefix != null) && !(elem.prefix).equals("")) {
286N/A fWriter.write(elem.prefix);
286N/A fWriter.write(":");
286N/A }
286N/A
286N/A fWriter.write(elem.localpart);
286N/A fWriter.write(CLOSE_END_TAG);
286N/A }
286N/A }
286N/A } catch (IOException e) {
286N/A throw new XMLStreamException(e);
286N/A } catch (ArrayIndexOutOfBoundsException e) {
286N/A throw new XMLStreamException("No more elements to write");
286N/A }
286N/A }
286N/A
286N/A public void writeEndElement() throws XMLStreamException {
286N/A try {
286N/A if (fStartTagOpened) {
286N/A closeStartTag();
286N/A }
286N/A
286N/A ElementState currentElement = (ElementState) fElementStack.pop();
286N/A
286N/A if (currentElement == null) {
286N/A throw new XMLStreamException("No element was found to write");
286N/A }
286N/A
286N/A if (currentElement.isEmpty) {
286N/A //fWriter.write(CLOSE_EMPTY_ELEMENT);
286N/A return;
286N/A }
286N/A
286N/A fWriter.write(OPEN_END_TAG);
286N/A
286N/A if ((currentElement.prefix != null) &&
286N/A !(currentElement.prefix).equals("")) {
286N/A fWriter.write(currentElement.prefix);
286N/A fWriter.write(":");
286N/A }
286N/A
286N/A fWriter.write(currentElement.localpart);
286N/A fWriter.write(CLOSE_END_TAG);
286N/A fInternalNamespaceContext.popContext();
286N/A } catch (IOException e) {
286N/A throw new XMLStreamException(e);
286N/A } catch (ArrayIndexOutOfBoundsException e) {
286N/A throw new XMLStreamException(
286N/A "No element was found to write: "
286N/A + e.toString(), e);
286N/A }
286N/A }
286N/A
286N/A public void writeEntityRef(String refName) throws XMLStreamException {
286N/A try {
286N/A if (fStartTagOpened) {
286N/A closeStartTag();
286N/A }
286N/A
286N/A fWriter.write('&');
286N/A fWriter.write(refName);
286N/A fWriter.write(';');
286N/A } catch (IOException e) {
286N/A throw new XMLStreamException(e);
286N/A }
286N/A }
286N/A
286N/A /**
286N/A * Write a Namespace declaration.
286N/A *
286N/A * If namespaceURI == null,
286N/A * then it is assumed to be equivilent to {@link XMLConstants.NULL_NS_URI},
286N/A * i.e. there is no Namespace.
286N/A *
286N/A * @param prefix Prefix to bind.
286N/A * @param namespaceURI NamespaceURI to declare.
286N/A *
286N/A * @throws XMLStreamException
286N/A *
286N/A * @see <a href="http://www.w3.org/TR/REC-xml-names/#defaulting">
286N/A * Namespaces in XML, 5.2 Namespace Defaulting</a>
286N/A */
286N/A public void writeNamespace(String prefix, String namespaceURI)
286N/A throws XMLStreamException {
286N/A
286N/A // normalize namespaceURI
286N/A String namespaceURINormalized = null;
286N/A if (namespaceURI == null) {
286N/A namespaceURINormalized = ""; // XMLConstants.NULL_NS_URI
286N/A } else {
286N/A namespaceURINormalized = namespaceURI;
286N/A }
286N/A
286N/A try {
286N/A QName qname = null;
286N/A
286N/A if (!fStartTagOpened) {
286N/A throw new IllegalStateException(
286N/A "Invalid state: start tag is not opened at writeNamespace("
286N/A + prefix
286N/A + ", "
286N/A + namespaceURINormalized
286N/A + ")");
286N/A }
286N/A
286N/A // is this the default Namespace?
286N/A if (prefix == null
286N/A || prefix.equals(XMLConstants.DEFAULT_NS_PREFIX)
286N/A || prefix.equals(XMLConstants.XMLNS_ATTRIBUTE)) {
286N/A writeDefaultNamespace(namespaceURINormalized);
286N/A return;
286N/A }
286N/A
286N/A if (prefix.equals(XMLConstants.XML_NS_PREFIX) && namespaceURINormalized.equals(XMLConstants.XML_NS_URI))
286N/A return;
286N/A
286N/A prefix = fSymbolTable.addSymbol(prefix);
286N/A namespaceURINormalized = fSymbolTable.addSymbol(namespaceURINormalized);
286N/A
286N/A if (fIsRepairingNamespace) {
286N/A String tmpURI = fInternalNamespaceContext.getURI(prefix);
286N/A
286N/A if ((tmpURI != null) && (tmpURI == namespaceURINormalized)) {
286N/A return;
286N/A }
286N/A
286N/A qname = new QName();
286N/A qname.setValues(prefix, XMLConstants.XMLNS_ATTRIBUTE, null,
286N/A namespaceURINormalized);
286N/A fNamespaceDecls.add(qname);
286N/A
286N/A return;
286N/A }
286N/A
286N/A
286N/A if (fInternalNamespaceContext.containsPrefixInCurrentContext(prefix)){
286N/A
286N/A String tmp = fInternalNamespaceContext.getURI(prefix);
286N/A
286N/A if (tmp != null && tmp != namespaceURINormalized) {
286N/A
286N/A throw new XMLStreamException("prefix "+prefix+
286N/A " has been already bound to " +tmp +
286N/A ". Rebinding it to "+ namespaceURINormalized+
286N/A " is an error");
286N/A }
286N/A }
286N/A
286N/A fInternalNamespaceContext.declarePrefix(prefix, namespaceURINormalized);
286N/A writenamespace(prefix, namespaceURINormalized);
286N/A
286N/A } catch (IOException e) {
286N/A throw new XMLStreamException(e);
286N/A }
286N/A }
286N/A
286N/A private void writenamespace(String prefix, String namespaceURI)
286N/A throws IOException {
286N/A fWriter.write(" xmlns");
286N/A
286N/A if ((prefix != null) && (prefix != XMLConstants.DEFAULT_NS_PREFIX)) {
286N/A fWriter.write(":");
286N/A fWriter.write(prefix);
286N/A }
286N/A
286N/A fWriter.write("=\"");
286N/A writeXMLContent(
286N/A namespaceURI,
286N/A true, // true = escapeChars
286N/A true); // true = escapeDoubleQuotes
286N/A fWriter.write("\"");
286N/A }
286N/A
286N/A public void writeProcessingInstruction(String target)
286N/A throws XMLStreamException {
286N/A try {
286N/A if (fStartTagOpened) {
286N/A closeStartTag();
286N/A }
286N/A
286N/A if (target != null) {
286N/A fWriter.write("<?");
286N/A fWriter.write(target);
286N/A fWriter.write("?>");
286N/A
286N/A return;
286N/A }
286N/A } catch (IOException e) {
286N/A throw new XMLStreamException(e);
286N/A }
286N/A
286N/A throw new XMLStreamException("PI target cannot be null");
286N/A }
286N/A
286N/A /**
286N/A * @param target
286N/A * @param data
286N/A * @throws XMLStreamException
286N/A */
286N/A public void writeProcessingInstruction(String target, String data)
286N/A throws XMLStreamException {
286N/A try {
286N/A if (fStartTagOpened) {
286N/A closeStartTag();
286N/A }
286N/A
286N/A if ((target == null) || (data == null)) {
286N/A throw new XMLStreamException("PI target cannot be null");
286N/A }
286N/A
286N/A fWriter.write("<?");
286N/A fWriter.write(target);
286N/A fWriter.write(SPACE);
286N/A fWriter.write(data);
286N/A fWriter.write("?>");
286N/A } catch (IOException e) {
286N/A throw new XMLStreamException(e);
286N/A }
286N/A }
286N/A
286N/A /**
286N/A * @throws XMLStreamException
286N/A */
286N/A public void writeStartDocument() throws XMLStreamException {
286N/A try {
286N/A fWriter.write(DEFAULT_XMLDECL);
286N/A } catch (IOException ex) {
286N/A throw new XMLStreamException(ex);
286N/A }
286N/A }
286N/A
286N/A /**
286N/A * @param version
286N/A * @throws XMLStreamException
286N/A */
286N/A public void writeStartDocument(String version) throws XMLStreamException {
286N/A try {
286N/A if ((version == null) || version.equals("")) {
286N/A writeStartDocument();
286N/A
286N/A return;
286N/A }
286N/A
286N/A fWriter.write("<?xml version=\"");
286N/A fWriter.write(version);
286N/A fWriter.write("\"");
286N/A
286N/A //fWriter.write(DEFAULT_ENCODING);
286N/A fWriter.write("?>");
286N/A } catch (IOException ex) {
286N/A throw new XMLStreamException(ex);
286N/A }
286N/A }
286N/A
286N/A /**
286N/A * @param encoding
286N/A * @param version
286N/A * @throws XMLStreamException
286N/A */
286N/A public void writeStartDocument(String encoding, String version)
286N/A throws XMLStreamException {
286N/A //Revisit : What about standalone ?
286N/A try {
286N/A if ((encoding == null) && (version == null)) {
286N/A writeStartDocument();
286N/A
286N/A return;
286N/A }
286N/A
286N/A if (encoding == null) {
286N/A writeStartDocument(version);
286N/A
286N/A return;
286N/A }
286N/A
286N/A String streamEncoding = null;
286N/A if (fWriter instanceof OutputStreamWriter) {
286N/A streamEncoding = ((OutputStreamWriter) fWriter).getEncoding();
286N/A }
286N/A else if (fWriter instanceof UTF8OutputStreamWriter) {
286N/A streamEncoding = ((UTF8OutputStreamWriter) fWriter).getEncoding();
286N/A }
286N/A else if (fWriter instanceof XMLWriter) {
286N/A streamEncoding = ((OutputStreamWriter) ((XMLWriter)fWriter).getWriter()).getEncoding();
286N/A }
286N/A
286N/A if (streamEncoding != null && !streamEncoding.equalsIgnoreCase(encoding)) {
286N/A // If the equality check failed, check for charset encoding aliases
286N/A boolean foundAlias = false;
286N/A Set aliases = Charset.forName(encoding).aliases();
286N/A for (Iterator it = aliases.iterator(); !foundAlias && it.hasNext(); ) {
286N/A if (streamEncoding.equalsIgnoreCase((String) it.next())) {
286N/A foundAlias = true;
286N/A }
286N/A }
286N/A // If no alias matches the encoding name, then report error
286N/A if (!foundAlias) {
286N/A throw new XMLStreamException("Underlying stream encoding '"
286N/A + streamEncoding
286N/A + "' and input paramter for writeStartDocument() method '"
286N/A + encoding + "' do not match.");
286N/A }
286N/A }
286N/A
286N/A
286N/A fWriter.write("<?xml version=\"");
286N/A
286N/A if ((version == null) || version.equals("")) {
286N/A fWriter.write(DEFAULT_XML_VERSION);
286N/A } else {
286N/A fWriter.write(version);
286N/A }
286N/A
286N/A if (!encoding.equals("")) {
286N/A fWriter.write("\" encoding=\"");
286N/A fWriter.write(encoding);
286N/A }
286N/A
286N/A fWriter.write("\"?>");
286N/A } catch (IOException ex) {
286N/A throw new XMLStreamException(ex);
286N/A }
286N/A }
286N/A
286N/A /**
286N/A * @param localName
286N/A * @throws XMLStreamException
286N/A */
286N/A public void writeStartElement(String localName) throws XMLStreamException {
286N/A try {
286N/A if (localName == null) {
286N/A throw new XMLStreamException("Local Name cannot be null");
286N/A }
286N/A
286N/A if (fStartTagOpened) {
286N/A closeStartTag();
286N/A }
286N/A
286N/A openStartTag();
286N/A fElementStack.push(null, localName, null, null, false);
286N/A fInternalNamespaceContext.pushContext();
286N/A
286N/A if (fIsRepairingNamespace) {
286N/A return;
286N/A }
286N/A
286N/A fWriter.write(localName);
286N/A } catch (IOException ex) {
286N/A throw new XMLStreamException(ex);
286N/A }
286N/A }
286N/A
286N/A /**
286N/A * @param namespaceURI
286N/A * @param localName
286N/A * @throws XMLStreamException
286N/A */
286N/A public void writeStartElement(String namespaceURI, String localName)
286N/A throws XMLStreamException {
286N/A if (localName == null) {
286N/A throw new XMLStreamException("Local Name cannot be null");
286N/A }
286N/A
286N/A if (namespaceURI == null) {
286N/A throw new XMLStreamException("NamespaceURI cannot be null");
286N/A }
286N/A
286N/A namespaceURI = fSymbolTable.addSymbol(namespaceURI);
286N/A
286N/A String prefix = null;
286N/A
286N/A if (!fIsRepairingNamespace) {
286N/A prefix = fNamespaceContext.getPrefix(namespaceURI);
286N/A
286N/A if (prefix != null) {
286N/A prefix = fSymbolTable.addSymbol(prefix);
286N/A }
286N/A }
286N/A
286N/A writeStartElement(prefix, localName, namespaceURI);
286N/A }
286N/A
286N/A /**
286N/A * @param prefix
286N/A * @param localName
286N/A * @param namespaceURI
286N/A * @throws XMLStreamException
286N/A */
286N/A public void writeStartElement(String prefix, String localName,
286N/A String namespaceURI) throws XMLStreamException {
286N/A try {
286N/A if (localName == null) {
286N/A throw new XMLStreamException("Local Name cannot be null");
286N/A }
286N/A
286N/A if (namespaceURI == null) {
286N/A throw new XMLStreamException("NamespaceURI cannot be null");
286N/A }
286N/A
286N/A if (!fIsRepairingNamespace) {
286N/A if (prefix == null) {
286N/A throw new XMLStreamException("Prefix cannot be null");
286N/A }
286N/A }
286N/A
286N/A if (fStartTagOpened) {
286N/A closeStartTag();
286N/A }
286N/A
286N/A openStartTag();
286N/A namespaceURI = fSymbolTable.addSymbol(namespaceURI);
286N/A
286N/A if (prefix != null) {
286N/A prefix = fSymbolTable.addSymbol(prefix);
286N/A }
286N/A
286N/A fElementStack.push(prefix, localName, null, namespaceURI, false);
286N/A fInternalNamespaceContext.pushContext();
286N/A
286N/A String tmpPrefix = fNamespaceContext.getPrefix(namespaceURI);
286N/A
286N/A
286N/A if ((prefix != null) &&
286N/A ((tmpPrefix == null) || !prefix.equals(tmpPrefix))) {
286N/A fInternalNamespaceContext.declarePrefix(prefix, namespaceURI);
286N/A
286N/A }
286N/A
286N/A if (fIsRepairingNamespace) {
286N/A if ((prefix == null) ||
286N/A ((tmpPrefix != null) && prefix.equals(tmpPrefix))) {
286N/A return;
286N/A }
286N/A
286N/A QName qname = new QName();
286N/A qname.setValues(prefix, XMLConstants.XMLNS_ATTRIBUTE, null,
286N/A namespaceURI);
286N/A fNamespaceDecls.add(qname);
286N/A
286N/A return;
286N/A }
286N/A
286N/A if ((prefix != null) && (prefix != XMLConstants.DEFAULT_NS_PREFIX)) {
286N/A fWriter.write(prefix);
286N/A fWriter.write(":");
286N/A }
286N/A
286N/A fWriter.write(localName);
286N/A
286N/A } catch (IOException ex) {
286N/A throw new XMLStreamException(ex);
286N/A }
286N/A }
286N/A
286N/A /**
286N/A * Writes XML content to underlying writer. Escapes characters unless
286N/A * escaping character feature is turned off.
286N/A */
286N/A private void writeXMLContent(char[] content, int start, int length,
286N/A boolean escapeChars) throws IOException {
286N/A if (!escapeChars) {
286N/A fWriter.write(content, start, length);
286N/A
286N/A return;
286N/A }
286N/A
286N/A // Index of the next char to be written
286N/A int startWritePos = start;
286N/A
286N/A final int end = start + length;
286N/A
286N/A for (int index = start; index < end; index++) {
286N/A char ch = content[index];
286N/A
286N/A if (fEncoder != null && !fEncoder.canEncode(ch)){
286N/A fWriter.write(content, startWritePos, index - startWritePos );
286N/A
286N/A // Escape this char as underlying encoder cannot handle it
286N/A fWriter.write( "&#x" );
286N/A fWriter.write(Integer.toHexString(ch));
286N/A fWriter.write( ';' );
286N/A startWritePos = index + 1;
286N/A continue;
286N/A }
286N/A
286N/A switch (ch) {
286N/A case '<':
286N/A fWriter.write(content, startWritePos, index - startWritePos);
286N/A fWriter.write("&lt;");
286N/A startWritePos = index + 1;
286N/A
286N/A break;
286N/A
286N/A case '&':
286N/A fWriter.write(content, startWritePos, index - startWritePos);
286N/A fWriter.write("&amp;");
286N/A startWritePos = index + 1;
286N/A
286N/A break;
286N/A
286N/A case '>':
286N/A fWriter.write(content, startWritePos, index - startWritePos);
286N/A fWriter.write("&gt;");
286N/A startWritePos = index + 1;
286N/A
286N/A break;
286N/A }
286N/A }
286N/A
286N/A // Write any pending data
286N/A fWriter.write(content, startWritePos, end - startWritePos);
286N/A }
286N/A
286N/A private void writeXMLContent(String content) throws IOException {
286N/A if ((content != null) && (content.length() > 0)) {
286N/A writeXMLContent(content,
286N/A fEscapeCharacters, // boolean = escapeChars
286N/A false); // false = escapeDoubleQuotes
286N/A }
286N/A }
286N/A
286N/A /**
286N/A * Writes XML content to underlying writer. Escapes characters unless
286N/A * escaping character feature is turned off.
286N/A */
286N/A private void writeXMLContent(
286N/A String content,
286N/A boolean escapeChars,
286N/A boolean escapeDoubleQuotes)
286N/A throws IOException {
286N/A
286N/A if (!escapeChars) {
286N/A fWriter.write(content);
286N/A
286N/A return;
286N/A }
286N/A
286N/A // Index of the next char to be written
286N/A int startWritePos = 0;
286N/A
286N/A final int end = content.length();
286N/A
286N/A for (int index = 0; index < end; index++) {
286N/A char ch = content.charAt(index);
286N/A
286N/A if (fEncoder != null && !fEncoder.canEncode(ch)){
286N/A fWriter.write(content, startWritePos, index - startWritePos );
286N/A
286N/A // Escape this char as underlying encoder cannot handle it
286N/A fWriter.write( "&#x" );
286N/A fWriter.write(Integer.toHexString(ch));
286N/A fWriter.write( ';' );
286N/A startWritePos = index + 1;
286N/A continue;
286N/A }
286N/A
286N/A switch (ch) {
286N/A case '<':
286N/A fWriter.write(content, startWritePos, index - startWritePos);
286N/A fWriter.write("&lt;");
286N/A startWritePos = index + 1;
286N/A
286N/A break;
286N/A
286N/A case '&':
286N/A fWriter.write(content, startWritePos, index - startWritePos);
286N/A fWriter.write("&amp;");
286N/A startWritePos = index + 1;
286N/A
286N/A break;
286N/A
286N/A case '>':
286N/A fWriter.write(content, startWritePos, index - startWritePos);
286N/A fWriter.write("&gt;");
286N/A startWritePos = index + 1;
286N/A
286N/A break;
286N/A
286N/A case '"':
286N/A fWriter.write(content, startWritePos, index - startWritePos);
286N/A if (escapeDoubleQuotes) {
286N/A fWriter.write("&quot;");
286N/A } else {
286N/A fWriter.write('"');
286N/A }
286N/A startWritePos = index + 1;
286N/A
286N/A break;
286N/A }
286N/A }
286N/A
286N/A // Write any pending data
286N/A fWriter.write(content, startWritePos, end - startWritePos);
286N/A }
286N/A
286N/A /**
286N/A * marks close of start tag and writes the same into the writer.
286N/A */
286N/A private void closeStartTag() throws XMLStreamException {
286N/A try {
286N/A ElementState currentElement = fElementStack.peek();
286N/A
286N/A if (fIsRepairingNamespace) {
286N/A repair();
286N/A correctPrefix(currentElement, XMLStreamConstants.START_ELEMENT);
286N/A
286N/A if ((currentElement.prefix != null) &&
286N/A (currentElement.prefix != XMLConstants.DEFAULT_NS_PREFIX)) {
286N/A fWriter.write(currentElement.prefix);
286N/A fWriter.write(":");
286N/A }
286N/A
286N/A fWriter.write(currentElement.localpart);
286N/A
286N/A int len = fNamespaceDecls.size();
286N/A QName qname = null;
286N/A
286N/A for (int i = 0; i < len; i++) {
286N/A qname = (QName) fNamespaceDecls.get(i);
286N/A
286N/A if (qname != null) {
286N/A if (fInternalNamespaceContext.declarePrefix(qname.prefix,
286N/A qname.uri)) {
286N/A writenamespace(qname.prefix, qname.uri);
286N/A }
286N/A }
286N/A }
286N/A
286N/A fNamespaceDecls.clear();
286N/A
286N/A Attribute attr = null;
286N/A
286N/A for (int j = 0; j < fAttributeCache.size(); j++) {
286N/A attr = (Attribute) fAttributeCache.get(j);
286N/A
286N/A if ((attr.prefix != null) && (attr.uri != null)) {
286N/A if (!attr.prefix.equals("") && !attr.uri.equals("") ) {
286N/A String tmp = fInternalNamespaceContext.getPrefix(attr.uri);
286N/A
286N/A if ((tmp == null) || (tmp != attr.prefix)) {
286N/A tmp = getAttrPrefix(attr.uri);
286N/A if (tmp == null) {
286N/A if (fInternalNamespaceContext.declarePrefix(attr.prefix,
286N/A attr.uri)) {
286N/A writenamespace(attr.prefix, attr.uri);
286N/A }
286N/A } else {
286N/A writenamespace(attr.prefix, attr.uri);
286N/A }
286N/A }
286N/A }
286N/A }
286N/A
286N/A writeAttributeWithPrefix(attr.prefix, attr.localpart,
286N/A attr.value);
286N/A }
286N/A fAttrNamespace = null;
286N/A fAttributeCache.clear();
286N/A }
286N/A
286N/A if (currentElement.isEmpty) {
286N/A fElementStack.pop();
286N/A fInternalNamespaceContext.popContext();
286N/A fWriter.write(CLOSE_EMPTY_ELEMENT);
286N/A } else {
286N/A fWriter.write(CLOSE_START_TAG);
286N/A }
286N/A
286N/A fStartTagOpened = false;
286N/A } catch (IOException ex) {
286N/A fStartTagOpened = false;
286N/A throw new XMLStreamException(ex);
286N/A }
286N/A }
286N/A
286N/A /**
286N/A * marks open of start tag and writes the same into the writer.
286N/A */
286N/A private void openStartTag() throws IOException {
286N/A fStartTagOpened = true;
286N/A fWriter.write(OPEN_START_TAG);
286N/A }
286N/A
286N/A /**
286N/A *
286N/A * @param uri
286N/A * @return
286N/A */
286N/A private void correctPrefix(QName attr, int type) {
286N/A String tmpPrefix = null;
286N/A String prefix;
286N/A String uri;
286N/A prefix = attr.prefix;
286N/A uri = attr.uri;
286N/A boolean isSpecialCaseURI = false;
286N/A
286N/A if (prefix == null || prefix.equals("")) {
286N/A if (uri == null) {
286N/A return;
286N/A }
286N/A
286N/A if (prefix == XMLConstants.DEFAULT_NS_PREFIX && uri == XMLConstants.DEFAULT_NS_PREFIX)
286N/A return;
286N/A
286N/A uri = fSymbolTable.addSymbol(uri);
286N/A
286N/A QName decl = null;
286N/A
286N/A for (int i = 0; i < fNamespaceDecls.size(); i++) {
286N/A decl = (QName) fNamespaceDecls.get(i);
286N/A
286N/A if ((decl != null) && (decl.uri == attr.uri)) {
286N/A attr.prefix = decl.prefix;
286N/A
286N/A return;
286N/A }
286N/A }
286N/A
286N/A tmpPrefix = fNamespaceContext.getPrefix(uri);
286N/A
286N/A if (tmpPrefix == XMLConstants.DEFAULT_NS_PREFIX) {
286N/A if (type == XMLStreamConstants.START_ELEMENT) {
286N/A return;
286N/A }
286N/A else if (type == XMLStreamConstants.ATTRIBUTE) {
286N/A //the uri happens to be the same as that of the default namespace
286N/A tmpPrefix = getAttrPrefix(uri);
286N/A isSpecialCaseURI = true;
286N/A }
286N/A }
286N/A
286N/A if (tmpPrefix == null) {
286N/A StringBuffer genPrefix = new StringBuffer("zdef");
286N/A
286N/A for (int i = 0; i < 1; i++) {
286N/A genPrefix.append(fPrefixGen.nextInt());
286N/A }
286N/A
286N/A prefix = genPrefix.toString();
286N/A prefix = fSymbolTable.addSymbol(prefix);
286N/A } else {
286N/A prefix = fSymbolTable.addSymbol(tmpPrefix);
286N/A }
286N/A
286N/A if (tmpPrefix == null) {
286N/A if (isSpecialCaseURI) {
286N/A addAttrNamespace(prefix, uri);
286N/A } else {
286N/A QName qname = new QName();
286N/A qname.setValues(prefix, XMLConstants.XMLNS_ATTRIBUTE, null, uri);
286N/A fNamespaceDecls.add(qname);
286N/A fInternalNamespaceContext.declarePrefix(fSymbolTable.addSymbol(
286N/A prefix), uri);
286N/A }
286N/A }
286N/A }
286N/A
286N/A attr.prefix = prefix;
286N/A }
286N/A
286N/A /**
286N/A * return the prefix if the attribute has an uri the same as that of the default namespace
286N/A */
286N/A private String getAttrPrefix(String uri) {
286N/A if (fAttrNamespace != null) {
286N/A return (String)fAttrNamespace.get(uri);
286N/A }
286N/A return null;
286N/A }
286N/A private void addAttrNamespace(String prefix, String uri) {
286N/A if (fAttrNamespace == null) {
286N/A fAttrNamespace = new HashMap();
286N/A }
286N/A fAttrNamespace.put(prefix, uri);
286N/A }
286N/A /**
286N/A * @param uri
286N/A * @return
286N/A */
286N/A private boolean isDefaultNamespace(String uri) {
286N/A String defaultNamespace = fInternalNamespaceContext.getURI(DEFAULT_PREFIX);
286N/A
286N/A if (uri == defaultNamespace) {
286N/A return true;
286N/A }
286N/A
286N/A return false;
286N/A }
286N/A
286N/A /**
286N/A * @param prefix
286N/A * @param uri
286N/A * @return
286N/A */
286N/A private boolean checkUserNamespaceContext(String prefix, String uri) {
286N/A if (fNamespaceContext.userContext != null) {
286N/A String tmpURI = fNamespaceContext.userContext.getNamespaceURI(prefix);
286N/A
286N/A if ((tmpURI != null) && tmpURI.equals(uri)) {
286N/A return true;
286N/A }
286N/A }
286N/A
286N/A return false;
286N/A }
286N/A
286N/A /**
286N/A * Correct's namespaces as per requirements of isReparisingNamespace property.
286N/A */
286N/A protected void repair() {
286N/A Attribute attr = null;
286N/A Attribute attr2 = null;
286N/A ElementState currentElement = fElementStack.peek();
286N/A removeDuplicateDecls();
286N/A
286N/A for(int i=0 ; i< fAttributeCache.size();i++){
286N/A attr = (Attribute)fAttributeCache.get(i);
286N/A if((attr.prefix != null && !attr.prefix.equals("")) || (attr.uri != null && !attr.uri.equals(""))) {
286N/A correctPrefix(currentElement,attr);
286N/A }
286N/A }
286N/A
286N/A if (!isDeclared(currentElement)) {
286N/A if ((currentElement.prefix != null) &&
286N/A (currentElement.uri != null)) {
286N/A if ((!currentElement.prefix.equals("")) && (!currentElement.uri.equals(""))) {
286N/A fNamespaceDecls.add(currentElement);
286N/A }
286N/A }
286N/A }
286N/A
286N/A for(int i=0 ; i< fAttributeCache.size();i++){
286N/A attr = (Attribute)fAttributeCache.get(i);
286N/A for(int j=i+1;j<fAttributeCache.size();j++){
286N/A attr2 = (Attribute)fAttributeCache.get(j);
286N/A if(!"".equals(attr.prefix)&& !"".equals(attr2.prefix)){
286N/A correctPrefix(attr,attr2);
286N/A }
286N/A }
286N/A }
286N/A
286N/A repairNamespaceDecl(currentElement);
286N/A
286N/A int i = 0;
286N/A
286N/A for (i = 0; i < fAttributeCache.size(); i++) {
286N/A attr = (Attribute) fAttributeCache.get(i);
286N/A /* If 'attr' is an attribute and it is in no namespace(which means that prefix="", uri=""), attr's
286N/A namespace should not be redinded. See [http://www.w3.org/TR/REC-xml-names/#defaulting].
286N/A */
286N/A if (attr.prefix != null && attr.prefix.equals("") && attr.uri != null && attr.uri.equals("")){
286N/A repairNamespaceDecl(attr);
286N/A }
286N/A }
286N/A
286N/A QName qname = null;
286N/A
286N/A for (i = 0; i < fNamespaceDecls.size(); i++) {
286N/A qname = (QName) fNamespaceDecls.get(i);
286N/A
286N/A if (qname != null) {
286N/A fInternalNamespaceContext.declarePrefix(qname.prefix, qname.uri);
286N/A }
286N/A }
286N/A
286N/A for (i = 0; i < fAttributeCache.size(); i++) {
286N/A attr = (Attribute) fAttributeCache.get(i);
286N/A correctPrefix(attr, XMLStreamConstants.ATTRIBUTE);
286N/A }
286N/A }
286N/A
286N/A /*
286N/A *If element and/or attribute names in the same start or empty-element tag
286N/A *are bound to different namespace URIs and are using the same prefix then
286N/A *the element or the first occurring attribute retains the original prefix
286N/A *and the following attributes have their prefixes replaced with a new prefix
286N/A *that is bound to the namespace URIs of those attributes.
286N/A */
286N/A void correctPrefix(QName attr1, QName attr2) {
286N/A String tmpPrefix = null;
286N/A QName decl = null;
286N/A boolean done = false;
286N/A
286N/A checkForNull(attr1);
286N/A checkForNull(attr2);
286N/A
286N/A if(attr1.prefix.equals(attr2.prefix) && !(attr1.uri.equals(attr2.uri))){
286N/A
286N/A tmpPrefix = fNamespaceContext.getPrefix(attr2.uri);
286N/A
286N/A if (tmpPrefix != null) {
286N/A attr2.prefix = fSymbolTable.addSymbol(tmpPrefix);
286N/A } else {
286N/A decl = null;
286N/A for(int n=0;n<fNamespaceDecls.size();n++){
286N/A decl = (QName)fNamespaceDecls.get(n);
286N/A if(decl != null && (decl.uri == attr2.uri)){
286N/A attr2.prefix = decl.prefix;
286N/A
286N/A return;
286N/A }
286N/A }
286N/A
286N/A //No namespace mapping found , so declare prefix.
286N/A StringBuffer genPrefix = new StringBuffer("zdef");
286N/A
286N/A for (int k = 0; k < 1; k++) {
286N/A genPrefix.append(fPrefixGen.nextInt());
286N/A }
286N/A
286N/A tmpPrefix = genPrefix.toString();
286N/A tmpPrefix = fSymbolTable.addSymbol(tmpPrefix);
286N/A attr2.prefix = tmpPrefix;
286N/A
286N/A QName qname = new QName();
286N/A qname.setValues(tmpPrefix, XMLConstants.XMLNS_ATTRIBUTE, null,
286N/A attr2.uri);
286N/A fNamespaceDecls.add(qname);
286N/A }
286N/A }
286N/A }
286N/A
286N/A void checkForNull(QName attr) {
286N/A if (attr.prefix == null) attr.prefix = XMLConstants.DEFAULT_NS_PREFIX;
286N/A if (attr.uri == null) attr.uri = XMLConstants.DEFAULT_NS_PREFIX;
286N/A }
286N/A
286N/A void removeDuplicateDecls(){
286N/A QName decl1,decl2;
286N/A for(int i =0;i<fNamespaceDecls.size();i++){
286N/A decl1 = (QName)fNamespaceDecls.get(i);
286N/A if(decl1!=null) {
286N/A for(int j=i+1;j<fNamespaceDecls.size();j++){
286N/A decl2 = (QName)fNamespaceDecls.get(j);
286N/A // QName.equals relies on identity equality, so we can't use it,
286N/A // because prefixes aren't interned
286N/A if(decl2!=null && decl1.prefix.equals(decl2.prefix) && decl1.uri.equals(decl2.uri))
286N/A fNamespaceDecls.remove(j);
286N/A }
286N/A }
286N/A }
286N/A }
286N/A
286N/A /*
286N/A *If an element or attribute name is bound to a prefix and there is a namespace
286N/A *declaration that binds that prefix to a different URI then that namespace declaration
286N/A *is either removed if the correct mapping is inherited from the parent context of that element,
286N/A *or changed to the namespace URI of the element or attribute using that prefix.
286N/A *
286N/A */
286N/A void repairNamespaceDecl(QName attr) {
286N/A QName decl = null;
286N/A String tmpURI;
286N/A
286N/A //check for null prefix.
286N/A for (int j = 0; j < fNamespaceDecls.size(); j++) {
286N/A decl = (QName) fNamespaceDecls.get(j);
286N/A
286N/A if (decl != null) {
286N/A if ((attr.prefix != null) &&
286N/A (attr.prefix.equals(decl.prefix) &&
286N/A !(attr.uri.equals(decl.uri)))) {
286N/A tmpURI = fNamespaceContext.getNamespaceURI(attr.prefix);
286N/A
286N/A //see if you need to add to symbole table.
286N/A if (tmpURI != null) {
286N/A if (tmpURI.equals(attr.uri)) {
286N/A fNamespaceDecls.set(j, null);
286N/A } else {
286N/A decl.uri = attr.uri;
286N/A }
286N/A }
286N/A }
286N/A }
286N/A }
286N/A }
286N/A
286N/A boolean isDeclared(QName attr) {
286N/A QName decl = null;
286N/A
286N/A for (int n = 0; n < fNamespaceDecls.size(); n++) {
286N/A decl = (QName) fNamespaceDecls.get(n);
286N/A
286N/A if ((attr.prefix != null) &&
286N/A ((attr.prefix == decl.prefix) && (decl.uri == attr.uri))) {
286N/A return true;
286N/A }
286N/A }
286N/A
286N/A if (attr.uri != null) {
286N/A if (fNamespaceContext.getPrefix(attr.uri) != null) {
286N/A return true;
286N/A }
286N/A }
286N/A
286N/A return false;
286N/A }
286N/A
286N/A /*
286N/A * Start of Internal classes.
286N/A *
286N/A */
286N/A protected class ElementStack {
286N/A /** The stack data. */
286N/A protected ElementState[] fElements;
286N/A
286N/A /** The size of the stack. */
286N/A protected short fDepth;
286N/A
286N/A /** Default constructor. */
286N/A public ElementStack() {
286N/A fElements = new ElementState[10];
286N/A
286N/A for (int i = 0; i < fElements.length; i++) {
286N/A fElements[i] = new ElementState();
286N/A }
286N/A }
286N/A
286N/A /**
286N/A * Pushes an element on the stack.
286N/A * <p>
286N/A * <strong>Note:</strong> The QName values are copied into the
286N/A * stack. In other words, the caller does <em>not</em> orphan
286N/A * the element to the stack. Also, the QName object returned
286N/A * is <em>not</em> orphaned to the caller. It should be
286N/A * considered read-only.
286N/A *
286N/A * @param element The element to push onto the stack.
286N/A *
286N/A * @return Returns the actual QName object that stores the
286N/A */
286N/A public ElementState push(ElementState element) {
286N/A if (fDepth == fElements.length) {
286N/A ElementState[] array = new ElementState[fElements.length * 2];
286N/A System.arraycopy(fElements, 0, array, 0, fDepth);
286N/A fElements = array;
286N/A
286N/A for (int i = fDepth; i < fElements.length; i++) {
286N/A fElements[i] = new ElementState();
286N/A }
286N/A }
286N/A
286N/A fElements[fDepth].setValues(element);
286N/A
286N/A return fElements[fDepth++];
286N/A }
286N/A
286N/A /**
286N/A *
286N/A * @param prefix
286N/A * @param localpart
286N/A * @param rawname
286N/A * @param uri
286N/A * @param isEmpty
286N/A * @return
286N/A */
286N/A public ElementState push(String prefix, String localpart,
286N/A String rawname, String uri, boolean isEmpty) {
286N/A if (fDepth == fElements.length) {
286N/A ElementState[] array = new ElementState[fElements.length * 2];
286N/A System.arraycopy(fElements, 0, array, 0, fDepth);
286N/A fElements = array;
286N/A
286N/A for (int i = fDepth; i < fElements.length; i++) {
286N/A fElements[i] = new ElementState();
286N/A }
286N/A }
286N/A
286N/A fElements[fDepth].setValues(prefix, localpart, rawname, uri, isEmpty);
286N/A
286N/A return fElements[fDepth++];
286N/A }
286N/A
286N/A /**
286N/A * Pops an element off of the stack by setting the values of
286N/A * the specified QName.
286N/A * <p>
286N/A * <strong>Note:</strong> The object returned is <em>not</em>
286N/A * orphaned to the caller. Therefore, the caller should consider
286N/A * the object to be read-only.
286N/A */
286N/A public ElementState pop() {
286N/A return fElements[--fDepth];
286N/A }
286N/A
286N/A /** Clears the stack without throwing away existing QName objects. */
286N/A public void clear() {
286N/A fDepth = 0;
286N/A }
286N/A
286N/A /**
286N/A * This function is as a result of optimization done for endElement --
286N/A * we dont need to set the value for every end element we encouter.
286N/A * For Well formedness checks we can have the same QName object that was pushed.
286N/A * the values will be set only if application need to know about the endElement
286N/A * -- neeraj.bajaj@sun.com
286N/A */
286N/A public ElementState peek() {
286N/A return fElements[fDepth - 1];
286N/A }
286N/A
286N/A /**
286N/A *
286N/A * @return
286N/A */
286N/A public boolean empty() {
286N/A return (fDepth > 0) ? false : true;
286N/A }
286N/A }
286N/A
286N/A /**
286N/A * Maintains element state . localName for now.
286N/A */
286N/A class ElementState extends QName {
286N/A public boolean isEmpty = false;
286N/A
286N/A public ElementState() {}
286N/A
286N/A public ElementState(String prefix, String localpart, String rawname,
286N/A String uri) {
286N/A super(prefix, localpart, rawname, uri);
286N/A }
286N/A
286N/A public void setValues(String prefix, String localpart, String rawname,
286N/A String uri, boolean isEmpty) {
286N/A super.setValues(prefix, localpart, rawname, uri);
286N/A this.isEmpty = isEmpty;
286N/A }
286N/A }
286N/A
286N/A /**
286N/A * Attributes
286N/A */
286N/A class Attribute extends QName {
286N/A String value;
286N/A
286N/A Attribute(String value) {
286N/A super();
286N/A this.value = value;
286N/A }
286N/A }
286N/A
286N/A /**
286N/A * Implementation of NamespaceContext .
286N/A *
286N/A */
286N/A class NamespaceContextImpl implements NamespaceContext {
286N/A //root namespace context set by user.
286N/A NamespaceContext userContext = null;
286N/A
286N/A //context built by the writer.
286N/A NamespaceSupport internalContext = null;
286N/A
286N/A public String getNamespaceURI(String prefix) {
286N/A String uri = null;
286N/A
286N/A if (prefix != null) {
286N/A prefix = fSymbolTable.addSymbol(prefix);
286N/A }
286N/A
286N/A if (internalContext != null) {
286N/A uri = internalContext.getURI(prefix);
286N/A
286N/A if (uri != null) {
286N/A return uri;
286N/A }
286N/A }
286N/A
286N/A if (userContext != null) {
286N/A uri = userContext.getNamespaceURI(prefix);
286N/A
286N/A return uri;
286N/A }
286N/A
286N/A return null;
286N/A }
286N/A
286N/A public String getPrefix(String uri) {
286N/A String prefix = null;
286N/A
286N/A if (uri != null) {
286N/A uri = fSymbolTable.addSymbol(uri);
286N/A }
286N/A
286N/A if (internalContext != null) {
286N/A prefix = internalContext.getPrefix(uri);
286N/A
286N/A if (prefix != null) {
286N/A return prefix;
286N/A }
286N/A }
286N/A
286N/A if (userContext != null) {
286N/A return userContext.getPrefix(uri);
286N/A }
286N/A
286N/A return null;
286N/A }
286N/A
286N/A public java.util.Iterator getPrefixes(String uri) {
286N/A Vector prefixes = null;
286N/A Iterator itr = null;
286N/A
286N/A if (uri != null) {
286N/A uri = fSymbolTable.addSymbol(uri);
286N/A }
286N/A
286N/A if (userContext != null) {
286N/A itr = userContext.getPrefixes(uri);
286N/A }
286N/A
286N/A if (internalContext != null) {
286N/A prefixes = internalContext.getPrefixes(uri);
286N/A }
286N/A
286N/A if ((prefixes == null) && (itr != null)) {
286N/A return itr;
286N/A } else if ((prefixes != null) && (itr == null)) {
286N/A return new ReadOnlyIterator(prefixes.iterator());
286N/A } else if ((prefixes != null) && (itr != null)) {
286N/A String ob = null;
286N/A
286N/A while (itr.hasNext()) {
286N/A ob = (String) itr.next();
286N/A
286N/A if (ob != null) {
286N/A ob = fSymbolTable.addSymbol(ob);
286N/A }
286N/A
286N/A if (!prefixes.contains(ob)) {
286N/A prefixes.add(ob);
286N/A }
286N/A }
286N/A
286N/A return new ReadOnlyIterator(prefixes.iterator());
286N/A }
286N/A
286N/A return fReadOnlyIterator;
286N/A }
286N/A }
286N/A
286N/A // -- Map Interface --------------------------------------------------
286N/A
286N/A public int size() {
286N/A return 1;
286N/A }
286N/A
286N/A public boolean isEmpty() {
286N/A return false;
286N/A }
286N/A
286N/A public boolean containsKey(Object key) {
286N/A return key.equals(OUTPUTSTREAM_PROPERTY);
286N/A }
286N/A
286N/A /**
286N/A * Returns the value associated to an implementation-specific
286N/A * property.
286N/A */
286N/A public Object get(Object key) {
286N/A if (key.equals(OUTPUTSTREAM_PROPERTY)) {
286N/A return fOutputStream;
286N/A }
286N/A return null;
286N/A }
286N/A
286N/A public java.util.Set entrySet() {
286N/A throw new UnsupportedOperationException();
286N/A }
286N/A
286N/A /**
286N/A * Overrides the method defined in AbstractMap which is
286N/A * not completely implemented. Calling toString() in
286N/A * AbstractMap would cause an unsupported exection to
286N/A * be thrown.
286N/A */
286N/A public String toString() {
286N/A return getClass().getName() + "@" + Integer.toHexString(hashCode());
286N/A }
286N/A
286N/A /**
286N/A * Overrides the method defined in AbstractMap
286N/A * This is required by the toString() method
286N/A */
286N/A public int hashCode() {
286N/A return fElementStack.hashCode();
286N/A }
286N/A /**
286N/A * Overrides the method defined in AbstractMap
286N/A * This is required to satisfy the contract for hashCode.
286N/A */
286N/A public boolean equals(Object obj) {
286N/A return (this == obj);
286N/A }
286N/A}