krysalis-update/src/java/org/krysalis/depot/common/util/envsafe RelativelySafe.java,NONE,1.1 ClassLoaderContext.java,NONE,1.1

Nick Chalko <[email protected]> Wed, 08 Dec 2004 09:07:17 +0000
Newsgroups gmane.comp.krysalis.cvs
Message-ID <[email protected]>
Update of /cvsroot/krysalis/krysalis-update/src/java/org/krysalis/depot/common/util/envsafe
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv24726/src/java/org/krysalis/depot/common/util/envsafe

Added Files:
	RelativelySafe.java ClassLoaderContext.java 
Log Message:
Copied from the apache incubator.

--- NEW FILE: ClassLoaderContext.java ---
/*
 * Copyright  2004 The Apache Software Foundation
 *
 *  Licensed 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.krysalis.depot.common.util.envsafe;

import java.io.InputStream;

import org.krysalis.depot.common.DepotError;
import org.krysalis.depot.common.DepotException;
import org.krysalis.depot.common.log.Logger;

/**
 * @author ajack
 */
public class ClassLoaderContext {

	/**
 	* The classloader that this context work upon 
 	*/
	private ClassLoader m_loader = null;

	// Another useful one...
	private static ClassLoaderContext l_root = null;

	static {
		l_root = new ClassLoaderContext(ClassLoader.getSystemClassLoader());
	}

	public ClassLoaderContext(ClassLoader loader) {
		m_loader = loader;
		classInit();
	}

	public ClassLoaderContext(Object context) {
		this(context.getClass());
		classInit();
	}

	public ClassLoaderContext(Class context) {
		m_loader = context.getClassLoader();
		classInit();
	}

	private void classInit() {
		// If not already specified...
		if (null == m_loader) {
			//
			// Last ditched effort...
			//
			m_loader = getContextClassLoader();
		}
	}

	public Class getClassForName(String name) throws ClassNotFoundException {
		return Class.forName(name, true, m_loader);
	}

	public InputStream getResourceAsStream(String name)
		throws ClassNotFoundException {
		return m_loader.getResourceAsStream(name);
	}

	/**
	* 
	* Return the thread context class loader if available.
	* Otherwise return null.
	*
	*/
	public ClassLoader getContextClassLoader() {
		return getContextClassLoader(null);
	}

	/**
	* 
	* Return the thread context class loader if available.
	* Otherwise return null.
	*
	*/
	public ClassLoader getContextClassLoader(Class context) {
		ClassLoader classLoader = null;

		//
		// Get the loader for the provided class
		//
		if (null != context)
			classLoader = context.getClassLoader();

		//
		//	:TODO: Is this better than using System?
		//
		if (classLoader == null) {
			classLoader =
				(ClassLoader) RelativelySafe.callMethod(
					Thread.currentThread(),
					"getContextClassLoader");
		}

		//
		//    A null return from Class.getClassLoader() means the
		//    System ClassLoader was used. [Sybase EAS, amongst 
		//	  other (no doubt) do this.] Spec says they can...
		//
		if (null == classLoader)
			classLoader = ClassLoader.getSystemClassLoader();

		// Return the selected class loader
		return classLoader;
	}

