1
//$Id: InstrumentTask.java 10209 2006-08-03 20:35:26Z steve.ebersole@jboss.com $
2
package org.hibernate.tool.instrument.cglib;
4
import org.hibernate.bytecode.util.BasicClassFilter;
5
import org.hibernate.bytecode.util.ClassDescriptor;
6
import org.hibernate.bytecode.cglib.BytecodeProviderImpl;
7
import org.hibernate.bytecode.ClassTransformer;
8
import org.hibernate.tool.instrument.BasicInstrumentationTask;
9
import org.objectweb.asm.ClassReader;
11
import java.io.ByteArrayInputStream;
13
import net.sf.cglib.core.ClassNameReader;
14
import net.sf.cglib.transform.impl.InterceptFieldEnabled;
17
* An Ant task for instrumenting persistent classes in order to enable
18
* field-level interception using CGLIB.
20
* In order to use this task, typically you would define a a taskdef
22
* <taskdef name="instrument" classname="org.hibernate.tool.instrument.cglib.InstrumentTask">
23
* <classpath refid="lib.class.path"/>
26
* where <tt>lib.class.path</tt> is an ANT path reference containing all the
27
* required Hibernate and CGLIB libraries.
29
* And then use it like:<pre>
30
* <instrument verbose="true">
31
* <fileset dir="${testclasses.dir}/org/hibernate/test">
32
* <include name="yadda/yadda/**"/>
37
* where the nested ANT fileset includes the class you would like to have
40
* Optionally you can chose to enable "Extended Instrumentation" if desired
41
* by specifying the extended attriubute on the task:<pre>
42
* <instrument verbose="true" extended="true">
46
* See the Hibernate manual regarding this option.
49
* @author Steve Ebersole
51
public class InstrumentTask extends BasicInstrumentationTask {
53
private static final BasicClassFilter CLASS_FILTER = new BasicClassFilter();
55
private final BytecodeProviderImpl provider = new BytecodeProviderImpl();
58
protected ClassDescriptor getClassDescriptor(byte[] byecode) throws Exception {
59
return new CustomClassDescriptor( byecode );
62
protected ClassTransformer getClassTransformer(ClassDescriptor descriptor) {
63
if ( descriptor.isInstrumented() ) {
64
logger.verbose( "class [" + descriptor.getName() + "] already instrumented" );
68
return provider.getTransformer( CLASS_FILTER, new CustomFieldFilter( descriptor ) );
72
private static class CustomClassDescriptor implements ClassDescriptor {
73
private final byte[] bytecode;
74
private final String name;
75
private final boolean isInstrumented;
77
public CustomClassDescriptor(byte[] bytecode) throws Exception {
78
this.bytecode = bytecode;
79
ClassReader reader = new ClassReader( new ByteArrayInputStream( bytecode ) );
80
String[] names = ClassNameReader.getClassInfo( reader );
82
boolean instrumented = false;
83
for ( int i = 1; i < names.length; i++ ) {
84
if ( InterceptFieldEnabled.class.getName().equals( names[i] ) ) {
89
this.isInstrumented = instrumented;
92
public String getName() {
96
public boolean isInstrumented() {
97
return isInstrumented;
100
public byte[] getBytes() {