--- old/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/runtime/output/NamespaceContextImpl.java 2018-01-30 20:33:40.000000000 -0500 +++ /dev/null 2018-01-30 20:33:40.000000000 -0500 @@ -1,559 +0,0 @@ -/* - * Copyright (c) 1997, 2015, 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. - */ - -package com.sun.xml.internal.bind.v2.runtime.output; - -import java.io.IOException; -import java.util.Collections; -import java.util.Iterator; - -import javax.xml.XMLConstants; -import javax.xml.stream.XMLStreamException; - -import com.sun.istack.internal.NotNull; -import com.sun.istack.internal.Nullable; -import com.sun.xml.internal.bind.marshaller.NamespacePrefixMapper; -import com.sun.xml.internal.bind.v2.WellKnownNamespace; -import com.sun.xml.internal.bind.v2.runtime.Name; -import com.sun.xml.internal.bind.v2.runtime.NamespaceContext2; -import com.sun.xml.internal.bind.v2.runtime.XMLSerializer; - -import org.xml.sax.SAXException; - -/** - * Keeps track of in-scope namespace bindings for the marshaller. - * - *
- * This class is also used to keep track of tag names for each element - * for the marshaller (for the performance reason.) - * - * @author Kohsuke Kawaguchi - */ -public final class NamespaceContextImpl implements NamespaceContext2 { - private final XMLSerializer owner; - - private String[] prefixes = new String[4]; - private String[] nsUris = new String[4]; -// /** -// * True if the correponding namespace declaration is an authentic one that should be printed. -// * -// * False if it's a re-discovered in-scope namespace binding available at the ancestor elements -// * outside this marhsalling. The false value is used to incorporate the in-scope namespace binding -// * information from {@link #inscopeNamespaceContext}. When false, such a declaration does not need -// * to be printed, as it's already available in ancestors. -// */ -// private boolean[] visible = new boolean[4]; -// -// /** -// * {@link NamespaceContext} that informs this {@link XMLSerializer} about the -// * in-scope namespace bindings of the ancestor elements outside this marshalling. -// * -// *
-// * This is used when the marshaller is marshalling into a subtree that has ancestor -// * elements created outside the JAXB marshaller. -// * -// * Its {@link NamespaceContext#getPrefix(String)} is used to discover in-scope namespace -// * binding, -// */ -// private final NamespaceContext inscopeNamespaceContext; - - /** - * Number of URIs declared. Identifies the valid portion of - * the {@link #prefixes} and {@link #nsUris} arrays. - */ - private int size; - - private Element current; - - /** - * This is the {@link Element} whose prev==null. - * This element is used to hold the contextual namespace bindings - * that are assumed to be outside of the document we are marshalling. - * Specifically the xml prefix and any other user-specified bindings. - * - * @see NamespacePrefixMapper#getPreDeclaredNamespaceUris() - */ - private final Element top; - - /** - * Never null. - */ - private NamespacePrefixMapper prefixMapper = defaultNamespacePrefixMapper; - - /** - * True to allow new URIs to be declared. False otherwise. - */ - public boolean collectionMode; - - - public NamespaceContextImpl(XMLSerializer owner) { - this.owner = owner; - - current = top = new Element(this,null); - // register namespace URIs that are implicitly bound - put(XMLConstants.XML_NS_URI,XMLConstants.XML_NS_PREFIX); - } - - public void setPrefixMapper( NamespacePrefixMapper mapper ) { - if(mapper==null) - mapper = defaultNamespacePrefixMapper; - this.prefixMapper = mapper; - } - - public NamespacePrefixMapper getPrefixMapper() { - return prefixMapper; - } - - public void reset() { - current = top; - size = 1; - collectionMode = false; - } - - /** - * Returns the prefix index to the specified URI. - * This method allocates a new URI if necessary. - */ - public int declareNsUri( String uri, String preferedPrefix, boolean requirePrefix ) { - preferedPrefix = prefixMapper.getPreferredPrefix(uri,preferedPrefix,requirePrefix); - - if(uri.length()==0) { - for( int i=size-1; i>=0; i-- ) { - if(nsUris[i].length()==0) - return i; // already declared - if(prefixes[i].length()==0) { - // the default prefix is already taken. - // move that URI to another prefix, then assign "" to the default prefix. - assert current.defaultPrefixIndex==-1 && current.oldDefaultNamespaceUriIndex==-1; - - String oldUri = nsUris[i]; - String[] knownURIs = owner.nameList.namespaceURIs; - - if(current.baseIndex<=i) { - // this default prefix is declared in this context. just reassign it - - nsUris[i] = ""; - - int subst = put(oldUri,null); - - // update uri->prefix table if necessary - for( int j=knownURIs.length-1; j>=0; j-- ) { - if(knownURIs[j].equals(oldUri)) { - owner.knownUri2prefixIndexMap[j] = subst; - break; - } - } - if (current.elementLocalName != null) { - current.setTagName(subst, current.elementLocalName, current.getOuterPeer()); - } - return i; - } else { - // first, if the previous URI assigned to "" is - // a "known URI", remember what we've reallocated - // so that we can fix it when this context pops. - for( int j=knownURIs.length-1; j>=0; j-- ) { - if(knownURIs[j].equals(oldUri)) { - current.defaultPrefixIndex = i; - current.oldDefaultNamespaceUriIndex = j; - // assert commented out; too strict/not valid any more - // assert owner.knownUri2prefixIndexMap[j]==current.defaultPrefixIndex; - // update the table to point to the prefix we'll declare - owner.knownUri2prefixIndexMap[j] = size; - break; - } - } - if (current.elementLocalName!=null) { - current.setTagName(size, current.elementLocalName, current.getOuterPeer()); - } - - put(nsUris[i],null); - return put("", ""); - } - } - } - - // "" isn't in use - return put("", ""); - } else { - // check for the existing binding - for( int i=size-1; i>=0; i-- ) { - String p = prefixes[i]; - if(nsUris[i].equals(uri)) { - if (!requirePrefix || p.length()>0) - return i; - // declared but this URI is bound to empty. Look further - } - if(p.equals(preferedPrefix)) { - // the suggested prefix is already taken. can't use it - preferedPrefix = null; - } - } - - if(preferedPrefix==null && requirePrefix) - // we know we can't bind to "", but we don't have any possible name at hand. - // generate it here to avoid this namespace to be bound to "". - preferedPrefix = makeUniquePrefix(); - - // haven't been declared. allocate a new one - // if the preferred prefix is already in use, it should have been set to null by this time - return put(uri, preferedPrefix); - } - } - - public int force(@NotNull String uri, @NotNull String prefix) { - // check for the existing binding - - for( int i=size-1; i>=0; i-- ) { - if(prefixes[i].equals(prefix)) { - if(nsUris[i].equals(uri)) - return i; // found duplicate - else - // the prefix is used for another namespace. we need to declare it - break; - } - } - - return put(uri, prefix); - } - - /** - * Puts this new binding into the declared prefixes list - * without doing any duplicate check. - * - * This can be used to forcibly set namespace declarations. - * - *
- * Most of the time {@link #declareNamespace(String, String, boolean)} shall be used.
- *
- * @return
- * the index of this new binding.
- */
- public int put(@NotNull String uri, @Nullable String prefix) {
- if(size==nsUris.length) {
- // reallocate
- String[] u = new String[nsUris.length*2];
- String[] p = new String[prefixes.length*2];
- System.arraycopy(nsUris,0,u,0,nsUris.length);
- System.arraycopy(prefixes,0,p,0,prefixes.length);
- nsUris = u;
- prefixes = p;
- }
- if(prefix==null) {
- if(size==1)
- prefix = ""; // if this is the first user namespace URI we see, use "".
- else {
- // otherwise make up an unique name
- prefix = makeUniquePrefix();
- }
- }
- nsUris[size] = uri;
- prefixes[size] = prefix;
-
- return size++;
- }
-
- private String makeUniquePrefix() {
- String prefix;
- prefix = new StringBuilder(5).append("ns").append(size).toString();
- while(getNamespaceURI(prefix)!=null) {
- prefix += '_'; // under a rare circumstance there might be existing 'nsNNN', so rename them
- }
- return prefix;
- }
-
-
- public Element getCurrent() {
- return current;
- }
-
- /**
- * Returns the prefix index of the specified URI.
- * It is an error if the URI is not declared.
- */
- public int getPrefixIndex( String uri ) {
- for( int i=size-1; i>=0; i-- ) {
- if(nsUris[i].equals(uri))
- return i;
- }
- throw new IllegalStateException();
- }
-
- /**
- * Gets the prefix from a prefix index.
- *
- * The behavior is undefined if the index is out of range.
- */
- public String getPrefix(int prefixIndex) {
- return prefixes[prefixIndex];
- }
-
- public String getNamespaceURI(int prefixIndex) {
- return nsUris[prefixIndex];
- }
-
- /**
- * Gets the namespace URI that is bound to the specified prefix.
- *
- * @return null
- * if the prefix is unbound.
- */
- public String getNamespaceURI(String prefix) {
- for( int i=size-1; i>=0; i-- )
- if(prefixes[i].equals(prefix))
- return nsUris[i];
- return null;
- }
-
- /**
- * Returns the prefix of the specified URI,
- * or null if none exists.
- */
- public String getPrefix( String uri ) {
- if(collectionMode) {
- return declareNamespace(uri,null,false);
- } else {
- for( int i=size-1; i>=0; i-- )
- if(nsUris[i].equals(uri))
- return prefixes[i];
- return null;
- }
- }
-
- public Iterator
- *
- */
- public final class Element {
-
- public final NamespaceContextImpl context;
-
- /**
- * {@link Element}s form a doubly-linked list.
- */
- private final Element prev;
- private Element next;
-
- private int oldDefaultNamespaceUriIndex;
- private int defaultPrefixIndex;
-
-
- /**
- * The numbe of prefixes declared by ancestor {@link Element}s.
- */
- private int baseIndex;
-
- /**
- * The depth of the {@link Element}.
- *
- * This value is equivalent as the result of the following computation.
- *
- *
- * int depth() {
- * int i=-1;
- * for(Element e=this; e!=null;e=e.prev)
- * i++;
- * return i;
- * }
- *
- */
- private final int depth;
-
-
-
- private int elementNamePrefix;
- private String elementLocalName;
-
- /**
- * Tag name of this element.
- * Either this field is used or the {@link #elementNamePrefix} and {@link #elementLocalName} pair.
- */
- private Name elementName;
-
- /**
- * Used for the binder. The JAXB object that corresponds to this element.
- */
- private Object outerPeer;
- private Object innerPeer;
-
-
- private Element(NamespaceContextImpl context,Element prev) {
- this.context = context;
- this.prev = prev;
- this.depth = (prev==null) ? 0 : prev.depth+1;
- }
-
- /**
- * Returns true if this {@link Element} represents the root element that
- * we are marshalling.
- */
- public boolean isRootElement() {
- return depth==1;
- }
-
- public Element push() {
- if(next==null)
- next = new Element(context,this);
- next.onPushed();
- return next;
- }
-
- public Element pop() {
- if(oldDefaultNamespaceUriIndex>=0) {
- // restore the old default namespace URI binding
- context.owner.knownUri2prefixIndexMap[oldDefaultNamespaceUriIndex] = defaultPrefixIndex;
- }
- context.size = baseIndex;
- context.current = prev;
- // release references to user objects
- outerPeer = innerPeer = null;
- return prev;
- }
-
- private void onPushed() {
- oldDefaultNamespaceUriIndex = defaultPrefixIndex = -1;
- baseIndex = context.size;
- context.current = this;
- }
-
- public void setTagName( int prefix, String localName, Object outerPeer ) {
- assert localName!=null;
- this.elementNamePrefix = prefix;
- this.elementLocalName = localName;
- this.elementName = null;
- this.outerPeer = outerPeer;
- }
-
- public void setTagName( Name tagName, Object outerPeer ) {
- assert tagName!=null;
- this.elementName = tagName;
- this.outerPeer = outerPeer;
- }
-
- public void startElement(XmlOutput out, Object innerPeer) throws IOException, XMLStreamException {
- this.innerPeer = innerPeer;
- if(elementName!=null) {
- out.beginStartTag(elementName);
- } else {
- out.beginStartTag(elementNamePrefix,elementLocalName);
- }
- }
-
- public void endElement(XmlOutput out) throws IOException, SAXException, XMLStreamException {
- if(elementName!=null) {
- out.endTag(elementName);
- elementName = null;
- } else {
- out.endTag(elementNamePrefix,elementLocalName);
- }
- }
-
- /**
- * Gets the number of bindings declared on this element.
- */
- public final int count() {
- return context.size-baseIndex;
- }
-
- /**
- * Gets the prefix declared in this context.
- *
- * @param idx
- * between 0 and {@link #count()}
- */
- public final String getPrefix(int idx) {
- return context.prefixes[baseIndex+idx];
- }
-
- /**
- * Gets the namespace URI declared in this context.
- *
- * @param idx
- * between 0 and {@link #count()}
- */
- public final String getNsUri(int idx) {
- return context.nsUris[baseIndex+idx];
- }
-
- public int getBase() {
- return baseIndex;
- }
-
- public Object getOuterPeer() {
- return outerPeer;
- }
-
- public Object getInnerPeer() {
- return innerPeer;
- }
-
- /**
- * Gets the parent {@link Element}.
- */
- public Element getParent() {
- return prev;
- }
- }
-
-
- /**
- * Default {@link NamespacePrefixMapper} implementation used when
- * it is not specified by the user.
- */
- private static final NamespacePrefixMapper defaultNamespacePrefixMapper = new NamespacePrefixMapper() {
- public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) {
- if( namespaceUri.equals(WellKnownNamespace.XML_SCHEMA_INSTANCE) )
- return "xsi";
- if( namespaceUri.equals(WellKnownNamespace.XML_SCHEMA) )
- return "xs";
- if( namespaceUri.equals(WellKnownNamespace.XML_MIME_URI) )
- return "xmime";
- return suggestion;
- }
- };
-}