1 /* 2 * Hibernate, Relational Persistence for Idiomatic Java 3 * 4 * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as 5 * indicated by the @author tags or express copyright attribution 6 * statements applied by the authors. All third-party contributions are 7 * distributed under license by Red Hat Middleware LLC. 8 * 9 * This copyrighted material is made available to anyone wishing to use, modify, 10 * copy, or redistribute it subject to the terms and conditions of the GNU 11 * Lesser General Public License, as published by the Free Software Foundation. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License 16 * for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public License 19 * along with this distribution; if not, write to: 20 * Free Software Foundation, Inc. 21 * 51 Franklin Street, Fifth Floor 22 * Boston, MA 02110-1301 USA 23 * 24 */ 25 package org.hibernate.bytecode.javassist; 26 27 import org.hibernate.bytecode.ProxyFactoryFactory; 28 import org.hibernate.bytecode.BasicProxyFactory; 29 import org.hibernate.proxy.ProxyFactory; 30 import org.hibernate.proxy.pojo.javassist.JavassistProxyFactory; 31 import org.hibernate.AssertionFailure; 32 import org.hibernate.HibernateException; 33 import javassist.util.proxy.MethodFilter; 34 import javassist.util.proxy.ProxyObject; 35 import javassist.util.proxy.MethodHandler; 36 37 import java.lang.reflect.Method; 38 import java.util.HashMap; 39 40 /** 41 * A factory for Javassist-based {@link ProxyFactory} instances. 42 * 43 * @author Steve Ebersole 44 */ 45 public class ProxyFactoryFactoryImpl implements ProxyFactoryFactory { 46 47 /** 48 * Builds a Javassist-based proxy factory. 49 * 50 * @return a new Javassist-based proxy factory. 51 */ 52 public ProxyFactory buildProxyFactory() { 53 return new JavassistProxyFactory(); 54 } 55 56 public BasicProxyFactory buildBasicProxyFactory(Class superClass, Class[] interfaces) { 57 return new BasicProxyFactoryImpl( superClass, interfaces ); 58 } 59 60 private static class BasicProxyFactoryImpl implements BasicProxyFactory { 61 private final Class proxyClass; 62 63 public BasicProxyFactoryImpl(Class superClass, Class[] interfaces) { 64 if ( superClass == null && ( interfaces == null || interfaces.length < 1 ) ) { 65 throw new AssertionFailure( "attempting to build proxy without any superclass or interfaces" ); 66 } 67 javassist.util.proxy.ProxyFactory factory = new javassist.util.proxy.ProxyFactory(); 68 factory.setFilter( FINALIZE_FILTER ); 69 if ( superClass != null ) { 70 factory.setSuperclass( superClass ); 71 } 72 if ( interfaces != null && interfaces.length > 0 ) { 73 factory.setInterfaces( interfaces ); 74 } 75 proxyClass = factory.createClass(); 76 } 77 78 public Object getProxy() { 79 try { 80 ProxyObject proxy = ( ProxyObject ) proxyClass.newInstance(); 81 proxy.setHandler( new PassThroughHandler( proxy, proxyClass.getName() ) ); 82 return proxy; 83 } 84 catch ( Throwable t ) { 85 throw new HibernateException( "Unable to instantiated proxy instance" ); 86 } 87 } 88 89 public boolean isInstance(Object object) { 90 return proxyClass.isInstance( object ); 91 } 92 } 93 94 private static final MethodFilter FINALIZE_FILTER = new MethodFilter() { 95 public boolean isHandled(Method m) { 96 // skip finalize methods 97 return !( m.getParameterTypes().length == 0 && m.getName().equals( "finalize" ) ); 98 } 99 }; 100 101 private static class PassThroughHandler implements MethodHandler { 102 private HashMap data = new HashMap(); 103 private final Object proxiedObject; 104 private final String proxiedClassName; 105 106 public PassThroughHandler(Object proxiedObject, String proxiedClassName) { 107 this.proxiedObject = proxiedObject; 108 this.proxiedClassName = proxiedClassName; 109 } 110 111 public Object invoke( 112 Object object, 113 Method method, 114 Method method1, 115 Object[] args) throws Exception { 116 String name = method.getName(); 117 if ( "toString".equals( name ) ) { 118 return proxiedClassName + "@" + System.identityHashCode( object ); 119 } 120 else if ( "equals".equals( name ) ) { 121 return proxiedObject == object ? Boolean.TRUE : Boolean.FALSE; 122 } 123 else if ( "hashCode".equals( name ) ) { 124 return new Integer( System.identityHashCode( object ) ); 125 } 126 boolean hasGetterSignature = method.getParameterTypes().length == 0 && method.getReturnType() != null; 127 boolean hasSetterSignature = method.getParameterTypes().length == 1 && ( method.getReturnType() == null || method.getReturnType() == void.class ); 128 if ( name.startsWith( "get" ) && hasGetterSignature ) { 129 String propName = name.substring( 3 ); 130 return data.get( propName ); 131 } 132 else if ( name.startsWith( "is" ) && hasGetterSignature ) { 133 String propName = name.substring( 2 ); 134 return data.get( propName ); 135 } 136 else if ( name.startsWith( "set" ) && hasSetterSignature) { 137 String propName = name.substring( 3 ); 138 data.put( propName, args[0] ); 139 return null; 140 } 141 else { 142 // todo : what else to do here? 143 return null; 144 } 145 } 146 } 147 }