	public Object loadClassWithFallbacks(
		String primaryOption,
		String secondaryOption,
		String tertiaryOption,
		String quaternaryOption) {

		Object implementation = null;

		DepotException primaryProblem = null;
		DepotException secondaryProblem = null;
		DepotException tertiaryProblem = null;
		DepotException quaternaryProblem = null;

		try {
			implementation = attemptLoad(primaryOption, "Primary");
		}
		catch (DepotException ve) {
			primaryProblem = ve;

			Logger.getLogger().debug(
				"Failed to load [" + primaryOption + "] due to ",
				primaryProblem);
		}

		if (null == implementation) {
			try {
				implementation = attemptLoad(secondaryOption, "Secondary");
			}

			catch (DepotException ve2) {
				secondaryProblem = ve2;

				Logger.getLogger().debug(
					"Failed to load [" + secondaryOption + "] due to ",
					secondaryProblem);
			}
		}

		if (null == implementation) {
			try {
				implementation = attemptLoad(tertiaryOption, "Tertiary");
			}

			catch (DepotException ve3) {
				tertiaryProblem = ve3;

				Logger.getLogger().debug(
					"Failed to load [" + tertiaryOption + "] due to ",
					tertiaryProblem);

			}
		}

		if (null == implementation) {
			try {
				implementation = attemptLoad(quaternaryOption, "Quaternary");
			}

			catch (DepotException ve4) {
				quaternaryProblem = ve4;

				Logger.getLogger().debug(
					"Failed to load [" + quaternaryOption + "] due to ",
					quaternaryProblem);

			}
		}

		if (null == implementation) {

			Logger.getLogger().error(
				"Failed to load [" + primaryOption + "] due to ",
				primaryProblem);

			Logger.getLogger().error(
				"Failed to load [" + secondaryOption + "] due to ",
				secondaryProblem);

			Logger.getLogger().error(
				"Failed to load [" + tertiaryOption + "] due to ",
				tertiaryProblem);

			Logger.getLogger().error(
				"Failed to load [" + quaternaryOption + "] due to ",
				quaternaryProblem);

			throw new DepotError(
				"Severe failure, a fallback ought exist",
				quaternaryProblem);
		}

		return implementation;
	}

	public Object loadClassWithFallbacks(
		String primaryOption,
		String secondaryOption,
		String tertiaryOption) {

		Object implementation = null;

		DepotException primaryProblem = null;
		DepotException secondaryProblem = null;
		DepotException tertiaryProblem = null;

		try {
			implementation = attemptLoad(primaryOption, "Primary");
		}
		catch (DepotException ve) {
			primaryProblem = ve;

			Logger.getLogger().debug(
				"Failed to load [" + primaryOption + "] due to ",
				primaryProblem);
		}

		if (null == implementation) {
			try {
				implementation = attemptLoad(secondaryOption, "Secondary");
			}

			catch (DepotException ve2) {
				secondaryProblem = ve2;

				Logger.getLogger().debug(
					"Failed to load [" + secondaryOption + "] due to ",
					secondaryProblem);

			}
		}

		if (null == implementation) {
			try {
				implementation = attemptLoad(tertiaryOption, "Tertiary");
			}

			catch (DepotException ve3) {
				tertiaryProblem = ve3;

				Logger.getLogger().debug(
					"Failed to load [" + tertiaryOption + "] due to ",
					tertiaryProblem);

			}
		}

		if (null == implementation) {

			Logger.getLogger().error(
				"Failed to load [" + primaryOption + "] due to ",
				primaryProblem);

			Logger.getLogger().error(
				"Failed to load [" + secondaryOption + "] due to ",
				secondaryProblem);

			Logger.getLogger().error(
				"Failed to load [" + tertiaryOption + "] due to ",
				tertiaryProblem);

			throw new DepotError(
				"Severe failure, a fallback ought exist",
				tertiaryProblem);
		}

		return implementation;
	}

	public Object loadClassWithFallback(
		String primaryOption,
		String secondaryOption) {

		DepotException primaryProblem = null;
		DepotException secondaryProblem = null;

		Object implementation = null;

		try {
			implementation = attemptLoad(primaryOption, "Primary");
		}
		catch (DepotException ve) {
			primaryProblem = ve;

			Logger.getLogger().debug(
				"Failed to load [" + primaryOption + "] due to ",
				primaryProblem);

		}

		if (null == implementation) {
			try {
				implementation = attemptLoad(secondaryOption, "Secondary");
			}

			catch (DepotException ve2) {
				secondaryProblem = ve2;

				Logger.getLogger().debug(
					"Failed to load [" + secondaryOption + "] due to ",
					secondaryProblem);

			}
		}

		//:TODO: We can't set cuase again, we can't attach two
		// causes. Hmm. Log both and throw one?

		if (null == implementation) {

			Logger.getLogger().error(
				"Failed to load [" + primaryOption + "] due to ",
				primaryProblem);

			Logger.getLogger().error(
				"Failed to load [" + secondaryOption + "] due to ",
				secondaryProblem);

			throw new DepotError(
				"Severe failure, a fallback ought exist",
				secondaryProblem);
		}

		return implementation;
	}

