Classloader Java 11 migration issue - java

I am migrating an app from java 8 to java 11. I did most of the upgrade but got stuck with the following exception.
class com.teamhub.plugins.sitemaps.jobs.SitemapUpdateJob cannot be cast to class org.quartz.Job (com...SitemapUpdateJob is in unnamed module of loader com...utils.ChildFirstClassLoader #bb39957; org.quartz.Job is in unnamed module of loader org.akhikhl.gretty.FilteringClassLoader #247667dd)
The application uses the normal context class loader but it loads plugins into the classpath using the ChildFirstClassLoader which on java 8 worked like a charm. In Java 11 though, it fails.
Looks like the issue is that the parent classloader loaded Job, and the child, ChildFirstClassLoader failes to use that to cast an implemented job.
public class ChildFirstClassLoader extends URLClassLoader {
private static final Set<String> FORCE_IN_PARENT = new HashSet<String>(); //ImmutableSet.of("");
private ClassLoader system;
public ChildFirstClassLoader(URL[] classpath, ClassLoader parent) {
super(classpath, parent);
system = getSystemClassLoader();
}
#Override
protected synchronized Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException {
// First, check if the class has already been loaded
Class<?> c = findLoadedClass(name);
if (c == null) {
try {
// checking local
c = findClass(name);
} catch (ClassNotFoundException | SecurityException e) {
c = loadClassFromParent(name, resolve);
}
}
if (resolve)
resolveClass(c);
return c;
}
#Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
for (String pkg : FORCE_IN_PARENT){
if (name.startsWith(pkg)) {
throw new ClassNotFoundException();
}
}
return super.findClass(name);
}
private Class<?> loadClassFromParent(String name, boolean resolve) throws ClassNotFoundException {
// checking parent
// This call to loadClass may eventually call findClass
// again, in case the parent doesn't find anything.
Class<?> c;
try {
c = super.loadClass(name, resolve);
} catch (ClassNotFoundException | SecurityException e) {
c = loadClassFromSystem(name);
}
return c;
}
private Class<?> loadClassFromSystem(String name) throws ClassNotFoundException{
Class<?> c = null;
if (system != null) {
// checking system: jvm classes, endorsed, cmd classpath,
// etc.
c = system.loadClass(name);
}
return c;
}
#Override
public URL getResource(String name) {
URL url = findResource(name);
if (url == null)
url = super.getResource(name);
if (url == null && system != null)
url = system.getResource(name);
return url;
}
#Override
public Enumeration<URL> getResources(String name) throws IOException {
/**
* Similar to super, but local resources are enumerated before parent
* resources
*/
Enumeration<URL> systemUrls = null;
if (system != null) {
systemUrls = system.getResources(name);
}
Enumeration<URL> localUrls = findResources(name);
Enumeration<URL> parentUrls = null;
if (getParent() != null) {
parentUrls = getParent().getResources(name);
}
final List<URL> urls = new ArrayList<URL>();
if (localUrls != null) {
while (localUrls.hasMoreElements()) {
URL local = localUrls.nextElement();
urls.add(local);
}
}
if (systemUrls != null) {
while (systemUrls.hasMoreElements()) {
urls.add(systemUrls.nextElement());
}
}
if (parentUrls != null) {
while (parentUrls.hasMoreElements()) {
urls.add(parentUrls.nextElement());
}
}
return new Enumeration<URL>() {
Iterator<URL> iter = urls.iterator();
public boolean hasMoreElements() {
return iter.hasNext();
}
public URL nextElement() {
return iter.next();
}
};
}
public InputStream getResourceAsStream(String name) {
URL url = getResource(name);
try {
return url != null ? url.openStream() : null;
} catch (IOException e) {
}
return null;
}
#Override
public String toString() {
return String.format("ChildFirstClassLoader [system=%s, getURLs()=%s, getParent()=%s]",
system, Arrays.toString(getURLs()), getParent());
}

Related

NoSuchMethodException when attempting to instantiate a dynamically loaded class with a constructor that includes a custom class

I am attempting to instantiate a dynamically loaded class (with a custom class loader) with a constructor that contains both a String object and a custom class I have created.
I have re-created the issue outside of my project, this is assuming that A.class is already in the target folder.
Main method:
public class simplifiedMainMethod {
static boolean propagate = false;
static Class<?> projectActions = null;
static Object oInstance;
public static void main (String[] args)
{
String projectName = "A";
String baseUrl = "https://www.google.com/";
simplifiedReport reporter = new simplifiedReport();
try
{
ClassLoader cl = Thread.currentThread().getContextClassLoader();
Reloader r = new Reloader(cl);
if (propagate)
Thread.currentThread().setContextClassLoader(r);
projectActions = r.loadClass("autobots_framework."+projectName);
Constructor<?> c = projectActions.getConstructor(String.class, simplifiedReport.class);
oInstance = c.newInstance(baseUrl, reporter);
}
catch (Exception e) {
e.printStackTrace();
}
}
}
simplifiedReport.java:
public class simplifiedReport
{
public simplifiedReport()
{
}
public void testMethod()
{
System.out.println("Hello World");
}
}
A.java:
public class A
{
public A(String testString, simplifiedReport testReport)
{
System.out.println(testString);
testReport.testMethod();
}
}
Here is the CustomClassLoader I am using:
public class ClassLoaderCompiler
{
public ClassLoaderCompiler()
{}
public static boolean compileCode(String fileDirectory, String projectName) throws IOException
{
JavaCompiler compiler = new EclipseCompiler();
DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null);
Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromStrings(Arrays.asList(fileDirectory));
JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, diagnostics, null, null, compilationUnits);
try
{
task.call();
fileManager.close();
return true;
}
catch(Exception e)
{
fileManager.close();
return false;
}
}
public static void moveClassFile(String projectName)
{
try
{
Files.deleteIfExists(new File(System.getProperty("user.dir")+"/target/classes/autobots_framework/"+projectName+".class").toPath());
Files.deleteIfExists(new File(System.getProperty("user.dir")+"/target/classes/autobots_framework/L_"+projectName+".class").toPath());
if (Files.exists(Paths.get(System.getProperty("user.dir")+"/projects/"+projectName+"/"+projectName+".class")))
{
Path temp = Files.move (Paths.get(System.getProperty("user.dir")+"/projects/"+projectName+"/"+projectName+".class"),Paths.get(System.getProperty("user.dir")+"/target/classes/autobots_framework/"+projectName+".class"));
Path tempLocator = Files.move (Paths.get(System.getProperty("user.dir")+"/projects/"+projectName+"/L_"+projectName+".class"),Paths.get(System.getProperty("user.dir")+"/target/classes/autobots_framework/L_"+projectName+".class"));
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
/**
* adapted from http://stackoverflow.com/a/3971771/7849
*/
class Reloader extends ClassLoader {
static URL url;
ClassLoader orig;
Reloader(ClassLoader orig) {
this.orig = orig;
}
#Override
public Class<?> loadClass(String s) {
return findClass(s);
}
#Override
public Class<?> findClass(String s) {
try {
byte[] bytes = loadClassData(s);
return defineClass(s, bytes, 0, bytes.length);
} catch (IOException ioe) {
try {
return super.loadClass(s);
} catch (ClassNotFoundException ignore) {
ignore.printStackTrace(System.out);
}
ioe.printStackTrace(System.out);
return null;
}
}
private byte[] loadClassData(String className) throws IOException {
try {
/*
* get the actual path using the original classloader
*/
Class<?> clazz = orig.loadClass(className);
url = clazz.getResource(clazz.getSimpleName() + ".class");
/*
* force reload
*/
File f = new File(url.toURI());
int size = (int) f.length();
byte buff[] = new byte[size];
FileInputStream fis = new FileInputStream(f);
DataInputStream dis = new DataInputStream(fis);
dis.readFully(buff);
dis.close();
return buff;
} catch (Exception ex) {
throw new IOException(ex);
}
}
}
I am getting this error as a result:
java.lang.NoSuchMethodException: autobots_framework.A.<init>(java.lang.String, autobots_framework.simplifiedReport)
at java.lang.Class.getConstructor0(Unknown Source)
at java.lang.Class.getConstructor(Unknown Source)
I figured this was due to the parameters not matching, so to confirm I tried finding what the constructor is implicitly looking for:
for (Constructor c : projectActions.getDeclaredConstructors())
{
System.out.print(c.toGenericString());
}
Yielding this result:
public autobots_framework.A(java.lang.String,autobots_framework.simplifiedReport)
Which is frustratingly looking a lot like what I have put here:
Constructor<?> c = projectActions.getConstructor(String.class, simplifiedReport.class);
oInstance = c.newInstance(baseUrl, reporter);
I understand that this has something to do with my class, as when I leave out simplifiedReport in the constructor and only instantiating it with String.class, I am successful. What modifier am I missing in my class to make this work?
This is all a function of my application to dynamically compile code and then instantiate them to run custom code and methods.

Extending URLClassLoader and overriding getPermissions does not work

When trying to implement a sandbox in a plugin-like environment, I came accross https://stackoverflow.com/a/5580239/2057294 which seems to be exactly what I want, however I am unable to get it working, what am I doing wrong?
I have the following setup:
final class ModURLClassLoader extends URLClassLoader {
ModURLClassLoader(final URL[] urls) {
super(urls);
}
ModURLClassLoader(final URL[] urls, final ClassLoader parent) {
super(urls, parent);
}
ModURLClassLoader(final URL[] urls, final ClassLoader parent, final URLStreamHandlerFactory factory) {
super(urls, parent, factory);
}
#Override
protected PermissionCollection getPermissions(final CodeSource codesource) {
PermissionCollection permissionCollection = super.getPermissions(codesource);
//give no permissions to the codesource
return permissionCollection;
}
#Override
protected Class<?> loadClass(final String name, final boolean resolve) throws ClassNotFoundException {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
int i = name.lastIndexOf('.');
if (i != -1) {
sm.checkPackageAccess(name.substring(0, i));
}
}
return super.loadClass(name, resolve);
}
}
The idea here is that code loaded through the ModURLClassLoader may have no permissions at all. I do want to be able to add extra permissions statically in case I block some permissions which a mod would generally want to have.
Then I load up my classes via the following:
public class JavaMod extends LoadableMod {
private ECSMod ecsMod;
private ModURLClassLoader modUrlClassLoader;
JavaMod(final Path modDirectory) throws ModNotLoadableException {
super(modDirectory);
}
#Override
protected void load0() throws ModNotLoadableException {
try {
Properties properties = ModLoaderHelper.getConfiguration(modDirectory);
String jarName = properties.getProperty("jar");
String entryPoint = properties.getProperty("entryPoint");
Path jarPath = modDirectory.resolve(jarName);
try {
modUrlClassLoader = AccessController.doPrivileged((PrivilegedExceptionAction<ModURLClassLoader>)() -> new ModURLClassLoader(new URL[] { jarPath.toUri().toURL() }, getClass().getClassLoader()));
} catch (PrivilegedActionException ex) {
throw new ModNotLoadableException(ex);
}
Class<?> clazz = Class.forName(entryPoint, false, modUrlClassLoader);
if (!ECSMod.class.isAssignableFrom(clazz)) {
throw new ModNotLoadableException(clazz + " does not implement ECSMod");
}
this.ecsMod = (ECSMod)clazz.newInstance();
} catch (Exception ex) {
throw new ModNotLoadableException(ex);
}
}
#Override
protected void unload0() {
try {
modUrlClassLoader.close();
} catch (IOException ex) {
throw new UncheckedIOException(ex);
}
}
#Override
protected ECSGame createGame0() {
ECSGame ecsGame = new ECSGame();
ecsMod.setupGame(ecsGame);
return ecsGame;
}
}
Which loads an untrusted JAR that has a class that implements ECSMod, I have confirmed that both the clazz and ecsMod belong to an instance of ModURLClassLoader.
Then the malicious code:
public final class UntrustedEvilMod implements ECSMod {
#Override
public void setupGame(final ECSGame game) {
System.exit(0);
}
}
Where ECSMod and ECSGame are classes that belong to the plugin (also called mod) API and reside in the original classloader.
I'm running this without a security manager, as I believe that this would be unnecessary in this context? As the ModURLClassLoader defines the security.
Why is this not working, meaning that it still causes the program to exit, whereas I would've wanted an AccessControlException?

Checking if loaded class is assignable from another?

So, I have a custom classloader to load classes into memory from byte arrays, and I have a problem: When I attempt to see if a class is assignable from another(ClassLoader.isAssignableFrom), it returns false, even if the compiled class extends or implements it. I assume because it's loaded by a different and custom classloader rather than the system one, so how would I fix this? The reason that I need to do this is I want to check if class files in a jar file are ClassLoaders themselves, because I'm making a java virus scanner for jar files.
Custom ClassLoader:
public class CL extends ClassLoader {
byte[] jar = null;
private HashMap<String, Class<?>> classes = new HashMap<String, Class<?>>();
private HashMap<String, byte[]> resources = new HashMap<String, byte[]>();
public CL(byte[] jar) {
this.jar = jar;
}
private JarInputStream getStream() {
try {
return new JarInputStream(new ByteArrayInputStream(jar));
}catch (IOException e) {
e.printStackTrace();
}
return null;
}
public InputStream getResourceAsStream(String name) {
if (!resources.containsKey(name)) {
try {
JarInputStream stream = getStream();
JarEntry entry = stream.getNextJarEntry();
ArrayList<JarEntry> ent = new ArrayList<JarEntry>();
while (entry != null) {
String en = entry.getName().replace("/", ".");
if (en.contains(".")) {
en = en.substring(0, en.lastIndexOf("."));
}
if (en.equals(name)) {
break;
}
ent.add(entry);
entry = stream.getNextJarEntry();
}
if (entry == null) {
for (JarEntry e : ent) {
String en = e.getName().replace("/", ".");
if (en.contains(".")) {
en = en.substring(0, en.lastIndexOf("."));
}
if (en.lastIndexOf(".") > 0 && en.substring(en.lastIndexOf(".") + 1).equals(name)) {
entry = e;
break;
}
}
}
if (entry == null) {
return null;
}
ent = null;
ByteArrayOutputStream byt = new ByteArrayOutputStream();
while (true) {
int r = stream.read();
if (r < 0) break;
byt.write(r);
}
stream.close();
byte[] reqc = byt.toByteArray();
return new ByteArrayInputStream(reqc);
}catch (IOException e) {
e.printStackTrace();
}
}else {
return new ByteArrayInputStream(resources.get(name));
}
return null;
}
public Class<?> findClass(String name) {
if (!classes.containsKey(name)) {
try {
JarInputStream stream = getStream();
JarEntry entry = stream.getNextJarEntry();
while (entry != null) {
String en = entry.getName().replace("/", ".");
if (en.contains(".")) {
en = en.substring(0, en.lastIndexOf("."));
}
if (en.equals(name)) {
break;
}
entry = stream.getNextJarEntry();
}
if (entry == null) {
return null;
}
ByteArrayOutputStream byt = new ByteArrayOutputStream();
while (true) {
int r = stream.read();
if (r < 0) break;
byt.write(r);
}
stream.close();
byte[] reqc = byt.toByteArray();
Class<?> c = defineClass(name, reqc, 0, reqc.length, CL.class.getProtectionDomain());
classes.put(name, c);
return c;
}catch (IOException e) {
e.printStackTrace();
}
}else {
return classes.get(name);
}
return null;
}
}
My code for checking if something is assignable from a classloader(cl is an instance of my classloader):
Class<?> cls = cl.findClass(fname);
boolean isCL = false;
if (cls.isAssignableFrom(ClassLoader.class)) {
isCL = true;
}
boolean bCL = false;
for (Method m : cls.getMethods()) {
String mn = m.getName();
if (isCL) {
if (mn.contains("loadClass") || mn.contains("defineClass") || mn.contains("findClass")) {
bCL = true;
}
}
}
The problem: the isAssignableFrom returns false, even if it should be true.
So, is there a fix to this? I do not want to switch classloaders, as I am initially loading from a jar, but I want to be able to load jars inside jars and zips. Thanks!
Your problem is that you are using isAssignableFrom incorrectly (albeit, it is a very confusing method). this is what you want:
ClassLoader.class.isAssignableFrom(cls)
I ended up figuring out a hack of sorts, for superclasses(superinterfaces are different) use this:
cls.getSuperclass().getName().equals("java.lang.ClassLoader") Where the java.lang.ClassLoader is the fully qualified name you need to check. You do not need to have the class loaded in your main classloader.

Custom Annotation Processor - Detect Method with Annotations

I am trying to write an annotation Procssor to detect the methods that are annotated with the #PrintMethod annotation. For example in the test Class below, i want to print the codes within the test Method. Is there a way to do it?
From the AnnotationProcessor class stated below, i am only able get the method name but not the details of the method.
Test Class
public class test {
public static void main(String[] args) {
System.out.println("Args");
}
#PrintMethod
private boolean testMethod(String input) {
if(input!=null) {
return true;
}
return false;
}
}
Annotation Processor Class
public class AnnotationProcessor extends AbstractProcessor {
//......
#Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
//retrieve test Anntoation
Set<? extends Element> ann =roundEnv.getElementsAnnotatedWith(PrintMethod.class);
//Print the Method Name
for(Element e: ann) {
String msg="Element ee :"+ee.getSimpleName().toString();
processingEnv.getMessager().printMessage( javax.tools.Diagnostic.Kind.ERROR, msg, e);
}
}
}
I was curious about this too so I decided to try and figure it out. Turns out to be easier than I expected. All you need to do is leverage the Trees api out of the proprietary tools.jar library. I've made a quick annotation processor along these lines here: https://github.com/johncarl81/printMethod
Here's the meat of it:
#SupportedSourceVersion(SourceVersion.RELEASE_6)
#SupportedAnnotationTypes("org.printMethod.PrintMethod")
public class PrintMethodAnnotationProcessor extends AbstractProcessor {
private Trees trees;
#Override
public synchronized void init(ProcessingEnvironment processingEnv) {
super.init(processingEnv);
trees = Trees.instance(processingEnv); //initialize the Trees api.
}
#Override
public boolean process(Set<? extends TypeElement> typeElements, RoundEnvironment roundEnvironment) {
MethodPrintScanner visitor = new MethodPrintScanner();
for (Element e : roundEnvironment.getElementsAnnotatedWith(PrintMethod.class)) {
TreePath tp = trees.getPath(e);
// visit the annotated methods
visitor.scan(tp, trees);
}
return true;
}
#Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latestSupported();
}
}
And the MethodPrintScanner:
public class MethodPrintScanner extends TreePathScanner {
#Override
public Object visitMethod(MethodTree methodTree, Object o) {
System.out.println(methodTree);
return null;
}
}
You can see that we are able to visit the TreePath associated with the given annotated Element. For each method, we simply println() the methodTree which gives us the contents of the method.
Using your example, here's the output of the program during compilation:
#PrintMethod()
private boolean testMethod(String input) {
if (input != null) {
return true;
}
return false;
}
It's one thing to make it work in your IDE. But it's another to detect them once your code is packed inside jar files. The following code can manage both.
public static List<Class> getPackageClassListHavingAnnotation(String pPackageName,
Class<? extends Annotation> pAnnotation) throws Exception
{
try
{
List<Class> classList = getPackageClassList(pPackageName);
if ((pAnnotation == null) || (classList == null)) return classList;
List<Class> resultList = new ArrayList<Class>(classList.size());
outerLoop:
for (Class clazz : classList)
{
try
{
for (Method method : clazz.getMethods())
{
if (method.isAnnotationPresent(pAnnotation))
{
resultList.add(clazz);
continue outerLoop;
}
}
}
catch (Throwable e)
{
}
}
return (resultList.isEmpty()) ? null : resultList;
}
catch (Exception e)
{
return null;
}
}
It requires the following helper methods:
public static List<Class> getPackageClassList(String pPackageName) throws Exception
{
try
{
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
String path = pPackageName.replace('.', '/');
List<File> dirs = new ArrayList<File>();
List<JarFile> jars = new ArrayList<JarFile>();
Enumeration<URL> resources = classLoader.getResources(path);
if (resources != null)
{
String fileName;
URL resource;
File file;
while (resources.hasMoreElements())
{
resource = resources.nextElement();
fileName = resource.getFile();
if (fileName.contains("!"))
{
// jar file
resource = new URL(StringUtil.getArrayFromString(fileName, "!")[0]);
file = urlToFile(resource);
if (!file.exists()) continue;
jars.add(new JarFile(file));
}
else
{
// class file that is not in a jar file
file = urlToFile(resource);
if (!file.exists()) continue;
dirs.add(file);
}
}
}
List<Class> resultList = new ArrayList<Class>(1000);
List<Class> tmpClassList;
for (File directory : dirs)
{
tmpClassList = getPckDirClassList(directory, pPackageName);
if (tmpClassList != null) resultList.addAll(tmpClassList);
}
for (JarFile jar : jars)
{
tmpClassList = getPckJarClassList(jar, pPackageName);
if (tmpClassList != null) resultList.addAll(tmpClassList);
}
return (resultList.isEmpty()) ? null : resultList;
}
catch (Exception e)
{
return null;
}
}
private static List<Class> getPckJarClassList(JarFile pJar, String pPackageName)
{
if ((pJar == null) || (pPackageName == null)) return null;
List<Class> resultList = new ArrayList<Class>(100);
Enumeration<JarEntry> jarEntries = (pJar.entries());
JarEntry jarEntry;
String fullClassName;
while (jarEntries.hasMoreElements())
{
jarEntry = jarEntries.nextElement();
fullClassName = jarEntry.getName().replaceAll("/", ".");
if (!fullClassName.startsWith(pPackageName)) continue;
if (!fullClassName.endsWith(".class")) continue;
// do not do a Class.forName for the following path, this can crash the server
try
{
resultList.add(Class.forName(fullClassName.substring(0, fullClassName.length() - 6)));
}
catch (Throwable e)
{
}
}
return (resultList.isEmpty()) ? null : resultList;
}
/**
* Recursive method to find all classes in a package directory tree.
*/
private static List<Class> getPckDirClassList(File pDirectory, String pPackageName) throws ClassNotFoundException
{
try
{
if ((pDirectory == null) || (pPackageName == null)) return null;
if (!pDirectory.exists()) return null;
File[] files = pDirectory.listFiles();
if ((files == null) || (files.length == 0)) return null;
List<Class> resultList = new ArrayList<Class>(100);
List<Class> tmpClassList;
for (File file : files)
{
if (file.isDirectory())
{
tmpClassList = getPckDirClassList(file, pPackageName + "." + file.getName());
if (tmpClassList != null) resultList.addAll(tmpClassList);
}
else if (file.getName().endsWith(".class"))
{
try
{
resultList.add(Class.forName(pPackageName + '.' + file.getName().substring(0, file.getName().length() - 6)));
}
catch (Throwable e)
{
}
}
}
return (resultList.isEmpty()) ? null : resultList;
}
catch (Exception e)
{
return null;
}
}
This code has been tested with .jar files on both windows and unix systems. It has also been tested with .java files in IntelliJ on windows.

