Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementing second level classLoading and JSonProvider #4

Open
wants to merge 1 commit into
base: trunk
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.lang.ref.SoftReference;
import java.lang.reflect.Method;
import java.net.URL;
import java.security.AccessController;
Expand All @@ -49,27 +50,66 @@
public abstract class JsonProvider {
private static final String DEFAULT_PROVIDER = "org.apache.johnzon.core.JsonProviderImpl";

private static volatile SoftReference<JsonProvider> cachedReference = null;

protected JsonProvider() {
// no-op
}

private static final JsonProvider getCache() {
if (cachedReference == null) {
return null;
}
else {
return cachedReference.get();
}
}


public static JsonProvider provider() {
if (System.getSecurityManager() != null) {
return AccessController.doPrivileged(new PrivilegedAction<JsonProvider>() {
public JsonProvider run() {
return doLoadProvider();
}
});
final JsonProvider referencee = getCache();

if (referencee != null) {
return referencee;
}
else {
if (System.getSecurityManager() != null) {
return AccessController.doPrivileged(new PrivilegedAction<JsonProvider>() {
public JsonProvider run() {
JsonProvider value = doLoadProvider();
cachedReference = new SoftReference<JsonProvider>(value);
return value;
}
});
}
JsonProvider value = doLoadProvider();
cachedReference = new SoftReference<JsonProvider>(value);
return value;
}
return doLoadProvider();
}

private static JsonProvider doLoadProvider() throws JsonException {
final ClassLoader tccl = Thread.currentThread().getContextClassLoader();
try {
return doLoad(tccl);
}
catch (Throwable cnfe) {
try {
// in certain environments it may not be possible the caller to set TCCL on every call
// so we try a second level using the same classLoader that loaded the Provider
return doLoad(JsonProvider.class.getClassLoader());
} catch (final Throwable cnfe2) {
throw new JsonException(DEFAULT_PROVIDER + " not found", cnfe2);
}

}
}

private static JsonProvider doLoad(ClassLoader classLoader) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
try {
final Class<?> clazz = Class.forName("org.apache.geronimo.osgi.locator.ProviderLocator");
final Method getServices = clazz.getDeclaredMethod("getServices", String.class, Class.class, ClassLoader.class);
final List<JsonProvider> osgiProviders = (List<JsonProvider>) getServices.invoke(null, JsonProvider.class.getName(), JsonProvider.class, tccl);
final List<JsonProvider> osgiProviders = (List<JsonProvider>) getServices.invoke(null, JsonProvider.class.getName(), JsonProvider.class, classLoader);
if (osgiProviders != null && !osgiProviders.isEmpty()) {
return osgiProviders.iterator().next();
}
Expand All @@ -82,10 +122,10 @@ private static JsonProvider doLoadProvider() throws JsonException {
final String name = "META-INF/services/" + JsonProvider.class.getName();
try {
Enumeration<URL> configs;
if (tccl == null) {
if (classLoader == null) {
configs = ClassLoader.getSystemResources(name);
} else {
configs = tccl.getResources(name);
configs = classLoader.getResources(name);
}

if (configs.hasMoreElements()) {
Expand All @@ -100,7 +140,7 @@ private static JsonProvider doLoadProvider() throws JsonException {
if (l.startsWith("#")) {
continue;
}
return JsonProvider.class.cast(tccl.loadClass(l).newInstance());
return JsonProvider.class.cast(classLoader.loadClass(l).newInstance());
}
} catch (final IOException x) {
// no-op
Expand All @@ -125,12 +165,8 @@ private static JsonProvider doLoadProvider() throws JsonException {
// no-op
}

try {
final Class<?> clazz = tccl.loadClass(DEFAULT_PROVIDER);
return JsonProvider.class.cast(clazz.newInstance());
} catch (final Throwable cnfe) {
throw new JsonException(DEFAULT_PROVIDER + " not found", cnfe);
}
final Class<?> clazz = classLoader.loadClass(DEFAULT_PROVIDER);
return JsonProvider.class.cast(clazz.newInstance());
}

public abstract JsonParser createParser(Reader reader);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.lang.ref.SoftReference;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
Expand All @@ -57,27 +58,66 @@
public abstract class JsonProvider {
private static final String DEFAULT_PROVIDER = "org.apache.johnzon.core.JsonProviderImpl";

private static volatile SoftReference<JsonProvider> cachedReference = null;

protected JsonProvider() {
// no-op
}

private static final JsonProvider getCache() {
if (cachedReference == null) {
return null;
}
else {
return cachedReference.get();
}
}


public static JsonProvider provider() {
if (System.getSecurityManager() != null) {
return AccessController.doPrivileged(new PrivilegedAction<JsonProvider>() {
public JsonProvider run() {
return doLoadProvider();
}
});
final JsonProvider referencee = getCache();

if (referencee != null) {
return referencee;
}
else {
if (System.getSecurityManager() != null) {
return AccessController.doPrivileged(new PrivilegedAction<JsonProvider>() {
public JsonProvider run() {
JsonProvider value = doLoadProvider();
cachedReference = new SoftReference<JsonProvider>(value);
return value;
}
});
}
JsonProvider value = doLoadProvider();
cachedReference = new SoftReference<JsonProvider>(value);
return value;
}
return doLoadProvider();
}

private static JsonProvider doLoadProvider() throws JsonException {
final ClassLoader tccl = Thread.currentThread().getContextClassLoader();
try {
return doLoad(tccl);
}
catch (Throwable cnfe) {
try {
// in certain environments it may not be possible the caller to set TCCL on every call
// so we try a second level using the same classLoader that loaded the Provider
return doLoad(JsonProvider.class.getClassLoader());
} catch (final Throwable cnfe2) {
throw new JsonException(DEFAULT_PROVIDER + " not found", cnfe2);
}

}
}

private static JsonProvider doLoad(ClassLoader classLoader) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
try {
final Class<?> clazz = Class.forName("org.apache.geronimo.osgi.locator.ProviderLocator");
final Method getServices = clazz.getDeclaredMethod("getServices", String.class, Class.class, ClassLoader.class);
final List<JsonProvider> osgiProviders = (List<JsonProvider>) getServices.invoke(null, JsonProvider.class.getName(), JsonProvider.class, tccl);
final List<JsonProvider> osgiProviders = (List<JsonProvider>) getServices.invoke(null, JsonProvider.class.getName(), JsonProvider.class, classLoader);
if (osgiProviders != null && !osgiProviders.isEmpty()) {
return osgiProviders.iterator().next();
}
Expand All @@ -90,10 +130,10 @@ private static JsonProvider doLoadProvider() throws JsonException {
final String name = "META-INF/services/" + JsonProvider.class.getName();
try {
Enumeration<URL> configs;
if (tccl == null) {
if (classLoader == null) {
configs = ClassLoader.getSystemResources(name);
} else {
configs = tccl.getResources(name);
configs = classLoader.getResources(name);
}

if (configs.hasMoreElements()) {
Expand All @@ -108,7 +148,7 @@ private static JsonProvider doLoadProvider() throws JsonException {
if (l.startsWith("#")) {
continue;
}
return JsonProvider.class.cast(tccl.loadClass(l).newInstance());
return JsonProvider.class.cast(classLoader.loadClass(l).newInstance());
}
} catch (final IOException x) {
// no-op
Expand All @@ -133,12 +173,8 @@ private static JsonProvider doLoadProvider() throws JsonException {
// no-op
}

try {
final Class<?> clazz = tccl.loadClass(DEFAULT_PROVIDER);
return JsonProvider.class.cast(clazz.newInstance());
} catch (final Throwable cnfe) {
throw new JsonException(DEFAULT_PROVIDER + " not found", cnfe);
}
final Class<?> clazz = classLoader.loadClass(DEFAULT_PROVIDER);
return JsonProvider.class.cast(clazz.newInstance());
}

public abstract JsonParser createParser(Reader reader);
Expand Down