Home » Hibernate-3.3.2.GA » org.hibernate » bytecode » cglib » [javadoc | source]

    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.cglib;
   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.cglib.CGLIBProxyFactory;
   31   import org.hibernate.AssertionFailure;
   32   import org.hibernate.HibernateException;
   33   import net.sf.cglib.proxy.Enhancer;
   34   import net.sf.cglib.proxy.CallbackFilter;
   35   import net.sf.cglib.proxy.MethodInterceptor;
   36   import net.sf.cglib.proxy.MethodProxy;
   37   import net.sf.cglib.proxy.NoOp;
   38   import net.sf.cglib.proxy.Callback;
   39   import net.sf.cglib.proxy.Factory;
   40   
   41   import java.lang.reflect.Method;
   42   import java.util.HashMap;
   43   
   44   /**
   45    * A factory for CGLIB-based {@link ProxyFactory} instances.
   46    *
   47    * @author Steve Ebersole
   48    */
   49   public class ProxyFactoryFactoryImpl implements ProxyFactoryFactory {
   50   
   51   	/**
   52   	 * Builds a CGLIB-based proxy factory.
   53   	 *
   54   	 * @return a new CGLIB-based proxy factory.
   55   	 */
   56   	public ProxyFactory buildProxyFactory() {
   57   		return new CGLIBProxyFactory();
   58   	}
   59   
   60   	public BasicProxyFactory buildBasicProxyFactory(Class superClass, Class[] interfaces) {
   61   		return new BasicProxyFactoryImpl( superClass, interfaces );
   62   	}
   63   
   64   	public static class BasicProxyFactoryImpl implements BasicProxyFactory {
   65   		private final Class proxyClass;
   66   		private final Factory factory;
   67   
   68   		public BasicProxyFactoryImpl(Class superClass, Class[] interfaces) {
   69   			if ( superClass == null && ( interfaces == null || interfaces.length < 1 ) ) {
   70   				throw new AssertionFailure( "attempting to build proxy without any superclass or interfaces" );
   71   			}
   72   
   73   			Enhancer en = new Enhancer();
   74   			en.setUseCache( false );
   75   			en.setInterceptDuringConstruction( false );
   76   			en.setUseFactory( true );
   77   			en.setCallbackTypes( CALLBACK_TYPES );
   78   			en.setCallbackFilter( FINALIZE_FILTER );
   79   			if ( superClass != null ) {
   80   				en.setSuperclass( superClass );
   81   			}
   82   			if ( interfaces != null && interfaces.length > 0 ) {
   83   				en.setInterfaces( interfaces );
   84   			}
   85   			proxyClass = en.createClass();
   86   			try {
   87   				factory = ( Factory ) proxyClass.newInstance();
   88   			}
   89   			catch ( Throwable t ) {
   90   				throw new HibernateException( "Unable to build CGLIB Factory instance" );
   91   			}
   92   		}
   93   
   94   		public Object getProxy() {
   95   			try {
   96   				return factory.newInstance(
   97   						new Callback[] { new PassThroughInterceptor( proxyClass.getName() ), NoOp.INSTANCE }
   98   				);
   99   			}
  100   			catch ( Throwable t ) {
  101   				throw new HibernateException( "Unable to instantiate proxy instance" );
  102   			}
  103   		}
  104   	}
  105   
  106   	private static final CallbackFilter FINALIZE_FILTER = new CallbackFilter() {
  107   		public int accept(Method method) {
  108   			if ( method.getParameterTypes().length == 0 && method.getName().equals("finalize") ){
  109   				return 1;
  110   			}
  111   			else {
  112   				return 0;
  113   			}
  114   		}
  115   	};
  116   
  117   	private static final Class[] CALLBACK_TYPES = new Class[] { MethodInterceptor.class, NoOp.class };
  118   
  119   	private static class PassThroughInterceptor implements MethodInterceptor {
  120   		private HashMap data = new HashMap();
  121   		private final String proxiedClassName;
  122   
  123   		public PassThroughInterceptor(String proxiedClassName) {
  124   			this.proxiedClassName = proxiedClassName;
  125   		}
  126   
  127   		public Object intercept(
  128   				Object obj,
  129   		        Method method,
  130   		        Object[] args,
  131   		        MethodProxy proxy) throws Throwable {
  132   			String name = method.getName();
  133   			if ( "toString".equals( name ) ) {
  134   				return proxiedClassName + "@" + System.identityHashCode( obj );
  135   			}
  136   			else if ( "equals".equals( name ) ) {
  137   				return args[0] instanceof Factory && ( ( Factory ) args[0] ).getCallback( 0 ) == this
  138   						? Boolean.TRUE
  139   			            : Boolean.FALSE;
  140   			}
  141   			else if ( "hashCode".equals( name ) ) {
  142   				return new Integer( System.identityHashCode( obj ) );
  143   			}
  144   			boolean hasGetterSignature = method.getParameterTypes().length == 0 && method.getReturnType() != null;
  145   			boolean hasSetterSignature = method.getParameterTypes().length == 1 && ( method.getReturnType() == null || method.getReturnType() == void.class );
  146   			if ( name.startsWith( "get" ) && hasGetterSignature ) {
  147   				String propName = name.substring( 3 );
  148   				return data.get( propName );
  149   			}
  150   			else if ( name.startsWith( "is" ) && hasGetterSignature ) {
  151   				String propName = name.substring( 2 );
  152   				return data.get( propName );
  153   			}
  154   			else if ( name.startsWith( "set" ) && hasSetterSignature) {
  155   				String propName = name.substring( 3 );
  156   				data.put( propName, args[0] );
  157   				return null;
  158   			}
  159   			else {
  160   				// todo : what else to do here?
  161   				return null;
  162   			}
  163   		}
  164   	}
  165   }

Home » Hibernate-3.3.2.GA » org.hibernate » bytecode » cglib » [javadoc | source]