[jbossws-commits] JBossWS SVN: r14918 - common/trunk/src/main/java/org/jboss/ws/common.

jbossws-commits at lists.jboss.org jbossws-commits at lists.jboss.org
Thu Sep 1 07:07:51 EDT 2011


Author: alessio.soldano at jboss.com
Date: 2011-09-01 07:07:51 -0400 (Thu, 01 Sep 2011)
New Revision: 14918

Modified:
   common/trunk/src/main/java/org/jboss/ws/common/DOMUtils.java
   common/trunk/src/main/java/org/jboss/ws/common/SecurityActions.java
Log:
[JBWS-3344] Caching default document builder factory to improve performances


Modified: common/trunk/src/main/java/org/jboss/ws/common/DOMUtils.java
===================================================================
--- common/trunk/src/main/java/org/jboss/ws/common/DOMUtils.java	2011-09-01 07:21:16 UTC (rev 14917)
+++ common/trunk/src/main/java/org/jboss/ws/common/DOMUtils.java	2011-09-01 11:07:51 UTC (rev 14918)
@@ -75,59 +75,64 @@
    private static final String DISALLOW_DOCTYPE_DECL_FEATURE = "http://apache.org/xml/features/disallow-doctype-decl";
    
    private static String documentBuilderFactoryName;
+   private static DocumentBuilderFactory documentBuilderFactory;
    
    private static final boolean alwaysResolveFactoryName = Boolean.getBoolean(Constants.ALWAYS_RESOLVE_DOCUMENT_BUILDER_FACTORY);
    private static final boolean disableDeferedNodeExpansion = Boolean.getBoolean(DISABLE_DEFERRED_NODE_EXPANSION);
    private static final boolean enableDoctypeDeclaration = Boolean.getBoolean(ENABLE_DOCTYPE_DECL);
    
+   static
+   {
+      //load default document builder factory using the DOMUtils' defining classloader
+      final ClassLoader classLoader = SecurityActions.getContextClassLoader();
+      SecurityActions.setContextClassLoader(DOMUtils.class.getClassLoader());
+      try
+      {
+         final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+
+         initializeFactory(factory);
+         documentBuilderFactoryName = factory.getClass().getCanonicalName();
+         documentBuilderFactory = factory;
+      }
+      finally
+      {
+         SecurityActions.setContextClassLoader(classLoader);
+      }
+   }
+   
    // All elements created by the same thread are created by the same builder and belong to the same doc
    private static ThreadLocal<Document> documentThreadLocal = new ThreadLocal<Document>();
    private static ThreadLocal<DocumentBuilder> builderThreadLocal = new ThreadLocal<DocumentBuilder>() {
       protected DocumentBuilder initialValue()
       {
-         DocumentBuilderFactory factory = null;
          try
          {
-            //slow
-            //factory = DocumentBuilderFactory.newInstance();
-            
-            //fast (requires JDK6 or greater)
-            if (documentBuilderFactoryName == null || alwaysResolveFactoryName)
+            DocumentBuilderFactory factory = null;
+            if (alwaysResolveFactoryName)
             {
                factory = DocumentBuilderFactory.newInstance();
-               if (!alwaysResolveFactoryName)
-               {
-                  documentBuilderFactoryName = factory.getClass().getCanonicalName();
-               }
             }
             else
             {
+               //this is faster then DocumentBuilderFactory.newInstance(); but requires JDK6 or greater
                factory = DocumentBuilderFactory.newInstance(documentBuilderFactoryName, SecurityActions.getContextClassLoader());
             }
             
-            
-            factory.setValidating(false);
-            factory.setNamespaceAware(true);
-            factory.setExpandEntityReferences(false);
-
-            try
+            //check if the factory we'd get for this thread is equivalent to the default one;
+            //in that case re-use the default one and skip the initialization, which is time-consuming
+            final DocumentBuilderFactory threadFactory ;
+            if (factory.getClass().getClassLoader() == documentBuilderFactory.getClass().getClassLoader() &&
+               (!alwaysResolveFactoryName || documentBuilderFactoryName.equals(factory.getClass().getCanonicalName())))
             {
-               factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
-               if (disableDeferedNodeExpansion)
-               {
-                  factory.setFeature(DEFER_NODE_EXPANSION_FEATURE, false);
-               }
-               if (!enableDoctypeDeclaration)
-               {
-                  factory.setFeature(DISALLOW_DOCTYPE_DECL_FEATURE, true);
-               }
+               threadFactory = documentBuilderFactory ;
             }
-            catch (ParserConfigurationException pce)
+            else
             {
-               log.fatal("Serious security risk, not able to configure parser feature", pce);
+               threadFactory = factory ;
+               initializeFactory(threadFactory) ;
             }
 
-            DocumentBuilder builder = factory.newDocumentBuilder();
+            DocumentBuilder builder = threadFactory.newDocumentBuilder();
             setEntityResolver(builder);
             return builder;
          }
@@ -172,6 +177,30 @@
       }
    };
    
+   private static void initializeFactory(final DocumentBuilderFactory factory)
+   {
+      factory.setValidating(false);
+      factory.setNamespaceAware(true);
+      factory.setExpandEntityReferences(false);
+
+      try
+      {
+         factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+         if (disableDeferedNodeExpansion)
+         {
+            factory.setFeature(DEFER_NODE_EXPANSION_FEATURE, false);
+         }
+         if (!enableDoctypeDeclaration)
+         {
+            factory.setFeature(DISALLOW_DOCTYPE_DECL_FEATURE, true);
+         }
+      }
+      catch (ParserConfigurationException pce)
+      {
+         log.error(pce);
+      }
+   }
+
    public static void clearThreadLocals()
    {
       documentThreadLocal.remove();

Modified: common/trunk/src/main/java/org/jboss/ws/common/SecurityActions.java
===================================================================
--- common/trunk/src/main/java/org/jboss/ws/common/SecurityActions.java	2011-09-01 07:21:16 UTC (rev 14917)
+++ common/trunk/src/main/java/org/jboss/ws/common/SecurityActions.java	2011-09-01 11:07:51 UTC (rev 14918)
@@ -57,8 +57,32 @@
          });
       }
    }
-   
+
    /**
+    * Set context classloader.
+    * 
+    * @param classLoader the context classloader
+    */
+   static void setContextClassLoader(final ClassLoader classLoader)
+   {
+      SecurityManager sm = System.getSecurityManager();
+      if (sm == null)
+      {
+         Thread.currentThread().setContextClassLoader(classLoader);
+      }
+      else
+      {
+         AccessController.doPrivileged(new PrivilegedAction<Object>() {
+            public Object run()
+            {
+               Thread.currentThread().setContextClassLoader(classLoader);
+               return null;
+            }
+         });
+      }
+   }
+
+   /**
     * Load a class using the provided classloader
     * 
     * @param name



More information about the jbossws-commits mailing list