Fixed classloading issues when a lesson contains an inner class. The plugin classloader only expected the lesson to be loaded, now we keep track of all the classes loaded for each plugin. For each class found in the plugin a plugin classloader was created we need one classloader per plugin
Also needed to rewrite the findClass method to lookup the class in the list instead of loading the class from the byte array.
This commit is contained in:
parent
6e8d8562d6
commit
264824eb14
@ -50,8 +50,10 @@ public class Plugin {
|
||||
}
|
||||
|
||||
public void loadClasses(Map<String, byte[]> classes) {
|
||||
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
|
||||
PluginClassLoader pluginClassLoader = new PluginClassLoader(contextClassLoader);
|
||||
for (Map.Entry<String, byte[]> clazz : classes.entrySet()) {
|
||||
loadClass(clazz.getKey(), clazz.getValue());
|
||||
loadClass(pluginClassLoader, clazz.getKey(), clazz.getValue());
|
||||
}
|
||||
if (lesson == null) {
|
||||
throw new PluginLoadingFailure(String
|
||||
@ -60,18 +62,13 @@ public class Plugin {
|
||||
}
|
||||
}
|
||||
|
||||
private void loadClass(String name, byte[] classFile) {
|
||||
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
|
||||
PluginClassLoader pluginClassLoader = new PluginClassLoader(contextClassLoader, name, classFile);
|
||||
try {
|
||||
private void loadClass(PluginClassLoader pluginClassLoader, String name, byte[] classFile) {
|
||||
String realClassName = name.replaceFirst("/", "").replaceAll("/", ".").replaceAll(".class", "");
|
||||
Class clazz = pluginClassLoader.loadClass(realClassName);
|
||||
|
||||
Class clazz = pluginClassLoader.loadClass(realClassName, classFile);
|
||||
if (AbstractLesson.class.isAssignableFrom(clazz)) {
|
||||
this.lesson = clazz;
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
logger.error("Unable to load class {}", name, e);
|
||||
}
|
||||
}
|
||||
|
||||
public void loadFiles(List<Path> files, boolean reload) {
|
||||
@ -97,7 +94,7 @@ public class Plugin {
|
||||
Files.copy(file, bos);
|
||||
Path propertiesPath = createPropertiesDirectory();
|
||||
ResourceBundleClassLoader.setPropertiesPath(propertiesPath);
|
||||
if ( reload ) {
|
||||
if (reload) {
|
||||
Files.write(propertiesPath.resolve(file.getFileName()), bos.toByteArray(), CREATE, APPEND);
|
||||
} else {
|
||||
Files.write(propertiesPath.resolve(file.getFileName()), bos.toByteArray(), CREATE, TRUNCATE_EXISTING);
|
||||
@ -117,8 +114,14 @@ public class Plugin {
|
||||
|
||||
public void rewritePaths(Path pluginTarget) {
|
||||
try {
|
||||
PluginFileUtils.replaceInFiles(this.lesson.getSimpleName() + "_files", pluginTarget.getFileName().toString() + "/plugin/" + this.lesson.getSimpleName() + "/lessonSolutions/en/" + this.lesson.getSimpleName() + "_files", solutionLanguageFiles.values());
|
||||
PluginFileUtils.replaceInFiles(this.lesson.getSimpleName() + "_files", pluginTarget.getFileName().toString() + "/plugin/" + this.lesson.getSimpleName() + "/lessonPlans/en/" + this.lesson.getSimpleName() + "_files", lessonPlansLanguageFiles.values());
|
||||
PluginFileUtils.replaceInFiles(this.lesson.getSimpleName() + "_files",
|
||||
pluginTarget.getFileName().toString() + "/plugin/" + this.lesson
|
||||
.getSimpleName() + "/lessonSolutions/en/" + this.lesson.getSimpleName() + "_files",
|
||||
solutionLanguageFiles.values());
|
||||
PluginFileUtils.replaceInFiles(this.lesson.getSimpleName() + "_files",
|
||||
pluginTarget.getFileName().toString() + "/plugin/" + this.lesson
|
||||
.getSimpleName() + "/lessonPlans/en/" + this.lesson.getSimpleName() + "_files",
|
||||
lessonPlansLanguageFiles.values());
|
||||
} catch (IOException e) {
|
||||
throw new PluginLoadingFailure("Unable to rewrite the paths in the solutions", e);
|
||||
}
|
||||
|
@ -1,22 +1,42 @@
|
||||
package org.owasp.webgoat.plugins;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.FluentIterable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class PluginClassLoader extends ClassLoader {
|
||||
|
||||
private final List<Class<?>> classes = new ArrayList<>();
|
||||
private final Logger logger = LoggerFactory.getLogger(Plugin.class);
|
||||
private final byte[] classFile;
|
||||
|
||||
public PluginClassLoader(ClassLoader parent, String nameOfClass, byte[] classFile) {
|
||||
super(parent);
|
||||
logger.debug("Creating class loader for {}", nameOfClass);
|
||||
this.classFile = classFile;
|
||||
public Class<?> loadClass(String nameOfClass, byte[] classFile) {
|
||||
Class<?> clazz = defineClass(nameOfClass, classFile, 0, classFile.length);
|
||||
classes.add(clazz);
|
||||
return clazz;
|
||||
}
|
||||
|
||||
public Class findClass(String name) {
|
||||
public PluginClassLoader(ClassLoader contextClassLoader) {
|
||||
super(contextClassLoader);
|
||||
}
|
||||
|
||||
public Class findClass(final String name) throws ClassNotFoundException {
|
||||
logger.debug("Finding class " + name);
|
||||
return defineClass(name, classFile, 0, classFile.length);
|
||||
Optional<Class<?>> foundClass = FluentIterable.from(classes)
|
||||
.firstMatch(new Predicate<Class<?>>() {
|
||||
@Override
|
||||
public boolean apply(Class<?> clazz) {
|
||||
return clazz.getName().equals(name);
|
||||
}
|
||||
});
|
||||
if (foundClass.isPresent()) {
|
||||
return foundClass.get();
|
||||
}
|
||||
throw new ClassNotFoundException("Class " + name + " not found");
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user