diff --git a/CVE-2012-0881.patch b/CVE-2012-0881.patch deleted file mode 100644 index 5a64361..0000000 --- a/CVE-2012-0881.patch +++ /dev/null @@ -1,1115 +0,0 @@ -From 992b5d9c24102ad20330d36c0a71162753a37449 Mon Sep 17 00:00:00 2001 -From: Michael Glavassevich -Date: Wed, 4 Jul 2012 19:56:10 +0000 -Subject: [PATCH] Enhancements to the hashing algorithms used in internal data - structures within Xerces to make them more resistant to collisions. To - improve the distribution a new hash function is randomly selected each time - the number of items in a bucket exceeds a threshold. - -git-svn-id: https://svn.apache.org/repos/asf/xerces/java/trunk@1357381 13f79535-47bb-0310-9956-ffa450edef68 ---- - .../apache/xerces/impl/dtd/DTDGrammar.java | 147 ++++++++++- - .../util/PrimeNumberSequenceGenerator.java | 43 +++ - .../xerces/util/SoftReferenceSymbolTable.java | 37 ++- - src/org/apache/xerces/util/SymbolHash.java | 104 ++++++-- - src/org/apache/xerces/util/SymbolTable.java | 95 ++++++- - .../apache/xerces/util/XMLAttributesImpl.java | 246 ++++++++++++++---- - 6 files changed, 584 insertions(+), 88 deletions(-) - create mode 100644 src/org/apache/xerces/util/PrimeNumberSequenceGenerator.java - -diff --git a/src/org/apache/xerces/impl/dtd/DTDGrammar.java b/src/org/apache/xerces/impl/dtd/DTDGrammar.java -index 6eb5ee580..220a4174b 100644 ---- a/src/org/apache/xerces/impl/dtd/DTDGrammar.java -+++ b/src/org/apache/xerces/impl/dtd/DTDGrammar.java -@@ -19,6 +19,7 @@ - - import java.util.ArrayList; - import java.util.Hashtable; -+import java.util.Random; - - import org.apache.xerces.impl.dtd.models.CMAny; - import org.apache.xerces.impl.dtd.models.CMBinOp; -@@ -2639,6 +2640,26 @@ public ChildrenList () {} - * @author Andy Clark, IBM - */ - protected static final class QNameHashtable { -+ -+ private static final class PrimeNumberSequenceGenerator { -+ -+ private static int [] PRIMES = { -+ 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, -+ 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, -+ 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, -+ 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, -+ 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, -+ 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, -+ 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, -+ 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727}; -+ -+ static void generateSequence(int[] arrayToFill) { -+ Random r = new Random(); -+ for (int i = 0; i < arrayToFill.length; ++i) { -+ arrayToFill[i] = PRIMES[r.nextInt(PRIMES.length)]; -+ } -+ } -+ } - - // - // Constants -@@ -2651,11 +2672,29 @@ public ChildrenList () {} - // that we get a better distribution for hashing. -Ac - /** Hashtable size (101). */ - private static final int HASHTABLE_SIZE = 101; -+ -+ /** Maximum hash collisions per bucket for a table with load factor == 1. */ -+ private static final int MAX_HASH_COLLISIONS = 40; -+ -+ private static final int MULTIPLIERS_SIZE = 1 << 5; -+ private static final int MULTIPLIERS_MASK = MULTIPLIERS_SIZE - 1; - - // - // Data - // - private Object[][] fHashTable = new Object[HASHTABLE_SIZE][]; -+ -+ /** actual table size **/ -+ private int fTableSize = HASHTABLE_SIZE; -+ -+ /** The total number of entries in the hash table. */ -+ private int fCount = 0; -+ -+ /** -+ * Array of randomly selected hash function multipliers or null -+ * if the default String.hashCode() function should be used. -+ */ -+ private int[] fHashMultipliers; - - // - // Public methods -@@ -2663,7 +2702,7 @@ public ChildrenList () {} - /** Associates the given value with the specified key tuple. */ - public void put(String key, int value) { - -- int hash = (key.hashCode() & 0x7FFFFFFF) % HASHTABLE_SIZE; -+ int hash = (hash(key) & 0x7FFFFFFF) % fTableSize; - Object[] bucket = fHashTable[hash]; - - if (bucket == null) { -@@ -2672,6 +2711,11 @@ public void put(String key, int value) { - bucket[1] = key; - bucket[2] = new int[]{value}; - fHashTable[hash] = bucket; -+ if (++fCount > fTableSize) { -+ // Rehash the table if the number of entries -+ // would exceed the number of buckets. -+ rehash(); -+ } - } else { - int count = ((int[])bucket[0])[0]; - int offset = 1 + 2*count; -@@ -2692,10 +2736,20 @@ public void put(String key, int value) { - } - j += 2; - } -- if (! found) { -+ if (!found) { - bucket[offset++] = key; - bucket[offset]= new int[]{value}; - ((int[])bucket[0])[0] = ++count; -+ if (++fCount > fTableSize) { -+ // Rehash the table if the number of entries -+ // would exceed the number of buckets. -+ rehash(); -+ } -+ else if (count > MAX_HASH_COLLISIONS) { -+ // Select a new hash function and rehash the table if -+ // MAX_HASH_COLLISIONS is exceeded. -+ rebalance(); -+ } - } - - } -@@ -2706,7 +2760,7 @@ public void put(String key, int value) { - - /** Returns the value associated with the specified key tuple. */ - public int get(String key) { -- int hash = (key.hashCode() & 0x7FFFFFFF) % HASHTABLE_SIZE; -+ int hash = (hash(key) & 0x7FFFFFFF) % fTableSize; - Object[] bucket = fHashTable[hash]; - - if (bucket == null) { -@@ -2724,6 +2778,93 @@ public int get(String key) { - return -1; - - } // get(int,String,String) -+ -+ public int hash(String symbol) { -+ if (fHashMultipliers == null) { -+ return symbol.hashCode(); -+ } -+ return hash0(symbol); -+ } // hash(String):int -+ -+ private int hash0(String symbol) { -+ int code = 0; -+ final int length = symbol.length(); -+ final int[] multipliers = fHashMultipliers; -+ for (int i = 0; i < length; ++i) { -+ code = code * multipliers[i & MULTIPLIERS_MASK] + symbol.charAt(i); -+ } -+ return code; -+ } // hash0(String):int -+ -+ private void rehash() { -+ rehashCommon(fHashTable.length * 2 + 1); -+ } // rehash() -+ -+ private void rebalance() { -+ if (fHashMultipliers == null) { -+ fHashMultipliers = new int[MULTIPLIERS_SIZE]; -+ } -+ PrimeNumberSequenceGenerator.generateSequence(fHashMultipliers); -+ rehashCommon(fHashTable.length); -+ } // rebalance() -+ -+ private void rehashCommon(final int newCapacity) { -+ -+ final int oldCapacity = fHashTable.length; -+ final Object[][] oldTable = fHashTable; -+ -+ final Object[][] newTable = new Object[newCapacity][]; -+ -+ fHashTable = newTable; -+ fTableSize = fHashTable.length; -+ -+ for (int i = 0; i < oldCapacity; ++i) { -+ final Object[] oldBucket = oldTable[i]; -+ if (oldBucket != null) { -+ final int oldCount = ((int[]) oldBucket[0])[0]; -+ boolean oldBucketReused = false; -+ int k = 1; -+ for (int j = 0; j < oldCount; ++j) { -+ final String key = (String) oldBucket[k]; -+ final Object value = oldBucket[k+1]; -+ -+ final int hash = (hash(key) & 0x7FFFFFFF) % fTableSize; -+ Object[] bucket = fHashTable[hash]; -+ -+ if (bucket == null) { -+ if (oldBucketReused) { -+ bucket = new Object[1 + 2*INITIAL_BUCKET_SIZE]; -+ bucket[0] = new int[]{1}; -+ } -+ else { -+ bucket = oldBucket; -+ ((int[])bucket[0])[0] = 1; -+ oldBucketReused = true; -+ } -+ bucket[1] = key; -+ bucket[2] = value; -+ fHashTable[hash] = bucket; -+ } -+ else { -+ int count = ((int[])bucket[0])[0]; -+ int offset = 1 + 2*count; -+ if (offset == bucket.length) { -+ int newSize = count + INITIAL_BUCKET_SIZE; -+ Object[] newBucket = new Object[1 + 2*newSize]; -+ System.arraycopy(bucket, 0, newBucket, 0, offset); -+ bucket = newBucket; -+ fHashTable[hash] = bucket; -+ } -+ bucket[offset++] = key; -+ bucket[offset]= value; -+ ((int[])bucket[0])[0] = ++count; -+ } -+ k += 2; -+ } -+ } -+ } -+ -+ } // rehashCommon(int) - - } // class QNameHashtable - -diff --git a/src/org/apache/xerces/util/PrimeNumberSequenceGenerator.java b/src/org/apache/xerces/util/PrimeNumberSequenceGenerator.java -new file mode 100644 -index 000000000..407eab1dc ---- /dev/null -+++ b/src/org/apache/xerces/util/PrimeNumberSequenceGenerator.java -@@ -0,0 +1,43 @@ -+/* -+ * Licensed to the Apache Software Foundation (ASF) under one or more -+ * contributor license agreements. See the NOTICE file distributed with -+ * this work for additional information regarding copyright ownership. -+ * The ASF licenses this file to You under the Apache License, Version 2.0 -+ * (the "License"); you may not use this file except in compliance with -+ * the License. You may obtain a copy of the License at -+ * -+ * http://www.apache.org/licenses/LICENSE-2.0 -+ * -+ * Unless required by applicable law or agreed to in writing, software -+ * distributed under the License is distributed on an "AS IS" BASIS, -+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -+ * See the License for the specific language governing permissions and -+ * limitations under the License. -+ */ -+ -+package org.apache.xerces.util; -+ -+import java.util.Random; -+ -+/** -+ * @version $Id$ -+ */ -+final class PrimeNumberSequenceGenerator { -+ -+ private static int [] PRIMES = { -+ 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, -+ 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, -+ 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, -+ 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, -+ 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, -+ 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, -+ 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, -+ 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727}; -+ -+ static void generateSequence(int[] arrayToFill) { -+ Random r = new Random(); -+ for (int i = 0; i < arrayToFill.length; ++i) { -+ arrayToFill[i] = PRIMES[r.nextInt(PRIMES.length)]; -+ } -+ } -+} -diff --git a/src/org/apache/xerces/util/SoftReferenceSymbolTable.java b/src/org/apache/xerces/util/SoftReferenceSymbolTable.java -index 542bfb7da..24bb8ceaf 100644 ---- a/src/org/apache/xerces/util/SoftReferenceSymbolTable.java -+++ b/src/org/apache/xerces/util/SoftReferenceSymbolTable.java -@@ -124,6 +124,7 @@ public SoftReferenceSymbolTable() { - public String addSymbol(String symbol) { - clean(); - // search for identical symbol -+ int collisionCount = 0; - int bucket = hash(symbol) % fTableSize; - for (SREntry entry = fBuckets[bucket]; entry != null; entry = entry.next) { - SREntryData data = (SREntryData)entry.get(); -@@ -133,13 +134,20 @@ public String addSymbol(String symbol) { - if (data.symbol.equals(symbol)) { - return data.symbol; - } -+ ++collisionCount; - } - - if (fCount >= fThreshold) { - // Rehash the table if the threshold is exceeded - rehash(); - bucket = hash(symbol) % fTableSize; -- } -+ } -+ else if (collisionCount >= fCollisionThreshold) { -+ // Select a new hash function and rehash the table if -+ // the collision threshold is exceeded. -+ rebalance(); -+ bucket = hash(symbol) % fTableSize; -+ } - - // add new entry - symbol = symbol.intern(); -@@ -162,6 +170,7 @@ public String addSymbol(String symbol) { - public String addSymbol(char[] buffer, int offset, int length) { - clean(); - // search for identical symbol -+ int collisionCount = 0; - int bucket = hash(buffer, offset, length) % fTableSize; - OUTER: for (SREntry entry = fBuckets[bucket]; entry != null; entry = entry.next) { - SREntryData data = (SREntryData)entry.get(); -@@ -171,18 +180,26 @@ public String addSymbol(char[] buffer, int offset, int length) { - if (length == data.characters.length) { - for (int i = 0; i < length; i++) { - if (buffer[offset + i] != data.characters[i]) { -+ ++collisionCount; - continue OUTER; - } - } - return data.symbol; - } -+ ++collisionCount; - } - - if (fCount >= fThreshold) { - // Rehash the table if the threshold is exceeded - rehash(); - bucket = hash(buffer, offset, length) % fTableSize; -- } -+ } -+ else if (collisionCount >= fCollisionThreshold) { -+ // Select a new hash function and rehash the table if -+ // the collision threshold is exceeded. -+ rebalance(); -+ bucket = hash(buffer, offset, length) % fTableSize; -+ } - - // add new entry - String symbol = new String(buffer, offset, length).intern(); -@@ -215,6 +232,20 @@ protected void compact() { - rehashCommon(((int) (fCount / fLoadFactor)) * 2 + 1); - } - -+ /** -+ * Randomly selects a new hash function and reorganizes this SymbolTable -+ * in order to more evenly distribute its entries across the table. This -+ * method is called automatically when the number keys in one of the -+ * SymbolTable's buckets exceeds the given collision threshold. -+ */ -+ protected void rebalance() { -+ if (fHashMultipliers == null) { -+ fHashMultipliers = new int[MULTIPLIERS_SIZE]; -+ } -+ PrimeNumberSequenceGenerator.generateSequence(fHashMultipliers); -+ rehashCommon(fBuckets.length); -+ } -+ - private void rehashCommon(final int newCapacity) { - - final int oldCapacity = fBuckets.length; -@@ -232,7 +263,7 @@ private void rehashCommon(final int newCapacity) { - - SREntryData data = (SREntryData)e.get(); - if (data != null) { -- int index = hash(data.characters, 0, data.characters.length) % newCapacity; -+ int index = hash(data.symbol) % newCapacity; - if (newTable[index] != null) { - newTable[index].prev = e; - } -diff --git a/src/org/apache/xerces/util/SymbolHash.java b/src/org/apache/xerces/util/SymbolHash.java -index 08caa7b03..f2c001a93 100644 ---- a/src/org/apache/xerces/util/SymbolHash.java -+++ b/src/org/apache/xerces/util/SymbolHash.java -@@ -31,19 +31,34 @@ - // - // Constants - // -- -+ - /** Default table size. */ -- protected int fTableSize = 101; -+ protected static final int TABLE_SIZE = 101; -+ -+ /** Maximum hash collisions per bucket. */ -+ protected static final int MAX_HASH_COLLISIONS = 40; -+ -+ protected static final int MULTIPLIERS_SIZE = 1 << 5; -+ protected static final int MULTIPLIERS_MASK = MULTIPLIERS_SIZE - 1; - - // - // Data - // -+ -+ /** Actual table size **/ -+ protected int fTableSize; - - /** Buckets. */ - protected Entry[] fBuckets; - - /** Number of elements. */ - protected int fNum = 0; -+ -+ /** -+ * Array of randomly selected hash function multipliers or null -+ * if the default String.hashCode() function should be used. -+ */ -+ protected int[] fHashMultipliers; - - // - // Constructors -@@ -51,7 +66,7 @@ - - /** Constructs a key table with the default size. */ - public SymbolHash() { -- fBuckets = new Entry[fTableSize]; -+ this(TABLE_SIZE); - } - - /** -@@ -77,26 +92,37 @@ public SymbolHash(int size) { - * @param value - */ - public void put(Object key, Object value) { -+ -+ // search for identical key -+ int collisionCount = 0; - final int hash = hash(key); - int bucket = hash % fTableSize; -- Entry entry = search(key, bucket); -- -- // replace old value -- if (entry != null) { -- entry.value = value; -- } -- // create new entry -- else { -- if (fNum >= fTableSize) { -- // Rehash the table if the number of entries -- // would exceed the number of buckets. -- rehash(); -- bucket = hash % fTableSize; -+ for (Entry entry = fBuckets[bucket]; entry != null; entry = entry.next) { -+ if (key.equals(entry.key)) { -+ // replace old value -+ entry.value = value; -+ return; - } -- entry = new Entry(key, value, fBuckets[bucket]); -- fBuckets[bucket] = entry; -- fNum++; -+ ++collisionCount; - } -+ -+ if (fNum >= fTableSize) { -+ // Rehash the table if the number of entries -+ // would exceed the number of buckets. -+ rehash(); -+ bucket = hash % fTableSize; -+ } -+ else if (collisionCount >= MAX_HASH_COLLISIONS && key instanceof String) { -+ // Select a new hash function and rehash the table if -+ // MAX_HASH_COLLISIONS is exceeded. -+ rebalance(); -+ bucket = hash(key) % fTableSize; -+ } -+ -+ // create new entry -+ Entry entry = new Entry(key, value, fBuckets[bucket]); -+ fBuckets[bucket] = entry; -+ ++fNum; - } - - /** -@@ -161,6 +187,7 @@ public int getValues(Object[] elements, int from) { - public SymbolHash makeClone() { - SymbolHash newTable = new SymbolHash(fTableSize); - newTable.fNum = fNum; -+ newTable.fHashMultipliers = fHashMultipliers != null ? (int[]) fHashMultipliers.clone() : null; - for (int i = 0; i < fTableSize; i++) { - if (fBuckets[i] != null) { - newTable.fBuckets[i] = fBuckets[i].makeClone(); -@@ -178,6 +205,7 @@ public void clear() { - fBuckets[i] = null; - } - fNum = 0; -+ fHashMultipliers = null; - } // clear(): void - - protected Entry search(Object key, int bucket) { -@@ -195,8 +223,21 @@ protected Entry search(Object key, int bucket) { - * @param key The key to hash. - */ - protected int hash(Object key) { -- return key.hashCode() & 0x7FFFFFFF; -- } -+ if (fHashMultipliers == null || !(key instanceof String)) { -+ return key.hashCode() & 0x7FFFFFFF; -+ } -+ return hash0((String) key); -+ } // hash(Object):int -+ -+ private int hash0(String symbol) { -+ int code = 0; -+ final int length = symbol.length(); -+ final int[] multipliers = fHashMultipliers; -+ for (int i = 0; i < length; ++i) { -+ code = code * multipliers[i & MULTIPLIERS_MASK] + symbol.charAt(i); -+ } -+ return code & 0x7FFFFFFF; -+ } // hash0(String):int - - /** - * Increases the capacity of and internally reorganizes this -@@ -205,11 +246,28 @@ protected int hash(Object key) { - * number of keys in the SymbolHash exceeds its number of buckets. - */ - protected void rehash() { -- -+ rehashCommon((fBuckets.length << 1) + 1); -+ } -+ -+ /** -+ * Randomly selects a new hash function and reorganizes this SymbolHash -+ * in order to more evenly distribute its entries across the table. This -+ * method is called automatically when the number keys in one of the -+ * SymbolHash's buckets exceeds MAX_HASH_COLLISIONS. -+ */ -+ protected void rebalance() { -+ if (fHashMultipliers == null) { -+ fHashMultipliers = new int[MULTIPLIERS_SIZE]; -+ } -+ PrimeNumberSequenceGenerator.generateSequence(fHashMultipliers); -+ rehashCommon(fBuckets.length); -+ } -+ -+ private void rehashCommon(final int newCapacity) { -+ - final int oldCapacity = fBuckets.length; - final Entry[] oldTable = fBuckets; - -- final int newCapacity = (oldCapacity << 1) + 1; - final Entry[] newTable = new Entry[newCapacity]; - - fBuckets = newTable; -diff --git a/src/org/apache/xerces/util/SymbolTable.java b/src/org/apache/xerces/util/SymbolTable.java -index 02ef70b2e..4c7cc1bcb 100644 ---- a/src/org/apache/xerces/util/SymbolTable.java -+++ b/src/org/apache/xerces/util/SymbolTable.java -@@ -84,6 +84,12 @@ - - /** Default table size. */ - protected static final int TABLE_SIZE = 101; -+ -+ /** Maximum hash collisions per bucket for a table with load factor == 1. */ -+ protected static final int MAX_HASH_COLLISIONS = 40; -+ -+ protected static final int MULTIPLIERS_SIZE = 1 << 5; -+ protected static final int MULTIPLIERS_MASK = MULTIPLIERS_SIZE - 1; - - // - // Data -@@ -104,6 +110,18 @@ - - /** The load factor for the SymbolTable. */ - protected float fLoadFactor; -+ -+ /** -+ * A new hash function is selected and the table is rehashed when -+ * the number of keys in the bucket exceeds this threshold. -+ */ -+ protected final int fCollisionThreshold; -+ -+ /** -+ * Array of randomly selected hash function multipliers or null -+ * if the default String.hashCode() function should be used. -+ */ -+ protected int[] fHashMultipliers; - - // - // Constructors -@@ -136,6 +154,7 @@ public SymbolTable(int initialCapacity, float loadFactor) { - fTableSize = initialCapacity; - fBuckets = new Entry[fTableSize]; - fThreshold = (int)(fTableSize * loadFactor); -+ fCollisionThreshold = (int)(MAX_HASH_COLLISIONS * loadFactor); - fCount = 0; - } - -@@ -174,18 +193,26 @@ public SymbolTable() { - public String addSymbol(String symbol) { - - // search for identical symbol -+ int collisionCount = 0; - int bucket = hash(symbol) % fTableSize; - for (Entry entry = fBuckets[bucket]; entry != null; entry = entry.next) { - if (entry.symbol.equals(symbol)) { - return entry.symbol; - } -+ ++collisionCount; - } - - if (fCount >= fThreshold) { - // Rehash the table if the threshold is exceeded - rehash(); - bucket = hash(symbol) % fTableSize; -- } -+ } -+ else if (collisionCount >= fCollisionThreshold) { -+ // Select a new hash function and rehash the table if -+ // the collision threshold is exceeded. -+ rebalance(); -+ bucket = hash(symbol) % fTableSize; -+ } - - // create new entry - Entry entry = new Entry(symbol, fBuckets[bucket]); -@@ -208,23 +235,32 @@ public String addSymbol(String symbol) { - public String addSymbol(char[] buffer, int offset, int length) { - - // search for identical symbol -+ int collisionCount = 0; - int bucket = hash(buffer, offset, length) % fTableSize; - OUTER: for (Entry entry = fBuckets[bucket]; entry != null; entry = entry.next) { - if (length == entry.characters.length) { - for (int i = 0; i < length; i++) { - if (buffer[offset + i] != entry.characters[i]) { -+ ++collisionCount; - continue OUTER; - } - } - return entry.symbol; - } -+ ++collisionCount; - } - - if (fCount >= fThreshold) { - // Rehash the table if the threshold is exceeded - rehash(); - bucket = hash(buffer, offset, length) % fTableSize; -- } -+ } -+ else if (collisionCount >= fCollisionThreshold) { -+ // Select a new hash function and rehash the table if -+ // the collision threshold is exceeded. -+ rebalance(); -+ bucket = hash(buffer, offset, length) % fTableSize; -+ } - - // add new entry - Entry entry = new Entry(buffer, offset, length, fBuckets[bucket]); -@@ -243,8 +279,21 @@ public String addSymbol(char[] buffer, int offset, int length) { - * @param symbol The symbol to hash. - */ - public int hash(String symbol) { -- return symbol.hashCode() & 0x7FFFFFFF; -+ if (fHashMultipliers == null) { -+ return symbol.hashCode() & 0x7FFFFFFF; -+ } -+ return hash0(symbol); - } // hash(String):int -+ -+ private int hash0(String symbol) { -+ int code = 0; -+ final int length = symbol.length(); -+ final int[] multipliers = fHashMultipliers; -+ for (int i = 0; i < length; ++i) { -+ code = code * multipliers[i & MULTIPLIERS_MASK] + symbol.charAt(i); -+ } -+ return code & 0x7FFFFFFF; -+ } // hash0(String):int - - /** - * Returns a hashcode value for the specified symbol information. -@@ -258,14 +307,25 @@ public int hash(String symbol) { - * @param length The length of the symbol. - */ - public int hash(char[] buffer, int offset, int length) { -+ if (fHashMultipliers == null) { -+ int code = 0; -+ for (int i = 0; i < length; ++i) { -+ code = code * 31 + buffer[offset + i]; -+ } -+ return code & 0x7FFFFFFF; -+ } -+ return hash0(buffer, offset, length); - -+ } // hash(char[],int,int):int -+ -+ private int hash0(char[] buffer, int offset, int length) { - int code = 0; -+ final int[] multipliers = fHashMultipliers; - for (int i = 0; i < length; ++i) { -- code = code * 31 + buffer[offset + i]; -+ code = code * multipliers[i & MULTIPLIERS_MASK] + buffer[offset + i]; - } - return code & 0x7FFFFFFF; -- -- } // hash(char[],int,int):int -+ } // hash0(char[],int,int):int - - /** - * Increases the capacity of and internally reorganizes this -@@ -275,11 +335,28 @@ public int hash(char[] buffer, int offset, int length) { - * and load factor. - */ - protected void rehash() { -- -+ rehashCommon(fBuckets.length * 2 + 1); -+ } -+ -+ /** -+ * Randomly selects a new hash function and reorganizes this SymbolTable -+ * in order to more evenly distribute its entries across the table. This -+ * method is called automatically when the number keys in one of the -+ * SymbolTable's buckets exceeds the given collision threshold. -+ */ -+ protected void rebalance() { -+ if (fHashMultipliers == null) { -+ fHashMultipliers = new int[MULTIPLIERS_SIZE]; -+ } -+ PrimeNumberSequenceGenerator.generateSequence(fHashMultipliers); -+ rehashCommon(fBuckets.length); -+ } -+ -+ private void rehashCommon(final int newCapacity) { -+ - int oldCapacity = fBuckets.length; - Entry[] oldTable = fBuckets; - -- int newCapacity = oldCapacity * 2 + 1; - Entry[] newTable = new Entry[newCapacity]; - - fThreshold = (int)(newCapacity * fLoadFactor); -@@ -291,7 +368,7 @@ protected void rehash() { - Entry e = old; - old = old.next; - -- int index = hash(e.characters, 0, e.characters.length) % newCapacity; -+ int index = hash(e.symbol) % newCapacity; - e.next = newTable[index]; - newTable[index] = e; - } -diff --git a/src/org/apache/xerces/util/XMLAttributesImpl.java b/src/org/apache/xerces/util/XMLAttributesImpl.java -index 63ef720d1..695731e37 100644 ---- a/src/org/apache/xerces/util/XMLAttributesImpl.java -+++ b/src/org/apache/xerces/util/XMLAttributesImpl.java -@@ -50,6 +50,12 @@ - /** Default table size. */ - protected static final int TABLE_SIZE = 101; - -+ /** Maximum hash collisions per bucket. */ -+ protected static final int MAX_HASH_COLLISIONS = 40; -+ -+ protected static final int MULTIPLIERS_SIZE = 1 << 5; -+ protected static final int MULTIPLIERS_MASK = MULTIPLIERS_SIZE - 1; -+ - /** - * Threshold at which an instance is treated - * as a large attribute list. -@@ -103,6 +109,12 @@ - * Indicates whether the table view contains consistent data. - */ - protected boolean fIsTableViewConsistent; -+ -+ /** -+ * Array of randomly selected hash function multipliers or null -+ * if the default String.hashCode() function should be used. -+ */ -+ protected int[] fHashMultipliers; - - // - // Constructors -@@ -203,7 +215,8 @@ else if (name.uri == null || - * the user of this class adds attributes, removes them, and - * then adds more. - */ -- if (!fIsTableViewConsistent || fLength == SIZE_LIMIT) { -+ if (!fIsTableViewConsistent || fLength == SIZE_LIMIT || -+ (fLength > SIZE_LIMIT && fLength > fTableViewBuckets)) { - prepareAndPopulateTableView(); - fIsTableViewConsistent = true; - } -@@ -232,12 +245,14 @@ else if (name.uri == null || - // We need to check if any of the attributes has the same rawname. - else { - // Search the table. -+ int collisionCount = 0; - Attribute found = fAttributeTableView[bucket]; - while (found != null) { - if (found.name.rawname == name.rawname) { - break; - } - found = found.next; -+ ++collisionCount; - } - // This attribute is unique. - if (found == null) { -@@ -250,10 +265,19 @@ else if (name.uri == null || - } - fAttributes = attributes; - } -- -- // Update table view -- fAttributes[index].next = fAttributeTableView[bucket]; -- fAttributeTableView[bucket] = fAttributes[index]; -+ // Select a new hash function and rehash the table view -+ // if the collision threshold is exceeded. -+ if (collisionCount >= MAX_HASH_COLLISIONS) { -+ // The current attribute will be processed in the rehash. -+ // Need to set its name first. -+ fAttributes[index].name.setValues(name); -+ rebalanceTableView(fLength); -+ } -+ else { -+ // Update table view -+ fAttributes[index].next = fAttributeTableView[bucket]; -+ fAttributeTableView[bucket] = fAttributes[index]; -+ } - } - // Duplicate. We still need to find the index. - else { -@@ -829,60 +853,84 @@ public void addAttributeNS(QName name, String type, String value) { - */ - public QName checkDuplicatesNS() { - // If the list is small check for duplicates using pairwise comparison. -- if (fLength <= SIZE_LIMIT) { -- for (int i = 0; i < fLength - 1; ++i) { -- Attribute att1 = fAttributes[i]; -- for (int j = i + 1; j < fLength; ++j) { -- Attribute att2 = fAttributes[j]; -+ final int length = fLength; -+ if (length <= SIZE_LIMIT) { -+ final Attribute[] attributes = fAttributes; -+ for (int i = 0; i < length - 1; ++i) { -+ Attribute att1 = attributes[i]; -+ for (int j = i + 1; j < length; ++j) { -+ Attribute att2 = attributes[j]; - if (att1.name.localpart == att2.name.localpart && - att1.name.uri == att2.name.uri) { -- return att2.name; -+ return att2.name; - } - } - } -+ return null; - } - // If the list is large check duplicates using a hash table. - else { -- // We don't want this table view to be read if someone calls -- // addAttribute so we invalidate it up front. -- fIsTableViewConsistent = false; -- -- prepareTableView(); -+ return checkManyDuplicatesNS(); -+ } -+ } -+ -+ private QName checkManyDuplicatesNS() { -+ // We don't want this table view to be read if someone calls -+ // addAttribute so we invalidate it up front. -+ fIsTableViewConsistent = false; - -- Attribute attr; -- int bucket; -+ prepareTableView(); - -- for (int i = fLength - 1; i >= 0; --i) { -- attr = fAttributes[i]; -- bucket = getTableViewBucket(attr.name.localpart, attr.name.uri); -+ Attribute attr; -+ int bucket; -+ -+ final int length = fLength; -+ final Attribute[] attributes = fAttributes; -+ final Attribute[] attributeTableView = fAttributeTableView; -+ final int[] attributeTableViewChainState = fAttributeTableViewChainState; -+ int largeCount = fLargeCount; -+ -+ for (int i = 0; i < length; ++i) { -+ attr = attributes[i]; -+ bucket = getTableViewBucket(attr.name.localpart, attr.name.uri); -+ -+ // The chain is stale. -+ // This must be a unique attribute. -+ if (attributeTableViewChainState[bucket] != largeCount) { -+ attributeTableViewChainState[bucket] = largeCount; -+ attr.next = null; -+ attributeTableView[bucket] = attr; -+ } -+ // This chain is active. -+ // We need to check if any of the attributes has the same name. -+ else { -+ // Search the table. -+ int collisionCount = 0; -+ Attribute found = attributeTableView[bucket]; -+ while (found != null) { -+ if (found.name.localpart == attr.name.localpart && -+ found.name.uri == attr.name.uri) { -+ return attr.name; -+ } -+ found = found.next; -+ ++collisionCount; -+ } - -- // The chain is stale. -- // This must be a unique attribute. -- if (fAttributeTableViewChainState[bucket] != fLargeCount) { -- fAttributeTableViewChainState[bucket] = fLargeCount; -- attr.next = null; -- fAttributeTableView[bucket] = attr; -- } -- // This chain is active. -- // We need to check if any of the attributes has the same name. -+ // Select a new hash function and rehash the table view -+ // if the collision threshold is exceeded. -+ if (collisionCount >= MAX_HASH_COLLISIONS) { -+ // The current attribute will be processed in the rehash. -+ rebalanceTableViewNS(i+1); -+ largeCount = fLargeCount; -+ } - else { -- // Search the table. -- Attribute found = fAttributeTableView[bucket]; -- while (found != null) { -- if (found.name.localpart == attr.name.localpart && -- found.name.uri == attr.name.uri) { -- return attr.name; -- } -- found = found.next; -- } -- - // Update table view -- attr.next = fAttributeTableView[bucket]; -- fAttributeTableView[bucket] = attr; -+ attr.next = attributeTableView[bucket]; -+ attributeTableView[bucket] = attr; - } - } -- } -- return null; -+ } -+ return null; - } - - /** -@@ -933,7 +981,7 @@ private String getReportableType(String type) { - * would be hashed - */ - protected int getTableViewBucket(String qname) { -- return (qname.hashCode() & 0x7FFFFFFF) % fTableViewBuckets; -+ return (hash(qname) & 0x7FFFFFFF) % fTableViewBuckets; - } - - /** -@@ -947,13 +995,36 @@ protected int getTableViewBucket(String qname) { - */ - protected int getTableViewBucket(String localpart, String uri) { - if (uri == null) { -- return (localpart.hashCode() & 0x7FFFFFFF) % fTableViewBuckets; -+ return (hash(localpart) & 0x7FFFFFFF) % fTableViewBuckets; - } - else { -- return ((localpart.hashCode() + uri.hashCode()) -- & 0x7FFFFFFF) % fTableViewBuckets; -+ return (hash(localpart, uri) & 0x7FFFFFFF) % fTableViewBuckets; - } - } -+ -+ private int hash(String localpart) { -+ if (fHashMultipliers == null) { -+ return localpart.hashCode(); -+ } -+ return hash0(localpart); -+ } // hash(String):int -+ -+ private int hash(String localpart, String uri) { -+ if (fHashMultipliers == null) { -+ return localpart.hashCode() + uri.hashCode() * 31; -+ } -+ return hash0(localpart) + hash0(uri) * fHashMultipliers[MULTIPLIERS_SIZE]; -+ } // hash(String,String):int -+ -+ private int hash0(String symbol) { -+ int code = 0; -+ final int length = symbol.length(); -+ final int[] multipliers = fHashMultipliers; -+ for (int i = 0; i < length; ++i) { -+ code = code * multipliers[i & MULTIPLIERS_MASK] + symbol.charAt(i); -+ } -+ return code; -+ } // hash0(String):int - - /** - * Purges all elements from the table view. -@@ -970,10 +1041,32 @@ protected void cleanTableView() { - } - } - -+ /** -+ * Increases the capacity of the table view. -+ */ -+ private void growTableView() { -+ final int length = fLength; -+ int tableViewBuckets = fTableViewBuckets; -+ do { -+ tableViewBuckets = (tableViewBuckets << 1) + 1; -+ if (tableViewBuckets < 0) { -+ tableViewBuckets = Integer.MAX_VALUE; -+ break; -+ } -+ } -+ while (length > tableViewBuckets); -+ fTableViewBuckets = tableViewBuckets; -+ fAttributeTableView = null; -+ fLargeCount = 1; -+ } -+ - /** - * Prepares the table view of the attributes list for use. - */ - protected void prepareTableView() { -+ if (fLength > fTableViewBuckets) { -+ growTableView(); -+ } - if (fAttributeTableView == null) { - fAttributeTableView = new Attribute[fTableViewBuckets]; - fAttributeTableViewChainState = new int[fTableViewBuckets]; -@@ -989,11 +1082,15 @@ protected void prepareTableView() { - * previously read. - */ - protected void prepareAndPopulateTableView() { -+ prepareAndPopulateTableView(fLength); -+ } -+ -+ private void prepareAndPopulateTableView(final int count) { - prepareTableView(); -- // Need to populate the hash table with the attributes we've scanned so far. -+ // Need to populate the hash table with the attributes we've processed so far. - Attribute attr; - int bucket; -- for (int i = 0; i < fLength; ++i) { -+ for (int i = 0; i < count; ++i) { - attr = fAttributes[i]; - bucket = getTableViewBucket(attr.name.rawname); - if (fAttributeTableViewChainState[bucket] != fLargeCount) { -@@ -1009,6 +1009,55 @@ public class XMLAttributesImpl - } - } - -+ private void prepareAndPopulateTableViewNS(final int count) { -+ prepareTableView(); -+ // Need to populate the hash table with the attributes we've processed so far. -+ Attribute attr; -+ int bucket; -+ for (int i = 0; i < count; ++i) { -+ attr = fAttributes[i]; -+ bucket = getTableViewBucket(attr.name.localpart, attr.name.uri); -+ if (fAttributeTableViewChainState[bucket] != fLargeCount) { -+ fAttributeTableViewChainState[bucket] = fLargeCount; -+ attr.next = null; -+ fAttributeTableView[bucket] = attr; -+ } -+ else { -+ // Update table view -+ attr.next = fAttributeTableView[bucket]; -+ fAttributeTableView[bucket] = attr; -+ } -+ } -+ } -+ -+ /** -+ * Randomly selects a new hash function and reorganizes the table view -+ * in order to more evenly distribute its entries. This method is called -+ * automatically when the number of attributes in one bucket exceeds -+ * MAX_HASH_COLLISIONS. -+ */ -+ private void rebalanceTableView(final int count) { -+ if (fHashMultipliers == null) { -+ fHashMultipliers = new int[MULTIPLIERS_SIZE + 1]; -+ } -+ PrimeNumberSequenceGenerator.generateSequence(fHashMultipliers); -+ prepareAndPopulateTableView(count); -+ } -+ -+ /** -+ * Randomly selects a new hash function and reorganizes the table view -+ * in order to more evenly distribute its entries. This method is called -+ * automatically when the number of attributes in one bucket exceeds -+ * MAX_HASH_COLLISIONS. -+ */ -+ private void rebalanceTableViewNS(final int count) { -+ if (fHashMultipliers == null) { -+ fHashMultipliers = new int[MULTIPLIERS_SIZE + 1]; -+ } -+ PrimeNumberSequenceGenerator.generateSequence(fHashMultipliers); -+ prepareAndPopulateTableViewNS(count); -+ } -+ - // - // Classes - // diff --git a/JIRA-Issue-1499-http-issues.apache.org-jira-browse-X.patch b/JIRA-Issue-1499-http-issues.apache.org-jira-browse-X.patch deleted file mode 100644 index 63e6fba..0000000 --- a/JIRA-Issue-1499-http-issues.apache.org-jira-browse-X.patch +++ /dev/null @@ -1,212 +0,0 @@ -From f890ce20b623f2bea736d096229677c8b99556ad Mon Sep 17 00:00:00 2001 -From: Michael Glavassevich -Date: Wed, 16 Mar 2011 15:57:02 +0000 -Subject: [PATCH] JIRA Issue #1499: - http://issues.apache.org/jira/browse/XERCESJ-1499. Reducing the initial - footprint of SymbolHash buckets within a SchemaGrammar from 1,515 to 177 - (about 12% of the default size). Implemented a rehash() method on SymbolHash - to grow the maps if they actually become filled. - -git-svn-id: https://svn.apache.org/repos/asf/xerces/java/trunk@1082175 13f79535-47bb-0310-9956-ffa450edef68 ---- - .../apache/xerces/impl/xs/SchemaGrammar.java | 44 ++++++++------- - .../xerces/impl/xs/traversers/XSDHandler.java | 14 ++--- - src/org/apache/xerces/util/SymbolHash.java | 55 +++++++++++++++++-- - 3 files changed, 81 insertions(+), 32 deletions(-) - -diff --git a/src/org/apache/xerces/impl/xs/SchemaGrammar.java b/src/org/apache/xerces/impl/xs/SchemaGrammar.java -index e522e9770..a4d5ca675 100644 ---- a/src/org/apache/xerces/impl/xs/SchemaGrammar.java -+++ b/src/org/apache/xerces/impl/xs/SchemaGrammar.java -@@ -144,35 +144,39 @@ public SchemaGrammar(String targetNamespace, XSDDescription grammarDesc, - fGrammarDescription = grammarDesc; - fSymbolTable = symbolTable; - -- // REVISIT: do we know the numbers of the following global decls -- // when creating this grammar? If so, we can pass the numbers in, -- // and use that number to initialize the following hashtables. -- fGlobalAttrDecls = new SymbolHash(); -- fGlobalAttrGrpDecls = new SymbolHash(); -- fGlobalElemDecls = new SymbolHash(); -- fGlobalGroupDecls = new SymbolHash(); -- fGlobalNotationDecls = new SymbolHash(); -- fGlobalIDConstraintDecls = new SymbolHash(); -+ // REVISIT: the initial sizes being chosen for each SymbolHash -+ // may not be ideal and could still be tuned. They were chosen -+ // somewhat arbitrarily to reduce the initial footprint of -+ // SymbolHash buckets from 1,515 to 177 (about 12% of the -+ // default size). -+ fGlobalAttrDecls = new SymbolHash(12); -+ fGlobalAttrGrpDecls = new SymbolHash(5); -+ fGlobalElemDecls = new SymbolHash(25); -+ fGlobalGroupDecls = new SymbolHash(5); -+ fGlobalNotationDecls = new SymbolHash(1); -+ fGlobalIDConstraintDecls = new SymbolHash(3); - - // Extended tables -- fGlobalAttrDeclsExt = new SymbolHash(); -- fGlobalAttrGrpDeclsExt = new SymbolHash(); -- fGlobalElemDeclsExt = new SymbolHash(); -- fGlobalGroupDeclsExt = new SymbolHash(); -- fGlobalNotationDeclsExt = new SymbolHash(); -- fGlobalIDConstraintDeclsExt = new SymbolHash(); -- fGlobalTypeDeclsExt = new SymbolHash(); -+ fGlobalAttrDeclsExt = new SymbolHash(12); -+ fGlobalAttrGrpDeclsExt = new SymbolHash(5); -+ fGlobalElemDeclsExt = new SymbolHash(25); -+ fGlobalGroupDeclsExt = new SymbolHash(5); -+ fGlobalNotationDeclsExt = new SymbolHash(1); -+ fGlobalIDConstraintDeclsExt = new SymbolHash(3); -+ fGlobalTypeDeclsExt = new SymbolHash(25); - - // All global elements table -- fAllGlobalElemDecls = new SymbolHash(); -+ fAllGlobalElemDecls = new SymbolHash(25); - - // if we are parsing S4S, put built-in types in first - // they might get overwritten by the types from S4S, but that's - // considered what the application wants to do. -- if (fTargetNamespace == SchemaSymbols.URI_SCHEMAFORSCHEMA) -+ if (fTargetNamespace == SchemaSymbols.URI_SCHEMAFORSCHEMA) { - fGlobalTypeDecls = SG_SchemaNS.fGlobalTypeDecls.makeClone(); -- else -- fGlobalTypeDecls = new SymbolHash(); -+ } -+ else { -+ fGlobalTypeDecls = new SymbolHash(25); -+ } - } // (String, XSDDescription) - - // Clone an existing schema grammar -diff --git a/src/org/apache/xerces/impl/xs/traversers/XSDHandler.java b/src/org/apache/xerces/impl/xs/traversers/XSDHandler.java -index e05409d6e..0937ac3a7 100644 ---- a/src/org/apache/xerces/impl/xs/traversers/XSDHandler.java -+++ b/src/org/apache/xerces/impl/xs/traversers/XSDHandler.java -@@ -445,13 +445,13 @@ private String doc2SystemId(Element ele) { - private String [][] fKeyrefNamespaceContext = new String[INIT_KEYREF_STACK][1]; - - // global decls: map from decl name to decl object -- SymbolHash fGlobalAttrDecls = new SymbolHash(); -- SymbolHash fGlobalAttrGrpDecls = new SymbolHash(); -- SymbolHash fGlobalElemDecls = new SymbolHash(); -- SymbolHash fGlobalGroupDecls = new SymbolHash(); -- SymbolHash fGlobalNotationDecls = new SymbolHash(); -- SymbolHash fGlobalIDConstraintDecls = new SymbolHash(); -- SymbolHash fGlobalTypeDecls = new SymbolHash(); -+ SymbolHash fGlobalAttrDecls = new SymbolHash(12); -+ SymbolHash fGlobalAttrGrpDecls = new SymbolHash(5); -+ SymbolHash fGlobalElemDecls = new SymbolHash(25); -+ SymbolHash fGlobalGroupDecls = new SymbolHash(5); -+ SymbolHash fGlobalNotationDecls = new SymbolHash(1); -+ SymbolHash fGlobalIDConstraintDecls = new SymbolHash(3); -+ SymbolHash fGlobalTypeDecls = new SymbolHash(25); - - // Constructors - public XSDHandler(){ -diff --git a/src/org/apache/xerces/util/SymbolHash.java b/src/org/apache/xerces/util/SymbolHash.java -index 63974da68..08caa7b03 100644 ---- a/src/org/apache/xerces/util/SymbolHash.java -+++ b/src/org/apache/xerces/util/SymbolHash.java -@@ -17,7 +17,6 @@ - - package org.apache.xerces.util; - -- - /** - * This class is an unsynchronized hash table primary used for String - * to Object mapping. -@@ -78,7 +77,8 @@ public SymbolHash(int size) { - * @param value - */ - public void put(Object key, Object value) { -- int bucket = (key.hashCode() & 0x7FFFFFFF) % fTableSize; -+ final int hash = hash(key); -+ int bucket = hash % fTableSize; - Entry entry = search(key, bucket); - - // replace old value -@@ -87,6 +87,12 @@ public void put(Object key, Object value) { - } - // create new entry - else { -+ if (fNum >= fTableSize) { -+ // Rehash the table if the number of entries -+ // would exceed the number of buckets. -+ rehash(); -+ bucket = hash % fTableSize; -+ } - entry = new Entry(key, value, fBuckets[bucket]); - fBuckets[bucket] = entry; - fNum++; -@@ -100,7 +106,7 @@ public void put(Object key, Object value) { - * @return the value associated with the given key. - */ - public Object get(Object key) { -- int bucket = (key.hashCode() & 0x7FFFFFFF) % fTableSize; -+ int bucket = hash(key) % fTableSize; - Entry entry = search(key, bucket); - if (entry != null) { - return entry.value; -@@ -156,14 +162,15 @@ public SymbolHash makeClone() { - SymbolHash newTable = new SymbolHash(fTableSize); - newTable.fNum = fNum; - for (int i = 0; i < fTableSize; i++) { -- if (fBuckets[i] != null) -+ if (fBuckets[i] != null) { - newTable.fBuckets[i] = fBuckets[i].makeClone(); -+ } - } - return newTable; - } - - /** -- * Remove all key/value assocaition. This tries to save a bit of GC'ing -+ * Remove all key/value association. This tries to save a bit of GC'ing - * by at least keeping the fBuckets array around. - */ - public void clear() { -@@ -182,6 +182,44 @@ public class SymbolHash { - return null; - } - -+ /** -+ * Returns a hashcode value for the specified key. -+ * -+ * @param key The key to hash. -+ */ -+ protected int hash(Object key) { -+ return key.hashCode() & 0x7FFFFFFF; -+ } -+ -+ /** -+ * Increases the capacity of and internally reorganizes this -+ * SymbolHash, in order to accommodate and access its entries more -+ * efficiently. This method is called automatically when the -+ * number of keys in the SymbolHash exceeds its number of buckets. -+ */ -+ protected void rehash() { -+ -+ final int oldCapacity = fBuckets.length; -+ final Entry[] oldTable = fBuckets; -+ -+ final int newCapacity = (oldCapacity << 1) + 1; -+ final Entry[] newTable = new Entry[newCapacity]; -+ -+ fBuckets = newTable; -+ fTableSize = fBuckets.length; -+ -+ for (int i = oldCapacity; i-- > 0;) { -+ for (Entry old = oldTable[i]; old != null; ) { -+ Entry e = old; -+ old = old.next; -+ -+ int index = hash(e.key) % newCapacity; -+ e.next = newTable[index]; -+ newTable[index] = e; -+ } -+ } -+ } -+ - // - // Classes - // diff --git a/JIRA-Issue-1521-http-issues.apache.org-jira-browse-X.patch b/JIRA-Issue-1521-http-issues.apache.org-jira-browse-X.patch deleted file mode 100644 index bbe60a0..0000000 --- a/JIRA-Issue-1521-http-issues.apache.org-jira-browse-X.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 51c3e1286d7923eb2ecbc97aade9d2cf5faa22b7 Mon Sep 17 00:00:00 2001 -From: Michael Glavassevich -Date: Tue, 9 Aug 2011 14:51:31 +0000 -Subject: [PATCH] JIRA Issue #1521: - http://issues.apache.org/jira/browse/XERCESJ-1521. Compact the - SoftReferenceSymbolTable if after cleaning out cleared SoftReferences the - number of symbols drops below 25% of the table's load factor threshold. - -git-svn-id: https://svn.apache.org/repos/asf/xerces/java/trunk@1155386 13f79535-47bb-0310-9956-ffa450edef68 ---- - .../xerces/util/SoftReferenceSymbolTable.java | 40 ++++++++++++++----- - 1 file changed, 31 insertions(+), 9 deletions(-) - -diff --git a/src/org/apache/xerces/util/SoftReferenceSymbolTable.java b/src/org/apache/xerces/util/SoftReferenceSymbolTable.java -index aebe2f449..542bfb7da 100644 ---- a/src/org/apache/xerces/util/SoftReferenceSymbolTable.java -+++ b/src/org/apache/xerces/util/SoftReferenceSymbolTable.java -@@ -200,12 +200,26 @@ public String addSymbol(char[] buffer, int offset, int length) { - * and load factor. - */ - protected void rehash() { -- -- int oldCapacity = fBuckets.length; -- SREntry[] oldTable = fBuckets; -- -- int newCapacity = oldCapacity * 2 + 1; -- SREntry[] newTable = new SREntry[newCapacity]; -+ rehashCommon(fBuckets.length * 2 + 1); -+ } -+ -+ /** -+ * Reduces the capacity of and internally reorganizes this -+ * SymbolTable, in order to accommodate and access its entries in -+ * a more memory efficient way. This method is called automatically when -+ * the number of keys in the SymbolTable drops below 25% of this -+ * hashtable's load factor (as a result of SoftReferences which have -+ * been cleared). -+ */ -+ protected void compact() { -+ rehashCommon(((int) (fCount / fLoadFactor)) * 2 + 1); -+ } -+ -+ private void rehashCommon(final int newCapacity) { -+ -+ final int oldCapacity = fBuckets.length; -+ final SREntry[] oldTable = fBuckets; -+ final SREntry[] newTable = new SREntry[newCapacity]; - - fThreshold = (int)(newCapacity * fLoadFactor); - fBuckets = newTable; -@@ -312,9 +312,17 @@ public class SoftReferenceSymbolTable ex - */ - private void clean() { - SREntry entry = (SREntry)fReferenceQueue.poll(); -- while (entry != null) { -- removeEntry(entry); -- entry = (SREntry)fReferenceQueue.poll(); -+ if (entry != null) { -+ do { -+ removeEntry(entry); -+ entry = (SREntry)fReferenceQueue.poll(); -+ } -+ while (entry != null); -+ // Reduce the number of buckets if the number of items -+ // in the table has dropped below 25% of the threshold. -+ if (fCount < (fThreshold >> 2)) { -+ compact(); -+ } - } - } - diff --git a/XJavac.java b/XJavac.java index 72d10d7..012b726 100644 --- a/XJavac.java +++ b/XJavac.java @@ -46,24 +46,27 @@ public class XJavac extends Javac { * @exception BuildException if the compilation has problems. */ public void execute() throws BuildException { - if(isJDK14OrHigher()) { + Properties props = null; + try { + props = System.getProperties(); + } catch (Exception e) { + throw new BuildException("unable to determine java vendor because could not access system properties!"); + } + String currBCP = (String)props.get("sun.boot.class.path"); // this property is absent / null with JDK 9 & above + + if(isJDK14OrHigher() && !(currBCP == null)) { // maybe the right one; check vendor: - // by checking system properties: - Properties props = null; - try { - props = System.getProperties(); - } catch (Exception e) { - throw new BuildException("unable to determine java vendor because could not access system properties!"); - } + // by checking system properties: // this is supposed to be provided by all JVM's from time immemorial String vendor = ((String)props.get("java.vendor")).toUpperCase(Locale.ENGLISH); if (vendor.indexOf("IBM") >= 0) { // we're on an IBM 1.4 or higher; fiddle with the bootclasspath. setBootclasspath(createIBMJDKBootclasspath()); } - // need to do special things for Sun too and also + // need to do special things for Sun/Oracle too and also // for Apple, HP, FreeBSD, SableVM, Kaffe and Blackdown: a Linux port of Sun Java else if( (vendor.indexOf("SUN") >= 0) || + (vendor.indexOf("ORACLE") >= 0) || (vendor.indexOf("BLACKDOWN") >= 0) || (vendor.indexOf("APPLE") >= 0) || (vendor.indexOf("HEWLETT-PACKARD") >= 0) || @@ -75,8 +78,7 @@ public class XJavac extends Javac { // we must use the classpath Path bcp = createBootclasspath(); Path clPath = getClasspath(); - bcp.append(clPath); - String currBCP = (String)props.get("sun.boot.class.path"); + bcp.append(clPath); Path currBCPath = new Path(null); currBCPath.createPathElement().setPath(currBCP); bcp.append(currBCPath); @@ -94,10 +96,16 @@ public class XJavac extends Javac { Path bcp = createBootclasspath(); String javaHome = System.getProperty("java.home"); StringBuffer bcpMember = new StringBuffer(); - bcpMember.append(javaHome).append("/lib/charsets.jar:"); + bcpMember.append(javaHome).append("/bin/default/jclSC170/vm.jar:"); + bcp.createPathElement().setPath(bcpMember.toString()); + bcpMember.replace(javaHome.length(), bcpMember.length(), "/lib/ppc/default/jclSC170/vm.jar:"); + bcp.createPathElement().setPath(bcpMember.toString()); + bcpMember.replace(javaHome.length(), bcpMember.length(), "/lib/charsets.jar:"); bcp.createPathElement().setPath(bcpMember.toString()); bcpMember.replace(javaHome.length(), bcpMember.length(), "/lib/core.jar:"); bcp.createPathElement().setPath(bcpMember.toString()); + bcpMember.replace(javaHome.length(), bcpMember.length(), "/lib/math.jar:"); + bcp.createPathElement().setPath(bcpMember.toString()); bcpMember.replace(javaHome.length(), bcpMember.length(), "/lib/vm.jar:"); bcp.createPathElement().setPath(bcpMember.toString()); bcpMember.replace(javaHome.length(), bcpMember.length(), "/lib/java.util.jar:"); diff --git a/Xerces-J-src.2.11.0.tar.gz b/Xerces-J-src.2.11.0.tar.gz deleted file mode 100644 index b01f77d..0000000 Binary files a/Xerces-J-src.2.11.0.tar.gz and /dev/null differ diff --git a/Xerces-J-src.2.12.2.tar.gz b/Xerces-J-src.2.12.2.tar.gz new file mode 100644 index 0000000..c17e4eb Binary files /dev/null and b/Xerces-J-src.2.12.2.tar.gz differ diff --git a/xerces-j2-CVE-2013-4002.patch b/xerces-j2-CVE-2013-4002.patch deleted file mode 100644 index 30d477a..0000000 --- a/xerces-j2-CVE-2013-4002.patch +++ /dev/null @@ -1,47 +0,0 @@ ---- a/src/org/apache/xerces/impl/XMLScanner.java 2013/07/03 18:25:06 1499505 -+++ b/src/org/apache/xerces/impl/XMLScanner.java 2013/07/03 18:29:43 1499506 -@@ -542,7 +542,7 @@ - // document is until we scan the encoding declaration - // you cannot reliably read any characters outside - // of the ASCII range here. -- mrglavas -- String name = fEntityScanner.scanName(); -+ String name = scanPseudoAttributeName(); - XMLEntityManager.print(fEntityManager.getCurrentEntity()); - if (name == null) { - reportFatalError("PseudoAttrNameExpected", null); -@@ -599,6 +599,35 @@ - } // scanPseudoAttribute(XMLString):String - - /** -+ * Scans the name of a pseudo attribute. The only legal names -+ * in XML 1.0/1.1 documents are 'version', 'encoding' and 'standalone'. -+ * -+ * @return the name of the pseudo attribute or null -+ * if a legal pseudo attribute name could not be scanned. -+ */ -+ private String scanPseudoAttributeName() throws IOException, XNIException { -+ final int ch = fEntityScanner.peekChar(); -+ switch (ch) { -+ case 'v': -+ if (fEntityScanner.skipString(fVersionSymbol)) { -+ return fVersionSymbol; -+ } -+ break; -+ case 'e': -+ if (fEntityScanner.skipString(fEncodingSymbol)) { -+ return fEncodingSymbol; -+ } -+ break; -+ case 's': -+ if (fEntityScanner.skipString(fStandaloneSymbol)) { -+ return fStandaloneSymbol; -+ } -+ break; -+ } -+ return null; -+ } // scanPseudoAttributeName() -+ -+ /** - * Scans a processing instruction. - *