	public Object attemptLoad(String className, String optionName)
		throws DepotException {
		Object implementation = null;

		try {
			Class optionClass = Class.forName(className);

			implementation = optionClass.newInstance();

		}
		catch (NoClassDefFoundError ncdfe) {
			throw new DepotException(
				getClassLoadMessage(className, optionName, ncdfe),
				ncdfe);
		}
		catch (ClassNotFoundException cnf) {
			throw new DepotException(
				getClassLoadMessage(className, optionName, cnf),
				cnf);
		}
		catch (IllegalAccessException iae) {
			throw new DepotException(
				getClassLoadMessage(className, optionName, iae),
				iae);
		}
		catch (InstantiationException ie) {
			throw new DepotException(
				getClassLoadMessage(className, optionName, ie),
				ie);
		}

		return implementation;
	}

	public Throwable thrownIfLoaded(String className) {
		Throwable thrown = null;

		try {
			Class.forName(className);
		}
		catch (ClassNotFoundException cnf) {
			thrown = cnf;
		}

		return thrown;
	}

	private String getClassLoadMessage(String o1, String o2, Throwable cause) {
		return "Failed to \"Safely Load\"  ["
			+ o1
			+ "] as ["
			+ o2
			+ "] :"
			+ cause;
	}
	/**
	 * @return
	 */
	public ClassLoader getClassLoader() {
		return m_loader;
	}

