/*
* Copyright 2008, Unitils.org
*
* 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.unitils.reflectionassert.util;
import org.unitils.core.UnitilsException;
/**
* Utility class for handling Hibernate proxies during the comparison.
* <p/>
* Every operation is performed through reflection to avoid a direct link to Hibernate. This way you do not
* need Hibernate in the classpath to use the reflection comparator.
*
* @author Tim Ducheyne
* @author Filip Neven
*/
public class HibernateUtil {
/**
* The hibernate proxy type, null if the class is not found in the classpath
*/
protected static Class<?> hibernateProxyClass;
static {
try {
hibernateProxyClass = Class.forName("org.hibernate.proxy.HibernateProxy");
} catch (ClassNotFoundException e) {
// hibernate not found in the classpath
hibernateProxyClass = null;
}
}
/**
* Checks whether the given ojbect is a HibernateProxy instance.
*
* @param object The object
* @return True if the object is a proxy
*/
public static boolean isHibernateProxy(Object object) {
return hibernateProxyClass != null && hibernateProxyClass.isInstance(object);
}
/**
* Checks whether the given proxy object has been loaded.
*
* @param object The object or proxy
* @return True if the object is a proxy and has been loaded
*/
public static boolean isUninitialized(Object object) {
if (!isHibernateProxy(object)) {
return false;
}
return (Boolean) invokeLazyInitializerMethod("isUninitialized", object);
}
/**
* Gets the class name of the proxied object
*
* @param object The object or proxy
* @return The class name of the object, null if the object is null
*/
public static String getEntitiyName(Object object) {
if (!isHibernateProxy(object)) {
return object == null ? null : object.getClass().getName();
}
return (String) invokeLazyInitializerMethod("getEntityName", object);
}
/**
* Gets the unique identifier of the given proxy object.
*
* @param object The object or proxy
* @return The identifier or null if the object was not a proxy
*/
public static Object getIdentifier(Object object) {
if (!isHibernateProxy(object)) {
return null;
}
return invokeLazyInitializerMethod("getIdentifier", object);
}
/**
* Gets (and loads) the wrapped object out of a given hibernate proxy.
* <p/>
* If the given object is not a proxy or if Hibernate is not found in the classpath, this method just returns
* the given object. If the given object is a proxy, the proxy is initialized (loaded) and the un-wrapped object
* is returned.
*
* @param object The object or proxy
* @return The uproxied object or the object itself if it was no proxy
*/
public static Object getUnproxiedValue(Object object) {
// check whether object is a proxy
if (!isHibernateProxy(object)) {
return object;
}
// found a proxy, load and un-wrap
return invokeLazyInitializerMethod("getImplementation", object);
}
/**
* Invokes the given method on the LazyInitializer that is associated with the given proxy.
*
* @param methodName The method to invoke, not null
* @param proxy The hibernate proxy instance, not null
* @return The result value of the method call
*/
protected static Object invokeLazyInitializerMethod(String methodName, Object proxy) {
try {
Object lazyInitializer = hibernateProxyClass.getMethod("getHibernateLazyInitializer").invoke(proxy);
return lazyInitializer.getClass().getMethod(methodName).invoke(lazyInitializer);
} catch (Exception e) {
throw new UnitilsException("Unable to invoke method on lazy initializer of Hibernate proxy. Method: " + methodName + ", proxy: " + proxy, e);
}
}
}