[jboss-user] [Javassist user questions] - Re: adding annotations

2009-07-05 Thread PaulKeeble
The beauty of a Java agent is it gets passed every loaded class, regardless of 
classloader. So although you need to filter the list as quickly as possible 
(you'll get thousands of calls from java.* classes for instance) it is the best 
way to do the instrumentation.

I have happily got annotation adding working in my code base recently so 
thought it might help you if I explained roughly how I do it.

First up getting a CtClass:

byte[] byteCode = 
ClassPool pool = 
CtClass clazz = pool.makeClass(new ByteArrayInputStream(byteCode)); 


If your using a Java agent it will give you the bytes directly, if you load 
them yourself in a custom classloader.

Next up you the annotations adding to a CtClass:

CtClass clazz = 
ClassFile classFile = clazz.getClassFile();
ConstPool cp = classFile.getConstPool();

AnnotationsAttribute attr = new AnnotationsAttribute(cp, 
AnnotationsAttribute.visibleTag); 

Annotation theAnnotation = new Annotation("org.package.AnnotationType",cp);
annotation.addMemberValue("name", new StringMemberValue("Paul",cp));

attr.setAnnotation(theAnnotation);

clazz.getClassInfo().addAttribute(attr);


That worked well for me as an approach. If you want to see a working version 
(the far more complicated version based on methods and arrays of values) you 
can see the latest version of my code at JEMM Git 
MethodAnnotationTransformation.java



View the original post : 
http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4241818#4241818

Reply to the post : 
http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=4241818
___
jboss-user mailing list
jboss-user@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/jboss-user


[jboss-user] [Javassist user questions] - Re: Adding annotations to methods

2009-07-05 Thread PaulKeeble
In the end I managed to work it out and answer my own question. The key was 
understanding that you need to add the AnnotationsAttribute instance to the 
Info of the method.

That is the rough solution is:


  | CtClass clazz = 
  | ClassFile classFile = clazz.getClassFile();
  | ConstPool cp = classFile.getConstPool();
  | AnnotationsAttribute attr = new AnnotationsAttribute(cp, 
AnnotationsAttribute.visibleTag); 
  | 
  | Annotation useAnnotation = new Annotation("org.package.AnnotationType",cp);
  | annotation.addMemberValue("name", new StringMemberValue("Paul",cp));
  | 
  | attr.setAnnotation(useAnnotation);
  | 
  | m.getMethodInfo().addAttribute(attr);
  | 
  | 

So the only real difference between the CtClass, CtMethod and even parameters 
is I needed to do the appropriate getXXXInfo and then add the attribute 
directly.

View the original post : 
http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4241819#4241819

Reply to the post : 
http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=4241819
___
jboss-user mailing list
jboss-user@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/jboss-user


[jboss-user] [Javassist user questions] - Re: adding annotations

2008-04-01 Thread cat4hire
After a lot I found that the following is the code that works for me:


  | ClassFile classFile = newProxyClass.getClassFile();
  | ConstPool constantPool = classFile.getConstPool();
  | AnnotationsAttribute attr = new AnnotationsAttribute(constantPool, 
AnnotationsAttribute.visibleTag);
  | javassist.bytecode.annotation.Annotation a = new 
javassist.bytecode.annotation.Annotation(this.annotationClassName, 
constantPool);
  | attr.setAnnotation(a);
  | classFile.addAttribute(attr);
  | classFile.setVersionToJava5();
  | 
  | 
  | ByteArrayOutputStream bos = new ByteArrayOutputStream();
  | DataOutputStream os = new DataOutputStream( bos );
  | classFile.write( os );
  | os.close();
  | 
  | // all done
  | return bos.toByteArray();
  | 

the above produces the byte code for a class with the added annotation.

Thanks,
Luca

View the original post : 
http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4140550#4140550

Reply to the post : 
http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4140550
___
jboss-user mailing list
jboss-user@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/jboss-user


[jboss-user] [Javassist user questions] - Re: adding annotations

2008-03-12 Thread cat4hire
Hi,
I'm still fighting with the annotation problem. I've made a code clean up, and 
now I've got the following piece of code:


  | // make a new class 
  | CtClass newProxyClass = pool.makeClass( subProxyClassName );
  | newProxyClass.setSuperclass( baseProxyClass );
  | 
  | // place a default constructor in the new class
  | CtConstructor constructor = new CtConstructor(null, 
newProxyClass );
  | constructor.setBody(";");
  | newProxyClass.addConstructor(constructor);
  | 
  | // get the class file and add the annotation
  | ClassFile classFile = newProxyClass.getClassFile();
  | ConstPool constantPool = classFile.getConstPool();
  | AnnotationsAttribute attr = new 
AnnotationsAttribute(constantPool, AnnotationsAttribute.visibleTag);
  | javassist.bytecode.annotation.Annotation a = new 
javassist.bytecode.annotation.Annotation(this.annotationClassName, 
constantPool);
  | attr.setAnnotation(a);
  | classFile.addAttribute(attr);
  | classFile.setVersionToJava5();
  | 
  | // transform the classfile into bytecode
  | ByteArrayOutputStream bos = new ByteArrayOutputStream();
  | DataOutputStream os = new DataOutputStream( bos );
  | classFile.write( os );
  | os.close();
  | 
  | // load the class
  | return this.defineClass(subProxyClassName, bytecode, 0, 
bytecode.length);
  | 

at runtime no exception are thrown, but the new class still has no annotation 
added!

Then I saved the bytecode to a file in two cases, the above piece of code and 
the one without the addAttribute, and I can see they are different, so it seems 
as the annotation is added, but it is not visible to the runtime system.

Please, any suggestion is appreciated!!!

Thanks,
Luca

View the original post : 
http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4135894#4135894

Reply to the post : 
http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4135894
___
jboss-user mailing list
jboss-user@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/jboss-user


[jboss-user] [Javassist user questions] - Re: adding annotations

2008-03-05 Thread cat4hire
I'm going mad, anyone with a suggestion?

I've found that the following piece of code:


  | ByteArrayOutputStream aos = new ByteArrayOutputStream();
  | AnnotationsWriter aw = new AnnotationsWriter(aos, 
constantPool);
  | aw.numAnnotations(1);
  | aw.annotation(this.annotationClassName, 0);
  | aw.close();
  | byte ab[] = aos.toByteArray();
  | System.out.println("\n\tAnnotation bytecode  for 
annotation " + this.annotationClassName + "");
  | System.out.println(new String(ab) );
  | System.out.println("\n\t++\n");
  | attribute = new AnnotationsAttribute(constantPool, 
AnnotationsAttribute.visibleTag, ab);
  | 

that should create the annotation specified, prints the following:


  | 
  | Annotation bytecode  for annotation 
whitecat.example.DBRoleAnnotation
  | 
  | 
  |+++
  | 
  |  

So I'm pretty sure that the bytecode generated for the annotation is empty, and 
that the annotation is regularly added to my class, but without a bytecode I 
cannot access it. Anyone can explain why the bytecode is null?

View the original post : 
http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4134189#4134189

Reply to the post : 
http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4134189
___
jboss-user mailing list
jboss-user@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/jboss-user


[jboss-user] [Javassist user questions] - Re: adding annotations

2008-02-29 Thread cat4hire
I've made another experiment: using an AnnotationsWriter as follows does not 
work too:


  | 
  | ByteArrayOutputStream aos = new ByteArrayOutputStream();
  | AnnotationsWriter aw = new AnnotationsWriter(aos, 
constantPool);
  | aw.numAnnotations(1);
  | aw.annotation(this.annotationClassName, 0);
  | aw.close();
  | byte ab[] = aos.toByteArray();
  | attribute = new AnnotationsAttribute(constantPool, 
AnnotationsAttribute.visibleTag, ab);
  | 
  | System.out.println("Annotation attribute " + 
attribute.getName() + " " + attribute.getAnnotations().length);
  | classFile.addAttribute( attribute );
  | 

The class can be loaded and instantiated, but I cannot access its annotations. 
In both cases, if I print the classfile content with a ClassFileWriter I got a 
message that lets me think I've got the annotations:


  | attribute: SourceFile (2 byte): javassist.bytecode.SourceFileAttribute
  | attribute: RuntimeVisibleAnnotations (6 byte): 
javassist.bytecode.AnnotationsAttribute
  | 

Moreover, in the case in which I use an AnnotationsWriter I got the following 
run-time exception when I try to access the annotations thru the 
Class.getAnnotations() method:


  | Exception in thread "Thread-Example-Main" 
java.lang.reflect.GenericSignatureFormatError
  | at 
sun.reflect.generics.parser.SignatureParser.error(SignatureParser.java:103)
  | at 
sun.reflect.generics.parser.SignatureParser.parseFieldTypeSignature(SignatureParser.java:233)
  | at 
sun.reflect.generics.parser.SignatureParser.parseTypeSignature(SignatureParser.java:359)
  | at 
sun.reflect.generics.parser.SignatureParser.parseTypeSig(SignatureParser.java:157)
  | at 
sun.reflect.annotation.AnnotationParser.parseSig(AnnotationParser.java:367)
  | at 
sun.reflect.annotation.AnnotationParser.parseAnnotation(AnnotationParser.java:181)
  | at 
sun.reflect.annotation.AnnotationParser.parseAnnotations2(AnnotationParser.java:69)
  | at 
sun.reflect.annotation.AnnotationParser.parseAnnotations(AnnotationParser.java:52)
  | at java.lang.Class.initAnnotationsIfNecessary(Class.java:3072)
  | at java.lang.Class.getAnnotations(Class.java:3052)
  | 

I cannot find whre I'm doing something wrong.

View the original post : 
http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4133207#4133207

Reply to the post : 
http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4133207
___
jboss-user mailing list
jboss-user@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/jboss-user


[jboss-user] [Javassist user questions] - Re: adding annotations

2008-02-29 Thread cat4hire
I've found how to make the ClassFile working for defining my new class, but I'm 
still unable to add the annotation. Now I work as follows:
1) I create a CtClass object and set the inheritance chain on that;
2) I get the byte[] from the CtClass and place them into a 
ByteArrayInputStream, used to create a ClassFile;
3) I add the annotation to the classfile;
4) I get the byte[] from the classfile thru a ByteArrayOutputStream;
5) I load the class thru the defineClass method.

