Provided utility for loading classes that falls back to the Thread Context Class Loader if class is not found.

This commit is contained in:
Ioannis Canellos 2011-11-18 22:09:25 +02:00
parent 10d617a4ca
commit 148b6abbb8
5 changed files with 112 additions and 14 deletions

View File

@ -34,6 +34,7 @@ import java.util.Properties;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.PropertiesBuilder;
import org.jclouds.util.ClassLoadingUtils;
import org.jclouds.util.SaxUtils;
import com.google.common.base.Function;
@ -90,7 +91,7 @@ public class Providers {
String provider = get(Splitter.on('.').split(keyString), 0);
Class<RestContextBuilder<Object, Object>> clazz = Providers.resolveContextBuilderClass(provider,
properties);
if (type.isAssignableFrom(clazz))
if (clazz != null && type.isAssignableFrom(clazz))
return provider;
} catch (ClassNotFoundException e) {
} catch (Exception e) {
@ -111,13 +112,18 @@ public class Providers {
String asyncClassName = properties.getProperty(provider + ".async");
if (syncClassName != null) {
checkArgument(asyncClassName != null, "please configure async class for " + syncClassName);
Class.forName(syncClassName);
Class.forName(asyncClassName);
return (Class<RestContextBuilder<S, A>>) (contextBuilderClassName != null ? Class
.forName(contextBuilderClassName) : RestContextBuilder.class);
if(ClassLoadingUtils.loadClass(Providers.class, syncClassName) == null) {
throw new ClassNotFoundException();
}
if(ClassLoadingUtils.loadClass(Providers.class, asyncClassName) == null) {
throw new ClassNotFoundException();
}
return (Class<RestContextBuilder<S, A>>) (contextBuilderClassName != null ? ClassLoadingUtils.
loadClass(Providers.class, contextBuilderClassName) : RestContextBuilder.class);
} else {
checkArgument(contextBuilderClassName != null, "please configure contextbuilder class for " + provider);
return (Class<RestContextBuilder<S, A>>) Class.forName(contextBuilderClassName);
return (Class<RestContextBuilder<S, A>>) ClassLoadingUtils.
loadClass(Providers.class, contextBuilderClassName);
}
}
@ -142,7 +148,7 @@ public class Providers {
NoSuchMethodException {
String propertiesBuilderClassName = props.getProperty(providerName + ".propertiesbuilder", null);
if (propertiesBuilderClassName != null) {
return (Class<PropertiesBuilder>) Class.forName(propertiesBuilderClassName);
return (Class<PropertiesBuilder>) ClassLoadingUtils.loadClass(Providers.class, propertiesBuilderClassName);
} else {
return PropertiesBuilder.class;
}

View File

@ -35,6 +35,7 @@ import javax.inject.Inject;
import org.jclouds.PropertiesBuilder;
import org.jclouds.location.reference.LocationConstants;
import org.jclouds.util.ClassLoadingUtils;
import org.jclouds.util.Modules2;
import org.jclouds.util.Strings2;
@ -303,8 +304,8 @@ public class RestContextFactory {
try {
contextBuilderClass = Providers.resolveContextBuilderClass(providerName, props);
propertiesBuilderClass = Providers.resolvePropertiesBuilderClass(providerName, props);
sync = (Class<S>) (syncClassName != null ? Class.forName(syncClassName) : null);
async = (Class<A>) (asyncClassName != null ? Class.forName(asyncClassName) : null);
sync = (Class<S>) (syncClassName != null ? ClassLoadingUtils.loadClass(getClass(), syncClassName) : null);
async = (Class<A>) (asyncClassName != null ? ClassLoadingUtils.loadClass(getClass(), asyncClassName) : null);
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException(
String.format(

View File

@ -0,0 +1,92 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.util;
import java.net.URL;
import com.google.common.io.Resources;
public class ClassLoadingUtils {
public ClassLoadingUtils() {
//Utility Class
}
/**
* Loads a class using the class loader.
* 1. The class loader of the context class is being used.
* 2. The thread context class loader is being used.
* If both approaches fail, returns null.
*
* @param contextClass The name of a context class to use.
* @param className The name of the class to load
* @return The class or null if no class loader could load the class.
*/
public static Class<?> loadClass(Class<?> contextClass, String className) {
Class clazz = null;
if (contextClass.getClassLoader() != null) {
clazz = silentLoadClass(className, contextClass.getClassLoader());
}
if (clazz == null && Thread.currentThread().getContextClassLoader() != null) {
clazz = silentLoadClass(className, Thread.currentThread().getContextClassLoader());
}
return clazz;
}
/**
* Returns the url of a resource.
* 1. The context class is being used.
* 2. The thread context class loader is being used.
* If both approach fail, returns null.
*
* @param contextClass
* @param resourceName
* @return
*/
public static URL loadResource(Class contextClass, String resourceName) {
URL url = null;
if (contextClass != null) {
url = Resources.getResource(contextClass, resourceName);
}
if (url == null && Thread.currentThread().getContextClassLoader() != null) {
url = Thread.currentThread().getContextClassLoader().getResource(resourceName);
}
return url;
}
/**
* Loads a {@link Class} from the specified {@link ClassLoader} without throwing {@ClassNotFoundException}.
*
* @param className
* @param classLoader
* @return
*/
private static Class<?> silentLoadClass(String className, ClassLoader classLoader) {
Class clazz = null;
if (classLoader != null && className != null) {
try {
clazz = classLoader.loadClass(className);
} catch (ClassNotFoundException e) {
//Ignore and proceed to the next class loader.
}
}
return clazz;
}
}

View File

@ -47,13 +47,11 @@ public class Modules2 {
@Override
public Module apply(String from) {
try {
return (Module) Class.forName(from).newInstance();
return (Module) ClassLoadingUtils.loadClass(Modules2.class, from).newInstance();
} catch (InstantiationException e) {
throw new RuntimeException("error instantiating " + from, e);
} catch (IllegalAccessException e) {
throw new RuntimeException("error instantiating " + from, e);
} catch (ClassNotFoundException e) {
throw new RuntimeException("error instantiating " + from, e);
}
}

View File

@ -36,6 +36,7 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.io.CharStreams;
import com.google.common.io.Resources;
import org.jclouds.util.ClassLoadingUtils;
/**
* Utilities used to build init scripts.
@ -135,8 +136,8 @@ public class Utils {
public static String writeFunctionFromResource(String function, OsFamily family) {
try {
String toReturn = CharStreams.toString(Resources.newReaderSupplier(Resources.getResource(Utils.class, String
.format("/functions/%s.%s", function, ShellToken.SH.to(family))), Charsets.UTF_8));
String toReturn = CharStreams.toString(Resources.newReaderSupplier(ClassLoadingUtils.loadResource(Utils.class, String
.format("/functions/%s.%s", function, ShellToken.SH.to(family))), Charsets.UTF_8));
String lf = ShellToken.LF.to(family);
return toReturn.endsWith(lf) ? toReturn : new StringBuilder(toReturn).append(lf).toString();
} catch (IOException e) {