001: //$Id: $
002: package org.hibernate.bytecode.javassist;
003:
004: import java.io.ByteArrayInputStream;
005: import java.io.ByteArrayOutputStream;
006: import java.io.DataInputStream;
007: import java.io.DataOutputStream;
008: import java.io.IOException;
009: import java.security.ProtectionDomain;
010:
011: import javassist.bytecode.ClassFile;
012: import org.apache.commons.logging.Log;
013: import org.apache.commons.logging.LogFactory;
014: import org.hibernate.HibernateException;
015: import org.hibernate.bytecode.AbstractClassTransformerImpl;
016: import org.hibernate.bytecode.util.ClassFilter;
017:
018: /**
019: * Enhance the classes allowing them to implements InterceptFieldEnabled
020: * This interface is then used by Hibernate for some optimizations.
021: *
022: * @author Emmanuel Bernard
023: * @author Steve Ebersole
024: */
025: public class JavassistClassTransformer extends
026: AbstractClassTransformerImpl {
027:
028: private static Log log = LogFactory
029: .getLog(JavassistClassTransformer.class.getName());
030:
031: public JavassistClassTransformer(ClassFilter classFilter,
032: org.hibernate.bytecode.util.FieldFilter fieldFilter) {
033: super (classFilter, fieldFilter);
034: }
035:
036: protected byte[] doTransform(ClassLoader loader, String className,
037: Class classBeingRedefined,
038: ProtectionDomain protectionDomain, byte[] classfileBuffer) {
039: ClassFile classfile;
040: try {
041: // WARNING: classfile only
042: classfile = new ClassFile(new DataInputStream(
043: new ByteArrayInputStream(classfileBuffer)));
044: } catch (IOException e) {
045: log.error("Unable to build enhancement metamodel for "
046: + className);
047: return classfileBuffer;
048: }
049: FieldTransformer transformer = getFieldTransformer(classfile);
050: if (transformer != null) {
051: if (log.isDebugEnabled()) {
052: log.debug("Enhancing " + className);
053: }
054: DataOutputStream out = null;
055: try {
056: transformer.transform(classfile);
057: ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
058: out = new DataOutputStream(byteStream);
059: classfile.write(out);
060: return byteStream.toByteArray();
061: } catch (Exception e) {
062: log.error("Unable to transform class", e);
063: throw new HibernateException(
064: "Unable to transform class: " + e.getMessage());
065: } finally {
066: try {
067: if (out != null)
068: out.close();
069: } catch (IOException e) {
070: //swallow
071: }
072: }
073: }
074: return classfileBuffer;
075: }
076:
077: protected FieldTransformer getFieldTransformer(
078: final ClassFile classfile) {
079: if (alreadyInstrumented(classfile)) {
080: return null;
081: }
082: return new FieldTransformer(new FieldFilter() {
083: public boolean handleRead(String desc, String name) {
084: return fieldFilter.shouldInstrumentField(classfile
085: .getName(), name);
086: }
087:
088: public boolean handleWrite(String desc, String name) {
089: return fieldFilter.shouldInstrumentField(classfile
090: .getName(), name);
091: }
092:
093: public boolean handleReadAccess(String fieldOwnerClassName,
094: String fieldName) {
095: return fieldFilter.shouldTransformFieldAccess(classfile
096: .getName(), fieldOwnerClassName, fieldName);
097: }
098:
099: public boolean handleWriteAccess(
100: String fieldOwnerClassName, String fieldName) {
101: return fieldFilter.shouldTransformFieldAccess(classfile
102: .getName(), fieldOwnerClassName, fieldName);
103: }
104: });
105: }
106:
107: private boolean alreadyInstrumented(ClassFile classfile) {
108: String[] intfs = classfile.getInterfaces();
109: for (int i = 0; i < intfs.length; i++) {
110: if (FieldHandled.class.getName().equals(intfs[i])) {
111: return true;
112: }
113: }
114: return false;
115: }
116: }
|