1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 /* 19 * $Id: $ 20 */ 21 22 package org.apache.xml.serializer.dom3; 23 24 import java.util.Enumeration; 25 import java.util.NoSuchElementException; 26 27 /** 28 * Namespace support for XML document handlers. This class doesn't 29 * perform any error checking and assumes that all strings passed 30 * as arguments to methods are unique symbols. The SymbolTable class 31 * can be used for this purpose. 32 * 33 * Derived from org.apache.xerces.util.NamespaceSupport 34 * 35 * @author Andy Clark, IBM 36 * 37 * @version $Id: Exp $ 38 */ 39 public class NamespaceSupport { 40 41 static final String PREFIX_XML = "xml".intern(); 42 43 static final String PREFIX_XMLNS = "xmlns".intern(); 44 45 /** 46 * The XML Namespace ("http://www.w3.org/XML/1998/namespace"). This is 47 * the Namespace URI that is automatically mapped to the "xml" prefix. 48 */ 49 public final static String XML_URI = "http://www.w3.org/XML/1998/namespace".intern(); 50 51 /** 52 * XML Information Set REC 53 * all namespace attributes (including those named xmlns, 54 * whose [prefix] property has no value) have a namespace URI of http://www.w3.org/2000/xmlns/ 55 */ 56 public final static String XMLNS_URI = "http://www.w3.org/2000/xmlns/".intern(); 57 58 // 59 // Data 60 // 61 62 /** 63 * Namespace binding information. This array is composed of a 64 * series of tuples containing the namespace binding information: 65 * <prefix, uri>. The default size can be set to anything 66 * as long as it is a power of 2 greater than 1. 67 * 68 * @see #fNamespaceSize 69 * @see #fContext 70 */ 71 protected String[] fNamespace = new String[16 * 2]; 72 73 /** The top of the namespace information array. */ 74 protected int fNamespaceSize; 75 76 // NOTE: The constructor depends on the initial context size 77 // being at least 1. -Ac 78 79 /** 80 * Context indexes. This array contains indexes into the namespace 81 * information array. The index at the current context is the start 82 * index of declared namespace bindings and runs to the size of the 83 * namespace information array. 84 * 85 * @see #fNamespaceSize 86 */ 87 protected int[] fContext = new int[8]; 88 89 /** The current context. */ 90 protected int fCurrentContext; 91 92 protected String[] fPrefixes = new String[16]; 93 94 // 95 // Constructors 96 // 97 98 /** Default constructor. */ 99 public NamespaceSupport() { 100 } // <init>() 101 102 // 103 // Public methods 104 // 105 106 /** 107 * @see org.apache.xerces.xni.NamespaceContext#reset() 108 */ 109 public void reset() { 110 111 // reset namespace and context info 112 fNamespaceSize = 0; 113 fCurrentContext = 0; 114 fContext[fCurrentContext] = fNamespaceSize; 115 116 // bind "xml" prefix to the XML uri 117 fNamespace[fNamespaceSize++] = PREFIX_XML; 118 fNamespace[fNamespaceSize++] = XML_URI; 119 // bind "xmlns" prefix to the XMLNS uri 120 fNamespace[fNamespaceSize++] = PREFIX_XMLNS; 121 fNamespace[fNamespaceSize++] = XMLNS_URI; 122 ++fCurrentContext; 123 124 } // reset(SymbolTable) 125 126 127 /** 128 * @see org.apache.xerces.xni.NamespaceContext#pushContext() 129 */ 130 public void pushContext() { 131 132 // extend the array, if necessary 133 if (fCurrentContext + 1 == fContext.length) { 134 int[] contextarray = new int[fContext.length * 2]; 135 System.arraycopy(fContext, 0, contextarray, 0, fContext.length); 136 fContext = contextarray; 137 } 138 139 // push context 140 fContext[++fCurrentContext] = fNamespaceSize; 141 142 } // pushContext() 143 144 145 /** 146 * @see org.apache.xerces.xni.NamespaceContext#popContext() 147 */ 148 public void popContext() { 149 fNamespaceSize = fContext[fCurrentContext--]; 150 } // popContext() 151 152 /** 153 * @see org.apache.xerces.xni.NamespaceContext#declarePrefix(String, String) 154 */ 155 public boolean declarePrefix(String prefix, String uri) { 156 // ignore "xml" and "xmlns" prefixes 157 if (prefix == PREFIX_XML || prefix == PREFIX_XMLNS) { 158 return false; 159 } 160 161 // see if prefix already exists in current context 162 for (int i = fNamespaceSize; i > fContext[fCurrentContext]; i -= 2) { 163 //if (fNamespace[i - 2] == prefix) { 164 if (fNamespace[i - 2].equals(prefix) ) { 165 // REVISIT: [Q] Should the new binding override the 166 // previously declared binding or should it 167 // it be ignored? -Ac 168 // NOTE: The SAX2 "NamespaceSupport" helper allows 169 // re-bindings with the new binding overwriting 170 // the previous binding. -Ac 171 fNamespace[i - 1] = uri; 172 return true; 173 } 174 } 175 176 // resize array, if needed 177 if (fNamespaceSize == fNamespace.length) { 178 String[] namespacearray = new String[fNamespaceSize * 2]; 179 System.arraycopy(fNamespace, 0, namespacearray, 0, fNamespaceSize); 180 fNamespace = namespacearray; 181 } 182 183 // bind prefix to uri in current context 184 fNamespace[fNamespaceSize++] = prefix; 185 fNamespace[fNamespaceSize++] = uri; 186 187 return true; 188 189 } // declarePrefix(String,String):boolean 190 191 /** 192 * @see org.apache.xerces.xni.NamespaceContext#getURI(String) 193 */ 194 public String getURI(String prefix) { 195 196 // find prefix in current context 197 for (int i = fNamespaceSize; i > 0; i -= 2) { 198 //if (fNamespace[i - 2] == prefix) { 199 if (fNamespace[i - 2].equals(prefix) ) { 200 return fNamespace[i - 1]; 201 } 202 } 203 204 // prefix not found 205 return null; 206 207 } // getURI(String):String 208 209 210 /** 211 * @see org.apache.xerces.xni.NamespaceContext#getPrefix(String) 212 */ 213 public String getPrefix(String uri) { 214 215 // find uri in current context 216 for (int i = fNamespaceSize; i > 0; i -= 2) { 217 //if (fNamespace[i - 1] == uri) { 218 if (fNamespace[i - 1].equals(uri) ) { 219 //if (getURI(fNamespace[i - 2]) == uri) 220 if (getURI(fNamespace[i - 2]).equals(uri) ) 221 return fNamespace[i - 2]; 222 } 223 } 224 225 // uri not found 226 return null; 227 228 } // getPrefix(String):String 229 230 231 /** 232 * @see org.apache.xerces.xni.NamespaceContext#getDeclaredPrefixCount() 233 */ 234 public int getDeclaredPrefixCount() { 235 return (fNamespaceSize - fContext[fCurrentContext]) / 2; 236 } // getDeclaredPrefixCount():int 237 238 /** 239 * @see org.apache.xerces.xni.NamespaceContext#getDeclaredPrefixAt(int) 240 */ 241 public String getDeclaredPrefixAt(int index) { 242 return fNamespace[fContext[fCurrentContext] + index * 2]; 243 } // getDeclaredPrefixAt(int):String 244 245 /** 246 * @see org.apache.xerces.xni.NamespaceContext#getAllPrefixes() 247 */ 248 public Enumeration getAllPrefixes() { 249 int count = 0; 250 if (fPrefixes.length < (fNamespace.length/2)) { 251 // resize prefix array 252 String[] prefixes = new String[fNamespaceSize]; 253 fPrefixes = prefixes; 254 } 255 String prefix = null; 256 boolean unique = true; 257 for (int i = 2; i < (fNamespaceSize-2); i += 2) { 258 prefix = fNamespace[i + 2]; 259 for (int k=0;k<count;k++){ 260 if (fPrefixes[k]==prefix){ 261 unique = false; 262 break; 263 } 264 } 265 if (unique){ 266 fPrefixes[count++] = prefix; 267 } 268 unique = true; 269 } 270 return new Prefixes(fPrefixes, count); 271 } 272 273 protected final class Prefixes implements Enumeration { 274 private String[] prefixes; 275 private int counter = 0; 276 private int size = 0; 277 278 /** 279 * Constructor for Prefixes. 280 */ 281 public Prefixes(String [] prefixes, int size) { 282 this.prefixes = prefixes; 283 this.size = size; 284 } 285 286 /** 287 * @see java.util.Enumeration#hasMoreElements() 288 */ 289 public boolean hasMoreElements() { 290 return (counter< size); 291 } 292 293 /** 294 * @see java.util.Enumeration#nextElement() 295 */ 296 public Object nextElement() { 297 if (counter< size){ 298 return fPrefixes[counter++]; 299 } 300 throw new NoSuchElementException("Illegal access to Namespace prefixes enumeration."); 301 } 302 303 public String toString(){ 304 StringBuffer buf = new StringBuffer(); 305 for (int i=0;i<size;i++){ 306 buf.append(prefixes[i]); 307 buf.append(" "); 308 } 309 310 return buf.toString(); 311 } 312 313 } 314 315 } // class NamespaceSupport 316