package org.springframework.util;

import java.io.InputStream;

/**
 * Utility class for class loading, and for diagnostic purposes
 * to analyze the ClassLoader hierarchy for any object.
 * @author Rod Johnson
 * @author Juergen Hoeller
 * @since 02 April 2001
 */
public abstract class ClassLoaderUtils {

	/**
	 * Load a resource from the classpath, first trying the thread context
	 * class loader, then the class loader of the given class.
	 * @param clazz a class to try the class loader of
	 * @param name the resource name
	 * @return an input stream for reading the resource,
	 * or null if not found
	 */
	public static InputStream getResourceAsStream(Class clazz, String name) {
		InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(name);
		if (in == null) {
			in = clazz.getResourceAsStream(name);
		}
		return in;
	}

	/**
	 * Show the class loader hierarchy for this class.
	 * @param obj object to analyze loader hierarchy for
	 * @param role a description of the role of this class in the application
	 * (e.g., "servlet" or "EJB reference")
	 * @param delim line break
	 * @param tabText text to use to set tabs
	 * @return a String showing the class loader hierarchy for this class
	 */
	public static String showClassLoaderHierarchy(Object obj, String role, String delim, String tabText) {
		String s = "object of " + obj.getClass() + ": role is " + role + delim;
		return s + showClassLoaderHierarchy(obj.getClass().getClassLoader(), delim, tabText, 0);
	}

	/**
	 * Show the class loader hierarchy for this class.
	 * @param cl class loader to analyze hierarchy for
	 * @param delim line break
	 * @param tabText text to use to set tabs
	 * @param indent nesting level (from 0) of this loader; used in pretty printing
	 * @return a String showing the class loader hierarchy for this class
	 */
	public static String showClassLoaderHierarchy(ClassLoader cl, String delim, String tabText, int indent) {
		if (cl == null) {
			String s = "null classloader " + delim;
			ClassLoader ctxcl = Thread.currentThread().getContextClassLoader();
			s += "Context class loader=" + ctxcl + " hc=" + ctxcl.hashCode();
			return s;
		}
		String s = ""; //"ClassLoader: ";
		for (int i = 0; i < indent; i++)
			s += tabText;
		s += cl + " hc=" + cl.hashCode() + delim;
		ClassLoader parent = cl.getParent();
		return s + showClassLoaderHierarchy(parent, delim, tabText, indent + 1);
	}

}

@@ -2419,10 +2419,1620 @@
 1);%0A%09%7D%0A%0A
+%09/**%0A%09 * Given an%09input class%09object,%09returns%09a string which consists%09of the class's package%0A%09 * name%09as a pathname, i.e., a leading '/' is added, and all dots ('.')%09are%09replaced by%0A%09 * slashes ('/'). A%09trailing slash is %3Cb%3Enot%3C/b%3E added.%0A%09 * @param clazz%09the%09input class%0A%09 * @return a path which%09represents the package name, including a leading slash%0A%09 */%0A%09public static String classPackageAsResourcePath(Class clazz) %7B%0A%09%09StringBuffer retval%09= new StringBuffer(%22/%22);%0A%09%09if (clazz == null)%0A%09%09%09return retval.toString();%0A%09%09StringTokenizer%09st = new StringTokenizer(clazz.getPackage().getName(), %22.%22);%0A%09%09while (st.hasMoreTokens()) %7B%0A%09%09%09retval.append(st.nextToken());%0A%09%09%09if (st.hasMoreTokens())%0A%09%09%09%09retval.append(%22/%22);%0A%09%09%7D%0A%09%09return retval.toString();%0A%09%7D%0A  %0A  %0A%09/**%0A%09 * Returns a path suitable for use with%09%7B@see Class.getResource%7D build by taking%0A%09 * the package of the specified%09class file,%09converting all dots%09('.') to slashes%0A%09 * ('/'), adding a trailing%09slash, and concatenating the specified resource%09name%0A%09 * to this.%09As such, this function may be used to build%09a path suitable%09for%09loading%0A%09 * a resource file that%09is in the same package as a%09class file.%0A%09 * @param clazz%09the%09Class whose%09package%09will be%09used as%09the%09base.%0A%09 * @param resourceName the resource%09name to%09append.%09A leading slash%09is optional.%0A%09 * @return The built-up%09resource path.%0A%09 */%0A%09public static String addResourcePathToPackagePath(Class%09clazz, String resourceName)%09%7B%0A%09%09if (!resourceName.startsWith(%22/%22))%0A%09%09%09return classPackageAsResourcePath(clazz) + %22/%22 + resourceName;%0A%09%09else%0A%09%09%09return classPackageAsResourcePath(clazz) + resourceName;%0A%09%7D %0A
 %7D%0A

add classPackageAsResourcePath and addResourcePathToPackagePath functions