So here is my issue. I am creating a piece of software that is similar to a DOS command line. I would like people to be able to add other commands by simply dropping a jar file containing classes extending the base Command
class into a folder. Nothing I have tried yet works.
Here is what I have tried:
- Using the Reflections library to add search the jar file for classes extending the Command class
This threw many an error and just didn't find the majority of the classes in my jar. I think this has something to do with all theSomeClass$1.class
stuff that goes on. - Iterating through every file in the jar and adding it to the classpath
I couldn't find a way for this to work because I simply couldn't turn the iterations ofZipEntry
into anything that could be added to the classpath, e.g URLs. - Adding the whole jar to the classpath
This didn't work either because the program won't know the names of these classes, therefore, it can't turn them into commands.
I would love some help here. Any suggestions on how I can make my program more extensible would be very much welcome. +1 for those including code ;)
If you need any further information just let me know.
EDIT:
New code:
URLClassLoader ucl = (URLClassLoader) ClassLoader.getSystemClassLoader();
for(File file : FileHelper.getProtectedFile("/packages/").listFiles()) {
if(file.getName().endsWith(".jar")) {
Set<Class<?>> set = new HashSet<Class<?>>();
JarFile jar = null;
try {
jar = new JarFile(file);
Enumeration<JarEntry> entries = jar.entries();
while(entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
if(!entry.getName().endsWith(".class"))
continue;
Class<?> clazz;
try {
clazz = ucl.loadClass(entry.getName().replace("/", ".").replace(".class", "")); // THIS IS LINE 71
} catch(ClassNotFoundException e) {
e.printStackTrace();
continue;
}
if(entry.getName().contains("$1"))
continue;
if(clazz.getName().startsWith("CMD_"))
set.add(clazz);
jar.close();
}
} catch(Exception e) {
//Ignore file
try {
jar.close();
} catch (IOException e1) {/* Don't worry about it too much... */}
OutputHelper.log("An error occurred whilst adding package " + OutputStyle.ITALIC + file.getName() + OutputStyle.DEFAULT + ". " + e.getMessage() + ". Deleting package...", error);
e.printStackTrace();
file.delete();
}
Error thrown:
java.lang.ClassNotFoundException: com.example.MyCommands.CMD_eggtimer
at java.net.URLClassLoader$1.run(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at com.MyWebsite.MyApplication.Commands.CommandList.update(CommandList.java:71)
Line 71 has been marked in the above code.