001: /*
002: * Copyright 2005-2006 The Kuali Foundation.
003: *
004: *
005: * Licensed under the Educational Community License, Version 1.0 (the "License");
006: * you may not use this file except in compliance with the License.
007: * You may obtain a copy of the License at
008: *
009: * http://www.opensource.org/licenses/ecl1.php
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.kuali.rice.util;
018:
019: import java.lang.reflect.InvocationHandler;
020: import java.lang.reflect.Proxy;
021: import java.util.Iterator;
022: import java.util.List;
023:
024: import org.apache.commons.lang.ClassUtils;
025:
026: /**
027: * Provides common utility methods for dealing with Classloaders.
028: *
029: * @author Kuali Rice Team (kuali-rice@googlegroups.com)
030: */
031: public class ClassLoaderUtils {
032:
033: private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger
034: .getLogger(ClassLoaderUtils.class);
035:
036: /**
037: * Returns the default class loader within the current context. If there is a context classloader
038: * it is returned, otherwise the classloader which loaded the ClassLoaderUtil Class is returned.
039: *
040: * @return the appropriate default classloader which is guaranteed to be non-null
041: */
042: public static ClassLoader getDefaultClassLoader() {
043: ClassLoader classLoader = Thread.currentThread()
044: .getContextClassLoader();
045: if (classLoader == null) {
046: classLoader = ClassLoaderUtils.class.getClassLoader();
047: }
048: return classLoader;
049: }
050:
051: /**
052: * Checks if the given object is an instance of the given class, unwrapping any proxies if
053: * necessary to get to the underlying object.
054: */
055: public static boolean isInstanceOf(Object object,
056: Class instanceClass) {
057: if (object == null) {
058: return false;
059: }
060: if (instanceClass.isInstance(object)) {
061: return true;
062: }
063: return isInstanceOf(unwrapFromProxyOnce(object), instanceClass);
064: }
065:
066: public static Object unwrapFromProxy(Object proxy) {
067: Object unwrapped = unwrapFromProxyOnce(proxy);
068: if (unwrapped == null) {
069: return proxy;
070: }
071: return unwrapFromProxy(unwrapped);
072: }
073:
074: /**
075: * Unwraps the underlying object from the given proxy (which may itself be a proxy). If the
076: * given object is not a valid proxy, then null is returned.
077: */
078: private static Object unwrapFromProxyOnce(Object proxy) {
079: if (proxy != null && Proxy.isProxyClass(proxy.getClass())) {
080: InvocationHandler invocationHandler = Proxy
081: .getInvocationHandler(proxy);
082: if (invocationHandler instanceof TargetedInvocationHandler) {
083: return ((TargetedInvocationHandler) invocationHandler)
084: .getTarget();
085: }
086: }
087: return null;
088: }
089:
090: /**
091: * Checks if the given Class is visible to the given ClassLoader.
092: */
093: public static boolean isClassVisible(ClassLoader classLoader,
094: Class classToCheck) {
095: try {
096: Class classFound = classLoader.loadClass(classToCheck
097: .getName());
098: return classFound.equals(classToCheck);
099: } catch (ClassNotFoundException e) {
100: return false;
101: }
102: }
103:
104: /**
105: * Determines the interfaces which need to be proxied and are visible to the given proxy ClassLoader.
106: */
107: public static Class[] getInterfacesToProxy(Object object,
108: ClassLoader proxyClassLoader, String[] packageNamesToFilter) {
109: List interfaces = ClassUtils
110: .getAllInterfaces(object.getClass());
111: outer: for (Iterator iterator = interfaces.iterator(); iterator
112: .hasNext();) {
113: Class objectInterface = (Class) iterator.next();
114: // check package name filters
115: if (packageNamesToFilter != null) {
116: for (String packageNames : packageNamesToFilter) {
117: if (objectInterface.getName().startsWith(
118: packageNames)) {
119: iterator.remove();
120: continue outer;
121: }
122: }
123: }
124: // check that the interface is visible from the given classloader
125: if (proxyClassLoader != null) {
126: if (!ClassLoaderUtils.isClassVisible(proxyClassLoader,
127: objectInterface)) {
128: if (LOG.isDebugEnabled()) {
129: LOG
130: .debug("The interface "
131: + objectInterface
132: + " was not visible from the proxy ClassLoader when attempting to proxy: "
133: + object);
134: }
135: iterator.remove();
136: continue outer;
137: }
138: }
139: }
140: Class[] interfaceArray = new Class[interfaces.size()];
141: return (Class[]) interfaces.toArray(interfaceArray);
142: }
143:
144: }
|