You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@santuario.apache.org by gi...@apache.org on 2015/02/03 20:22:18 UTC

svn commit: r1656896 - in /santuario/xml-security-java/trunk/src: main/java/org/apache/xml/security/utils/ test/java/org/apache/xml/security/test/dom/utils/

Author: giger
Date: Tue Feb  3 19:22:18 2015
New Revision: 1656896

URL: http://svn.apache.org/r1656896
Log:
- try to make DocumentBuilderPooling tests more reliable and additionally some small impl. fixes

Added:
    santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/dom/utils/DocumentBuilderPoolingTest.java
      - copied, changed from r1656879, santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/dom/utils/PoolingTest.java
Removed:
    santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/dom/utils/PoolingTest.java
Modified:
    santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/utils/WeakObjectPool.java
    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/WeakObjectPool.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/utils/WeakObjectPool.java?rev=1656896&r1=1656895&r2=1656896&view=diff
==============================================================================
--- santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/utils/WeakObjectPool.java (original)
+++ santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/utils/WeakObjectPool.java Tue Feb  3 19:22:18 2015
@@ -27,7 +27,7 @@ import java.util.concurrent.LinkedBlocki
 
 /**
  * Abstract base class for pooling objects.  The two public methods are
- * {@link #getObject()} and ({@link #repool()}.  Objects are held through
+ * {@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()}.
@@ -40,6 +40,16 @@ public abstract class WeakObjectPool<T,
 
     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.
      */
@@ -76,7 +86,6 @@ public abstract class WeakObjectPool<T,
         if (retValue == null) {
             //empty pool; create & add new one
             retValue = createObject();
-            ref = new WeakReference<T>(retValue);
         }
         onLoan.put(retValue, MARKER_VALUE);
         return retValue;
@@ -102,14 +111,4 @@ public abstract class WeakObjectPool<T,
         }
         return false;
     }
-
-    /** 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;
 }

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=1656896&r1=1656895&r2=1656896&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 Tue Feb  3 19:22:18 2015
@@ -1074,8 +1074,7 @@ public final class XMLUtils {
     /**
      * Return this document builder to be reused
      * @param db DocumentBuilder returned from any of {@link #createDocumentBuilder} methods.
-     * @param disAllowDocTypeDeclarations We can't figure out its value from the documentBuilder itself 
-     * @return whether it was successfully returned to the pool  
+     * @return whether it was successfully returned to the pool
      */
     public static boolean repoolDocumentBuilder(DocumentBuilder db) {
         if (db == null || !(db instanceof DocumentBuilderProxy)) {
@@ -1107,10 +1106,6 @@ public final class XMLUtils {
             return disAllowDocTypeDeclarations;
         }
         
-        public int hashCode() {
-            return delegate.hashCode();
-        }
-
         public void reset() {
             delegate.reset();
         }
@@ -1119,10 +1114,6 @@ public final class XMLUtils {
             return delegate.parse(is);
         }
 
-        public boolean equals(Object obj) {
-            return delegate.equals(obj);
-        }
-
         public Document parse(InputStream is, String systemId)
                 throws SAXException, IOException {
             return delegate.parse(is, systemId);
@@ -1136,10 +1127,6 @@ public final class XMLUtils {
             return delegate.parse(f);
         }
 
-        public String toString() {
-            return delegate.toString();
-        }
-
         public Schema getSchema() {
             return delegate.getSchema();
         }

Copied: santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/dom/utils/DocumentBuilderPoolingTest.java (from r1656879, santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/dom/utils/PoolingTest.java)
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/dom/utils/DocumentBuilderPoolingTest.java?p2=santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/dom/utils/DocumentBuilderPoolingTest.java&p1=santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/dom/utils/PoolingTest.java&r1=1656879&r2=1656896&rev=1656896&view=diff
==============================================================================
--- santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/dom/utils/PoolingTest.java (original)
+++ santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/dom/utils/DocumentBuilderPoolingTest.java Tue Feb  3 19:22:18 2015
@@ -18,125 +18,152 @@
  */
 package org.apache.xml.security.test.dom.utils;
 
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNotSame;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.util.Random;
-import java.util.concurrent.CancellationException;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
+import org.apache.xml.security.utils.WeakObjectPool;
+import org.apache.xml.security.utils.XMLUtils;
+import org.junit.Test;
 
 import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.ParserConfigurationException;
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Field;
+import java.util.Iterator;
+import java.util.concurrent.*;
 
-import org.apache.xml.security.utils.XMLUtils;
-import org.junit.Test;
+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);
+    }
 
-public class PoolingTest {
-    
     @Test
-    public void testPooling() throws ParserConfigurationException, InterruptedException, ExecutionException {
-        //assert parameters
-        DocumentBuilder db = XMLUtils.createDocumentBuilder(true);
-        assertTrue(db.isValidating());
-        DocumentBuilder db2 = XMLUtils.createDocumentBuilder(false);
-        assertFalse(db2.isValidating());
-        assertNotEquals(db2, db);
-        DocumentBuilder db3 = XMLUtils.createDocumentBuilder(true, false);
-        assertTrue(db3.isValidating());
-        DocumentBuilder db4 = XMLUtils.createDocumentBuilder(false, false);
-        assertFalse(db4.isValidating());
-        
-        //assert get
-        DocumentBuilder db_ = XMLUtils.createDocumentBuilder(true);
-        assertNotSame("db wasn't returned", db, db_);
-        DocumentBuilder db2_ = XMLUtils.createDocumentBuilder(false);
-        assertNotSame(db2, db2_);
-        DocumentBuilder db3_ = XMLUtils.createDocumentBuilder(true, false);
-        assertNotSame(db3, db3_);
-        DocumentBuilder db4_ = XMLUtils.createDocumentBuilder(false, false);
-        assertNotSame(db4, db4_);
-        
-        //assert get after return
-        assertTrue(XMLUtils.repoolDocumentBuilder(db_));
-        assertFalse("can't repool the same object twice!", XMLUtils.repoolDocumentBuilder(db_));
-        DocumentBuilder db_1 = XMLUtils.createDocumentBuilder(true);
-        assertSame(db_, db_1);
-        
-        assertTrue(XMLUtils.repoolDocumentBuilder(db2_));
-        assertFalse("can't repool the same object twice!", XMLUtils.repoolDocumentBuilder(db2_));
-        DocumentBuilder db_2 = XMLUtils.createDocumentBuilder(false);
-        assertSame(db2_, db_2);
-        
-        assertTrue(XMLUtils.repoolDocumentBuilder(db3_));
-        assertFalse("can't repool the same object twice!", XMLUtils.repoolDocumentBuilder(db3_));
-        DocumentBuilder db_3 = XMLUtils.createDocumentBuilder(true, false);
-        assertSame(db3_, db_3);
-        
-        assertTrue(XMLUtils.repoolDocumentBuilder(db4_));
-        assertFalse("can't repool the same object twice!", XMLUtils.repoolDocumentBuilder(db4_));
-        DocumentBuilder db_4 = XMLUtils.createDocumentBuilder(false, false);
-        assertSame(db4_, db_4);
-        
-//        final byte[] largeArrays[] = new byte[1024][];
-//        final DocumentBuilder[] dbLargeArrays = new DocumentBuilder[largeArrays.length];
+    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));
+    }
 
