Save This Page
Home » hibernate-distribution-3.3.1.GA-dist » org.hibernate » proxy » pojo » javassist » [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.proxy.pojo.javassist;
   26   
   27   import java.io.Serializable;
   28   import java.lang.reflect.InvocationTargetException;
   29   import java.lang.reflect.Method;
   30   
   31   import javassist.util.proxy.MethodFilter;
   32   import javassist.util.proxy.MethodHandler;
   33   import javassist.util.proxy.ProxyFactory;
   34   import javassist.util.proxy.ProxyObject;
   35   
   36   import org.slf4j.LoggerFactory;
   37   import org.hibernate.HibernateException;
   38   import org.hibernate.engine.SessionImplementor;
   39   import org.hibernate.proxy.pojo.BasicLazyInitializer;
   40   import org.hibernate.proxy.HibernateProxy;
   41   import org.hibernate.type.AbstractComponentType;
   42   import org.hibernate.util.ReflectHelper;
   43   
   44   /**
   45    * A Javassist-based lazy initializer proxy.
   46    *
   47    * @author Muga Nishizawa
   48    */
   49   public class JavassistLazyInitializer extends BasicLazyInitializer implements MethodHandler {
   50   
   51   	private static final MethodFilter FINALIZE_FILTER = new MethodFilter() {
   52   		public boolean isHandled(Method m) {
   53   			// skip finalize methods
   54   			return !( m.getParameterTypes().length == 0 && m.getName().equals( "finalize" ) );
   55   		}
   56   	};
   57   
   58   	private Class[] interfaces;
   59   	private boolean constructed = false;
   60   
   61   	private JavassistLazyInitializer(
   62   			final String entityName,
   63   	        final Class persistentClass,
   64   	        final Class[] interfaces,
   65   	        final Serializable id,
   66   	        final Method getIdentifierMethod,
   67   	        final Method setIdentifierMethod,
   68   	        final AbstractComponentType componentIdType,
   69   	        final SessionImplementor session) {
   70   		super( entityName, persistentClass, id, getIdentifierMethod, setIdentifierMethod, componentIdType, session );
   71   		this.interfaces = interfaces;
   72   	}
   73   
   74   	public static HibernateProxy getProxy(
   75   			final String entityName,
   76   	        final Class persistentClass,
   77   	        final Class[] interfaces,
   78   	        final Method getIdentifierMethod,
   79   	        final Method setIdentifierMethod,
   80   	        AbstractComponentType componentIdType,
   81   	        final Serializable id,
   82   	        final SessionImplementor session) throws HibernateException {
   83   		// note: interface is assumed to already contain HibernateProxy.class
   84   		try {
   85   			final JavassistLazyInitializer instance = new JavassistLazyInitializer(
   86   					entityName,
   87   			        persistentClass,
   88   			        interfaces,
   89   			        id,
   90   			        getIdentifierMethod,
   91   			        setIdentifierMethod,
   92   			        componentIdType,
   93   			        session
   94   			);
   95   			ProxyFactory factory = new ProxyFactory();
   96   			factory.setSuperclass( interfaces.length == 1 ? persistentClass : null );
   97   			factory.setInterfaces( interfaces );
   98   			factory.setFilter( FINALIZE_FILTER );
   99   			Class cl = factory.createClass();
  100   			final HibernateProxy proxy = ( HibernateProxy ) cl.newInstance();
  101   			( ( ProxyObject ) proxy ).setHandler( instance );
  102   			instance.constructed = true;
  103   			return proxy;
  104   		}
  105   		catch ( Throwable t ) {
  106   			LoggerFactory.getLogger( BasicLazyInitializer.class ).error(
  107   					"Javassist Enhancement failed: " + entityName, t
  108   			);
  109   			throw new HibernateException(
  110   					"Javassist Enhancement failed: "
  111   					+ entityName, t
  112   			);
  113   		}
  114   	}
  115   
  116   	public static HibernateProxy getProxy(
  117   			final Class factory,
  118   	        final String entityName,
  119   	        final Class persistentClass,
  120   	        final Class[] interfaces,
  121   	        final Method getIdentifierMethod,
  122   	        final Method setIdentifierMethod,
  123   	        final AbstractComponentType componentIdType,
  124   	        final Serializable id,
  125   	        final SessionImplementor session) throws HibernateException {
  126   
  127   		final JavassistLazyInitializer instance = new JavassistLazyInitializer(
  128   				entityName,
  129   		        persistentClass,
  130   		        interfaces, id,
  131   		        getIdentifierMethod,
  132   		        setIdentifierMethod,
  133   		        componentIdType,
  134   		        session
  135   		);
  136   
  137   		final HibernateProxy proxy;
  138   		try {
  139   			proxy = ( HibernateProxy ) factory.newInstance();
  140   		}
  141   		catch ( Exception e ) {
  142   			throw new HibernateException(
  143   					"Javassist Enhancement failed: "
  144   					+ persistentClass.getName(), e
  145   			);
  146   		}
  147   		( ( ProxyObject ) proxy ).setHandler( instance );
  148   		instance.constructed = true;
  149   		return proxy;
  150   	}
  151   
  152   	public static Class getProxyFactory(
  153   			Class persistentClass,
  154   	        Class[] interfaces) throws HibernateException {
  155   		// note: interfaces is assumed to already contain HibernateProxy.class
  156   
  157   		try {
  158   			ProxyFactory factory = new ProxyFactory();
  159   			factory.setSuperclass( interfaces.length == 1 ? persistentClass : null );
  160   			factory.setInterfaces( interfaces );
  161   			factory.setFilter( FINALIZE_FILTER );
  162   			return factory.createClass();
  163   		}
  164   		catch ( Throwable t ) {
  165   			LoggerFactory.getLogger( BasicLazyInitializer.class ).error(
  166   					"Javassist Enhancement failed: "
  167   					+ persistentClass.getName(), t
  168   			);
  169   			throw new HibernateException(
  170   					"Javassist Enhancement failed: "
  171   					+ persistentClass.getName(), t
  172   			);
  173   		}
  174   	}
  175   
  176   	public Object invoke(
  177   			final Object proxy,
  178   			final Method thisMethod,
  179   			final Method proceed,
  180   			final Object[] args) throws Throwable {
  181   		if ( this.constructed ) {
  182   			Object result;
  183   			try {
  184   				result = this.invoke( thisMethod, args, proxy );
  185   			}
  186   			catch ( Throwable t ) {
  187   				throw new Exception( t.getCause() );
  188   			}
  189   			if ( result == INVOKE_IMPLEMENTATION ) {
  190   				Object target = getImplementation();
  191   				final Object returnValue;
  192   				try {
  193   					if ( ReflectHelper.isPublic( persistentClass, thisMethod ) ) {
  194   						if ( !thisMethod.getDeclaringClass().isInstance( target ) ) {
  195   							throw new ClassCastException( target.getClass().getName() );
  196   						}
  197   						returnValue = thisMethod.invoke( target, args );
  198   					}
  199   					else {
  200   						if ( !thisMethod.isAccessible() ) {
  201   							thisMethod.setAccessible( true );
  202   						}
  203   						returnValue = thisMethod.invoke( target, args );
  204   					}
  205   					return returnValue == target ? proxy : returnValue;
  206   				}
  207   				catch ( InvocationTargetException ite ) {
  208   					throw ite.getTargetException();
  209   				}
  210   			}
  211   			else {
  212   				return result;
  213   			}
  214   		}
  215   		else {
  216   			// while constructor is running
  217   			if ( thisMethod.getName().equals( "getHibernateLazyInitializer" ) ) {
  218   				return this;
  219   			}
  220   			else {
  221   				return proceed.invoke( proxy, args );
  222   			}
  223   		}
  224   	}
  225   
  226   	protected Object serializableProxy() {
  227   		return new SerializableProxy(
  228   				getEntityName(),
  229   		        persistentClass,
  230   		        interfaces,
  231   		        getIdentifier(),
  232   		        getIdentifierMethod,
  233   		        setIdentifierMethod,
  234   		        componentIdType
  235   		);
  236   	}
  237   }

Save This Page
Home » hibernate-distribution-3.3.1.GA-dist » org.hibernate » proxy » pojo » javassist » [javadoc | source]