I was wondering if anyone has used Sapphire dealing with Java Types and in particularly with Java Reflection Utilities.
I have implemented a Java Type picker and i have to retrieve the fields available in that particular selected Java Class and pull that out onto the XML as attributes. Screenshot attached !
@Type( base = JavaTypeName.class )
@Reference( target = JavaType.class)
@XmlBinding( path = "@name" )
@Label( standard = "& Module Name" )
ValueProperty PROP_MODULE_NAME = new ValueProperty( TYPE, "ModuleName" );
void setModuleName( String value );
void setModuleName( JavaTypeName value );
Now i want to run Reflection Utils like getDeclaredFields() on the Java Class selected from this window. To get this done i am making use of a service which extends PossibleValuesService .
This custom service class has the Java Reflection code and in this segment i need the class which i have picked earlier to pass a reference to this.
Class c = Class.forName(ClsName);
System.out.println("Class Name :"+c.getName()+"\n");
Field allFieldArray = c.getDeclaredFields();
int size = allFieldArray.length;
for(int i = 0 ; i < size ; i++)
System.out.println("Field ( "+i+" ) :"+allFieldArray[i]);
I am passing the ClsName ( Java String ) of the earlier selected Class using the getModuleName method of the model, for which it says class not found. This is problem number one.
Also is there a way to get hold of the class reference directly along with just the string name of the class so that i can pass it to the reflection utils directly as an object.
If you call element.getModuleName().resolve(), you will get a JavaType object (unless type is not found). From a JavaType, you can call artifact() to get a Class object. Note that artifact() will return null if the referenced type is a Java source file in a project. For those types, there is no Class object in existence and you have to use JDT's type API instead of reflection. The JavaType class does provide some methods for accessing type metadata without differentiating between Java reflection and JDT, but there is no API today to get at the fields. I am not opposed to expanding JavaType API if there is a need.
I was scratching my head on getting NPE from the JavaType object until i read your line which says you will get null from a java source file after reflection. Irony is that i only have access to the source files ! I have to work around that !
That points me to the next part , is there a way to specify a path to the Java Type picker (the browse button) to choose the class files from?
Or may be some filter which lets you select class files from a specified package (something similar to the @JavaTypeConstraint functionality).
The JavaType object you get has a reference to JDT's IType which can be used similarly to reflection, but it doesn't make IType accessible. If this would be useful, please open an enhancement request.
The Java type picker and other Java type handling functionality (validation, jump to, etc.) all operate in the Java context relative to the file that your model is editing. You will see types from the project the file is in as well as types from everything that the project references. There is no facility to define other contexts.
But what are my options if i dont have to deal with JDT Type API and to go ahead with Reflection ?
Also, I have problems loading any class file using class.forName(clsName). Its not resolving . Tried it with the 3 parameters forName, it ain't working.
Do you think the problem also lies with the class loaders since the launched Eclipse RCP app points its classpath to somewhere inside the Eclipse / Plugins directory and not to the project specific workspace where i intend it to be !
For examples, If i search the classpath it is pointing to
There is no class loader with your project's classes when in development, as such you cannot use Java Reflection and have to use JDT's API if you need to inspect the types. Your project classes are only in a class loader when you are running it.