[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[aspectj-dev] Extension of ASM to Support AspectJ Attributes?

Hi All,

Does anyone have an extension to Objectweb's ASM library that defines the
bytecode attributes that AspectJ attributes use? It looks like this would be
relatively easy to write, as long as you know the format for these
attributes. you would just define subclasses of Attribute that understand
how to parse the AspectJ-specific attributes.

I ask because I've been trying to use a tool, "jar jar links", which lets
you rename packages in dependent jars (e.g., mapping
org.apache.commons.logging to org.myprod.foo.commons.logging) and collect
the result as a single jar. This uses asm to parse & emit the classes,
transforming any packages it encounters. Jar jar's home page is
http://tonicsystems.com/products/jarjar/ (it can be hard to Google for, as
you can imagine!)

I wrote a little aspect that patches asm to not choke on unknown attributes
and to just emit them unchanged. This lets you jarjar up a project with
AspectJ aspects as long as you don't need library aspects or to reweave any
aspects (since it doesn't know how to fix up the types inside AspectJ
pointcut attributes). It would also be nice to contribute a more
maintainable version of the enhancement to be included in jarjar, since this
use of AspectJ to patch asm is expedient but dubious as an improvement in
modularity and the project is probably not going to adopt AspectJ for this
purpose.

Here's the aspect I'm currently using:

import org.objectweb.asm.Attribute;
import org.objectweb.asm.ByteVector;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.Label;


public privileged aspect PatchClassWriter {
	
	pointcut checkingAttr() :
		call(boolean Attribute.isUnknown()) &&  within(Attribute);
	
	// bypass attribute checks
	boolean around() : checkingAttr() {
		//System.out.println("checkAttr");
		return false;
	}

	// store the content for unknown attributes
	private byte[] Attribute.content;

	// match names for 2.0 RC1 and the apparently refactored version in
cvs head
	pointcut inRead() : 
		execution(Attribute ClassReader.a(..)) ||
		execution(Attribute ClassReader.readAttribute (..));
	
	// replace the read method in ClassReader
	Attribute around(ClassReader cr, Attribute[] attrs, String type, int
off, int len, char[] buf, int codeOff, Label[] labels) : 
	  inRead() && args(attrs, type, off,len,buf,codeOff,labels) &&
this(cr) {
		//System.out.println("in read attr for"+cr);
		for (int i = 0; i < attrs.length; ++i) {
			if (attrs[i].type.equals(type)) {
				return attrs[i].read(cr, off, len, buf,
codeOff, labels);
		    }
	    }
		
		//System.out.println("storing attribute data for "+cr);
	    Attribute res = new Attribute(type);
	    res.content = new byte[len];
	    System.arraycopy(cr.b, off, res.content, 0, len);

	    return res;		
	}
		
	// output the stored byte array...
	after(Attribute attribute) returning(ByteVector bv) : 
		execution(ByteVector write(..)) && within(Attribute) &&
this(attribute) {
		//System.out.println("reemitting attribute data for
"+attribute);
	    bv.putByteArray(attribute.content, 0, attribute.content.length);
	}

	//declare warning: checkingAttr(): "check attr";
	//declare warning: inRead(): "in read";

}