Java Reflection - How to exclude interface when loading the class dynamically

I use spring framework to find the class and its methods and arguments dynamically.
these are the methods I use :
public List<Class> findMyTypes(String basePackage) throws IOException, ClassNotFoundException
{
ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(resourcePatternResolver);
List<Class> candidates = new ArrayList<Class>();
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
resolveBasePackage(basePackage) + "/" + "**/*.class";
Resource[] resources = resourcePatternResolver.getResources(packageSearchPath);
for (Resource resource : resources) {
if (resource.isReadable()) {
MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(resource);
if (isCandidate(metadataReader)) {
candidates.add(Class.forName(metadataReader.getClassMetadata().getClassName()));
}
}
}
return candidates;
}
public String resolveBasePackage(String basePackage) {
return ClassUtils.convertClassNameToResourcePath(SystemPropertyUtils.resolvePlaceholders(basePackage));
}
#SuppressWarnings({ "rawtypes", "unchecked" })
public boolean isCandidate(MetadataReader metadataReader) throws ClassNotFoundException
{
try {
Class c = Class.forName(metadataReader.getClassMetadata().getClassName());
if (c.getAnnotation(Controller.class) != null) {
return true;
}
}
catch(Throwable e){
}
return false;
}
I load the class which has got annotation #Controller. It is working fine but I want to load only the class not interface also how do I get the methods and the arguments of the class loaded.
EDIT :
This is how I get all the class names and try to get the methods name :
List classNames = hexgenClassUtils.findMyTypes("com.hexgen.*");
Iterator<Class> it = classNames.iterator();
while(it.hasNext())
{
Class obj = it.next();
System.out.println("Class :"+obj.toString());
cls = Class.forName(obj.toString());
Method[] method = cls.getMethods();
for (Method method2 : method) {
System.out.println("Method name : "+method2.toGenericString());
}
// TODO something with obj
}
The problem I face is class com.hexgen.api.facade.HexgenWebAPI here class is coming because of which I am not able to load the class dynamically and get the following exception.
java.lang.ClassNotFoundException: class com.hexgen.api.facade.HexgenWebAPI so how to solve it.
Kindly help me to find the solution.
Best Regards
try
Class c = Class.forName(metadataReader.getClassMetadata().getClassName());
if (!c.isInterface() && c.getAnnotation(Controller.class) != null) {
return true;
}

Categories

Resources