You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@santuario.apache.org by co...@apache.org on 2018/06/08 15:19:20 UTC
svn commit: r1833190 - in
/santuario/xml-security-java/branches/2.0.x-fixes/src:
main/java/org/apache/jcp/xml/dsig/internal/dom/
main/java/org/apache/xml/security/ main/java/org/apache/xml/security/c14n/
main/java/org/apache/xml/security/encryption/ ma...
Author: coheigea
Date: Fri Jun 8 15:19:20 2018
New Revision: 1833190
URL: http://svn.apache.org/viewvc?rev=1833190&view=rev
Log:
Revert "Revert "[SANTUARIO-394] - Performance issue with getting XML parsers. Thanks to Anli Shundi for the patch.""
This reverts commit 2ffbc438cf5aabafb1e7cf43f8782d3a203f5ae1.
Added:
santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/utils/WeakObjectPool.java
santuario/xml-security-java/branches/2.0.x-fixes/src/test/java/org/apache/xml/security/test/dom/utils/DocumentBuilderPoolingTest.java
Modified:
santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/jcp/xml/dsig/internal/dom/DOMRetrievalMethod.java
santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/Init.java
santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/c14n/Canonicalizer.java
santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/c14n/CanonicalizerSpi.java
santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/encryption/DocumentSerializer.java
santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/keys/keyresolver/KeyResolverSpi.java
santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/keys/keyresolver/implementations/KeyInfoReferenceResolver.java
santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/keys/keyresolver/implementations/RetrievalMethodResolver.java
santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/signature/SignedInfo.java
santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/signature/XMLSignatureInput.java
santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/utils/XMLUtils.java
santuario/xml-security-java/branches/2.0.x-fixes/src/test/java/org/apache/xml/security/test/dom/secure_val/ForbiddenReferenceTest.java
santuario/xml-security-java/branches/2.0.x-fixes/src/test/java/org/apache/xml/security/test/dom/signature/SignatureReferenceTest.java
Modified: santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/jcp/xml/dsig/internal/dom/DOMRetrievalMethod.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/jcp/xml/dsig/internal/dom/DOMRetrievalMethod.java?rev=1833190&r1=1833189&r2=1833190&view=diff
==============================================================================
--- santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/jcp/xml/dsig/internal/dom/DOMRetrievalMethod.java (original)
+++ santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/jcp/xml/dsig/internal/dom/DOMRetrievalMethod.java Fri Jun 8 15:19:20 2018
@@ -35,13 +35,25 @@ import java.io.ByteArrayInputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.Provider;
-import java.util.*;
-
-import javax.xml.crypto.*;
-import javax.xml.crypto.dsig.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.xml.crypto.Data;
+import javax.xml.crypto.MarshalException;
+import javax.xml.crypto.NodeSetData;
+import javax.xml.crypto.URIDereferencer;
+import javax.xml.crypto.URIReferenceException;
+import javax.xml.crypto.XMLCryptoContext;
+import javax.xml.crypto.XMLStructure;
import javax.xml.crypto.dom.DOMURIReference;
+import javax.xml.crypto.dsig.Transform;
+import javax.xml.crypto.dsig.XMLSignature;
import javax.xml.crypto.dsig.keyinfo.RetrievalMethod;
-import javax.xml.parsers.*;
+import javax.xml.parsers.DocumentBuilder;
+
+import org.apache.xml.security.utils.XMLUtils;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
@@ -254,11 +266,11 @@ public final class DOMRetrievalMethod ex
public XMLStructure dereferenceAsXMLStructure(XMLCryptoContext context)
throws URIReferenceException
{
+ DocumentBuilder db = null;
+ boolean secVal = Utils.secureValidation(context);
try {
ApacheData data = (ApacheData)dereference(context);
- boolean secVal = Utils.secureValidation(context);
- DocumentBuilder db =
- org.apache.xml.security.utils.XMLUtils.createDocumentBuilder(false, secVal);
+ db = XMLUtils.createDocumentBuilder(false, secVal);
Document doc = db.parse(new ByteArrayInputStream
(data.getXMLSignatureInput().getBytes()));
Element kiElem = doc.getDocumentElement();
@@ -270,6 +282,10 @@ public final class DOMRetrievalMethod ex
}
} catch (Exception e) {
throw new URIReferenceException(e);
+ } finally {
+ if (db != null) {
+ XMLUtils.repoolDocumentBuilder(db);
+ }
}
}
Modified: santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/Init.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/Init.java?rev=1833190&r1=1833189&r2=1833190&view=diff
==============================================================================
--- santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/Init.java (original)
+++ santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/Init.java Fri Jun 8 15:19:20 2018
@@ -158,7 +158,13 @@ public class Init {
try {
/* read library configuration file */
DocumentBuilder db = XMLUtils.createDocumentBuilder(false);
- Document doc = db.parse(is);
+ Document doc;
+ try {
+ doc = db.parse(is);
+ } finally {
+ XMLUtils.repoolDocumentBuilder(db);
+ db = null;
+ }
Node config = doc.getFirstChild();
for (; config != null; config = config.getNextSibling()) {
if ("Configuration".equals(config.getLocalName())) {
Modified: santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/c14n/Canonicalizer.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/c14n/Canonicalizer.java?rev=1833190&r1=1833189&r2=1833190&view=diff
==============================================================================
--- santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/c14n/Canonicalizer.java (original)
+++ santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/c14n/Canonicalizer.java Fri Jun 8 15:19:20 2018
@@ -281,7 +281,12 @@ public class Canonicalizer {
*/
db.setErrorHandler(new org.apache.xml.security.utils.IgnoreAllErrorHandler());
- Document document = db.parse(in);
+ Document document;
+ try {
+ document = db.parse(in);
+ } finally {
+ XMLUtils.repoolDocumentBuilder(db);
+ }
return this.canonicalizeSubtree(document);
}
Modified: santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/c14n/CanonicalizerSpi.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/c14n/CanonicalizerSpi.java?rev=1833190&r1=1833189&r2=1833190&view=diff
==============================================================================
--- santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/c14n/CanonicalizerSpi.java (original)
+++ santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/c14n/CanonicalizerSpi.java Fri Jun 8 15:19:20 2018
@@ -61,7 +61,12 @@ public abstract class CanonicalizerSpi {
DocumentBuilder db = XMLUtils.createDocumentBuilder(false, secureValidation);
- Document document = db.parse(in);
+ Document document;
+ try {
+ document = db.parse(in);
+ } finally {
+ XMLUtils.repoolDocumentBuilder(db);
+ }
return this.engineCanonicalizeSubTree(document);
}
Modified: santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/encryption/DocumentSerializer.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/encryption/DocumentSerializer.java?rev=1833190&r1=1833189&r2=1833190&view=diff
==============================================================================
--- santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/encryption/DocumentSerializer.java (original)
+++ santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/encryption/DocumentSerializer.java Fri Jun 8 15:19:20 2018
@@ -67,8 +67,9 @@ public class DocumentSerializer extends
* @throws XMLEncryptionException
*/
private Node deserialize(Node ctx, InputSource inputSource) throws XMLEncryptionException {
+ DocumentBuilder db = null;
try {
- DocumentBuilder db = XMLUtils.createDocumentBuilder(false, secureValidation);
+ db = XMLUtils.createDocumentBuilder(false, secureValidation);
Document d = db.parse(inputSource);
Document contextDocument = null;
@@ -94,6 +95,10 @@ public class DocumentSerializer extends
throw new XMLEncryptionException(pce);
} catch (IOException ioe) {
throw new XMLEncryptionException(ioe);
+ } finally {
+ if (db != null) {
+ XMLUtils.repoolDocumentBuilder(db);
+ }
}
}
Modified: santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/keys/keyresolver/KeyResolverSpi.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/keys/keyresolver/KeyResolverSpi.java?rev=1833190&r1=1833189&r2=1833190&view=diff
==============================================================================
--- santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/keys/keyresolver/KeyResolverSpi.java (original)
+++ santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/keys/keyresolver/KeyResolverSpi.java Fri Jun 8 15:19:20 2018
@@ -261,6 +261,7 @@ public abstract class KeyResolverSpi {
this.globalResolver = globalResolver;
}
+
/**
* Parses a byte array and returns the parsed Element.
*
@@ -280,6 +281,10 @@ public abstract class KeyResolverSpi {
throw new KeyResolverException(ex);
} catch (ParserConfigurationException ex) {
throw new KeyResolverException(ex);
+ } finally {
+ if (db != null) {
+ XMLUtils.repoolDocumentBuilder(db);
+ }
}
}
Modified: santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/keys/keyresolver/implementations/KeyInfoReferenceResolver.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/keys/keyresolver/implementations/KeyInfoReferenceResolver.java?rev=1833190&r1=1833189&r2=1833190&view=diff
==============================================================================
--- santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/keys/keyresolver/implementations/KeyInfoReferenceResolver.java (original)
+++ santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/keys/keyresolver/implementations/KeyInfoReferenceResolver.java Fri Jun 8 15:19:20 2018
@@ -271,5 +271,4 @@ public class KeyInfoReferenceResolver ex
}
return e;
}
-
}
Modified: santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/keys/keyresolver/implementations/RetrievalMethodResolver.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/keys/keyresolver/implementations/RetrievalMethodResolver.java?rev=1833190&r1=1833189&r2=1833190&view=diff
==============================================================================
--- santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/keys/keyresolver/implementations/RetrievalMethodResolver.java (original)
+++ santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/keys/keyresolver/implementations/RetrievalMethodResolver.java Fri Jun 8 15:19:20 2018
@@ -309,7 +309,7 @@ public class RetrievalMethodResolver ext
}
return resource;
}
-
+
/**
* Method engineResolveSecretKey
* @inheritDoc
Modified: santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/signature/SignedInfo.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/signature/SignedInfo.java?rev=1833190&r1=1833189&r2=1833190&view=diff
==============================================================================
--- santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/signature/SignedInfo.java (original)
+++ santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/signature/SignedInfo.java Fri Jun 8 15:19:20 2018
@@ -21,6 +21,7 @@ package org.apache.xml.security.signatur
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.OutputStream;
+
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.parsers.ParserConfigurationException;
@@ -30,9 +31,9 @@ import org.apache.xml.security.c14n.Cano
import org.apache.xml.security.c14n.Canonicalizer;
import org.apache.xml.security.c14n.InvalidCanonicalizerException;
import org.apache.xml.security.exceptions.XMLSecurityException;
+import org.apache.xml.security.transforms.params.InclusiveNamespaces;
import org.apache.xml.security.utils.Constants;
import org.apache.xml.security.utils.XMLUtils;
-import org.apache.xml.security.transforms.params.InclusiveNamespaces;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
@@ -210,17 +211,18 @@ public class SignedInfo extends Manifest
c14nizer.setSecureValidation(secureValidation);
byte[] c14nizedBytes = c14nizer.canonicalizeSubtree(element);
-
- javax.xml.parsers.DocumentBuilder db =
- XMLUtils.createDocumentBuilder(false, secureValidation);
- Document newdoc =
- db.parse(new ByteArrayInputStream(c14nizedBytes));
- Node imported =
- element.getOwnerDocument().importNode(newdoc.getDocumentElement(), true);
-
- element.getParentNode().replaceChild(imported, element);
-
- return (Element) imported;
+ javax.xml.parsers.DocumentBuilder db =
+ XMLUtils.createDocumentBuilder(false, secureValidation);
+ try {
+ Document newdoc = db.parse(new ByteArrayInputStream(
+ c14nizedBytes));
+ Node imported = element.getOwnerDocument().importNode(
+ newdoc.getDocumentElement(), true);
+ element.getParentNode().replaceChild(imported, element);
+ return (Element) imported;
+ } finally {
+ XMLUtils.repoolDocumentBuilder(db);
+ }
} catch (ParserConfigurationException ex) {
throw new XMLSecurityException(ex);
} catch (IOException ex) {
Modified: santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/signature/XMLSignatureInput.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/signature/XMLSignatureInput.java?rev=1833190&r1=1833189&r2=1833190&view=diff
==============================================================================
--- santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/signature/XMLSignatureInput.java (original)
+++ santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/signature/XMLSignatureInput.java Fri Jun 8 15:19:20 2018
@@ -32,9 +32,9 @@ import javax.xml.parsers.DocumentBuilder
import javax.xml.parsers.ParserConfigurationException;
import org.apache.xml.security.c14n.CanonicalizationException;
-import org.apache.xml.security.c14n.implementations.CanonicalizerBase;
-import org.apache.xml.security.c14n.implementations.Canonicalizer20010315OmitComments;
import org.apache.xml.security.c14n.implementations.Canonicalizer11_OmitComments;
+import org.apache.xml.security.c14n.implementations.Canonicalizer20010315OmitComments;
+import org.apache.xml.security.c14n.implementations.CanonicalizerBase;
import org.apache.xml.security.exceptions.XMLSecurityRuntimeException;
import org.apache.xml.security.utils.JavaUtils;
import org.apache.xml.security.utils.XMLUtils;
@@ -587,8 +587,9 @@ public class XMLSignatureInput {
byte result[] = baos.toByteArray();
Document document = db.parse(new ByteArrayInputStream(result));
- this.subNode = document.getDocumentElement().getFirstChild().getFirstChild();
+ this.subNode = document.getDocumentElement().getFirstChild().getFirstChild();
} finally {
+ XMLUtils.repoolDocumentBuilder(db);
if (this.inputOctetStreamProxy != null) {
this.inputOctetStreamProxy.close();
}
Added: santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/utils/WeakObjectPool.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/utils/WeakObjectPool.java?rev=1833190&view=auto
==============================================================================
--- santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/utils/WeakObjectPool.java (added)
+++ santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/utils/WeakObjectPool.java Fri Jun 8 15:19:20 2018
@@ -0,0 +1,114 @@
+/**
+ * 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.xml.security.utils;
+
+import java.lang.ref.WeakReference;
+import java.util.Collections;
+import java.util.Map;
+import java.util.WeakHashMap;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingDeque;
+
+/**
+ * Abstract base class for pooling objects. The two public methods are
+ * {@link #getObject()} and ({@link #repool(Object)}. Objects are held through
+ * weak references so even objects that are not repooled are subject to garbage collection.
+ *
+ * Subclasses must implement the abstract {@link #createObject()}.
+ * <p>
+ *
+ * Internally, the pool is stored in a java.util.concurrent.LinkedBlockingDeque
+ * instance.
+ */
+public abstract class WeakObjectPool<T, E extends Throwable> {
+
+ private static final Integer MARKER_VALUE = Integer.MAX_VALUE;//once here rather than auto-box it?
+
+ /** created, available objects to be checked out to clients */
+ private final BlockingQueue<WeakReference<T>> available;
+
+ /**
+ * Synchronized, identity map of loaned out objects (WeakHashMap);
+ * use to ensure we repool only object originating from here
+ * and do it once.
+ */
+ private final Map<T, Integer> onLoan;
+
+ /**
+ * The lone constructor.
+ */
+ protected WeakObjectPool() {
+ //alternative implementations: ArrayBlockingQueue has a fixed size
+ // PriorityBlockingQueue: requires a dummy comparator; less memory but more overhead
+ available = new LinkedBlockingDeque<WeakReference<T>>();
+ this.onLoan = Collections.synchronizedMap(new WeakHashMap<T, Integer>());
+ }
+
+ /**
+ * Called whenever a new pool object is desired; subclasses must implement.
+ *
+ * @return object of the type desired by the subclass
+ * @throws parameterizable Throwable's subclass
+ */
+ protected abstract T createObject() throws E;
+
+
+ /**
+ * Subclasses can subclass to return a more specific type.
+ *
+ * @return an object from the pool; will block until an object is available
+ * @throws E
+ */
+ public T getObject() throws E {
+ WeakReference<T> ref;
+ T retValue = null;
+ do {
+ //remove any stale entries as well
+ ref = available.poll();
+ } while (ref != null && (retValue = ref.get()) == null);
+
+ if (retValue == null) {
+ //empty pool; create & add new one
+ retValue = createObject();
+ }
+ onLoan.put(retValue, MARKER_VALUE);
+ return retValue;
+ }
+
+
+ /**
+ * Adds the given object to the pool, provided that the object
+ * was created by this pool.
+ *
+ * @param obj the object to return to the pool
+ * @return whether the object was successfully added as available
+ */
+ public boolean repool(T obj) {
+ if (obj != null && onLoan.containsKey(obj)) {
+ //synchronize to protect against a caller returning the same object again...
+ synchronized (obj) {
+ //...and check to see that it was removed
+ if (onLoan.remove(obj) != null) {
+ return available.offer(new WeakReference<T>(obj));
+ }
+ }
+ }
+ return false;
+ }
+}
Modified: santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/utils/XMLUtils.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/utils/XMLUtils.java?rev=1833190&r1=1833189&r2=1833190&view=diff
==============================================================================
--- santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/utils/XMLUtils.java (original)
+++ santuario/xml-security-java/branches/2.0.x-fixes/src/main/java/org/apache/xml/security/utils/XMLUtils.java Fri Jun 8 15:19:20 2018
@@ -18,7 +18,9 @@
*/
package org.apache.xml.security.utils;
+import java.io.File;
import java.io.IOException;
+import java.io.InputStream;
import java.io.OutputStream;
import java.security.AccessController;
import java.security.PrivilegedAction;
@@ -32,17 +34,23 @@ import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.validation.Schema;
import org.apache.xml.security.c14n.CanonicalizationException;
import org.apache.xml.security.c14n.Canonicalizer;
import org.apache.xml.security.c14n.InvalidCanonicalizerException;
import org.w3c.dom.Attr;
+import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
/**
* DOM and XML accessibility and comfort functions.
@@ -59,6 +67,15 @@ public final class XMLUtils {
}
});
+ @SuppressWarnings("unchecked")
+ private static final WeakObjectPool<DocumentBuilder, ParserConfigurationException> pools[] = new WeakObjectPool[4];
+ static {
+ pools[0] = new DocumentBuilderPool(false, false);
+ pools[1] = new DocumentBuilderPool(false, true);
+ pools[2] = new DocumentBuilderPool(true, false);
+ pools[3] = new DocumentBuilderPool(true, true);
+ }
+
private static volatile String dsPrefix = "ds";
private static volatile String ds11Prefix = "dsig11";
private static volatile String xencPrefix = "xenc";
@@ -1052,25 +1069,143 @@ public final class XMLUtils {
public static DocumentBuilder createDocumentBuilder(
boolean validating, boolean disAllowDocTypeDeclarations
) throws ParserConfigurationException {
- DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance();
- dfactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, Boolean.TRUE);
- if (disAllowDocTypeDeclarations) {
- dfactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
- }
- dfactory.setValidating(validating);
- dfactory.setNamespaceAware(true);
-
- return dfactory.newDocumentBuilder();
+ int idx = getPoolsIndex(validating, disAllowDocTypeDeclarations);
+ return pools[idx].getObject();
}
+
/**
* Return this document builder to be reused
* @param db DocumentBuilder returned from any of {@link #createDocumentBuilder} methods.
* @return whether it was successfully returned to the pool
*/
- @Deprecated
public static boolean repoolDocumentBuilder(DocumentBuilder db) {
- return true;
+ if (!(db instanceof DocumentBuilderProxy)) {
+ return false;
+ }
+ db.reset();
+ boolean disAllowDocTypeDeclarations =
+ ((DocumentBuilderProxy)db).disAllowDocTypeDeclarations();
+ int idx = getPoolsIndex(db.isValidating(), disAllowDocTypeDeclarations);
+ return pools[idx].repool(db);
+ }
+
+
+ /**
+ * We need this proxy wrapping DocumentBuilder to record the value
+ * passed to disAllowDoctypeDeclarations. It's needed to figure out
+ * on which pool to return.
+ */
+ private static class DocumentBuilderProxy extends DocumentBuilder {
+ private final DocumentBuilder delegate;
+ private final boolean disAllowDocTypeDeclarations;
+
+ private DocumentBuilderProxy(DocumentBuilder actual, boolean disAllowDocTypeDeclarations) {
+ delegate = actual;
+ this.disAllowDocTypeDeclarations = disAllowDocTypeDeclarations;
+ }
+
+ boolean disAllowDocTypeDeclarations() {
+ return disAllowDocTypeDeclarations;
+ }
+
+ public void reset() {
+ delegate.reset();
+ }
+
+ public Document parse(InputStream is) throws SAXException, IOException {
+ return delegate.parse(is);
+ }
+
+ public Document parse(InputStream is, String systemId)
+ throws SAXException, IOException {
+ return delegate.parse(is, systemId);
+ }
+
+ public Document parse(String uri) throws SAXException, IOException {
+ return delegate.parse(uri);
+ }
+
+ public Document parse(File f) throws SAXException, IOException {
+ return delegate.parse(f);
+ }
+
+ public Schema getSchema() {
+ return delegate.getSchema();
+ }
+
+ public boolean isXIncludeAware() {
+ return delegate.isXIncludeAware();
+ }
+
+ @Override
+ public Document parse(InputSource is) throws SAXException, IOException {
+ return delegate.parse(is);
+ }
+
+ @Override
+ public boolean isNamespaceAware() {
+ return delegate.isNamespaceAware();
+ }
+
+ @Override
+ public boolean isValidating() {
+ return delegate.isValidating();
+ }
+
+ @Override
+ public void setEntityResolver(EntityResolver er) {
+ delegate.setEntityResolver(er);
+ }
+
+ @Override
+ public void setErrorHandler(ErrorHandler eh) {
+ delegate.setErrorHandler(eh);
+ }
+
+ @Override
+ public Document newDocument() {
+ return delegate.newDocument();
+ }
+
+ @Override
+ public DOMImplementation getDOMImplementation() {
+ return delegate.getDOMImplementation();
+ }
+
+ }
+
+ private static final class DocumentBuilderPool
+ extends WeakObjectPool<DocumentBuilder, ParserConfigurationException> {
+
+ private final boolean validating, disAllowDocTypeDeclarations;
+
+ public DocumentBuilderPool(boolean validating, boolean disAllowDocTypeDeclarations) {
+ this.validating = validating;
+ this.disAllowDocTypeDeclarations = disAllowDocTypeDeclarations;
+ }
+
+ @Override
+ protected DocumentBuilder createObject() throws ParserConfigurationException {
+ DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance();
+ dfactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, Boolean.TRUE);
+ if (disAllowDocTypeDeclarations) {
+ dfactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
+ }
+ dfactory.setValidating(validating);
+ dfactory.setNamespaceAware(true);
+ return new DocumentBuilderProxy(dfactory.newDocumentBuilder(), disAllowDocTypeDeclarations);
+ }
+ }
+
+ /**
+ * Maps the two boolean configuration options for the factories to the array index for the WeakObjectPool
+ * @param validating
+ * @param disAllowDocTypeDeclarations
+ * @return the index to the {@link #pools}
+ */
+ private static int getPoolsIndex(boolean validating, boolean disAllowDocTypeDeclarations) {
+ return (validating ? 2 : 0) + (disAllowDocTypeDeclarations ? 1 : 0);
}
}
Modified: santuario/xml-security-java/branches/2.0.x-fixes/src/test/java/org/apache/xml/security/test/dom/secure_val/ForbiddenReferenceTest.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/branches/2.0.x-fixes/src/test/java/org/apache/xml/security/test/dom/secure_val/ForbiddenReferenceTest.java?rev=1833190&r1=1833189&r2=1833190&view=diff
==============================================================================
--- santuario/xml-security-java/branches/2.0.x-fixes/src/test/java/org/apache/xml/security/test/dom/secure_val/ForbiddenReferenceTest.java (original)
+++ santuario/xml-security-java/branches/2.0.x-fixes/src/test/java/org/apache/xml/security/test/dom/secure_val/ForbiddenReferenceTest.java Fri Jun 8 15:19:20 2018
@@ -71,6 +71,7 @@ public class ForbiddenReferenceTest exte
javax.xml.parsers.DocumentBuilder db = XMLUtils.createDocumentBuilder(false);
org.w3c.dom.Document doc = db.parse(f);
+ XMLUtils.repoolDocumentBuilder(db);
Element manifestElement =
(Element) doc.getElementsByTagNameNS(Constants.SignatureSpecNS,
Modified: santuario/xml-security-java/branches/2.0.x-fixes/src/test/java/org/apache/xml/security/test/dom/signature/SignatureReferenceTest.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/branches/2.0.x-fixes/src/test/java/org/apache/xml/security/test/dom/signature/SignatureReferenceTest.java?rev=1833190&r1=1833189&r2=1833190&view=diff
==============================================================================
--- santuario/xml-security-java/branches/2.0.x-fixes/src/test/java/org/apache/xml/security/test/dom/signature/SignatureReferenceTest.java (original)
+++ santuario/xml-security-java/branches/2.0.x-fixes/src/test/java/org/apache/xml/security/test/dom/signature/SignatureReferenceTest.java Fri Jun 8 15:19:20 2018
@@ -125,6 +125,8 @@ public class SignatureReferenceTest exte
referenceElement.appendChild(digestValue);
new WrappedReference(referenceElement, "_54321", null);
+
+ XMLUtils.repoolDocumentBuilder(db);
}
/**
Added: santuario/xml-security-java/branches/2.0.x-fixes/src/test/java/org/apache/xml/security/test/dom/utils/DocumentBuilderPoolingTest.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/branches/2.0.x-fixes/src/test/java/org/apache/xml/security/test/dom/utils/DocumentBuilderPoolingTest.java?rev=1833190&view=auto
==============================================================================
--- santuario/xml-security-java/branches/2.0.x-fixes/src/test/java/org/apache/xml/security/test/dom/utils/DocumentBuilderPoolingTest.java (added)
+++ santuario/xml-security-java/branches/2.0.x-fixes/src/test/java/org/apache/xml/security/test/dom/utils/DocumentBuilderPoolingTest.java Fri Jun 8 15:19:20 2018
@@ -0,0 +1,176 @@
+/**
+ * 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.xml.security.test.dom.utils;
+
+import org.apache.xml.security.utils.WeakObjectPool;
+import org.apache.xml.security.utils.XMLUtils;
+import org.junit.Test;
+
+import javax.xml.parsers.DocumentBuilder;
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Field;
+import java.util.Iterator;
+import java.util.concurrent.*;
+
+import static org.junit.Assert.*;
+
+public class DocumentBuilderPoolingTest {
+
+ private static final String DOCUMENTBUILDERPROXY_CLASSNAME =
+ "org.apache.xml.security.utils.XMLUtils$DocumentBuilderProxy";
+
+ @Test
+ public void testEquals() throws Exception {
+ DocumentBuilder documentBuilder = XMLUtils.createDocumentBuilder(true);
+ assertEquals(documentBuilder, documentBuilder);
+ assertSame(documentBuilder, documentBuilder);
+ }
+
+ @Test
+ public void testGetValidatingDocumentBuilder() throws Exception {
+ DocumentBuilder documentBuilder = XMLUtils.createDocumentBuilder(true);
+ assertTrue(documentBuilder.isValidating());
+ }
+
+ @Test
+ public void testGetNonValidatingDocumentBuilder() throws Exception {
+ DocumentBuilder documentBuilder = XMLUtils.createDocumentBuilder(false);
+ assertFalse(documentBuilder.isValidating());
+ }
+
+ @Test
+ public void testGetValidatingAndAllowDocTypeDeclarationsDocumentBuilder() throws Exception {
+ DocumentBuilder documentBuilder = XMLUtils.createDocumentBuilder(true, false);
+ assertTrue(documentBuilder.isValidating());
+ assertEquals(documentBuilder.getClass().getName(), DOCUMENTBUILDERPROXY_CLASSNAME);
+ assertAllowDocTypeDeclarations(documentBuilder, false);
+ }
+
+ @Test
+ public void testGetValidatingAndDisAllowDocTypeDeclarationsDocumentBuilder() throws Exception {
+ DocumentBuilder documentBuilder = XMLUtils.createDocumentBuilder(true, true);
+ assertTrue(documentBuilder.isValidating());
+ assertEquals(documentBuilder.getClass().getName(), DOCUMENTBUILDERPROXY_CLASSNAME);
+ assertAllowDocTypeDeclarations(documentBuilder, true);
+ }
+
+ private void assertAllowDocTypeDeclarations(DocumentBuilder documentBuilder, boolean allow) throws Exception {
+ Field field = documentBuilder.getClass().getDeclaredField("disAllowDocTypeDeclarations");
+ field.setAccessible(true);
+ assertEquals(allow, field.get(documentBuilder));
+ }
+
+ @Test
+ public void testNewDocumentBuilderInstances() throws Exception {
+ int count = 4;
+
+ // get all possible combinations of DocumentBuilders:
+ DocumentBuilder[] documentBuilders = new DocumentBuilder[count];
+ for (int i = 0; i < count; i++) {
+ documentBuilders[i] = XMLUtils.createDocumentBuilder(i / 2 > 0, i % 2 == 1);
+ }
+
+ //test that we got always a new instance:
+ for (int i = 0; i < count; i++) {
+ for (int j = i + 1; j < count; j++) {
+ assertNotEquals(documentBuilders[i], documentBuilders[j]);
+ assertNotSame(documentBuilders[i], documentBuilders[j]);
+ }
+ }
+ }
+
+ @Test
+ public void testRepoolingTwice() throws Exception {
+ DocumentBuilder documentBuilder = XMLUtils.createDocumentBuilder(true);
+ assertTrue(XMLUtils.repoolDocumentBuilder(documentBuilder));
+ assertFalse("can't repool the same object twice!", XMLUtils.repoolDocumentBuilder(documentBuilder));
+ }
+
+ @Test(timeout = 30000)
+ public void testPooling() throws Exception {
+ int nThreads = 8;
+ ExecutorService exec = Executors.newFixedThreadPool(nThreads);
+ Future<?>[] results = new Future[nThreads];
+ for (int i = 0; i < nThreads - 1; i++) {
+ results[i] = exec.submit(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ while (true) {
+ // retrieve some DocumentBuilders...
+ DocumentBuilder documentBuilders[] = new DocumentBuilder[10];
+ for (int j = 0; j < documentBuilders.length; j++) {
+ documentBuilders[j] = XMLUtils.createDocumentBuilder(false);
+ assertNotNull(documentBuilders[j]);
+ }
+ // ...then repool them so that another thread may pickup them again
+ for (int j = 0; j < documentBuilders.length; j++) {
+ assertTrue(XMLUtils.repoolDocumentBuilder(documentBuilders[j]));
+ }
+ }
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
+ }
+ // more or less mimic gc
+ results[nThreads - 1] = exec.submit(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ final Field poolField = XMLUtils.class.getDeclaredField("pools");
+ poolField.setAccessible(true);
+ final WeakObjectPool[] weakObjectPools = (WeakObjectPool[]) poolField.get(null);
+
+ final Field availableField = WeakObjectPool.class.getDeclaredField("available");
+ availableField.setAccessible(true);
+
+ while (true) {
+ final BlockingDeque blockingDeque = (BlockingDeque) availableField.get(weakObjectPools[1]);
+ Iterator iterator = blockingDeque.iterator();
+ while (iterator.hasNext()) {
+ ((WeakReference) iterator.next()).clear();
+ }
+ Thread.sleep(200);
+ }
+ } catch (InterruptedException e) {
+ return;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
+
+ exec.shutdown();
+ exec.awaitTermination(5, TimeUnit.SECONDS);
+ for (Future<?> f : results) {
+ if (!f.isDone()) {
+ f.cancel(false);
+ }
+ try {
+ assertNull(f.get(1000, TimeUnit.MILLISECONDS));
+ } catch (CancellationException ce) {
+ //expected since we did cancel it
+ } catch (TimeoutException e) {
+ fail(f + "didn't cancel after timeout?");
+ }
+ }
+ }
+}