001: package org.hibernate.bytecode.cglib;
002:
003: import org.hibernate.bytecode.ProxyFactoryFactory;
004: import org.hibernate.bytecode.BasicProxyFactory;
005: import org.hibernate.proxy.ProxyFactory;
006: import org.hibernate.proxy.pojo.cglib.CGLIBProxyFactory;
007: import org.hibernate.AssertionFailure;
008: import org.hibernate.HibernateException;
009: import net.sf.cglib.proxy.Enhancer;
010: import net.sf.cglib.proxy.CallbackFilter;
011: import net.sf.cglib.proxy.MethodInterceptor;
012: import net.sf.cglib.proxy.MethodProxy;
013: import net.sf.cglib.proxy.NoOp;
014: import net.sf.cglib.proxy.Callback;
015: import net.sf.cglib.proxy.Factory;
016:
017: import java.lang.reflect.Method;
018: import java.util.HashMap;
019:
020: /**
021: * A factory for CGLIB-based {@link ProxyFactory} instances.
022: *
023: * @author Steve Ebersole
024: */
025: public class ProxyFactoryFactoryImpl implements ProxyFactoryFactory {
026:
027: /**
028: * Builds a CGLIB-based proxy factory.
029: *
030: * @return a new CGLIB-based proxy factory.
031: */
032: public ProxyFactory buildProxyFactory() {
033: return new CGLIBProxyFactory();
034: }
035:
036: public BasicProxyFactory buildBasicProxyFactory(Class super Class,
037: Class[] interfaces) {
038: return new BasicProxyFactoryImpl(super Class, interfaces);
039: }
040:
041: public static class BasicProxyFactoryImpl implements
042: BasicProxyFactory {
043: private final Class proxyClass;
044: private final Factory factory;
045:
046: public BasicProxyFactoryImpl(Class super Class,
047: Class[] interfaces) {
048: if (super Class == null
049: && (interfaces == null || interfaces.length < 1)) {
050: throw new AssertionFailure(
051: "attempting to build proxy without any superclass or interfaces");
052: }
053:
054: Enhancer en = new Enhancer();
055: en.setUseCache(false);
056: en.setInterceptDuringConstruction(false);
057: en.setUseFactory(true);
058: en.setCallbackTypes(CALLBACK_TYPES);
059: en.setCallbackFilter(FINALIZE_FILTER);
060: if (super Class != null) {
061: en.setSuperclass(super Class);
062: }
063: if (interfaces != null && interfaces.length > 0) {
064: en.setInterfaces(interfaces);
065: }
066: proxyClass = en.createClass();
067: try {
068: factory = (Factory) proxyClass.newInstance();
069: } catch (Throwable t) {
070: throw new HibernateException(
071: "Unable to build CGLIB Factory instance");
072: }
073: }
074:
075: public Object getProxy() {
076: try {
077: return factory
078: .newInstance(new Callback[] {
079: new PassThroughInterceptor(proxyClass
080: .getName()), NoOp.INSTANCE });
081: } catch (Throwable t) {
082: throw new HibernateException(
083: "Unable to instantiate proxy instance");
084: }
085: }
086: }
087:
088: private static final CallbackFilter FINALIZE_FILTER = new CallbackFilter() {
089: public int accept(Method method) {
090: if (method.getParameterTypes().length == 0
091: && method.getName().equals("finalize")) {
092: return 1;
093: } else {
094: return 0;
095: }
096: }
097: };
098:
099: private static final Class[] CALLBACK_TYPES = new Class[] {
100: MethodInterceptor.class, NoOp.class };
101:
102: private static class PassThroughInterceptor implements
103: MethodInterceptor {
104: private HashMap data = new HashMap();
105: private final String proxiedClassName;
106:
107: public PassThroughInterceptor(String proxiedClassName) {
108: this .proxiedClassName = proxiedClassName;
109: }
110:
111: public Object intercept(Object obj, Method method,
112: Object[] args, MethodProxy proxy) throws Throwable {
113: String name = method.getName();
114: if ("toString".equals(name)) {
115: return proxiedClassName + "@"
116: + System.identityHashCode(obj);
117: } else if ("equals".equals(name)) {
118: return args[0] instanceof Factory
119: && ((Factory) args[0]).getCallback(0) == this ? Boolean.TRUE
120: : Boolean.FALSE;
121: } else if ("hashCode".equals(name)) {
122: return new Integer(System.identityHashCode(obj));
123: }
124: boolean hasGetterSignature = method.getParameterTypes().length == 0
125: && method.getReturnType() != null;
126: boolean hasSetterSignature = method.getParameterTypes().length == 1
127: && (method.getReturnType() == null || method
128: .getReturnType() == void.class);
129: if (name.startsWith("get") && hasGetterSignature) {
130: String propName = name.substring(3);
131: return data.get(propName);
132: } else if (name.startsWith("is") && hasGetterSignature) {
133: String propName = name.substring(2);
134: return data.get(propName);
135: } else if (name.startsWith("set") && hasSetterSignature) {
136: String propName = name.substring(3);
137: data.put(propName, args[0]);
138: return null;
139: } else {
140: // todo : what else to do here?
141: return null;
142: }
143: }
144: }
145: }
|