Now the class is of the right type, but it has no the annotation.
The following is my code; anyone has an idea of which is my error adding the 
annotation?


  | subProxyClassName += this.getSubClassNameSuffix();
  | 
  | // make a new class and prepare the annotation
  | CtClass newProxyClass = pool.makeClass(subProxyClassName);
  | newProxyClass.setSuperclass( baseProxyClass );
  | ByteArrayInputStream is = new ByteArrayInputStream( 
newProxyClass.toBytecode() );
  | DataInputStream dis = new DataInputStream( is );
  | ClassFile classFile = new ClassFile( dis );
  | newProxyClass.defrost();
  | ConstPool constantPool = classFile.getConstPool();
  | AnnotationsAttribute attribute = new AnnotationsAttribute( 
constantPool, AnnotationsAttribute.visibleTag );
  | javassist.bytecode.annotation.Annotation annotation = new 
javassist.bytecode.annotation.Annotation( this.annotationClassName, 
constantPool );
  | attribute.setAnnotation( annotation );
  | classFile.addAttribute( attribute );
  | classFile.setVersionToJava5();
  | ByteArrayOutputStream bos = new ByteArrayOutputStream();
  | DataOutputStream os = new DataOutputStream( bos );
  | classFile.write( os );
  | new javassist.bytecode.annotation.Annotation( constantPool, subProxy );
  | bytecode = bos.toByteArray();
  | baseProxyClass = null;
  | 
  | ... 
  | 
  | Class clazz = this.defineClass(subProxyClassName, bytecode, 
0, bytecode.length);
  | 
  | 

