Switch to double check idiom for runtime delegate singleton; adopt EE 6 recommended class loading strategy.

svn path=/trunk/; revision=558
diff --git a/src/jsr311-api/src/javax/ws/rs/ext/FactoryFinder.java b/src/jsr311-api/src/javax/ws/rs/ext/FactoryFinder.java
index a9ee62c..cb92624 100644
--- a/src/jsr311-api/src/javax/ws/rs/ext/FactoryFinder.java
+++ b/src/jsr311-api/src/javax/ws/rs/ext/FactoryFinder.java
@@ -23,9 +23,24 @@
 import java.io.FileInputStream;
 import java.io.InputStream;
 import java.io.InputStreamReader;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.Properties;
 
 class FactoryFinder {
+    
+    static ClassLoader getContextClassLoader() { 
+        return AccessController.doPrivileged( 
+            new PrivilegedAction<ClassLoader>() { 
+                public ClassLoader run() { 
+                    ClassLoader cl = null;
+                    try { 
+                        cl = Thread.currentThread().getContextClassLoader(); 
+                    } catch (SecurityException ex) { } 
+                    return cl; 
+                } 
+        }); 
+    }
 
     /**
      * Creates an instance of the specified class using the specified 
@@ -41,7 +56,11 @@
             if (classLoader == null) {
                 spiClass = Class.forName(className);
             } else {
-                spiClass = classLoader.loadClass(className);
+                try { 
+                    spiClass = Class.forName(className, false, classLoader); 
+                } catch (ClassNotFoundException ex) { 
+                    spiClass = Class.forName(className); 
+                } 
             }
             return spiClass.newInstance();
         } catch (ClassNotFoundException x) {
@@ -74,12 +93,7 @@
      * @exception WebServiceException if there is an error
      */
     static Object find(String factoryId, String fallbackClassName) throws ClassNotFoundException {
-        ClassLoader classLoader;
-        try {
-            classLoader = Thread.currentThread().getContextClassLoader();
-        } catch (Exception x) {
-            throw new ClassNotFoundException(x.toString(), x);
-        }
+        ClassLoader classLoader = getContextClassLoader();
 
         String serviceId = "META-INF/services/" + factoryId;
         // try to find services in CLASSPATH
diff --git a/src/jsr311-api/src/javax/ws/rs/ext/RuntimeDelegate.java b/src/jsr311-api/src/javax/ws/rs/ext/RuntimeDelegate.java
index 7ee70dc..1fbed8f 100644
--- a/src/jsr311-api/src/javax/ws/rs/ext/RuntimeDelegate.java
+++ b/src/jsr311-api/src/javax/ws/rs/ext/RuntimeDelegate.java
@@ -21,7 +21,6 @@
 
 import java.lang.reflect.ReflectPermission;
 import java.net.URL;
-import java.util.concurrent.atomic.AtomicReference;
 import javax.ws.rs.core.Application;
 import javax.ws.rs.core.Response.ResponseBuilder;
 import javax.ws.rs.core.Variant.VariantListBuilder;
@@ -42,13 +41,12 @@
     private static final String JAXRS_DEFAULT_RUNTIME_DELEGATE
         = "com.sun.ws.rs.ext.RuntimeDelegateImpl";
     
-    private static AtomicReference<RuntimeDelegate> rdr = 
-            new AtomicReference<RuntimeDelegate>();
-    
     private static ReflectPermission rp = new ReflectPermission("suppressAccessChecks");
 
     protected RuntimeDelegate() {
     }
+
+    private static volatile RuntimeDelegate rd;
     
     /**
      * Obtain a RuntimeDelegate instance. If an instance had not already been
@@ -84,39 +82,48 @@
      * @return an instance of RuntimeDelegate
      */
     public static RuntimeDelegate getInstance() {
-        RuntimeDelegate rd = rdr.get();
-        if (rd != null)
-            return rd;
-        synchronized(rdr) {
-            rd = rdr.get();
-            if (rd != null)
-                return rd;
-            try {
-                Object delegate =
-                        FactoryFinder.find(JAXRS_RUNTIME_DELEGATE_PROPERTY,
-                        JAXRS_DEFAULT_RUNTIME_DELEGATE);
-                if (!(delegate instanceof RuntimeDelegate)) {
-                    Class pClass = RuntimeDelegate.class;
-                    String classnameAsResource = pClass.getName().replace('.', '/') + ".class";
-                    ClassLoader loader = pClass.getClassLoader();
-                    if(loader == null) {
-                        loader = ClassLoader.getSystemClassLoader();
-                    }
-                    URL targetTypeURL  = loader.getResource(classnameAsResource);
-                    throw new LinkageError("ClassCastException: attempting to cast" +
-                            delegate.getClass().getClassLoader().getResource(classnameAsResource) +
-                            "to" + targetTypeURL.toString() );
-                }
-                rd = (RuntimeDelegate) delegate;
-            } catch (Exception ex) {
-                throw new RuntimeException(ex);
-            }
-            rdr.compareAndSet(null,rd);
-        }
-        return rdr.get();
+       // Double-check idiom for lazy initialization of fields.
+       RuntimeDelegate result = rd;
+       if (result == null) { // First check (no locking)
+           synchronized(RuntimeDelegate.class) {
+               result = rd;
+               if (result == null) { // Second check (with locking)
+                   rd = result = findDelegate();
+               }
+           }
+       }
+       return result;
     }
     
     /**
+     * Obtain a RuntimeDelegate instance using the method described in
+     * {@link #getInstance}.
+     * @return an instance of RuntimeDelegate
+     */
+    private static RuntimeDelegate findDelegate() {
+        try {
+            Object delegate =
+                    FactoryFinder.find(JAXRS_RUNTIME_DELEGATE_PROPERTY,
+                    JAXRS_DEFAULT_RUNTIME_DELEGATE);
+            if (!(delegate instanceof RuntimeDelegate)) {
+                Class pClass = RuntimeDelegate.class;
+                String classnameAsResource = pClass.getName().replace('.', '/') + ".class";
+                ClassLoader loader = pClass.getClassLoader();
+                if(loader == null) {
+                    loader = ClassLoader.getSystemClassLoader();
+                }
+                URL targetTypeURL  = loader.getResource(classnameAsResource);
+                throw new LinkageError("ClassCastException: attempting to cast" +
+                        delegate.getClass().getClassLoader().getResource(classnameAsResource) +
+                        "to" + targetTypeURL.toString() );
+            }
+            return (RuntimeDelegate) delegate;
+        } catch (Exception ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+
+    /**
      * Set the runtime delegate that will be used by JAX-RS classes. If this method
      * is not called prior to {@link #getInstance} then an implementation will
      * be sought as described in {@link #getInstance}.
@@ -129,7 +136,9 @@
         if (security != null) {
             security.checkPermission(rp);
         }
-        rdr.set(rd);
+        synchronized(RuntimeDelegate.class) {
+            RuntimeDelegate.rd = rd;
+        }
     }
     
     /**