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);
}
}