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 java.security.ProtectionDomain;
   28   import java.io.ByteArrayInputStream;
   29   import java.io.IOException;
   30   import java.io.ByteArrayOutputStream;
   31   
   32   import net.sf.cglib.transform.ClassTransformer;
   33   import net.sf.cglib.transform.TransformingClassGenerator;
   34   import net.sf.cglib.transform.ClassReaderGenerator;
   35   import net.sf.cglib.transform.impl.InterceptFieldEnabled;
   36   import net.sf.cglib.transform.impl.InterceptFieldFilter;
   37   import net.sf.cglib.transform.impl.InterceptFieldTransformer;
   38   import net.sf.cglib.core.ClassNameReader;
   39   import net.sf.cglib.core.DebuggingClassWriter;
   40   import org.slf4j.Logger;
   41   import org.slf4j.LoggerFactory;
   42   import org.hibernate.bytecode.AbstractClassTransformerImpl;
   43   import org.hibernate.bytecode.util.FieldFilter;
   44   import org.hibernate.bytecode.util.ClassFilter;
   45   import org.hibernate.HibernateException;
   46   import org.objectweb.asm.Type;
   47   import org.objectweb.asm.ClassReader;
   48   import org.objectweb.asm.ClassWriter;
   49   
   50   /**
   51    * Enhance the classes allowing them to implements InterceptFieldEnabled
   52    * This interface is then used by Hibernate for some optimizations.
   53    *
   54    * @author Emmanuel Bernard
   55    */
   56   public class CglibClassTransformer extends AbstractClassTransformerImpl {
   57   
   58   	private static Logger log = LoggerFactory.getLogger( CglibClassTransformer.class.getName() );
   59   
   60   	public CglibClassTransformer(ClassFilter classFilter, FieldFilter fieldFilter) {
   61   		super( classFilter, fieldFilter );
   62   	}
   63   
   64   	protected byte[] doTransform(
   65   			ClassLoader loader,
   66   			String className,
   67   			Class classBeingRedefined,
   68   			ProtectionDomain protectionDomain,
   69   			byte[] classfileBuffer) {
   70   		ClassReader reader;
   71   		try {
   72   			reader = new ClassReader( new ByteArrayInputStream( classfileBuffer ) );
   73   		}
   74   		catch (IOException e) {
   75   			log.error( "Unable to read class", e );
   76   			throw new HibernateException( "Unable to read class: " + e.getMessage() );
   77   		}
   78   
   79   		String[] names = ClassNameReader.getClassInfo( reader );
   80   		ClassWriter w = new DebuggingClassWriter( ClassWriter.COMPUTE_MAXS  );
   81   		ClassTransformer t = getClassTransformer( names );
   82   		if ( t != null ) {
   83   			if ( log.isDebugEnabled() ) {
   84   				log.debug( "Enhancing " + className );
   85   			}
   86   			ByteArrayOutputStream out;
   87   			byte[] result;
   88   			try {
   89   				reader = new ClassReader( new ByteArrayInputStream( classfileBuffer ) );
   90   				new TransformingClassGenerator(
   91   						new ClassReaderGenerator( reader, skipDebug() ), t
   92   				).generateClass( w );
   93   				out = new ByteArrayOutputStream();
   94   				out.write( w.toByteArray() );
   95   				result = out.toByteArray();
   96   				out.close();
   97   			}
   98   			catch (Exception e) {
   99   				log.error( "Unable to transform class", e );
  100   				throw new HibernateException( "Unable to transform class: " + e.getMessage() );
  101   			}
  102   			return result;
  103   		}
  104   		return classfileBuffer;
  105   	}
  106   
  107   	private int skipDebug() {
  108   		return ClassReader.SKIP_DEBUG;
  109   	}
  110   
  111   	private ClassTransformer getClassTransformer(final String[] classInfo) {
  112   		if ( isAlreadyInstrumented( classInfo ) ) {
  113   			return null;
  114   		}
  115   		return new InterceptFieldTransformer(
  116   				new InterceptFieldFilter() {
  117   					public boolean acceptRead(Type owner, String name) {
  118   						return fieldFilter.shouldTransformFieldAccess( classInfo[0], owner.getClassName(), name );
  119   					}
  120   
  121   					public boolean acceptWrite(Type owner, String name) {
  122   						return fieldFilter.shouldTransformFieldAccess( classInfo[0], owner.getClassName(), name );
  123   					}
  124   				}
  125   		);
  126   	}
  127   
  128   	private boolean isAlreadyInstrumented(String[] classInfo) {
  129   		for ( int i = 1; i < classInfo.length; i++ ) {
  130   			if ( InterceptFieldEnabled.class.getName().equals( classInfo[i] ) ) {
  131   				return true;
  132   			}
  133   		}
  134   		return false;
  135   	}
  136   }

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