- *

diff --git a/xerces-j2-build.patch b/xerces-j2-build.patch
index ef83b5d..700997d 100644
--- a/xerces-j2-build.patch
+++ b/xerces-j2-build.patch
@@ -39,7 +39,7 @@
      
      
-@@ -1231,30 +1206,6 @@
+@@ -1232,30 +1207,6 @@
      
      
diff --git a/xerces-j2-constants.sh b/xerces-j2-constants.sh
deleted file mode 100644
index e722360..0000000
--- a/xerces-j2-constants.sh
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/sh
-# 
-# Xerces-J2 constants script
-# JPackage Project (http://www.jpackage.org/)
-# $Id: xerces-j2-constants.sh,v 1.3 2005/05/26 14:21:22 gbenson Exp $
-
-# Source functions library
-. /usr/share/java-utils/java-functions
-
-# Configuration
-MAIN_CLASS=org.apache.xerces.impl.Constants
-
-# Set parameters
-set_jvm
-export CLASSPATH=$(build-classpath xerces-j2)
-set_flags $BASE_FLAGS
-set_options $BASE_OPTIONS
-
-# Let's start
-run "$@"
diff --git a/xerces-j2-manifest.patch b/xerces-j2-manifest.patch
index fe1b030..78085d8 100644
--- a/xerces-j2-manifest.patch
+++ b/xerces-j2-manifest.patch
@@ -1,17 +1,17 @@
---- a/src/manifest.xerces.orig	2010-11-26 22:42:07.000000000 +0200
-+++ b/src/manifest.xerces	2012-12-17 11:11:52.200392844 +0200
+--- a/src/manifest.xerces.orig	2021-03-12 13:20:16.568489549 +0000
++++ b/src/manifest.xerces	2021-03-12 13:22:20.091482375 +0000
 @@ -1,5 +1,14 @@
  Manifest-Version: 1.0
  Created-By: @java.version@ (@java.vendor@)