Thanks,
Luca

View the original post : 
http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4133098#4133098

Reply to the post : 
http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4133098
___
jboss-user mailing list
jboss-user@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/jboss-user


[jboss-user] [Javassist user questions] - Re: adding annotations

2008-02-26 Thread cat4hire
I've made another try: I've tried to get the classfile from a CtClass object 
instantied with the class name of the base class:


  | // make a new class and prepare the annotation
  | CtClass newProxyClass = pool.makeClass(subProxyClassName);
  | ClassFile classFile = newProxyClass.getClassFile();  //new 
ClassFile( false, subProxyClassName, baseProxyClass.getName() );
  | ConstPool constantPool = classFile.getConstPool();
  | AnnotationsAttribute attribute = new AnnotationsAttribute( 
constantPool, AnnotationsAttribute.visibleTag );
  | javassist.bytecode.annotation.Annotation annotation = new 
javassist.bytecode.annotation.Annotation( this.annotationClassName, 
constantPool );
  | attribute.setAnnotation( annotation );
  | classFile.addAttribute( attribute );
  | classFile.setVersionToJava5();
  | classFile.setName(subProxyClassName);
  | classFile.setSuperclass( baseProxyClass.getName() );
  | ByteArrayOutputStream bos = new ByteArrayOutputStream();
  | DataOutputStream os = new DataOutputStream( bos );
  | classFile.write( os );
  | bytecode = bos.toByteArray();
  | 

