aoqi@0: /* aoqi@0: * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. Oracle designates this aoqi@0: * particular file as subject to the "Classpath" exception as provided aoqi@0: * by Oracle in the LICENSE file that accompanied this code. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: * aoqi@0: * THIS FILE WAS MODIFIED BY SUN MICROSYSTEMS, INC. aoqi@0: */ aoqi@0: aoqi@0: package com.sun.xml.internal.fastinfoset.util; aoqi@0: aoqi@0: import com.sun.xml.internal.fastinfoset.EncodingConstants; aoqi@0: import com.sun.xml.internal.fastinfoset.CommonResourceBundle; aoqi@0: import java.util.Iterator; aoqi@0: import java.util.NoSuchElementException; aoqi@0: import com.sun.xml.internal.org.jvnet.fastinfoset.FastInfosetException; aoqi@0: aoqi@0: public class PrefixArray extends ValueArray { aoqi@0: public static final int PREFIX_MAP_SIZE = 64; aoqi@0: aoqi@0: private int _initialCapacity; aoqi@0: aoqi@0: public String[] _array; aoqi@0: aoqi@0: private PrefixArray _readOnlyArray; aoqi@0: aoqi@0: private static class PrefixEntry { aoqi@0: private PrefixEntry next; aoqi@0: private int prefixId; aoqi@0: } aoqi@0: aoqi@0: private PrefixEntry[] _prefixMap = new PrefixEntry[PREFIX_MAP_SIZE]; aoqi@0: aoqi@0: private PrefixEntry _prefixPool; aoqi@0: aoqi@0: private static class NamespaceEntry { aoqi@0: private NamespaceEntry next; aoqi@0: private int declarationId; aoqi@0: private int namespaceIndex; aoqi@0: aoqi@0: private String prefix; aoqi@0: private String namespaceName; aoqi@0: private int prefixEntryIndex; aoqi@0: } aoqi@0: aoqi@0: private NamespaceEntry _namespacePool; aoqi@0: aoqi@0: private NamespaceEntry[] _inScopeNamespaces; aoqi@0: aoqi@0: public int[] _currentInScope; aoqi@0: aoqi@0: public int _declarationId; aoqi@0: aoqi@0: public PrefixArray(int initialCapacity, int maximumCapacity) { aoqi@0: _initialCapacity = initialCapacity; aoqi@0: _maximumCapacity = maximumCapacity; aoqi@0: aoqi@0: _array = new String[initialCapacity]; aoqi@0: // Sizes of _inScopeNamespaces and _currentInScope need to be two aoqi@0: // greater than _array because 0 represents the empty string and aoqi@0: // 1 represents the xml prefix aoqi@0: _inScopeNamespaces = new NamespaceEntry[initialCapacity + 2]; aoqi@0: _currentInScope = new int[initialCapacity + 2]; aoqi@0: aoqi@0: increaseNamespacePool(initialCapacity); aoqi@0: increasePrefixPool(initialCapacity); aoqi@0: aoqi@0: initializeEntries(); aoqi@0: } aoqi@0: aoqi@0: public PrefixArray() { aoqi@0: this(DEFAULT_CAPACITY, MAXIMUM_CAPACITY); aoqi@0: } aoqi@0: aoqi@0: private final void initializeEntries() { aoqi@0: _inScopeNamespaces[0] = _namespacePool; aoqi@0: _namespacePool = _namespacePool.next; aoqi@0: _inScopeNamespaces[0].next = null; aoqi@0: _inScopeNamespaces[0].prefix = ""; aoqi@0: _inScopeNamespaces[0].namespaceName = ""; aoqi@0: _inScopeNamespaces[0].namespaceIndex = _currentInScope[0] = 0; aoqi@0: aoqi@0: int index = KeyIntMap.indexFor(KeyIntMap.hashHash(_inScopeNamespaces[0].prefix.hashCode()), _prefixMap.length); aoqi@0: _prefixMap[index] = _prefixPool; aoqi@0: _prefixPool = _prefixPool.next; aoqi@0: _prefixMap[index].next = null; aoqi@0: _prefixMap[index].prefixId = 0; aoqi@0: aoqi@0: aoqi@0: _inScopeNamespaces[1] = _namespacePool; aoqi@0: _namespacePool = _namespacePool.next; aoqi@0: _inScopeNamespaces[1].next = null; aoqi@0: _inScopeNamespaces[1].prefix = EncodingConstants.XML_NAMESPACE_PREFIX; aoqi@0: _inScopeNamespaces[1].namespaceName = EncodingConstants.XML_NAMESPACE_NAME; aoqi@0: _inScopeNamespaces[1].namespaceIndex = _currentInScope[1] = 1; aoqi@0: aoqi@0: index = KeyIntMap.indexFor(KeyIntMap.hashHash(_inScopeNamespaces[1].prefix.hashCode()), _prefixMap.length); aoqi@0: if (_prefixMap[index] == null) { aoqi@0: _prefixMap[index] = _prefixPool; aoqi@0: _prefixPool = _prefixPool.next; aoqi@0: _prefixMap[index].next = null; aoqi@0: } else { aoqi@0: final PrefixEntry e = _prefixMap[index]; aoqi@0: _prefixMap[index] = _prefixPool; aoqi@0: _prefixPool = _prefixPool.next; aoqi@0: _prefixMap[index].next = e; aoqi@0: } aoqi@0: _prefixMap[index].prefixId = 1; aoqi@0: } aoqi@0: aoqi@0: private final void increaseNamespacePool(int capacity) { aoqi@0: if (_namespacePool == null) { aoqi@0: _namespacePool = new NamespaceEntry(); aoqi@0: } aoqi@0: aoqi@0: for (int i = 0; i < capacity; i++) { aoqi@0: NamespaceEntry ne = new NamespaceEntry(); aoqi@0: ne.next = _namespacePool; aoqi@0: _namespacePool = ne; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: private final void increasePrefixPool(int capacity) { aoqi@0: if (_prefixPool == null) { aoqi@0: _prefixPool = new PrefixEntry(); aoqi@0: } aoqi@0: aoqi@0: for (int i = 0; i < capacity; i++) { aoqi@0: PrefixEntry pe = new PrefixEntry(); aoqi@0: pe.next = _prefixPool; aoqi@0: _prefixPool = pe; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: public int countNamespacePool() { aoqi@0: int i = 0; aoqi@0: NamespaceEntry e = _namespacePool; aoqi@0: while (e != null) { aoqi@0: i++; aoqi@0: e = e.next; aoqi@0: } aoqi@0: return i; aoqi@0: } aoqi@0: aoqi@0: public int countPrefixPool() { aoqi@0: int i = 0; aoqi@0: PrefixEntry e = _prefixPool; aoqi@0: while (e != null) { aoqi@0: i++; aoqi@0: e = e.next; aoqi@0: } aoqi@0: return i; aoqi@0: } aoqi@0: aoqi@0: public final void clear() { aoqi@0: for (int i = _readOnlyArraySize; i < _size; i++) { aoqi@0: _array[i] = null; aoqi@0: } aoqi@0: _size = _readOnlyArraySize; aoqi@0: } aoqi@0: aoqi@0: public final void clearCompletely() { aoqi@0: _prefixPool = null; aoqi@0: _namespacePool = null; aoqi@0: aoqi@0: for (int i = 0; i < _size + 2; i++) { aoqi@0: _currentInScope[i] = 0; aoqi@0: _inScopeNamespaces[i] = null; aoqi@0: } aoqi@0: aoqi@0: for (int i = 0; i < _prefixMap.length; i++) { aoqi@0: _prefixMap[i] = null; aoqi@0: } aoqi@0: aoqi@0: increaseNamespacePool(_initialCapacity); aoqi@0: increasePrefixPool(_initialCapacity); aoqi@0: aoqi@0: initializeEntries(); aoqi@0: aoqi@0: _declarationId = 0; aoqi@0: aoqi@0: clear(); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Returns cloned version of internal String[]. aoqi@0: * @return cloned version of internal String[]. aoqi@0: */ aoqi@0: public final String[] getArray() { aoqi@0: if (_array == null) return null; aoqi@0: aoqi@0: final String[] clonedArray = new String[_array.length]; aoqi@0: System.arraycopy(_array, 0, clonedArray, 0, _array.length); aoqi@0: return clonedArray; aoqi@0: } aoqi@0: aoqi@0: public final void setReadOnlyArray(ValueArray readOnlyArray, boolean clear) { aoqi@0: if (!(readOnlyArray instanceof PrefixArray)) { aoqi@0: throw new IllegalArgumentException(CommonResourceBundle.getInstance(). aoqi@0: getString("message.illegalClass", new Object[]{readOnlyArray})); aoqi@0: } aoqi@0: aoqi@0: setReadOnlyArray((PrefixArray)readOnlyArray, clear); aoqi@0: } aoqi@0: aoqi@0: public final void setReadOnlyArray(PrefixArray readOnlyArray, boolean clear) { aoqi@0: if (readOnlyArray != null) { aoqi@0: _readOnlyArray = readOnlyArray; aoqi@0: _readOnlyArraySize = readOnlyArray.getSize(); aoqi@0: aoqi@0: clearCompletely(); aoqi@0: aoqi@0: // Resize according to size of read only arrays aoqi@0: _inScopeNamespaces = new NamespaceEntry[_readOnlyArraySize + _inScopeNamespaces.length]; aoqi@0: _currentInScope = new int[_readOnlyArraySize + _currentInScope.length]; aoqi@0: // Intialize first two entries aoqi@0: initializeEntries(); aoqi@0: aoqi@0: if (clear) { aoqi@0: clear(); aoqi@0: } aoqi@0: aoqi@0: _array = getCompleteArray(); aoqi@0: _size = _readOnlyArraySize; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: public final String[] getCompleteArray() { aoqi@0: if (_readOnlyArray == null) { aoqi@0: // Return cloned version of internal _array aoqi@0: return getArray(); aoqi@0: // return _array; aoqi@0: } else { aoqi@0: final String[] ra = _readOnlyArray.getCompleteArray(); aoqi@0: final String[] a = new String[_readOnlyArraySize + _array.length]; aoqi@0: System.arraycopy(ra, 0, a, 0, _readOnlyArraySize); aoqi@0: return a; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: public final String get(int i) { aoqi@0: return _array[i]; aoqi@0: } aoqi@0: aoqi@0: public final int add(String s) { aoqi@0: if (_size == _array.length) { aoqi@0: resize(); aoqi@0: } aoqi@0: aoqi@0: _array[_size++] = s; aoqi@0: return _size; aoqi@0: } aoqi@0: aoqi@0: protected final void resize() { aoqi@0: if (_size == _maximumCapacity) { aoqi@0: throw new ValueArrayResourceException(CommonResourceBundle.getInstance().getString("message.arrayMaxCapacity")); aoqi@0: } aoqi@0: aoqi@0: int newSize = _size * 3 / 2 + 1; aoqi@0: if (newSize > _maximumCapacity) { aoqi@0: newSize = _maximumCapacity; aoqi@0: } aoqi@0: aoqi@0: final String[] newArray = new String[newSize]; aoqi@0: System.arraycopy(_array, 0, newArray, 0, _size); aoqi@0: _array = newArray; aoqi@0: aoqi@0: newSize += 2; aoqi@0: final NamespaceEntry[] newInScopeNamespaces = new NamespaceEntry[newSize]; aoqi@0: System.arraycopy(_inScopeNamespaces, 0, newInScopeNamespaces, 0, _inScopeNamespaces.length); aoqi@0: _inScopeNamespaces = newInScopeNamespaces; aoqi@0: aoqi@0: final int[] newCurrentInScope = new int[newSize]; aoqi@0: System.arraycopy(_currentInScope, 0, newCurrentInScope, 0, _currentInScope.length); aoqi@0: _currentInScope = newCurrentInScope; aoqi@0: } aoqi@0: aoqi@0: public final void clearDeclarationIds() { aoqi@0: for (int i = 0; i < _size; i++) { aoqi@0: final NamespaceEntry e = _inScopeNamespaces[i]; aoqi@0: if (e != null) { aoqi@0: e.declarationId = 0; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: _declarationId = 1; aoqi@0: } aoqi@0: aoqi@0: public final void pushScope(int prefixIndex, int namespaceIndex) throws FastInfosetException { aoqi@0: if (_namespacePool == null) { aoqi@0: increaseNamespacePool(16); aoqi@0: } aoqi@0: aoqi@0: final NamespaceEntry e = _namespacePool; aoqi@0: _namespacePool = e.next; aoqi@0: aoqi@0: final NamespaceEntry current = _inScopeNamespaces[++prefixIndex]; aoqi@0: if (current == null) { aoqi@0: e.declarationId = _declarationId; aoqi@0: e.namespaceIndex = _currentInScope[prefixIndex] = ++namespaceIndex; aoqi@0: e.next = null; aoqi@0: aoqi@0: _inScopeNamespaces[prefixIndex] = e; aoqi@0: } else if (current.declarationId < _declarationId) { aoqi@0: e.declarationId = _declarationId; aoqi@0: e.namespaceIndex = _currentInScope[prefixIndex] = ++namespaceIndex; aoqi@0: e.next = current; aoqi@0: aoqi@0: current.declarationId = 0; aoqi@0: _inScopeNamespaces[prefixIndex] = e; aoqi@0: } else { aoqi@0: throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.duplicateNamespaceAttribute")); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: public final void pushScopeWithPrefixEntry(String prefix, String namespaceName, aoqi@0: int prefixIndex, int namespaceIndex) throws FastInfosetException { aoqi@0: if (_namespacePool == null) { aoqi@0: increaseNamespacePool(16); aoqi@0: } aoqi@0: if (_prefixPool == null) { aoqi@0: increasePrefixPool(16); aoqi@0: } aoqi@0: aoqi@0: final NamespaceEntry e = _namespacePool; aoqi@0: _namespacePool = e.next; aoqi@0: aoqi@0: final NamespaceEntry current = _inScopeNamespaces[++prefixIndex]; aoqi@0: if (current == null) { aoqi@0: e.declarationId = _declarationId; aoqi@0: e.namespaceIndex = _currentInScope[prefixIndex] = ++namespaceIndex; aoqi@0: e.next = null; aoqi@0: aoqi@0: _inScopeNamespaces[prefixIndex] = e; aoqi@0: } else if (current.declarationId < _declarationId) { aoqi@0: e.declarationId = _declarationId; aoqi@0: e.namespaceIndex = _currentInScope[prefixIndex] = ++namespaceIndex; aoqi@0: e.next = current; aoqi@0: aoqi@0: current.declarationId = 0; aoqi@0: _inScopeNamespaces[prefixIndex] = e; aoqi@0: } else { aoqi@0: throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.duplicateNamespaceAttribute")); aoqi@0: } aoqi@0: aoqi@0: final PrefixEntry p = _prefixPool; aoqi@0: _prefixPool = _prefixPool.next; aoqi@0: p.prefixId = prefixIndex; aoqi@0: aoqi@0: e.prefix = prefix; aoqi@0: e.namespaceName = namespaceName; aoqi@0: e.prefixEntryIndex = KeyIntMap.indexFor(KeyIntMap.hashHash(prefix.hashCode()), _prefixMap.length); aoqi@0: aoqi@0: final PrefixEntry pCurrent = _prefixMap[e.prefixEntryIndex]; aoqi@0: p.next = pCurrent; aoqi@0: _prefixMap[e.prefixEntryIndex] = p; aoqi@0: } aoqi@0: aoqi@0: public final void popScope(int prefixIndex) { aoqi@0: final NamespaceEntry e = _inScopeNamespaces[++prefixIndex]; aoqi@0: _inScopeNamespaces[prefixIndex] = e.next; aoqi@0: _currentInScope[prefixIndex] = (e.next != null) ? e.next.namespaceIndex : 0; aoqi@0: aoqi@0: e.next = _namespacePool; aoqi@0: _namespacePool = e; aoqi@0: } aoqi@0: aoqi@0: public final void popScopeWithPrefixEntry(int prefixIndex) { aoqi@0: final NamespaceEntry e = _inScopeNamespaces[++prefixIndex]; aoqi@0: aoqi@0: _inScopeNamespaces[prefixIndex] = e.next; aoqi@0: _currentInScope[prefixIndex] = (e.next != null) ? e.next.namespaceIndex : 0; aoqi@0: aoqi@0: e.prefix = e.namespaceName = null; aoqi@0: e.next = _namespacePool; aoqi@0: _namespacePool = e; aoqi@0: aoqi@0: PrefixEntry current = _prefixMap[e.prefixEntryIndex]; aoqi@0: if (current.prefixId == prefixIndex) { aoqi@0: _prefixMap[e.prefixEntryIndex] = current.next; aoqi@0: current.next = _prefixPool; aoqi@0: _prefixPool = current; aoqi@0: } else { aoqi@0: PrefixEntry prev = current; aoqi@0: current = current.next; aoqi@0: while (current != null) { aoqi@0: if (current.prefixId == prefixIndex) { aoqi@0: prev.next = current.next; aoqi@0: current.next = _prefixPool; aoqi@0: _prefixPool = current; aoqi@0: break; aoqi@0: } aoqi@0: prev = current; aoqi@0: current = current.next; aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: public final String getNamespaceFromPrefix(String prefix) { aoqi@0: final int index = KeyIntMap.indexFor(KeyIntMap.hashHash(prefix.hashCode()), _prefixMap.length); aoqi@0: PrefixEntry pe = _prefixMap[index]; aoqi@0: while (pe != null) { aoqi@0: final NamespaceEntry ne = _inScopeNamespaces[pe.prefixId]; aoqi@0: if (prefix == ne.prefix || prefix.equals(ne.prefix)) { aoqi@0: return ne.namespaceName; aoqi@0: } aoqi@0: pe = pe.next; aoqi@0: } aoqi@0: aoqi@0: return null; aoqi@0: } aoqi@0: aoqi@0: public final String getPrefixFromNamespace(String namespaceName) { aoqi@0: int position = 0; aoqi@0: while (++position < _size + 2) { aoqi@0: final NamespaceEntry ne = _inScopeNamespaces[position]; aoqi@0: if (ne != null && namespaceName.equals(ne.namespaceName)) { aoqi@0: return ne.prefix; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: return null; aoqi@0: } aoqi@0: aoqi@0: public final Iterator getPrefixes() { aoqi@0: return new Iterator() { aoqi@0: int _position = 1; aoqi@0: NamespaceEntry _ne = _inScopeNamespaces[_position]; aoqi@0: aoqi@0: public boolean hasNext() { aoqi@0: return _ne != null; aoqi@0: } aoqi@0: aoqi@0: public Object next() { aoqi@0: if (_position == _size + 2) { aoqi@0: throw new NoSuchElementException(); aoqi@0: } aoqi@0: aoqi@0: final String prefix = _ne.prefix; aoqi@0: moveToNext(); aoqi@0: return prefix; aoqi@0: } aoqi@0: aoqi@0: public void remove() { aoqi@0: throw new UnsupportedOperationException(); aoqi@0: } aoqi@0: aoqi@0: private final void moveToNext() { aoqi@0: while (++_position < _size + 2) { aoqi@0: _ne = _inScopeNamespaces[_position]; aoqi@0: if (_ne != null) { aoqi@0: return; aoqi@0: } aoqi@0: } aoqi@0: _ne = null; aoqi@0: } aoqi@0: aoqi@0: }; aoqi@0: } aoqi@0: aoqi@0: public final Iterator getPrefixesFromNamespace(final String namespaceName) { aoqi@0: return new Iterator() { aoqi@0: String _namespaceName = namespaceName; aoqi@0: int _position = 0; aoqi@0: NamespaceEntry _ne; aoqi@0: aoqi@0: { aoqi@0: moveToNext(); aoqi@0: } aoqi@0: aoqi@0: public boolean hasNext() { aoqi@0: return _ne != null; aoqi@0: } aoqi@0: aoqi@0: public Object next() { aoqi@0: if (_position == _size + 2) { aoqi@0: throw new NoSuchElementException(); aoqi@0: } aoqi@0: aoqi@0: final String prefix = _ne.prefix; aoqi@0: moveToNext(); aoqi@0: return prefix; aoqi@0: } aoqi@0: aoqi@0: public void remove() { aoqi@0: throw new UnsupportedOperationException(); aoqi@0: } aoqi@0: aoqi@0: private final void moveToNext() { aoqi@0: while (++_position < _size + 2) { aoqi@0: _ne = _inScopeNamespaces[_position]; aoqi@0: if (_ne != null && _namespaceName.equals(_ne.namespaceName)) { aoqi@0: return; aoqi@0: } aoqi@0: } aoqi@0: _ne = null; aoqi@0: } aoqi@0: }; aoqi@0: } aoqi@0: }