diff --git a/core/src/main/java/org/jclouds/rest/Providers.java b/core/src/main/java/org/jclouds/rest/Providers.java index cbb758cc81..a9a94e106c 100644 --- a/core/src/main/java/org/jclouds/rest/Providers.java +++ b/core/src/main/java/org/jclouds/rest/Providers.java @@ -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> 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>) (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>) (contextBuilderClassName != null ? ClassLoadingUtils. + loadClass(Providers.class, contextBuilderClassName) : RestContextBuilder.class); } else { checkArgument(contextBuilderClassName != null, "please configure contextbuilder class for " + provider); - return (Class>) Class.forName(contextBuilderClassName); + return (Class>) 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) Class.forName(propertiesBuilderClassName); + return (Class) ClassLoadingUtils.loadClass(Providers.class, propertiesBuilderClassName); } else { return PropertiesBuilder.class; } diff --git a/core/src/main/java/org/jclouds/rest/RestContextFactory.java b/core/src/main/java/org/jclouds/rest/RestContextFactory.java index 01de0ae9fc..49efd3f825 100644 --- a/core/src/main/java/org/jclouds/rest/RestContextFactory.java +++ b/core/src/main/java/org/jclouds/rest/RestContextFactory.java @@ -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) (syncClassName != null ? Class.forName(syncClassName) : null); - async = (Class) (asyncClassName != null ? Class.forName(asyncClassName) : null); + sync = (Class) (syncClassName != null ? ClassLoadingUtils.loadClass(getClass(), syncClassName) : null); + async = (Class) (asyncClassName != null ? ClassLoadingUtils.loadClass(getClass(), asyncClassName) : null); } catch (IllegalArgumentException e) { throw new IllegalArgumentException( String.format( diff --git a/core/src/main/java/org/jclouds/util/ClassLoadingUtils.java b/core/src/main/java/org/jclouds/util/ClassLoadingUtils.java new file mode 100644 index 0000000000..b24ffbacc2 --- /dev/null +++ b/core/src/main/java/org/jclouds/util/ClassLoadingUtils.java @@ -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; + } +} diff --git a/core/src/main/java/org/jclouds/util/Modules2.java b/core/src/main/java/org/jclouds/util/Modules2.java index 3ae639374e..9a45924a51 100644 --- a/core/src/main/java/org/jclouds/util/Modules2.java +++ b/core/src/main/java/org/jclouds/util/Modules2.java @@ -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); } } diff --git a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/util/Utils.java b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/util/Utils.java index 2a5f3bc66d..031e507ddd 100644 --- a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/util/Utils.java +++ b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/util/Utils.java @@ -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) {