	/**
	 * @param loader
	 */
	public void setClassLoader(ClassLoader loader) {
		m_loader = loader;
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	public boolean equals(Object arg0) {
		return m_loader.equals(((ClassLoaderContext)arg0).m_loader);
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#hashCode()
	 */
	public int hashCode() {
		return m_loader.hashCode();
	}
}

--- NEW FILE: RelativelySafe.java ---
/*
 * Copyright  2004 The Apache Software Foundation
 *
 *  Licensed 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.krysalis.depot.common.util.envsafe;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

import org.krysalis.depot.common.DepotError;
import org.krysalis.depot.common.log.Logger;
import org.krysalis.depot.common.util.SystemUtils;

/**
 * @author ajack
 */
public class RelativelySafe {
	private static boolean l_initialized = false;
	private static boolean l_isJVM12 = false;
	private static boolean l_isJVM13 = false;
	private static boolean l_isJVM14 = true;

	public static synchronized void initialize() {
		if (l_initialized)
			return;

		String version =
			System.getProperties().getProperty("java.specification.version");

		if ("1.2".equals(version)) {
			l_isJVM12 = true;
			l_isJVM13 = l_isJVM14 = false;
		}
		else if ("1.3".equals(version)) {
			l_isJVM13 = true;
			l_isJVM12 = l_isJVM14 = false;
		}
		else if ("1.4".equals(version) || ("1.4".compareTo(version) < 0)) {
			// Fail safe if anything about JVM 1.4 comes out whilst this code 
			// is still around
			l_isJVM14 = true;
			l_isJVM12 = l_isJVM13 = false;
		}
		else {
			throw new DepotError("Unhandled JVM version: " + version);
		}

	}

	public static boolean isJVM12() {
		if (!l_initialized)
			initialize();

		return l_isJVM12;
	}

	public static boolean isJVM13() {
		if (!l_initialized)
			initialize();

		return l_isJVM13;
	}

	public static boolean isJVM14() {
		if (!l_initialized)
			initialize();

		return l_isJVM14;
	}

	public static Object callMethod(Object obj, String name) {
		return attemptMethod(obj, name, null);
	}

	public static Object callMethod(Object obj, String name, Object argument) {
		Object args[] = new Object[1];
		args[0] = argument;

		return attemptMethod(obj, name, args);
	}

	public static Object callMethod(
		Object obj,
		String name,
		Class argumentClass,
		Object argument) {
		Class argClasses[] = new Class[1];
		argClasses[0] = argumentClass;

		Object args[] = new Object[1];
		args[0] = argument;

		return attemptMethod(obj, name, argClasses, args);
	}

	public static Object callMethod(
		Object obj,
		String name,
		Object argument1,
		Object argument2) {
		Object args[] = new Object[2];
		args[0] = argument1;
		args[1] = argument2;

		return attemptMethod(obj, name, args);
	}

	public static Object callMethod(
		Object obj,
		String name,
		Object arguments[]) {
		return attemptMethod(obj, name, arguments);
	}

	private static Object attemptMethod(
		Object obj,
		String name,
		Object arguments[]) {
		return attemptMethod(obj, name, null, arguments);
	}

	private static Object attemptMethod(
		Object obj,
		String name,
		Class argumentClasses[],
		Object arguments[]) {
		Object result = null;

		Class objectClass = obj.getClass();

		//
		//    Construct some if not passed...
		//
		if (null == argumentClasses) {
			if (null != arguments) {
				argumentClasses = new Class[arguments.length];

				for (int i = 0; i < arguments.length; ++i) {
					Class argClass = (arguments[i]).getClass();
					argumentClasses[i] = argClass;
				}
			}
			else {
				argumentClasses = new Class[0];
			}
		}
		else if (argumentClasses.length != arguments.length)
			throw new DepotError(
				"Mismatch Classes to Arguments: "
					+ argumentClasses.length
					+ " != "
					+ arguments.length);

		try {
			Method method = objectClass.getMethod(name, argumentClasses);

			int modifiers = method.getModifiers();

			if (Modifier.isPublic(modifiers)
				&& !Modifier.isStatic(modifiers)) {
				result = method.invoke(obj, arguments);
			}
		}
		catch (InvocationTargetException ite) {
			Logger.getLogger().debug(
				getMethodMessage(name, argumentClasses, arguments),
				ite);
		}
		catch (IllegalAccessException iae) {
			Logger.getLogger().debug(
				getMethodMessage(name, argumentClasses, arguments),
				iae);
		}
		catch (NoSuchMethodException nsme) {
			Logger.getLogger().debug(
				getMethodMessage(name, argumentClasses, arguments),
				nsme);
		}

		return result;
	}

	private static String getMethodMessage(
		String name,
		Class argumentClasses[],
		Object arguments[]) {
		StringBuffer buffer =
			new StringBuffer(
				"Failed to \"Safely Invoke\" method [" + name + "] using [");
		if (null != argumentClasses) {
			buffer.append(Integer.toString(arguments.length));
			buffer.append(" :");

			for (int ac = 0; ac < argumentClasses.length; ++ac) {
				Class clazz = argumentClasses[ac];
				buffer.append(SystemUtils.getShortName(clazz));
				if ((ac + 1) < argumentClasses.length)
					buffer.append(", ");
			}
		}
		buffer.append("] w/ [");
		if (null != arguments) {
			buffer.append(Integer.toString(arguments.length));
			buffer.append(" :");

			for (int a = 0; a < arguments.length; ++a) {
				Object obj = arguments[a];
				buffer.append(obj.toString());
				if ((a + 1) < arguments.length)
					buffer.append(", ");
			}
		}
		buffer.append("]");

		return buffer.toString();
	}

}



-------------------------------------------------------
SF email is sponsored by - The IT Product Guide
Read honest & candid reviews on hundreds of IT Products from real users.
Discover which products truly live up to the hype. Start reading now. 
http://productguide.itmanagersjournal.com/