-+Bundle-RequiredExecutionEnvironment: J2SE-1.5
++Automatic-Module-Name: org.apache.xerces
 +Bundle-SymbolicName: org.apache.xerces
 +Bundle-ManifestVersion: 2
-+Bundle-Name: @impl.name@
-+Bundle-Localization: plugin
-+Bundle-Version: @impl.version@
 +Bundle-Vendor: Apache Software Foundation
-+Require-Bundle: system.bundle,javax.xml;visibility:=reexport, org.apache.xml.resolver;bundle-version="[1.2.0,2.0.0)";visibility:=reexport,org.apache.xml.serializer;bundle-version="[2.7.1,3.0.0)"
-+Export-Package: META-INF.services;version="@impl.version@",org.apache.html.dom;version="@impl.version@",org.apache.wml;version="@impl.version@",org.apache.wml.dom;version="@impl.version@",org.apache.xerces.dom;version="@impl.version@",org.apache.xerces.dom.events;version="@impl.version@",org.apache.xerces.dom3.as;version="@impl.version@",org.apache.xerces.impl;version="@impl.version@",org.apache.xerces.impl.dtd;version="@impl.version@",org.apache.xerces.impl.dtd.models;version="@impl.version@",org.apache.xerces.impl.dv;version="@impl.version@",org.apache.xerces.impl.dv.dtd;version="@impl.version@",org.apache.xerces.impl.dv.util;version="@impl.version@",org.apache.xerces.impl.dv.xs;version="@impl.version@",org.apache.xerces.impl.io;version="@impl.version@",org.apache.xerces.impl.msg;version="@impl.version@",org.apache.xerces.impl.validation;version="@impl.version@",org.apache.xerces.impl.xpath;version="@impl.version@",org.apache.xerces.impl.xpath.regex;version="@impl.version@",org.apache.xerces.impl.xs;version="@impl.version@",org.apache.xerces.impl.xs.identity;version="@impl.version@",org.apache.xerces.impl.xs.models;version="@impl.version@",org.apache.xerces.impl.xs.opti;version="@impl.version@",org.apache.xerces.impl.xs.traversers;version="@impl.version@",org.apache.xerces.impl.xs.util;version="@impl.version@",org.apache.xerces.jaxp;version="@impl.version@",org.apache.xerces.jaxp.datatype;version="@impl.version@",org.apache.xerces.jaxp.validation;version="@impl.version@",org.apache.xerces.parsers;version="@impl.version@",org.apache.xerces.stax;version="@impl.version@",org.apache.xerces.stax.events;version="@impl.version@",org.apache.xerces.util;version="@impl.version@",org.apache.xerces.xinclude;version="@impl.version@",org.apache.xerces.xni;version="@impl.version@",org.apache.xerces.xni.grammars;version="@impl.version@",org.apache.xerces.xni.parser;version="@impl.version@",org.apache.xerces.xpointer;version="@impl.version@",org.apache.xerces.xs;version="@impl.version@",org.apache.xerces.xs.datatypes;version="@impl.version@",org.apache.xml.serialize;version="@impl.version@",org.w3c.dom.html;version="@impl.version@"
++Import-Package: sun.io;resolution:=optional,javax.xml.datatype,javax.xml.namespace,javax.xml.parsers,javax.xml.stream,javax.xml.stream.events,javax.xml.transform,javax.xml.transform.dom,javax.xml.transform.sax,javax.xml.transform.stax,javax.xml.transform.stream,javax.xml.validation,org.apache.wml;version="[2.12,3)",org.apache.xerces.dom;version="[2.12,3)",org.apache.xerces.dom.events;version="[2.12,3)",org.apache.xerces.dom3.as;version="[2.12,3)",org.apache.xerces.impl;version="[2.12,3)",org.apache.xerces.impl.dtd;version="[2.12,3)",org.apache.xerces.impl.dtd.models;version="[2.12,3)",org.apache.xerces.impl.dv;version="[2.12,3)",org.apache.xerces.impl.dv.util;version="[2.12,3)",org.apache.xerces.impl.dv.xs;version="[2.12,3)",org.apache.xerces.impl.io;version="[2.12,3)",org.apache.xerces.impl.msg;version="[2.12,3)",org.apache.xerces.impl.validation;version="[2.12,3)",org.apache.xerces.impl.xpath;version="[2.12,3)",org.apache.xerces.impl.xpath.regex;version="[2.12,3)",org.apache.xerces.impl.xs;version="[2.12,3)",org.apache.xerces.impl.xs.identity;version="[2.12,3)",org.apache.xerces.impl.xs.models;version="[2.12,3)",org.apache.xerces.impl.xs.opti;version="[2.12,3)",org.apache.xerces.impl.xs.traversers;version="[2.12,3)",org.apache.xerces.impl.xs.util;version="[2.12,3)",org.apache.xerces.jaxp;version="[2.12,3)",org.apache.xerces.jaxp.datatype;version="[2.12,3)",org.apache.xerces.jaxp.validation;version="[2.12,3)",org.apache.xerces.parsers;version="[2.12,3)",org.apache.xerces.stax;version="[2.12,3)",org.apache.xerces.stax.events;version="[2.12,3)",org.apache.xerces.util;version="[2.12,3)",org.apache.xerces.xinclude;version="[2.12,3)",org.apache.xerces.xni;version="[2.12,3)",org.apache.xerces.xni.grammars;version="[2.12,3)",org.apache.xerces.xni.parser;version="[2.12,3)",org.apache.xerces.xpointer;version="[2.12,3)",org.apache.xerces.xs;version="[2.12,3)",org.apache.xerces.xs.datatypes;version="[2.12,3)",org.apache.xml.resolver,org.apache.xml.resolver.readers,org.apache.xml.serialize;version="[2.12,3)",org.w3c.dom,org.w3c.dom.events,org.w3c.dom.html;version="[2.12,3)",org.w3c.dom.ls,org.w3c.dom.ranges,org.w3c.dom.traversal,org.w3c.dom.views,org.xml.sax,org.xml.sax.ext,org.xml.sax.helpers
++Require-Capability: osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=1.8))"
++Export-Package: org.apache.xerces.impl;x-internal:=true;version="@impl.version@";uses:="org.apache.xerces.impl.dtd,org.apache.xerces.impl.validation,org.apache.xerces.util,org.apache.xerces.xni,org.apache.xerces.xni.grammars,org.apache.xerces.xni.parser,org.xml.sax",org.apache.xerces.impl.dtd;x-internal:=true;version="@impl.version@";uses:="org.apache.xerces.impl,org.apache.xerces.impl.dtd.models,org.apache.xerces.impl.dv,org.apache.xerces.impl.validation,org.apache.xerces.util,org.apache.xerces.xni,org.apache.xerces.xni.grammars,org.apache.xerces.xni.parser",org.apache.xerces.impl.dtd.models;x-internal:=true;version="@impl.version@";uses:="org.apache.xerces.xni",org.apache.xerces.impl.dv;x-internal:=true;version="@impl.version@";uses:="org.apache.xerces.impl.xs.util,org.apache.xerces.util,org.apache.xerces.xs",org.apache.xerces.impl.dv.dtd;x-internal:=true;version="@impl.version@";uses:="org.apache.xerces.impl.dv",org.apache.xerces.impl.dv.util;x-internal:=true;version="@impl.version@";uses:="org.apache.xerces.xs,org.apache.xerces.xs.datatypes",org.apache.xerces.impl.dv.xs;x-internal:=true;version="@impl.version@";uses:="javax.xml.datatype,org.apache.xerces.impl.dv,org.apache.xerces.impl.xs,org.apache.xerces.impl.xs.util,org.apache.xerces.util,org.apache.xerces.xs,org.apache.xerces.xs.datatypes,org.w3c.dom",org.apache.xerces.impl.io;x-internal:=true;version="@impl.version@";uses:="org.apache.xerces.util",org.apache.xerces.impl.msg;x-internal:=true;version="@impl.version@";uses:="org.apache.xerces.util",org.apache.xerces.impl.validation;x-internal:=true;version="@impl.version@";uses:="org.apache.xerces.impl.dv,org.apache.xerces.util,org.apache.xerces.xni",org.apache.xerces.impl.xpath;x-internal:=true;version="@impl.version@";uses:="org.apache.xerces.util,org.apache.xerces.xni",org.apache.xerces.impl.xpath.regex;x-internal:=true;version="@impl.version@",org.apache.xerces.impl.xs;x-internal:=true;version="@impl.version@";uses:="org.apache.xerces.dom,org.apache.xerces.impl,org.apache.xerces.impl.dv,org.apache.xerces.impl.dv.xs,org.apache.xerces.impl.validation,org.apache.xerces.impl.xs.identity,org.apache.xerces.impl.xs.models,org.apache.xerces.impl.xs.util,org.apache.xerces.util,org.apache.xerces.xni,org.apache.xerces.xni.grammars,org.apache.xerces.xni.parser,org.apache.xerces.xs,org.apache.xerces.xs.datatypes,org.w3c.dom,org.w3c.dom.ls",org.apache.xerces.impl.xs.identity;x-internal:=true;version="@impl.version@";uses:="org.apache.xerces.impl.xpath,org.apache.xerces.impl.xs,org.apache.xerces.util,org.apache.xerces.xni,org.apache.xerces.xs",org.apache.xerces.impl.xs.models;x-internal:=true;version="@impl.version@";uses:="org.apache.xerces.impl.dtd.models,org.apache.xerces.impl.xs,org.apache.xerces.xni,org.apache.xerces.xni.parser",org.apache.xerces.impl.xs.opti;x-internal:=true;version="@impl.version@";uses:="org.apache.xerces.impl,org.apache.xerces.impl.dv,org.apache.xerces.impl.validation,org.apache.xerces.parsers,org.apache.xerces.util,org.apache.xerces.xni,org.apache.xerces.xni.grammars,org.apache.xerces.xni.parser,org.w3c.dom",org.apache.xerces.impl.xs.traversers;x-internal:=true;version="@impl.version@";uses:="org.apache.xerces.impl.dv,org.apache.xerces.impl.xs,org.apache.xerces.impl.xs.util,org.apache.xerces.util,org.apache.xerces.xni,org.apache.xerces.xni.parser,org.w3c.dom",org.apache.xerces.impl.xs.util;x-internal:=true;version="@impl.version@";uses:="org.apache.xerces.impl.xs,org.apache.xerces.util,org.apache.xerces.xni,org.apache.xerces.xni.parser,org.apache.xerces.xs,org.apache.xerces.xs.datatypes,org.w3c.dom.ls",org.apache.html.dom;version="@impl.version@";uses:="org.apache.xerces.dom,org.w3c.dom,org.w3c.dom.html,org.xml.sax",org.apache.wml;version="@impl.version@";uses:="org.w3c.dom",org.apache.wml.dom;version="@impl.version@";uses:="org.apache.wml,org.apache.xerces.dom,org.w3c.dom",org.apache.xerces.dom;version="@impl.version@";uses:="org.apache.xerces.dom3.as,org.apache.xerces.impl,org.apache.xerces.impl.dv,org.apache.xerces.impl.validation,org.apache.xerces.impl.xs,org.apache.xerces.util,org.apache.xerces.xni,org.apache.xerces.xni.parser,org.apache.xerces.xs,org.w3c.dom,org.w3c.dom.events,org.w3c.dom.ls,org.w3c.dom.ranges,org.w3c.dom.traversal",org.apache.xerces.dom.events;version="@impl.version@";uses:="org.w3c.dom,org.w3c.dom.events,org.w3c.dom.views",org.apache.xerces.dom3.as;version="@impl.version@";uses:="org.w3c.dom,org.w3c.dom.ls",org.apache.xerces.jaxp;version="@impl.version@";uses:="javax.xml.parsers,javax.xml.validation,org.apache.xerces.parsers,org.apache.xerces.xs,org.w3c.dom,org.xml.sax,org.xml.sax.helpers",org.apache.xerces.jaxp.datatype;version="@impl.version@";uses:="javax.xml.datatype",org.apache.xerces.jaxp.validation;version="@impl.version@";uses:="javax.xml.transform,javax.xml.validation,org.apache.xerces.xni.grammars,org.w3c.dom.ls,org.xml.sax",org.apache.xerces.parsers;version="@impl.version@";uses:="org.apache.xerces.dom,org.apache.xerces.dom3.as,org.apache.xerces.impl,org.apache.xerces.impl.dtd,org.apache.xerces.impl.dv,org.apache.xerces.impl.validation,org.apache.xerces.impl.xs,org.apache.xerces.util,org.apache.xerces.xinclude,org.apache.xerces.xni,org.apache.xerces.xni.grammars,org.apache.xerces.xni.parser,org.apache.xerces.xs,org.w3c.dom,org.w3c.dom.ls,org.xml.sax,org.xml.sax.ext",org.apache.xerces.stax;version="@impl.version@";uses:="javax.xml.namespace,javax.xml.stream,javax.xml.stream.events",org.apache.xerces.stax.events;version="@impl.version@";uses:="javax.xml.namespace,javax.xml.stream,javax.xml.stream.events",org.apache.xerces.util;version="@impl.version@";uses:="javax.xml.namespace,javax.xml.stream,org.apache.xerces.dom,org.apache.xerces.impl,org.apache.xerces.xni,org.apache.xerces.xni.grammars,org.apache.xerces.xni.parser,org.w3c.dom,org.w3c.dom.ls,org.xml.sax,org.xml.sax.ext",org.apache.xerces.xinclude;version="@impl.version@";uses:="org.apache.xerces.impl,org.apache.xerces.util,org.apache.xerces.xni,org.apache.xerces.xni.parser,org.apache.xerces.xpointer",org.apache.xerces.xni;version="@impl.version@";uses:="org.apache.xerces.xni.parser",org.apache.xerces.xni.grammars;version="@impl.version@";uses:="org.apache.xerces.xni,org.apache.xerces.xni.parser,org.apache.xerces.xs",org.apache.xerces.xni.parser;version="@impl.version@";uses:="org.apache.xerces.xni",org.apache.xerces.xpointer;version="@impl.version@";uses:="org.apache.xerces.impl,org.apache.xerces.util,org.apache.xerces.xinclude,org.apache.xerces.xni,org.apache.xerces.xni.parser",org.apache.xerces.xs;version="@impl.version@";uses:="org.apache.xerces.xs.datatypes,org.w3c.dom,org.w3c.dom.ls",org.apache.xerces.xs.datatypes;version="@impl.version@";uses:="javax.xml.datatype,javax.xml.namespace,org.apache.xerces.xni,org.apache.xerces.xs",org.apache.xml.serialize;version="@impl.version@";uses:="org.apache.xerces.dom,org.apache.xerces.util,org.w3c.dom,org.w3c.dom.ls,org.xml.sax,org.xml.sax.ext",org.w3c.dom.html;version="@impl.version@";uses:="org.w3c.dom"
++Bundle-Name: @impl.name@
++Bundle-Version: @impl.version@
  
