| /* |
| * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| * |
| * THIS FILE WAS MODIFIED BY SUN MICROSYSTEMS, INC. |
| */ |
| |
| package com.sun.xml.internal.fastinfoset.sax; |
| |
| import com.sun.xml.internal.fastinfoset.EncodingConstants; |
| import com.sun.xml.internal.fastinfoset.QualifiedName; |
| import com.sun.xml.internal.fastinfoset.util.KeyIntMap; |
| import com.sun.xml.internal.fastinfoset.util.LocalNameQualifiedNamesMap; |
| import com.sun.xml.internal.fastinfoset.util.StringIntMap; |
| import java.io.IOException; |
| import java.util.HashMap; |
| import org.xml.sax.SAXException; |
| import java.util.Map; |
| import com.sun.xml.internal.org.jvnet.fastinfoset.FastInfosetException; |
| import com.sun.xml.internal.org.jvnet.fastinfoset.RestrictedAlphabet; |
| import com.sun.xml.internal.org.jvnet.fastinfoset.sax.EncodingAlgorithmAttributes; |
| import org.xml.sax.Attributes; |
| |
| /** |
| * The Fast Infoset SAX serializer that maps prefixes to user specified prefixes |
| * that are specified in a namespace URI to prefix map. |
| * <p> |
| * This serializer will not preserve the original prefixes and this serializer |
| * should not be used when prefixes need to be preserved, such as the case |
| * when there are qualified names in content. |
| * <p> |
| * A namespace URI to prefix map is utilized such that the prefixes |
| * in the map are utilized rather than the prefixes specified in |
| * the qualified name for elements and attributes. |
| * <p> |
| * Any namespace declarations with a namespace URI that is not present in |
| * the map are added. |
| * <p> |
| */ |
| public class SAXDocumentSerializerWithPrefixMapping extends SAXDocumentSerializer { |
| protected Map _namespaceToPrefixMapping; |
| protected Map _prefixToPrefixMapping; |
| protected String _lastCheckedNamespace; |
| protected String _lastCheckedPrefix; |
| |
| protected StringIntMap _declaredNamespaces; |
| |
| public SAXDocumentSerializerWithPrefixMapping(Map namespaceToPrefixMapping) { |
| // Use the local name to look up elements/attributes |
| super(true); |
| _namespaceToPrefixMapping = new HashMap(namespaceToPrefixMapping); |
| _prefixToPrefixMapping = new HashMap(); |
| |
| // Empty prefix |
| _namespaceToPrefixMapping.put("", ""); |
| // 'xml' prefix |
| _namespaceToPrefixMapping.put(EncodingConstants.XML_NAMESPACE_NAME, EncodingConstants.XML_NAMESPACE_PREFIX); |
| |
| _declaredNamespaces = new StringIntMap(4); |
| } |
| |
| public final void startPrefixMapping(String prefix, String uri) throws SAXException { |
| try { |
| if (_elementHasNamespaces == false) { |
| encodeTermination(); |
| |
| // Mark the current buffer position to flag attributes if necessary |
| mark(); |
| _elementHasNamespaces = true; |
| |
| // Write out Element byte with namespaces |
| write(EncodingConstants.ELEMENT | EncodingConstants.ELEMENT_NAMESPACES_FLAG); |
| |
| _declaredNamespaces.clear(); |
| _declaredNamespaces.obtainIndex(uri); |
| } else { |
| if (_declaredNamespaces.obtainIndex(uri) != KeyIntMap.NOT_PRESENT) { |
| final String p = getPrefix(uri); |
| if (p != null) { |
| _prefixToPrefixMapping.put(prefix, p); |
| } |
| return; |
| } |
| } |
| |
| final String p = getPrefix(uri); |
| if (p != null) { |
| encodeNamespaceAttribute(p, uri); |
| _prefixToPrefixMapping.put(prefix, p); |
| } else { |
| putPrefix(uri, prefix); |
| encodeNamespaceAttribute(prefix, uri); |
| } |
| |
| } catch (IOException e) { |
| throw new SAXException("startElement", e); |
| } |
| } |
| |
| protected final void encodeElement(String namespaceURI, String qName, String localName) throws IOException { |
| LocalNameQualifiedNamesMap.Entry entry = _v.elementName.obtainEntry(localName); |
| if (entry._valueIndex > 0) { |
| if (encodeElementMapEntry(entry, namespaceURI)) return; |
| // Check the entry is a member of the read only map |
| if (_v.elementName.isQNameFromReadOnlyMap(entry._value[0])) { |
| entry = _v.elementName.obtainDynamicEntry(localName); |
| if (entry._valueIndex > 0) { |
| if (encodeElementMapEntry(entry, namespaceURI)) return; |
| } |
| } |
| } |
| |
| encodeLiteralElementQualifiedNameOnThirdBit(namespaceURI, getPrefix(namespaceURI), |
| localName, entry); |
| } |
| |
| protected boolean encodeElementMapEntry(LocalNameQualifiedNamesMap.Entry entry, String namespaceURI) throws IOException { |
| QualifiedName[] names = entry._value; |
| for (int i = 0; i < entry._valueIndex; i++) { |
| if ((namespaceURI == names[i].namespaceName || namespaceURI.equals(names[i].namespaceName))) { |
| encodeNonZeroIntegerOnThirdBit(names[i].index); |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| |
| protected final void encodeAttributes(Attributes atts) throws IOException, FastInfosetException { |
| boolean addToTable; |
| boolean mustToBeAddedToTable; |
| String value; |
| if (atts instanceof EncodingAlgorithmAttributes) { |
| final EncodingAlgorithmAttributes eAtts = (EncodingAlgorithmAttributes)atts; |
| Object data; |
| String alphabet; |
| for (int i = 0; i < eAtts.getLength(); i++) { |
| final String uri = atts.getURI(i); |
| if (encodeAttribute(uri, atts.getQName(i), atts.getLocalName(i))) { |
| data = eAtts.getAlgorithmData(i); |
| // If data is null then there is no algorithm data |
| if (data == null) { |
| value = eAtts.getValue(i); |
| addToTable = isAttributeValueLengthMatchesLimit(value.length()); |
| mustToBeAddedToTable = eAtts.getToIndex(i); |
| alphabet = eAtts.getAlpababet(i); |
| if (alphabet == null) { |
| if (uri == "http://www.w3.org/2001/XMLSchema-instance" || |
| uri.equals("http://www.w3.org/2001/XMLSchema-instance")) { |
| value = convertQName(value); |
| } |
| encodeNonIdentifyingStringOnFirstBit(value, _v.attributeValue, addToTable, mustToBeAddedToTable); |
| } else if (alphabet == RestrictedAlphabet.DATE_TIME_CHARACTERS) { |
| encodeDateTimeNonIdentifyingStringOnFirstBit( |
| value, addToTable, mustToBeAddedToTable); |
| } else if (alphabet == RestrictedAlphabet.NUMERIC_CHARACTERS) { |
| encodeNumericNonIdentifyingStringOnFirstBit( |
| value, addToTable, mustToBeAddedToTable); |
| } else { |
| encodeNonIdentifyingStringOnFirstBit(value, _v.attributeValue, addToTable, mustToBeAddedToTable); |
| } |
| } else { |
| encodeNonIdentifyingStringOnFirstBit(eAtts.getAlgorithmURI(i), |
| eAtts.getAlgorithmIndex(i), data); |
| } |
| } |
| } |
| } else { |
| for (int i = 0; i < atts.getLength(); i++) { |
| final String uri = atts.getURI(i); |
| if (encodeAttribute(atts.getURI(i), atts.getQName(i), atts.getLocalName(i))) { |
| value = atts.getValue(i); |
| addToTable = isAttributeValueLengthMatchesLimit(value.length()); |
| |
| if (uri == "http://www.w3.org/2001/XMLSchema-instance" || |
| uri.equals("http://www.w3.org/2001/XMLSchema-instance")) { |
| value = convertQName(value); |
| } |
| encodeNonIdentifyingStringOnFirstBit(value, _v.attributeValue, addToTable, false); |
| } |
| } |
| } |
| _b = EncodingConstants.TERMINATOR; |
| _terminate = true; |
| } |
| |
| private String convertQName(String qName) { |
| int i = qName.indexOf(':'); |
| String prefix = ""; |
| String localName = qName; |
| if (i != -1) { |
| prefix = qName.substring(0, i); |
| localName = qName.substring(i + 1); |
| } |
| |
| String p = (String)_prefixToPrefixMapping.get(prefix); |
| if (p != null) { |
| if (p.length() == 0) |
| return localName; |
| else |
| return p + ":" + localName; |
| } else { |
| return qName; |
| } |
| } |
| |
| protected final boolean encodeAttribute(String namespaceURI, String qName, String localName) throws IOException { |
| LocalNameQualifiedNamesMap.Entry entry = _v.attributeName.obtainEntry(localName); |
| if (entry._valueIndex > 0) { |
| if (encodeAttributeMapEntry(entry, namespaceURI)) return true; |
| // Check the entry is a member of the read only map |
| if (_v.attributeName.isQNameFromReadOnlyMap(entry._value[0])) { |
| entry = _v.attributeName.obtainDynamicEntry(localName); |
| if (entry._valueIndex > 0) { |
| if (encodeAttributeMapEntry(entry, namespaceURI)) return true; |
| } |
| } |
| } |
| |
| return encodeLiteralAttributeQualifiedNameOnSecondBit(namespaceURI, getPrefix(namespaceURI), |
| localName, entry); |
| } |
| |
| protected boolean encodeAttributeMapEntry(LocalNameQualifiedNamesMap.Entry entry, String namespaceURI) throws IOException { |
| QualifiedName[] names = entry._value; |
| for (int i = 0; i < entry._valueIndex; i++) { |
| if ((namespaceURI == names[i].namespaceName || namespaceURI.equals(names[i].namespaceName))) { |
| encodeNonZeroIntegerOnSecondBitFirstBitZero(names[i].index); |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| protected final String getPrefix(String namespaceURI) { |
| if (_lastCheckedNamespace == namespaceURI) return _lastCheckedPrefix; |
| |
| _lastCheckedNamespace = namespaceURI; |
| return _lastCheckedPrefix = (String)_namespaceToPrefixMapping.get(namespaceURI); |
| } |
| |
| protected final void putPrefix(String namespaceURI, String prefix) { |
| _namespaceToPrefixMapping.put(namespaceURI, prefix); |
| |
| _lastCheckedNamespace = namespaceURI; |
| _lastCheckedPrefix = prefix; |
| } |
| } |