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/04 10:31:54 UTC

svn commit: r1832811 - /santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/utils/XMLUtils.java

Author: coheigea
Date: Mon Jun  4 10:31:54 2018
New Revision: 1832811

URL: http://svn.apache.org/viewvc?rev=1832811&view=rev
Log:
Replacing ThreadLocals in XMLUtils with a cache again

Modified:
    santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/utils/XMLUtils.java

Modified: santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/utils/XMLUtils.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/utils/XMLUtils.java?rev=1832811&r1=1832810&r2=1832811&view=diff
==============================================================================
--- santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/utils/XMLUtils.java (original)
+++ santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/utils/XMLUtils.java Mon Jun  4 10:31:54 2018
@@ -25,12 +25,14 @@ import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.ArrayList;
 import java.util.Base64;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
+import java.util.WeakHashMap;
 
-import javax.xml.XMLConstants;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
@@ -55,15 +57,9 @@ public final class XMLUtils {
     private static boolean ignoreLineBreaks =
         AccessController.doPrivileged(
             (PrivilegedAction<Boolean>) () -> Boolean.getBoolean("org.apache.xml.security.ignoreLineBreaks"));
-    
-    @SuppressWarnings("unchecked")
-    private static final ThreadLocal<DocumentBuilder> tl[][] = new ThreadLocal[2][2];
-    static {
-        tl[0][0] = new MyThreadLocal(false, false);
-        tl[0][1] = new MyThreadLocal(false, true);
-        tl[1][0] = new MyThreadLocal(true, false);
-        tl[1][1] = new MyThreadLocal(true, true);
-    }
+
+    private static final Map<ClassLoader, DocumentBuilder[][]> DOCUMENT_BUILDERS =
+        Collections.synchronizedMap(new WeakHashMap<ClassLoader, DocumentBuilder[][]>());
 
     private static volatile String dsPrefix = "ds";
     private static volatile String ds11Prefix = "dsig11";
@@ -1061,9 +1057,9 @@ public final class XMLUtils {
     public static DocumentBuilder createDocumentBuilder(
         boolean validating, boolean disAllowDocTypeDeclarations
     ) throws ParserConfigurationException {
-        DocumentBuilder documentBuilder = tl[validating ? 1 : 0][disAllowDocTypeDeclarations ? 1 : 0].get();
-        documentBuilder.reset();
-        return documentBuilder;
+        DocumentBuilder db = getDocumentBuilder(validating, disAllowDocTypeDeclarations);
+        db.reset();
+        return db;
     }
 
     /**
@@ -1120,32 +1116,64 @@ public final class XMLUtils {
 
         return resizedBytes;
     }
-    
-    private static final class MyThreadLocal extends ThreadLocal<DocumentBuilder> {
-        private final boolean validating;
-        private final boolean disAllowDocTypeDeclarations;
-
-        public MyThreadLocal(boolean validating, boolean disAllowDocTypeDeclarations) {
-            this.validating = validating;
-            this.disAllowDocTypeDeclarations = disAllowDocTypeDeclarations;
+
+    private static DocumentBuilder getDocumentBuilder(boolean validating, boolean disAllowDocTypeDeclarations) throws ParserConfigurationException {
+        ClassLoader loader = getContextClassLoader();
+        if (loader == null) {
+            loader = getClassLoader(XMLUtils.class);
+        }
+        if (loader == null) {
+            return newDocumentBuilder(validating, disAllowDocTypeDeclarations);
         }
 
-        @Override
-        protected DocumentBuilder initialValue() {
-            try {
-                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);
+        DocumentBuilder[][] cacheValue = DOCUMENT_BUILDERS.get(loader);
+        if (cacheValue == null) {
+            cacheValue = new DocumentBuilder[2][2];
+            DOCUMENT_BUILDERS.put(loader, cacheValue);
+        }
+
+        DocumentBuilder db = cacheValue[validating ? 1 : 0][disAllowDocTypeDeclarations ? 1 : 0];
+        if (db == null) {
+            db = newDocumentBuilder(validating, disAllowDocTypeDeclarations);
+            cacheValue[validating ? 1 : 0][disAllowDocTypeDeclarations ? 1 : 0] = db;
+        }
+
+        return db;
+    }
+
+    private static DocumentBuilder newDocumentBuilder(boolean validating, boolean disAllowDocTypeDeclarations) throws ParserConfigurationException {
+        DocumentBuilderFactory f = DocumentBuilderFactory.newInstance();
+        f.setNamespaceAware(true);
+        f.setFeature(javax.xml.XMLConstants.FEATURE_SECURE_PROCESSING, true);
+        if (disAllowDocTypeDeclarations) {
+            f.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
+        }
+        f.setValidating(validating);
+        return f.newDocumentBuilder();
+    }
+
+    private static ClassLoader getContextClassLoader() {
+        final SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
+                public ClassLoader run() {
+                    return Thread.currentThread().getContextClassLoader();
                 }
-                dfactory.setValidating(validating);        
-                dfactory.setNamespaceAware(true);
-                
-                return dfactory.newDocumentBuilder();
-            } catch (ParserConfigurationException e) {
-                throw new RuntimeException(e);
-            }
+            });
+        }
+        return Thread.currentThread().getContextClassLoader();
+    }
+
+    private static ClassLoader getClassLoader(final Class<?> clazz) {
+        final SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
+                public ClassLoader run() {
+                    return clazz.getClassLoader();
+                }
+            });
         }
+        return clazz.getClassLoader();
     }
 
 }