but again, when I try to instantiate this class, that is of kind "proxy", I got 
an instantiation error:


  | Class clazz = this.defineClass(subProxyClassName, bytecode, 0, 
bytecode.length);
  | AgentProxy aProxy = (AgentProxy) clazz.newInstance();
  | 

I got the same instantiation exception of the previous post.
Any idea?

View the original post : 
http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4132254#4132254

Reply to the post : 
http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4132254
___
jboss-user mailing list
jboss-user@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/jboss-user


[jboss-user] [Javassist user questions] - Re: adding annotations

2008-02-25 Thread cat4hire
I've tried to define the class within the class loader, introspecting it in 
place to see what happens. In other words, I added the following code:



  | subProxyClassName += this.getSubClassNameSuffix();
  | 
  | // make a new class and prepare the annotation
  | ClassFile classFile = new ClassFile( false, 
subProxyClassName, baseProxyClass.getName() );
  | ConstPool constantPool = classFile.getConstPool();
  | AnnotationsAttribute attribute = new AnnotationsAttribute( 
constantPool, AnnotationsAttribute.visibleTag );
  | javassist.bytecode.annotation.Annotation annotation = new 
javassist.bytecode.annotation.Annotation( this.annotationClassName, 
constantPool );
  | attribute.setAnnotation( annotation );
  | classFile.addAttribute( attribute );
  | classFile.setVersionToJava5();
  | classFile.setSuperclass( baseProxyClass.getName() );
  | ByteArrayOutputStream bos = new ByteArrayOutputStream();
  | DataOutputStream os = new DataOutputStream( bos );
  | classFile.write( os );
  | bytecode = bos.toByteArray();
  | baseProxyClass = null;
  | 
  | Class clazz = this.defineClass(subProxyClassName, bytecode, 
0, bytecode.length);
  | System.out.println("Class " + clazz.getName());
  | System.out.println("Superclass " + clazz.getSuperclass());
  | System.out.println("Annotations");
  | try {
  | AgentProxy aProxy = (AgentProxy) clazz.newInstance();
  | } catch (InstantiationException e) {
  | // TODO Auto-generated catch block
  | e.printStackTrace();
  | } catch (IllegalAccessException e) {
  | // TODO Auto-generated catch block
  | e.printStackTrace();
  | }
  | for(Annotation a : clazz.getAnnotations())
  | System.out.println("annotazione " + a);
  | 

I believe that the way I'm using the ClassFile is wrong, since I'm not able to 
load the class, or better the class that is loaded is unable to be instantied 
as child of the parent class. 
The class hierarchy is the following:
proxy
  ^
   |
proxy_roled_1_24325842 <- when creating this class 
 I need to inject an annotation



  | Class whitecat.proxy_roled_1_24325842
  | Superclass class whitecat.proxy
  | Annotations
  | java.lang.InstantiationException: whitecat.proxy_roled_1_24325842
  | at java.lang.Class.newInstance0(Class.java:340)
  | at java.lang.Class.newInstance(Class.java:308)
  | at whitecat.core.RoleEngine.findClass(RoleEngine.java:701)
  | at whitecat.core.RoleEngine.injectAnnotation(RoleEngine.java:538)
  | at whitecat.example.ExampleMain.run(ExampleMain.java:132)
  | at java.lang.Thread.run(Thread.java:619)
  | 


Any suggestion about this?

View the original post : 
http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4131943#4131943

Reply to the post : 
http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4131943
___
jboss-user mailing list
jboss-user@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/jboss-user


[jboss-user] [Javassist user questions] - Re: adding annotations

