Author: desruisseaux
Date: Wed Jul 31 12:27:37 2013
New Revision: 1508830

URL: http://svn.apache.org/r1508830
Log:
Use one instance of ServiceLoader per MarshallerPool rather than a system-wide 
instance.
The purpose is to avoid issue with class loaders in two applications are loaded 
as two distinct OSGi modules.

Modified:
    
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/AdapterReplacement.java
    
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/TypeRegistration.java
    
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/xml/MarshallerPool.java

Modified: 
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/AdapterReplacement.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/AdapterReplacement.java?rev=1508830&r1=1508829&r2=1508830&view=diff
==============================================================================
--- 
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/AdapterReplacement.java
 [UTF-8] (original)
+++ 
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/AdapterReplacement.java
 [UTF-8] Wed Jul 31 12:27:37 2013
@@ -16,7 +16,6 @@
  */
 package org.apache.sis.internal.jaxb;
 
-import java.util.ServiceLoader;
 import javax.xml.bind.Marshaller;
 import javax.xml.bind.Unmarshaller;
 import javax.xml.bind.JAXBException;
@@ -47,22 +46,6 @@ import javax.xml.bind.annotation.adapter
  */
 public interface AdapterReplacement {
     /**
-     * The system-wide provider of {@code AdapterReplacement} instances.
-     * <strong>Every usage of this service loader must be 
synchronized.</strong>
-     * This loader is public for {@link org.apache.sis.xml.MarshallerPool} 
usage.
-     *
-     * <p>This loader needs to be cleared as below when modules are loaded or 
unloaded.
-     * This is done opportunistically by {@link TypeRegistration}.</p>
-     *
-     * {@preformat java
-     *     synchronized (AdapterReplacement.PROVIDER) {
-     *         AdapterReplacement.PROVIDER.reload();
-     *     }
-     * }
-     */
-    ServiceLoader<AdapterReplacement> PROVIDER = 
ServiceLoader.load(AdapterReplacement.class);
-
-    /**
      * Invoked when a new adapter is created by {@link 
org.apache.sis.xml.MarshallerPool}.
      * Typical implementations will be as below:
      *

Modified: 
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/TypeRegistration.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/TypeRegistration.java?rev=1508830&r1=1508829&r2=1508830&view=diff
==============================================================================
--- 
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/TypeRegistration.java
 [UTF-8] (original)
+++ 
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/TypeRegistration.java
 [UTF-8] Wed Jul 31 12:27:37 2013
@@ -49,22 +49,11 @@ public abstract class TypeRegistration {
     /**
      * The JAXB context, or {@code null} if not yet created or if the 
classpath changed.
      */
-    private static Reference<JAXBContext> context;
+    private static volatile Reference<JAXBContext> context;
     static {
         SystemListener.add(new SystemListener(Modules.UTILITIES) {
             @Override protected void classpathChanged() {
-                synchronized (TypeRegistration.class) {
-                    context = null;
-                }
-                /*
-                 * Opportunistically clears the AdapterReplacement.PROVIDER. 
We can not do this work in the
-                 * AdapterReplacement interface because we can not declare 
static initializer in interfaces.
-                 * This TypeRegistration class is an acceptable fallback 
because MarshallerPool uses this
-                 * class before to use AdapterReplacement.
-                 */
-                synchronized (AdapterReplacement.PROVIDER) {
-                    AdapterReplacement.PROVIDER.reload();
-                }
+                context = null;
             }
         });
     }
@@ -116,8 +105,9 @@ public abstract class TypeRegistration {
      * @throws JAXBException If an error occurred while creating the JAXB 
context.
      */
     public static synchronized JAXBContext getSharedContext() throws 
JAXBException {
-        if (context != null) {
-            final JAXBContext instance = context.get();
+        final Reference<JAXBContext> c = context;
+        if (c != null) {
+            final JAXBContext instance = c.get();
             if (instance != null) {
                 return instance;
             }

Modified: 
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/xml/MarshallerPool.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/xml/MarshallerPool.java?rev=1508830&r1=1508829&r2=1508830&view=diff
==============================================================================
--- 
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/xml/MarshallerPool.java
 [UTF-8] (original)
+++ 
sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/xml/MarshallerPool.java
 [UTF-8] Wed Jul 31 12:27:37 2013
@@ -18,6 +18,7 @@ package org.apache.sis.xml;
 
 import java.util.Map;
 import java.util.Deque;
+import java.util.ServiceLoader;
 import java.util.concurrent.ConcurrentLinkedDeque;
 import java.util.concurrent.atomic.AtomicBoolean;
 import javax.xml.bind.JAXBContext;
@@ -94,6 +95,17 @@ public class MarshallerPool {
     private final Object mapper;
 
     /**
+     * The provider of {@code AdapterReplacement} instances.
+     * <strong>Every usage of this service loader must be 
synchronized.</strong>
+     *
+     * {@note Each <code>MarshallerPool</code> has its own service loader 
instance rather than using a
+     *        system-wide instance because the <code>ClassLoader</code> used 
by the service loader is
+     *        the <cite>context class loader</cite>, which depends on the 
thread that created the pool.
+     *        So two pools in two different applications could have two 
different set of replacements.}
+     */
+    private final ServiceLoader<AdapterReplacement> replacements;
+
+    /**
      * The {@link PooledTemplate} to use for initializing recycled 
(un)marshaller.
      */
     private final PooledTemplate template;
@@ -167,6 +179,7 @@ public class MarshallerPool {
     public MarshallerPool(final JAXBContext context, final Map<String,?> 
properties) throws JAXBException {
         ArgumentChecks.ensureNonNull("context", context);
         this.context = context;
+        replacements = ServiceLoader.load(AdapterReplacement.class);
         /*
          * Detects if we are using the endorsed JAXB implementation (i.e. the 
one provided in
          * separated JAR files) or the one bundled in JDK 6. We use the JAXB 
context package
@@ -424,8 +437,8 @@ public class MarshallerPool {
             }
             // Do nothing for the OTHER case.
         }
-        synchronized (AdapterReplacement.PROVIDER) {
-            for (final AdapterReplacement adapter : 
AdapterReplacement.PROVIDER) {
+        synchronized (replacements) {
+            for (final AdapterReplacement adapter : replacements) {
                 adapter.register(marshaller);
             }
         }
@@ -442,8 +455,8 @@ public class MarshallerPool {
      */
     protected Unmarshaller createUnmarshaller() throws JAXBException {
         final Unmarshaller unmarshaller = context.createUnmarshaller();
-        synchronized (AdapterReplacement.PROVIDER) {
-            for (final AdapterReplacement adapter : 
AdapterReplacement.PROVIDER) {
+        synchronized (replacements) {
+            for (final AdapterReplacement adapter : replacements) {
                 adapter.register(unmarshaller);
             }
         }


Reply via email to