- Name: org/apache/xerces/impl/Version.class
+ Name: org/apache/xerces/impl/
  Comment: @impl.name@ 
diff --git a/xerces-j2-version.sh b/xerces-j2-version.sh
deleted file mode 100644
index bd5e7c2..0000000
--- a/xerces-j2-version.sh
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/sh
-# 
-# Xerces-J2 version script
-# JPackage Project (http://www.jpackage.org/)
-# $Id: xerces-j2-version.sh,v 1.3 2005/05/26 14:21:22 gbenson Exp $
-
-# Source functions library
-. /usr/share/java-utils/java-functions
-
-# Configuration
-MAIN_CLASS=org.apache.xerces.impl.Version
-
-# Set parameters
-set_jvm
-export CLASSPATH=$(build-classpath xerces-j2)
-set_flags $BASE_FLAGS
-set_options $BASE_OPTIONS
-
-# Let's start
-run "$@"
diff --git a/xerces-j2.spec b/xerces-j2.spec
index e0a6678..ddec672 100644
--- a/xerces-j2.spec
+++ b/xerces-j2.spec
@@ -1,29 +1,24 @@
 Name:          xerces-j2
-Version:       2.11.0
-Release:       37
+Version:       2.12.2
+Release:       1
 Summary:       Java XML parser
 License:       ASL 2.0 and W3C
 URL:           http://xerces.apache.org/xerces2-j/
 