2008-02-25 Thread cat4hire
This is what I've tried to do in my class loader:


  | subProxyClassName += this.getSubClassNameSuffix();
  | 
  | // make a new class and prepare the annotation
  | ClassFile classFile = new ClassFile( false, 
subProxyClassName, baseProxyClass.getName() );
  | ConstPool constantPool = classFile.getConstPool();
  | AnnotationsAttribute attribute = new AnnotationsAttribute( 
constantPool, AnnotationsAttribute.visibleTag );
  | javassist.bytecode.annotation.Annotation annotation = new 
javassist.bytecode.annotation.Annotation( this.annotationClassName, 
constantPool );
  | attribute.setAnnotation( annotation );
  | classFile.addAttribute( attribute );
  | classFile.setVersionToJava5();
  | classFile.setSuperclass( baseProxyClass.getName() );
  | ByteArrayOutputStream bos = new ByteArrayOutputStream();
  | DataOutputStream os = new DataOutputStream( bos );
  | classFile.write( os );
  | bytecode = bos.toByteArray();
  | return this.defineClass(subProxyClassName, bytecode, 0, 
bytecode.length);
  | 

The above is the findClass method of my class loader. The idea is that I have 
to create a subclass of the baseProxyClass (a CtClass object) and I have to add 
to it the annotation indicated by annotationClassName. When I return from the 
findClass method, the Class object I've got says me that it is a subclass of my 
proxy, but it cannot be instantiated as a proxy object (InstantiationError), as 
well as the getAnnotations() method returns an empty array.
What am I doing wrong?

Thanks,
Luca

View the original post : 
http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4131820#4131820

Reply to the post : 
http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4131820
___
jboss-user mailing list
jboss-user@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/jboss-user


[jboss-user] [Javassist user questions] - Re: adding annotations

2008-02-21 Thread cat4hire
Just to make it more clear: I've got a special class loader that is going to 
subclass a class that it must load to add specific behaviours, one of such 
behaviour should be an annotation. That is why I'm searching to do them thru 
Javassist.
Any suggestion?

View the original post : 
http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4131290#4131290

Reply to the post : 
http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4131290
___
jboss-user mailing list
jboss-user@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/jboss-user


[jboss-user] [Javassist user questions] - Re: adding annotations

2008-02-21 Thread cat4hire
I'm not sure about the use of an agent, because it will perform the annotation 
addition at the program load time, while I have to perform it depending on 
run-time conditions at class loading time, and most important I could have 
separate class loaders that add or not the annotations to the class they are 
loading. Is this possible with the agents?

View the original post : 
http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4131005#4131005

Reply to the post : 
http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4131005
___
jboss-user mailing list
jboss-user@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/jboss-user


[jboss-user] [Javassist user questions] - Re: adding annotations

2008-02-20 Thread gkorland
To add annotation to a class on load time the cleaner way to do it is to use 
javaagent.
See: 
http://javahowto.blogspot.com/2006/07/javaagent-option.html

Guy

View the original post : 
http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4130933#4130933

Reply to the post : 
http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4130933
___
jboss-user mailing list
jboss-user@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/jboss-user


[jboss-user] [Javassist user questions] - Re: adding annotations

2008-02-20 Thread cat4hire
Hi,
thanks for your reply, I was having a look at annotation_attribute, 
annotationwriter and annotationattribute, and now I've got a doubt: is the 
annotation only stored in the class file? Because what I'd like to obtain is to 
"inject" an annotation into a class (Runtime retention) when the class is 
loaded, without modifying the class file. But if I use the ClassFile object I 
have to modify the class file on the disk, is this correct? Is there a way to 
add an annotation at load time?

Thanks,
Luca

View the original post : 
http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4130748#4130748

Reply to the post : 
http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4130748
___
jboss-user mailing list
jboss-user@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/jboss-user


[jboss-user] [Javassist user questions] - Re: adding annotations

2008-02-19 Thread gkorland
Hi Luca,
Check the AnnotationsAttribute JDoc.

ClassFile cf = ... ;
ConstPool cp = cf.getConstPool();
AnnotationsAttribute attr  = new AnnotationsAttribute(cp, 
AnnotationsAttribute.visibleTag);

Annotation a = new Annotation("Author", cp);
a.addMemberValue("name", new 

StringMemberValue("Chiba", cp));
attr.setAnnotation(a);
cf.addAttribute(attr);
cf.setVersionToJava5();

Guy

View the original post : 
http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4130552#4130552

Reply to the post : 
http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4130552
___
jboss-user mailing list
jboss-user@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/jboss-user