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