Custom validator in launched Eclipse cannot find classes from project workspace sources [message #987533] |
Mon, 26 November 2012 19:55  |
Eclipse User |
|
|
|
My custom Validator in Launched Eclipse cannot find classes from project workspace sources. The Class.forName(qualifiedName) in my custom validator works in integration tests but not when run as Eclipse Application.
My language DeepCloneJavaValidator works well in tests but gives ClassNotFoundException for any class in workspace/src directory when the DSL is launched as Run as Eclipse Application.
I need to get real Class object from JvmTypeReference assignment value. I need the class to compare fields via introspection with declared fields in the DSL, they must match. And also I can infer types of fields and sub-classes. Only root type needs to be specified this way.
The JvmTypeReference assignment works flawlessly. The contextual help sees correctly project classes, like a.b.m.Book, dummy classes from my dummy project. Just Validator Class Loader does not see them.
Here is the problematic check.
@Check
public void checkFieldClass(ClassCloner rootCloner) {
String qualifiedName = rootCloner.getClassToClone().getQualifiedName();
try {
Class<?> clazz = Class.forName(qualifiedName);
rootCloner.setJavaType(clazz.getName());
} catch (ClassNotFoundException e) {
error("Class '" + qualifiedName + "' does not exist (DCValidator)",
DeepClonePackage.Literals.CLASS_CLONER__CLASS_TO_CLONE);
}
}
// Method name is somewhat misleading, it should be like checkRootClonerClass()
I have tried different class loaders, but nothing works:
Class<?> clazz = Class.forName(qualifiedName);
Class<?> clazz = Class.forName(qualifiedName, false, ClassLoader.getSystemClassLoader());
Class<?> clazz = Class.forName(qualifiedName); // internally calls ClassLoader.getCallerClassLoader();
Class<?> clazz = Class.forName(qualifiedName, false, this.getClass().getClassLoader());
Class<?> clazz = getClass().getClassLoader().loadClass(qualifiedName);
Each approach gives different ClassLoader but none recognizes my project workspace classes (a.b.m.Book).
Sources for Validator:
https://bitbucket.org/espinosa/deepclonedsl/src/86cee21b23cf884bffce2d8140338e98123db7c7/src/my/home/dsl/validation/DeepCloneJavaValidator.java?at=master
Sources for language definition:
https://bitbucket.org/espinosa/deepclonedsl/src/3f6ca054212223ccad2f43f7ec1c934e358f05f7/src/my/home/dsl/DeepClone.xtext?at=master
Sources of my validator tests (all passing tests!):
https://bitbucket.org/espinosa/deepclonedsl.tests/src/e89ce276a060641aac65ba0701d37a865edb69e6/src/my/home/dsl/deepclone/DeepCloneValidationTest.xtend?at=master
Stacktrace (clipped):
java.lang.ClassNotFoundException: a.b.m.Book
org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:501)
org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:421)
org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:412) org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(DefaultClassLoader.java:107)
java.lang.ClassLoader.loadClass(ClassLoader.java:247) my.home.dsl.validation.DeepCloneJavaValidator.checkFieldClass(DeepCloneJavaValidator.java:73) . . .
Stacktrace when SystemClassLoader is used (clipped):
java.lang.ClassNotFoundException: a.b.m.Book
java.net.URLClassLoader$1.run(URLClassLoader.java:202)
java.security.AccessController.doPrivileged(Native Method)
java.net.URLClassLoader.findClass(URLClassLoader.java:190)
java.lang.ClassLoader.loadClass(ClassLoader.java:306)
sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
java.lang.ClassLoader.loadClass(ClassLoader.java:247)
java.lang.Class.forName0(Native Method)
java.lang.Class.forName(Class.java:247) my.home.dsl.validation.DeepCloneJavaValidator.checkFieldClass(DeepCloneJavaValidator.java:70) . . .
Any hints?
Espinosa
|
|
|
|
|
|
|
Re: Custom validator in launched Eclipse cannot find classes from project workspace sources [message #987865 is a reply to message #987533] |
Wed, 28 November 2012 07:45  |
Eclipse User |
|
|
|
I have found a solution. I have not solved the ClassLoader issue, but found at least a way out. Key is to redefine question, do I really need introspection?
Instead I can use Xtext Common Types package to get the same information.
Instead of java.bean.Introspector and PropertyDescriptors I can use org.eclipse.xtext.common.types.JvmTypeReference, JvmDeclaredType and JvmField.
Benefits - no dealings with any ClassLoader and I guess better handling of things like generics, build time versus run-time information.
Here is example how to get list of all member fields names for a given JVM Type (Java Class):
public List<String> getFieldNamesForClass(JvmTypeReference jvmTypeRef) {
List<String> result = new ArrayList<String>();
if (jvmTypeRef.getType() instanceof JvmDeclaredType) {
JvmDeclaredType declaredType = (JvmDeclaredType)jvmTypeRef.getType();
for (JvmField field : declaredType.getDeclaredFields()) {
result.add(field.getSimpleName());
}
}
return result;
}
The input parameter is provided by the model.
For full code see https://bitbucket.org/espinosa/deepclonedsl/src/f9e146b33aadaa70f26a900bc8cffe1b928ffc60/src/my/home/dsl/utils/ReflectionUtils.java?at=master
Espinosa, 28/11/2012, 12:45 GMT
[Updated on: Wed, 05 December 2012 15:42] by Moderator
|
|
|
Powered by
FUDForum. Page generated in 0.42657 seconds