-        int nThreads = Runtime.getRuntime().availableProcessors();
+    @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++) {
+        Future<?>[] results = new Future[nThreads];
+        for (int i = 0; i < nThreads - 1; i++) {
             results[i] = exec.submit(new Runnable() {
                 @Override
                 public void run() {
-                    for(;;) {
-                        DocumentBuilder dbA[] = new DocumentBuilder[10];
-                        for (int i = 0; i < dbA.length; i++) {
-                            try {
-                                dbA[i] = XMLUtils.createDocumentBuilder(false);
-                                assertNotNull(dbA[i]);
-                            } catch (ParserConfigurationException e) {
-                                e.printStackTrace();
-                                fail(e.toString());
+                    try {
+                        while (true) {
+                            // retrieve some DocumentBuilders...
+                            DocumentBuilder documentBuilders[] = new DocumentBuilder[10];
+                            for (int i = 0; i < documentBuilders.length; i++) {
+                                documentBuilders[i] = XMLUtils.createDocumentBuilder(false);
+                                assertNotNull(documentBuilders[i]);
+                            }
+                            // ...then repool them so that another thread may pickup them again
+                            for (int i = 0; i < documentBuilders.length; i++) {
+                                assertTrue(XMLUtils.repoolDocumentBuilder(documentBuilders[i]));
                             }
-                            assertNotNull(dbA[i]);
-                        }
-                        for(int i = 0; i < new Random().nextInt(dbA.length); i++) {
-                            assertTrue(XMLUtils.repoolDocumentBuilder(dbA[i]));
                         }
+                    } catch (Exception e) {
+                        throw new RuntimeException(e);
                     }
                 }
             });
         }
-        results[nThreads-1] = exec.submit(new Runnable() {
+        // more or less mimic gc
+        results[nThreads - 1] = exec.submit(new Runnable() {
             @Override
             public void run() {
-                for(;;) {
-                    byte[] largeArrays[] = new byte[1024][];
-                    for (int i = 0; i < largeArrays.length; i++)
-                        try {
-                            largeArrays[i] = new byte[1024*1024];
-                        } catch (OutOfMemoryError e) {
-                            System.out.println("OOM from largeArray");
-                            break;
+                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())
+        for (Future<?> f : results) {
+            if (!f.isDone()) {
                 f.cancel(false);
+            }
             try {
                 assertNull(f.get(1000, TimeUnit.MILLISECONDS));
             } catch (CancellationException ce) {