-Source0:       http://archive.apache.org/dist/xerces/j/Xerces-J-src.%{version}.tar.gz
-Source1:       %{name}-version.sh
-Source2:       %{name}-constants.sh
+Source0:       http://mirror.ox.ac.uk/sites/rsync.apache.org/xerces/j/source/Xerces-J-src.%{version}.tar.gz
 Source11:      %{name}-version.1
 Source12:      %{name}-constants.1
-Source3:       https://svn.apache.org/repos/asf/xerces/java/tags/Xerces-J_2_11_0/tools/src/XJavac.java
-Source5:       https://svn.apache.org/repos/asf/xerces/java/tags/Xerces-J_2_11_0/tools/src/ExperimentalTaglet.java
-Source6:       https://svn.apache.org/repos/asf/xerces/java/tags/Xerces-J_2_11_0/tools/src/InternalTaglet.java
+Source3:       https://svn.apache.org/repos/asf/xerces/java/tags/Xerces-J_2_12_2/tools/src/XJavac.java
+Source5:       https://svn.apache.org/repos/asf/xerces/java/tags/Xerces-J_2_12_2/tools/src/ExperimentalTaglet.java
+Source6:       https://svn.apache.org/repos/asf/xerces/java/tags/Xerces-J_2_12_2/tools/src/InternalTaglet.java
 Source7:       %{name}-pom.xml
 
 Patch0:        %{name}-build.patch
 Patch1:        %{name}-manifest.patch
