001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the "License"); 007 * you may not use this file except in compliance with the License. 008 * You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 /* 019 * $Id: NamespaceSupport.java 1225426 2011-12-29 04:13:08Z mrglavas $ 020 */ 021 022 package org.apache.xml.serializer.dom3; 023 024 import java.util.Enumeration; 025 import java.util.NoSuchElementException; 026 027 /** 028 * Namespace support for XML document handlers. This class doesn't 029 * perform any error checking and assumes that all strings passed 030 * as arguments to methods are unique symbols. The SymbolTable class 031 * can be used for this purpose. 032 * 033 * Derived from org.apache.xerces.util.NamespaceSupport 034 * 035 * @author Andy Clark, IBM 036 * 037 * @version $Id: NamespaceSupport.java 1225426 2011-12-29 04:13:08Z mrglavas $ 038 */ 039 public class NamespaceSupport { 040 041 static final String PREFIX_XML = "xml".intern(); 042 043 static final String PREFIX_XMLNS = "xmlns".intern(); 044 045 /** 046 * The XML Namespace ("http://www.w3.org/XML/1998/namespace"). This is 047 * the Namespace URI that is automatically mapped to the "xml" prefix. 048 */ 049 public final static String XML_URI = "http://www.w3.org/XML/1998/namespace".intern(); 050 051 /** 052 * XML Information Set REC 053 * all namespace attributes (including those named xmlns, 054 * whose [prefix] property has no value) have a namespace URI of http://www.w3.org/2000/xmlns/ 055 */ 056 public final static String XMLNS_URI = "http://www.w3.org/2000/xmlns/".intern(); 057 058 // 059 // Data 060 // 061 062 /** 063 * Namespace binding information. This array is composed of a 064 * series of tuples containing the namespace binding information: 065 * <prefix, uri>. The default size can be set to anything 066 * as long as it is a power of 2 greater than 1. 067 * 068 * @see #fNamespaceSize 069 * @see #fContext 070 */ 071 protected String[] fNamespace = new String[16 * 2]; 072 073 /** The top of the namespace information array. */ 074 protected int fNamespaceSize; 075 076 // NOTE: The constructor depends on the initial context size 077 // being at least 1. -Ac 078 079 /** 080 * Context indexes. This array contains indexes into the namespace 081 * information array. The index at the current context is the start 082 * index of declared namespace bindings and runs to the size of the 083 * namespace information array. 084 * 085 * @see #fNamespaceSize 086 */ 087 protected int[] fContext = new int[8]; 088 089 /** The current context. */ 090 protected int fCurrentContext; 091 092 protected String[] fPrefixes = new String[16]; 093 094 // 095 // Constructors 096 // 097 098 /** Default constructor. */ 099 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