Parse .java file and analyze its AST - java

Im looking for a parser that could parse .java file and create some object, which should held informations about this file's methods, attributes. classes, interfaces, methods parameters and annotations.
Do you know any?
I found https://code.google.com/p/javaparser/, but im not sure if it can handle annotations, which are important for me..
any advice?
thanks

Why not use the standard Java Compiler API? I know it was discussed within the latest Java Magazine issue -- for some source samples, see here.

You could use the Java Grammar (http://docs.oracle.com/javase/specs/jls/se7/html/jls-18.html) and use a parser generator (for example YACC) or Scala ParserCombinators to generate an AST. In this grammar, annotations are contained.

I am using JavaParser to parse java Code, and yes - it can handle annotations, for example - getting method's annotations:
List<AnnotationExpr> annotations = method.getAnnotations();
Adding annotations (by name) to a method:
annotations.add(new NormalAnnotationExpr( ASTHelper.createNameExpr("Override"), null));

Related

Java reflection: How to get comments?

I have faced some difficulties with Java parsing. I need somehow to get comments of class, fields, methods etc. via reflection.
I have found JavaParser and it looks like it can elicit comments but I haven't got how to do it as all the examples just parse given string. I have found TypeSolver that can take Canonical name but it looks like that it can't work with comments.
My question is how to find comments if I have only Class<?> and also the project has some other jar's that should also be introspected. Via debugging I see the original source code and it looks like that it is possible to do somehow.
Thanks.
P.S. I have source code, I need to match Class<?> with source code and then extract comments via JavaParser
First of all, you cannot directly get comments using reflection, and you cannot get them by using a library that reads the ".class" file. The information is not present the ".class" file, and reflection only knows about information is directly available from there.
As people have pointed out, you can only get comments if you have the source code. And if you have a source code file you should be able to extract comments using JavaParser or (possibly) some other library, ... or by writing your own parser.
The problem will be mapping from a Class object to the corresponding source code file. Let us assume that you have multiple source trees corresponding to multiple JARs on the application's classpath. You will need:
the URIs for each JAR or directory on the classpath,
a mapping from each URI to a corresponding source tree.
The approach would be:
Get the fully qualified class name from the Class object.
Map the classname to a relative Java source path; e.g. foo.bar.Baz would become foo/bar/Baz.java
Use clazz.getProtectionDomain().getCodeSource().getLocation().toURI() to get the URI from whence the class was loaded.
Map the URI to the corresponding source tree ... using your mappings.
Resolve the relative path relative to the root of the source tree.
Open the source file.
Some of the above steps could present problems. For example:
in step 2, you need to deal with nested classes,
in step 3, getCodeSource() could return null,
in step 3, the resulting URI could have a weird protocol,
if your mapping are incomplete, step 4 could fail,
if your source code doesn't match the code you are executing, step 5 could fail.
Once you have the source file open, you construct a Reader and parse the source code ... using your chosen Java parser.
If yours was a "green field" project, it may be simpler to define a custom annotation type (with retention runtime) and turn your comments into annotations. These annotations can be extracted simply and quickly, with none of the possible failure modes in the above.
But the flipside is that annotations are cumbersome to write (in the source code) compared to comments. Also, you would be bloating the ".class" files with the extra annotations.
I haven't got how to do it as all the [JavaParser] examples just parse given string.
The javadoc shows that you can use a JavaParser instance to parse a File, an InputStream, a Reader or a String.
I doubt that comments are contained in compiled code - so there is no way to do it by reflection. Closest tool to do it would be XDoclet-1/2 which parsed javadoc tags and used them to generate other stuff (and this inspired annotations) - but this tool is obsolete and not suppported anymore
If you have the source code, it is probably in form of a JAR file. It is quite easy to locate the source file in the JAR file as the class provides both the package as well as local name. You have to consider a case with nested classes, but its is actually quite easy to implement.
When you've located the source file, you can easily parse it with JavaParser and retrieve the comments:
String classText = "public class Dummy{\n" + "//Comment\n" + "}";
StringReader reader = new StringReader(classText);
CompilationUnit compilationUnit = JavaParser.parse(reader, true);
for (Comment comment : compilationUnit.getAllContainedComments()) {
System.out.println(comment.getContent());
}
You can't.
Bytecode does not contain any comments, either inline or in JavaDoc format, from the original source code, as they are removed during the compilation phase.
If you need the comments to somehow be transferred into the Bytecode, consider using Java's Annotations instead.

Import Java Custom Method in Xquery

I am using Weblogic Integration framework. While transforming one XML format to another using .xq file, I want to apply some logic written in a custom Java Class.
For example, XML1 has tag: <UnitCode>XYZ</UnitCode>
Custom Java Class:
public class unitcodemapper{
public static String getMappedUnitCode(String unitCode){
if(unitCode=="XYZ")
return <<value from DB table>>
else
return unitCode;
}
}
XML2 will have a tag: <UnitCode>unitcodemapper.getMappedUnitCode(XML1/UnitCode)</UnitCode>
I cannot find any documentation or example to do this. Can someone please help in understanding how this can be done?
This is known as an "extension function". The documentation for your XQuery implementation should have a section telling you how to write such functions and plug them into the processor. (The details may differ from one XQuery processor to another, which is why I'm referring you to the manual.)
Whilst #keshlam mentions Extension Functions, which are indeed supported by many implementations each with their own API.
I think perhaps what you are looking for instead is Java Binding from XQuery. Many implementations also support this and tend to use the same approach. I do not know whether WebLogic supports this or not! If it does, the trick is to use java: at the start of your namespace URI declaration, you can then use the fully qualified Java class name of a static class, each static method you may then call directly from that namespace.
You can from two examples of implementations that offer the same Java Binding from XQuery functionality here:
http://exist-db.org/exist/apps/doc/xquery.xml#calling-java
http://docs.basex.org/wiki/Java_Bindings
These could serve as examples for you to try on WebLogic to see if it is supported in the same way. However, I strongly suggest you check their documentation as they may take a different approach.

How can I include #Annotations in JavaDoc? [duplicate]

This question already has an answer here:
Is there a way to get the javadoc tool to document annotations?
(1 answer)
Closed 4 years ago.
I would like to document some properties of classes and methods in JavaDoc and be able to load these information at runtime. Therefore I thought it might be convenient to write a custom annotation and annotate all necessary files and methods with this annotation. With this annotation, I could load these information at runtime.
Here's a hypothetic code snippet to demonstrate my use case:
public class ImportantClass {
#DetailedDescription(description="originated from data source XYZ")
public void importantMethod() {
// snip
}
}
The String "originated from data source XYZ" should be displayed in the JavaDoc and be readable via reflections or something similar. My problem is that the JavaDoc does not contain annotation information.
Is it possible to configure the JavaDoc task (preferrably with Maven) to include annotation information?
Clarification: I'm not interested in doclets (~javadoc annotations) as they are not readable at runtime.
I finally found a nice solution without duplication. Use the #Documented annotation on the annotation interface (DetailedDescription in this case) and all instances of this annotation are documented in the JavaDoc.
See this question:
Is there a way to get the javadoc tool to document annotations?
This is more of a comment than an answer, but it is long so I need this format
Why do you want an annotation for that? The Oracle documentation says that for this kind of use, you should use both a javadoc tag and an annotation. From the link I provided:
If you need to affect both program semantics and documentation, you probably need both an annotation and a tag. For example, our guidelines now recommend using the #Deprecated annotation for alerting the compiler warning and the #deprecated tag for the comment text
Use javadocs, it provides exactly what you are trying to achieve.
Annotations provide metadata at the code level, and are meant to play role in the behaviour of your app. Should not be used for documentation.

How to create java object by reflection by reading field names and types from an xml file?

I want to create a class dynamically at run time by reading field names and its types from an xml file.For example my xml file looks like this:
<person>
<name type="String">abc</name>
<age type="Integer">30</age>
</person>
I also want to have getter and setters methods for each field.
Any examples or best approaches available for this?
Take a look at XStream, it is extremely easy to serialize to/from XML.
This is technically possible, but (unless someone can point out an existing solution) it would be a lot of work. (You can do a lot of clever things by generating source code and compiling it at runtime ... for example.)
But to be honest, this is probably not a useful thing to do. Once you've loaded your XML object as an instance of a brand new Java class, you'll have great difficulty using it. For a start, your existing statically compiled application will only be able to access the fields and methods of the new class reflectively.
IMO, you'd be better of loading the XML into generic Map objects or Properties objects. Or, just use a DOM created by an off-the-shelf XML parser.
Alternatively, get hold of a DTD, XSD, or some other kind of "schema" for the XML and generate Java classes from that. Then can write and statically compile your application to call those classes.
Java is not a dynamic language, so you cannot create classes dynamically, but the term 'create' is not well defined in your question.
If you mean instantiate and initialize, that can be done very easily through serialization with libraries like:
jaxb.dev.java.net/
www.castor.org/
jibx.sourceforge.net/
http://x-stream.github.io/
etc.
If you mean you want to actually create a class file within the JVM at runtime, you might want to look at more dynamic langauges capable of running in a JVM like Groovy, or JRuby, etc. Groovy has some pretty cool dynamic capabilities.

How to Check References of Annotated Methods

I'm trying to find a way to check my classes for references of methods with a particular annotation (think "Deprecated").
As far as i see it, analysing byte code won't work because it doesn't contain any annotations.
Using APT doesn't really help because i need the references to the methods, not the annotated methods themselves.
So, what options do i have?
The best i can come up with is compiling a list of the annotated methods followed by a full code analysis, checking every method call against the list.
Is there a way to do that efficiently in an eclipse plug-in or an ant task?
Analysing bytecode will works!
ASM for an example is handling annotation very well.
In another question I asked for a Java parser of the Java language. For my analysis of code I use this one. Perhaps it's good for you, too.
Using the Reflections library, it's simple as:
Reflections reflections = new Reflections("my.package", new MethodAnnotationsScanner());
Set<Method> deprecated = reflections.getMethodsAnnotatedWith(Deprecated.class);

Categories