001: package org.hibernate.proxy.pojo.javassist;
002:
003: import java.io.Serializable;
004: import java.lang.reflect.InvocationTargetException;
005: import java.lang.reflect.Method;
006:
007: import javassist.util.proxy.MethodFilter;
008: import javassist.util.proxy.MethodHandler;
009: import javassist.util.proxy.ProxyFactory;
010: import javassist.util.proxy.ProxyObject;
011:
012: import org.apache.commons.logging.LogFactory;
013: import org.hibernate.HibernateException;
014: import org.hibernate.engine.SessionImplementor;
015: import org.hibernate.proxy.pojo.BasicLazyInitializer;
016: import org.hibernate.proxy.HibernateProxy;
017: import org.hibernate.type.AbstractComponentType;
018: import org.hibernate.util.ReflectHelper;
019:
020: /**
021: * A Javassist-based lazy initializer proxy.
022: *
023: * @author Muga Nishizawa
024: */
025: public class JavassistLazyInitializer extends BasicLazyInitializer
026: implements MethodHandler {
027:
028: private static final MethodFilter FINALIZE_FILTER = new MethodFilter() {
029: public boolean isHandled(Method m) {
030: // skip finalize methods
031: return !(m.getParameterTypes().length == 0 && m.getName()
032: .equals("finalize"));
033: }
034: };
035:
036: private Class[] interfaces;
037: private boolean constructed = false;
038:
039: private JavassistLazyInitializer(final String entityName,
040: final Class persistentClass, final Class[] interfaces,
041: final Serializable id, final Method getIdentifierMethod,
042: final Method setIdentifierMethod,
043: final AbstractComponentType componentIdType,
044: final SessionImplementor session) {
045: super (entityName, persistentClass, id, getIdentifierMethod,
046: setIdentifierMethod, componentIdType, session);
047: this .interfaces = interfaces;
048: }
049:
050: public static HibernateProxy getProxy(final String entityName,
051: final Class persistentClass, final Class[] interfaces,
052: final Method getIdentifierMethod,
053: final Method setIdentifierMethod,
054: AbstractComponentType componentIdType,
055: final Serializable id, final SessionImplementor session)
056: throws HibernateException {
057: // note: interface is assumed to already contain HibernateProxy.class
058: try {
059: final JavassistLazyInitializer instance = new JavassistLazyInitializer(
060: entityName, persistentClass, interfaces, id,
061: getIdentifierMethod, setIdentifierMethod,
062: componentIdType, session);
063: ProxyFactory factory = new ProxyFactory();
064: factory
065: .setSuperclass(interfaces.length == 1 ? persistentClass
066: : null);
067: factory.setInterfaces(interfaces);
068: factory.setFilter(FINALIZE_FILTER);
069: Class cl = factory.createClass();
070: final HibernateProxy proxy = (HibernateProxy) cl
071: .newInstance();
072: ((ProxyObject) proxy).setHandler(instance);
073: instance.constructed = true;
074: return proxy;
075: } catch (Throwable t) {
076: LogFactory.getLog(BasicLazyInitializer.class).error(
077: "Javassist Enhancement failed: " + entityName, t);
078: throw new HibernateException(
079: "Javassist Enhancement failed: " + entityName, t);
080: }
081: }
082:
083: public static HibernateProxy getProxy(final Class factory,
084: final String entityName, final Class persistentClass,
085: final Class[] interfaces, final Method getIdentifierMethod,
086: final Method setIdentifierMethod,
087: final AbstractComponentType componentIdType,
088: final Serializable id, final SessionImplementor session)
089: throws HibernateException {
090:
091: final JavassistLazyInitializer instance = new JavassistLazyInitializer(
092: entityName, persistentClass, interfaces, id,
093: getIdentifierMethod, setIdentifierMethod,
094: componentIdType, session);
095:
096: final HibernateProxy proxy;
097: try {
098: proxy = (HibernateProxy) factory.newInstance();
099: } catch (Exception e) {
100: throw new HibernateException(
101: "Javassist Enhancement failed: "
102: + persistentClass.getName(), e);
103: }
104: ((ProxyObject) proxy).setHandler(instance);
105: instance.constructed = true;
106: return proxy;
107: }
108:
109: public static Class getProxyFactory(Class persistentClass,
110: Class[] interfaces) throws HibernateException {
111: // note: interfaces is assumed to already contain HibernateProxy.class
112:
113: try {
114: ProxyFactory factory = new ProxyFactory();
115: factory
116: .setSuperclass(interfaces.length == 1 ? persistentClass
117: : null);
118: factory.setInterfaces(interfaces);
119: factory.setFilter(FINALIZE_FILTER);
120: return factory.createClass();
121: } catch (Throwable t) {
122: LogFactory.getLog(BasicLazyInitializer.class).error(
123: "Javassist Enhancement failed: "
124: + persistentClass.getName(), t);
125: throw new HibernateException(
126: "Javassist Enhancement failed: "
127: + persistentClass.getName(), t);
128: }
129: }
130:
131: public Object invoke(final Object proxy, final Method this Method,
132: final Method proceed, final Object[] args) throws Throwable {
133: if (this .constructed) {
134: Object result;
135: try {
136: result = this .invoke(this Method, args, proxy);
137: } catch (Throwable t) {
138: throw new Exception(t.getCause());
139: }
140: if (result == INVOKE_IMPLEMENTATION) {
141: Object target = getImplementation();
142: final Object returnValue;
143: try {
144: if (ReflectHelper.isPublic(persistentClass,
145: this Method)) {
146: if (!this Method.getDeclaringClass().isInstance(
147: target)) {
148: throw new ClassCastException(target
149: .getClass().getName());
150: }
151: returnValue = this Method.invoke(target, args);
152: } else {
153: if (!this Method.isAccessible()) {
154: this Method.setAccessible(true);
155: }
156: returnValue = this Method.invoke(target, args);
157: }
158: return returnValue == target ? proxy : returnValue;
159: } catch (InvocationTargetException ite) {
160: throw ite.getTargetException();
161: }
162: } else {
163: return result;
164: }
165: } else {
166: // while constructor is running
167: if (this Method.getName().equals(
168: "getHibernateLazyInitializer")) {
169: return this ;
170: } else {
171: return proceed.invoke(proxy, args);
172: }
173: }
174: }
175:
176: protected Object serializableProxy() {
177: return new SerializableProxy(getEntityName(), persistentClass,
178: interfaces, getIdentifier(), getIdentifierMethod,
179: setIdentifierMethod, componentIdType);
180: }
181: }
|