src/share/jaxws_classes/com/sun/xml/internal/stream/buffer/stax/NamespaceContexHelper.java

Thu, 31 Aug 2017 15:18:52 +0800

author
aoqi
date
Thu, 31 Aug 2017 15:18:52 +0800
changeset 637
9c07ef4934dd
parent 368
0989ad8c0860
parent 0
373ffda63c9a
permissions
-rw-r--r--

merge

     1 /*
     2  * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    26 package com.sun.xml.internal.stream.buffer.stax;
    28 import java.util.ArrayList;
    29 import java.util.Collections;
    30 import java.util.Iterator;
    31 import java.util.List;
    32 import com.sun.xml.internal.org.jvnet.staxex.NamespaceContextEx;
    34 /**
    35  * A helper class for managing the declaration of namespaces.
    36  * <p>
    37  * A namespace is declared on a namespace context.
    38  * Namespace contexts are pushed on and popped off the namespace context stack.
    39  * <p>
    40  * A declared namespace will be in scope iff the context that it was declared on
    41  * has not been popped off the stack.
    42  * <p>
    43  * When instantiated the namespace stack consists of the root namespace context,
    44  * which contains, by default, the "xml" and "xmlns" declarations.
    45  * Namespaces may be declarations may be declared on the root context.
    46  * The root context cannot be popped but can be reset to contain just the
    47  * "xml" and "xmlns" declarations.
    48  * <p>
    49  * Implementation note: determining the prefix from a namespace URI
    50  * (or vice versa) is efficient when there are few namespace
    51  * declarations i.e. what is considered to be the case for namespace
    52  * declarations in 'average' XML documents. The look up of a namespace URI
    53  * given a prefix is performed in O(n) time. The look up of a prefix given
    54  * a namespace URI is performed in O(2n) time.
    55  * <p>
    56  * The implementation does not scale when there are many namespace
    57  * declarations. TODO: Use a hash map when there are many namespace
    58  * declarations.
    59  *
    60  * @author Paul.Sandoz@Sun.Com
    61  */
    62 final public class NamespaceContexHelper implements NamespaceContextEx {
    63     private static int DEFAULT_SIZE = 8;
    65     // The prefixes of the namespace declarations
    66     private String[] prefixes = new String[DEFAULT_SIZE];
    67     // The URIs of the namespace declarations
    68     private String[] namespaceURIs = new String[DEFAULT_SIZE];
    69     // Current position to store the next namespace declaration
    70     private int namespacePosition;
    72     // The namespace contexts
    73     private int[] contexts = new int[DEFAULT_SIZE];
    74     // Current position to store the next namespace context
    75     private int contextPosition;
    77     /**
    78      * Create a new NamespaceContexHelper.
    79      *
    80      */
    81     public NamespaceContexHelper() {
    82         // The default namespace declarations that are always in scope
    83         prefixes[0] = "xml";
    84         namespaceURIs[0] = "http://www.w3.org/XML/1998/namespace";
    85         prefixes[1] = "xmlns";
    86         namespaceURIs[1] = "http://www.w3.org/2000/xmlns/";
    88         namespacePosition = 2;
    89     }
    92     // NamespaceContext interface
    94     public String getNamespaceURI(String prefix) {
    95         if (prefix == null) throw new IllegalArgumentException();
    97         prefix = prefix.intern();
    99         for (int i = namespacePosition - 1; i >= 0; i--) {
   100             final String declaredPrefix = prefixes[i];
   101             if (declaredPrefix == prefix) {
   102                 return namespaceURIs[i];
   103             }
   104         }
   106         return "";
   107     }
   109     public String getPrefix(String namespaceURI) {
   110         if (namespaceURI == null) throw new IllegalArgumentException();
   112         for (int i = namespacePosition - 1; i >= 0; i--) {
   113             final String declaredNamespaceURI = namespaceURIs[i];
   114             if (declaredNamespaceURI == namespaceURI || declaredNamespaceURI.equals(namespaceURI)) {
   115                 final String declaredPrefix = prefixes[i];
   117                 // Check if prefix is out of scope
   118                 for (++i; i < namespacePosition; i++)
   119                     if (declaredPrefix == prefixes[i])
   120                         return null;
   122                 return declaredPrefix;
   123             }
   124         }
   126         return null;
   127     }
   129     public Iterator getPrefixes(String namespaceURI) {
   130         if (namespaceURI == null) throw new IllegalArgumentException();
   132         List<String> l = new ArrayList<String>();
   134         NAMESPACE_LOOP: for (int i = namespacePosition - 1; i >= 0; i--) {
   135             final String declaredNamespaceURI = namespaceURIs[i];
   136             if (declaredNamespaceURI == namespaceURI || declaredNamespaceURI.equals(namespaceURI)) {
   137                 final String declaredPrefix = prefixes[i];
   139                 // Check if prefix is out of scope
   140                 for (int j = i + 1; j < namespacePosition; j++)
   141                     if (declaredPrefix == prefixes[j])
   142                         continue NAMESPACE_LOOP;
   144                 l.add(declaredPrefix);
   145             }
   146         }
   148         return l.iterator();
   149     }
   151     // NamespaceContextEx interface
   153     public Iterator<NamespaceContextEx.Binding> iterator() {
   154         if (namespacePosition == 2)
   155             return Collections.EMPTY_LIST.iterator();
   157         final List<NamespaceContextEx.Binding> namespaces =
   158                 new ArrayList<NamespaceContextEx.Binding>(namespacePosition);
   160         NAMESPACE_LOOP: for (int i = namespacePosition - 1; i >= 2; i--) {
   161             final String declaredPrefix = prefixes[i];
   163             // Check if prefix is out of scope
   164             for (int j = i + 1; j < namespacePosition; j++) {
   165                 if (declaredPrefix == prefixes[j])
   166                     continue NAMESPACE_LOOP;
   168                 namespaces.add(new NamespaceBindingImpl(i));
   169             }
   170         }
   172         return namespaces.iterator();
   173     }
   175     final private class NamespaceBindingImpl implements NamespaceContextEx.Binding {
   176         int index;
   178         NamespaceBindingImpl(int index) {
   179             this.index = index;
   180         }
   182         public String getPrefix() {
   183             return prefixes[index];
   184         }
   186         public String getNamespaceURI() {
   187             return namespaceURIs[index];
   188         }
   189     }
   191     /**
   192      * Declare a default namespace.
   193      * <p>
   194      * @param namespaceURI the namespace URI to declare, may be null.
   195      */
   196     public void declareDefaultNamespace(String namespaceURI) {
   197         declareNamespace("", namespaceURI);
   198     }
   200     /**
   201      * Declare a namespace.
   202      * <p>
   203      * The namespace will be declared on the current namespace context.
   204      * <p>
   205      * The namespace can be removed by popping the current namespace
   206      * context, or, if the declaration occured in the root context, by
   207      * reseting the namespace context.
   208      * <p>
   209      * A default namespace can be declared by passing <code>""</code> as
   210      * the value of the prefix parameter.
   211      * A namespace may be undeclared by passing <code>null</code> as the
   212      * value of the namespaceURI parameter.
   213      * <p>
   214      * @param prefix the namespace prefix to declare, may not be null.
   215      * @param namespaceURI the namespace URI to declare, may be null.
   216      * @throws IllegalArgumentException, if the prefix is null.
   217      */
   218     public void declareNamespace(String prefix, String namespaceURI) {
   219         if (prefix == null) throw new IllegalArgumentException();
   221         prefix = prefix.intern();
   222         // Ignore the "xml" or "xmlns" declarations
   223         if (prefix == "xml" || prefix == "xmlns")
   224             return;
   226         // Check for undeclaration
   227         if (namespaceURI != null)
   228             namespaceURI = namespaceURI.intern();
   230         if (namespacePosition == namespaceURIs.length)
   231             resizeNamespaces();
   233         // Add new declaration
   234         prefixes[namespacePosition] = prefix;
   235         namespaceURIs[namespacePosition++] = namespaceURI;
   236     }
   238     private void resizeNamespaces() {
   239         final int newLength = namespaceURIs.length * 3 / 2 + 1;
   241         String[] newPrefixes = new String[newLength];
   242         System.arraycopy(prefixes, 0, newPrefixes, 0, prefixes.length);
   243         prefixes = newPrefixes;
   245         String[] newNamespaceURIs = new String[newLength];
   246         System.arraycopy(namespaceURIs, 0, newNamespaceURIs, 0, namespaceURIs.length);
   247         namespaceURIs = newNamespaceURIs;
   248     }
   250     /**
   251      * Push a namespace context on the stack.
   252      */
   253     public void pushContext() {
   254         if (contextPosition == contexts.length)
   255             resizeContexts();
   257         contexts[contextPosition++] = namespacePosition;
   258     }
   260     private void resizeContexts() {
   261         int[] newContexts = new int[contexts.length * 3 / 2 + 1];
   262         System.arraycopy(contexts, 0, newContexts, 0, contexts.length);
   263         contexts = newContexts;
   264     }
   266     /**
   267      * Pop the namespace context off the stack.
   268      * <p>
   269      * Namespaces declared within the context (to be popped)
   270      * will be removed and no longer be in scope.
   271      */
   272     public void popContext() {
   273         if (contextPosition > 0) {
   274             namespacePosition = contexts[--contextPosition];
   275         }
   276     }
   278     /**
   279      * Reset namespace contexts.
   280      * <p>
   281      * Pop all namespace contexts and reset the root context.
   282      */
   283     public void resetContexts() {
   284         namespacePosition = 2;
   285     }
   286 }

mercurial