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,27 +50,24 @@ public class Plugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void loadClasses(Map<String, byte[]> classes) {
|
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()) {
|
for (Map.Entry<String, byte[]> clazz : classes.entrySet()) {
|
||||||
loadClass(clazz.getKey(), clazz.getValue());
|
loadClass(pluginClassLoader, clazz.getKey(), clazz.getValue());
|
||||||
}
|
}
|
||||||
if (lesson == null) {
|
if (lesson == null) {
|
||||||
throw new PluginLoadingFailure(String
|
throw new PluginLoadingFailure(String
|
||||||
.format("Lesson class not found, following classes were detected in the plugin: %s",
|
.format("Lesson class not found, following classes were detected in the plugin: %s",
|
||||||
StringUtils.collectionToCommaDelimitedString(classes.keySet())));
|
StringUtils.collectionToCommaDelimitedString(classes.keySet())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadClass(String name, byte[] classFile) {
|
private void loadClass(PluginClassLoader pluginClassLoader, String name, byte[] classFile) {
|
||||||
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
|
String realClassName = name.replaceFirst("/", "").replaceAll("/", ".").replaceAll(".class", "");
|
||||||
PluginClassLoader pluginClassLoader = new PluginClassLoader(contextClassLoader, name, classFile);
|
|
||||||
try {
|
Class clazz = pluginClassLoader.loadClass(realClassName, classFile);
|
||||||
String realClassName = name.replaceFirst("/", "").replaceAll("/", ".").replaceAll(".class", "");
|
if (AbstractLesson.class.isAssignableFrom(clazz)) {
|
||||||
Class clazz = pluginClassLoader.loadClass(realClassName);
|
this.lesson = clazz;
|
||||||
if (AbstractLesson.class.isAssignableFrom(clazz)) {
|
|
||||||
this.lesson = clazz;
|
|
||||||
}
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
logger.error("Unable to load class {}", name, e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,7 +94,7 @@ public class Plugin {
|
|||||||
Files.copy(file, bos);
|
Files.copy(file, bos);
|
||||||
Path propertiesPath = createPropertiesDirectory();
|
Path propertiesPath = createPropertiesDirectory();
|
||||||
ResourceBundleClassLoader.setPropertiesPath(propertiesPath);
|
ResourceBundleClassLoader.setPropertiesPath(propertiesPath);
|
||||||
if ( reload ) {
|
if (reload) {
|
||||||
Files.write(propertiesPath.resolve(file.getFileName()), bos.toByteArray(), CREATE, APPEND);
|
Files.write(propertiesPath.resolve(file.getFileName()), bos.toByteArray(), CREATE, APPEND);
|
||||||
} else {
|
} else {
|
||||||
Files.write(propertiesPath.resolve(file.getFileName()), bos.toByteArray(), CREATE, TRUNCATE_EXISTING);
|
Files.write(propertiesPath.resolve(file.getFileName()), bos.toByteArray(), CREATE, TRUNCATE_EXISTING);
|
||||||
@ -117,8 +114,14 @@ public class Plugin {
|
|||||||
|
|
||||||
public void rewritePaths(Path pluginTarget) {
|
public void rewritePaths(Path pluginTarget) {
|
||||||
try {
|
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",
|
||||||
PluginFileUtils.replaceInFiles(this.lesson.getSimpleName() + "_files", pluginTarget.getFileName().toString() + "/plugin/" + this.lesson.getSimpleName() + "/lessonPlans/en/" + this.lesson.getSimpleName() + "_files", lessonPlansLanguageFiles.values());
|
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) {
|
} catch (IOException e) {
|
||||||
throw new PluginLoadingFailure("Unable to rewrite the paths in the solutions", e);
|
throw new PluginLoadingFailure("Unable to rewrite the paths in the solutions", e);
|
||||||
}
|
}
|
||||||
|
@ -1,22 +1,42 @@
|
|||||||
package org.owasp.webgoat.plugins;
|
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.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class PluginClassLoader extends ClassLoader {
|
public class PluginClassLoader extends ClassLoader {
|
||||||
|
|
||||||
|
private final List<Class<?>> classes = new ArrayList<>();
|
||||||
private final Logger logger = LoggerFactory.getLogger(Plugin.class);
|
private final Logger logger = LoggerFactory.getLogger(Plugin.class);
|
||||||
private final byte[] classFile;
|
|
||||||
|
|
||||||
public PluginClassLoader(ClassLoader parent, String nameOfClass, byte[] classFile) {
|
public Class<?> loadClass(String nameOfClass, byte[] classFile) {
|
||||||
super(parent);
|
Class<?> clazz = defineClass(nameOfClass, classFile, 0, classFile.length);
|
||||||
logger.debug("Creating class loader for {}", nameOfClass);
|
classes.add(clazz);
|
||||||
this.classFile = classFile;
|
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);
|
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