-Patch2:        xerces-j2-CVE-2013-4002.patch
-Patch3:        JIRA-Issue-1521-http-issues.apache.org-jira-browse-X.patch
-Patch4:        JIRA-Issue-1499-http-issues.apache.org-jira-browse-X.patch
-Patch5:        CVE-2012-0881.patch
 
 BuildRequires: javapackages-local ant apache-parent xalan-j2 >= 2.7.1
 BuildRequires: xml-commons-apis >= 1.4.01 xml-commons-resolver >= 1.2
+BuildRequires: java-1.8.0-openjdk-devel
 
 Requires:      xalan-j2 >= 2.7.1 xml-commons-resolver >= 1.2
 Requires:      xml-commons-apis >= 1.4.01 javapackages-tools
@@ -75,13 +70,14 @@ Obsoletes:      %{name}-javadoc-other < %{version}-%{release}
 Man pages and other related documents for %{name}.
 
 %prep
-%autosetup -p1 -n xerces-2_11_0
+%autosetup -p1 -n xerces-2_12_2
 install -d tools/org/apache/xerces/util
 install -d tools/bin
 cp -a %{SOURCE3} %{SOURCE5} %{SOURCE6} tools/org/apache/xerces/util
 find -name '*.class' -exec rm -f '{}' \;
 find -name '*.jar' -exec rm -f '{}' \;
 sed -i 's/\r//' LICENSE README NOTICE
