1 /* 2 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. 3 * @LastModified: Oct 2017 4 */ 5 /* 6 * Licensed to the Apache Software Foundation (ASF) under one or more 7 * contributor license agreements. See the NOTICE file distributed with 8 * this work for additional information regarding copyright ownership. 9 * The ASF licenses this file to You under the Apache License, Version 2.0 10 * (the "License"); you may not use this file except in compliance with 11 * the License. You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 */ 21 22 package com.sun.org.apache.xerces.internal.xinclude; 23 24 import com.sun.org.apache.xerces.internal.util.NamespaceSupport; 25 import com.sun.org.apache.xerces.internal.util.XMLSymbols; 26 import com.sun.org.apache.xerces.internal.xni.NamespaceContext; 27 import java.util.Enumeration; 28 29 /** 30 * This implementation of NamespaceContext has the ability to maintain multiple 31 * scopes of namespace/prefix bindings. This is useful in situations when it is 32 * not always appropriate for elements to inherit the namespace bindings of their 33 * ancestors (such as included elements in XInclude). 34 * 35 * When searching for a URI to match a prefix, or a prefix to match a URI, it is 36 * searched for in the current context, then the ancestors of the current context, 37 * up to the beginning of the current scope. Other scopes are not searched. 38 * 39 * @author Peter McCracken, IBM 40 * 41 */ 42 public class MultipleScopeNamespaceSupport extends NamespaceSupport { 43 44 protected int[] fScope = new int[8]; 45 protected int fCurrentScope; 46 47 /** 48 * 49 */ 50 public MultipleScopeNamespaceSupport() { 51 super(); 52 fCurrentScope = 0; 53 fScope[0] = 0; 54 } 55 56 /** 57 * @param context 58 */ 59 public MultipleScopeNamespaceSupport(NamespaceContext context) { 60 super(context); 61 fCurrentScope = 0; 62 fScope[0] = 0; 63 } 64 65 /* (non-Javadoc) 66 * @see com.sun.org.apache.xerces.internal.xni.NamespaceContext#getAllPrefixes() 67 */ 68 public Enumeration<String> getAllPrefixes() { 69 int count = 0; 70 if (fPrefixes.length < (fNamespace.length / 2)) { 71 // resize prefix array 72 String[] prefixes = new String[fNamespaceSize]; 73 fPrefixes = prefixes; 74 } 75 String prefix = null; 76 boolean unique = true; 77 for (int i = fContext[fScope[fCurrentScope]]; 78 i <= (fNamespaceSize - 2); 79 i += 2) { 80 prefix = fNamespace[i]; 81 for (int k = 0; k < count; k++) { 82 if (fPrefixes[k] == prefix) { 83 unique = false; 84 break; 85 } 86 } 87 if (unique) { 88 fPrefixes[count++] = prefix; 89 } 90 unique = true; 91 } 92 return new Prefixes(fPrefixes, count); 93 } 94 95 public int getScopeForContext(int context) { 96 int scope = fCurrentScope; 97 while (context < fScope[scope]) { 98 scope--; 99 } 100 return scope; 101 } 102 103 /* (non-Javadoc) 104 * @see com.sun.org.apache.xerces.internal.xni.NamespaceContext#getPrefix(java.lang.String) 105 */ 106 public String getPrefix(String uri) { 107 return getPrefix(uri, fNamespaceSize, fContext[fScope[fCurrentScope]]); 108 } 109 110 /* (non-Javadoc) 111 * @see com.sun.org.apache.xerces.internal.xni.NamespaceContext#getURI(java.lang.String) 112 */ 113 public String getURI(String prefix) { 114 return getURI(prefix, fNamespaceSize, fContext[fScope[fCurrentScope]]); 115 } 116 117 public String getPrefix(String uri, int context) { 118 return getPrefix(uri, fContext[context+1], fContext[fScope[getScopeForContext(context)]]); 119 } 120 121 public String getURI(String prefix, int context) { 122 return getURI(prefix, fContext[context+1], fContext[fScope[getScopeForContext(context)]]); 123 } 124 125 public String getPrefix(String uri, int start, int end) { 126 // this saves us from having a copy of each of these in fNamespace for each scope 127 if (uri == NamespaceContext.XML_URI) { 128 return XMLSymbols.PREFIX_XML; 129 } 130 if (uri == NamespaceContext.XMLNS_URI) { 131 return XMLSymbols.PREFIX_XMLNS; 132 } 133 134 // find uri in current context 135 for (int i = start; i > end; i -= 2) { 136 if (fNamespace[i - 1] == uri) { 137 if (getURI(fNamespace[i - 2]) == uri) 138 return fNamespace[i - 2]; 139 } 140 } 141 142 // uri not found 143 return null; 144 } 145 146 public String getURI(String prefix, int start, int end) { 147 // this saves us from having a copy of each of these in fNamespace for each scope 148 if (prefix == XMLSymbols.PREFIX_XML) { 149 return NamespaceContext.XML_URI; 150 } 151 if (prefix == XMLSymbols.PREFIX_XMLNS) { 152 return NamespaceContext.XMLNS_URI; 153 } 154 155 // find prefix in current context 156 for (int i = start; i > end; i -= 2) { 157 if (fNamespace[i - 2] == prefix) { 158 return fNamespace[i - 1]; 159 } 160 } 161 162 // prefix not found 163 return null; 164 } 165 166 /** 167 * Only resets the current scope -- all namespaces defined in lower scopes 168 * remain valid after a call to reset. 169 */ 170 public void reset() { 171 fCurrentContext = fScope[fCurrentScope]; 172 fNamespaceSize = fContext[fCurrentContext]; 173 } 174 175 /** 176 * Begins a new scope. None of the previous namespace bindings will be used, 177 * until the new scope is popped with popScope() 178 */ 179 public void pushScope() { 180 if (fCurrentScope + 1 == fScope.length) { 181 int[] contextarray = new int[fScope.length * 2]; 182 System.arraycopy(fScope, 0, contextarray, 0, fScope.length); 183 fScope = contextarray; 184 } 185 pushContext(); 186 fScope[++fCurrentScope] = fCurrentContext; 187 } 188 189 /** 190 * Pops the current scope. The namespace bindings from the new current scope 191 * are then used for searching for namespaces and prefixes. 192 */ 193 public void popScope() { 194 fCurrentContext = fScope[fCurrentScope--]; 195 popContext(); 196 } 197 }