+sed -i -e "s|additionalparam='|additionalparam='-Xdoclint:none |" build.xml
 %mvn_alias : xerces:xerces xerces:xmlParserAPIs apache:%{name}
 %mvn_file : %{name} jaxp_parser_impl
 
@@ -96,8 +92,8 @@ ln -sf $(build-classpath xml-commons-apis) xml-apis.jar
 ln -sf $(build-classpath xml-commons-resolver) resolver.jar
 ln -sf $(build-classpath %{name}) x.jar
 popd
-export ANT_OPTS="-Xmx256m -Djava.endorsed.dirs=$(pwd)/tools -Djava.awt.headless=true -Dbuild.sysclasspath=first -Ddisconnected=true"
-ant -Djavac.source=1.5 -Djavac.target=1.5 -Dbuild.compiler=modern clean jars javadocs
+export ANT_OPTS="-Xmx512m -Djava.awt.headless=true -Dbuild.sysclasspath=first -Ddisconnected=true"
+%ant -Djavac.source=1.6 -Djavac.target=1.6 -Dbuild.compiler=modern clean jars javadocs
 %mvn_artifact %{SOURCE7} build/xercesImpl.jar
 
 %install
@@ -112,8 +108,8 @@ cp -pr build/docs/javadocs/xerces2/* $RPM_BUILD_ROOT%{_javadocdir}/%{name}/impl
 cp -pr build/docs/javadocs/api/* $RPM_BUILD_ROOT%{_javadocdir}/%{name}/xs
 cp -pr build/docs/javadocs/xni/* $RPM_BUILD_ROOT%{_javadocdir}/%{name}/xni
 cp -pr build/docs/javadocs/other/* $RPM_BUILD_ROOT%{_javadocdir}/%{name}/other
-install -pD -m755 -T %{SOURCE1} $RPM_BUILD_ROOT%{_bindir}/%{name}-version
-install -pD -m755 -T %{SOURCE2} $RPM_BUILD_ROOT%{_bindir}/%{name}-constants
+%jpackage_script org.apache.xerces.impl.Version "" "" %{name} %{name}-version 1
+%jpackage_script org.apache.xerces.impl.Constants "" "" %{name} %{name}-constants 1
 install -d -m 755 $RPM_BUILD_ROOT%{_mandir}/man1
 install -p -m 644 %{SOURCE11} $RPM_BUILD_ROOT%{_mandir}/man1
 install -p -m 644 %{SOURCE12} $RPM_BUILD_ROOT%{_mandir}/man1
@@ -135,6 +131,9 @@ ln -sf %{name}.jar %{_javadir}/jaxp_parser_impl.jar
 %{_mandir}/*/*
 
 %changelog
+* Wed Apr 27 2022 yaoxin  - 2.12.2-1
+- Upgrade to 2.12.2 for fix CVE-2022-23437
+
 * Sat Sep 19 2020 wangxiao - 2.11.0-37
 - fix CVE-2012-0881
 * Mon Feb 17 2020 zhouyihang - 2.11.0-36