diff --git a/src/main/java/org/owasp/webgoat/plugins/Plugin.java b/src/main/java/org/owasp/webgoat/plugins/Plugin.java index 7d34b361e..39c9e9774 100644 --- a/src/main/java/org/owasp/webgoat/plugins/Plugin.java +++ b/src/main/java/org/owasp/webgoat/plugins/Plugin.java @@ -1,21 +1,43 @@ package org.owasp.webgoat.plugins; import org.owasp.webgoat.lessons.AbstractLesson; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.StringUtils; import java.io.IOException; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; public class Plugin { + private static final Logger logger = LoggerFactory.getLogger(Plugin.class); private final Class lesson; private final Path pluginDirectory; + public static class PluginLoadingFailure extends RuntimeException { + + public PluginLoadingFailure(String message) { + super(message); + } + } + public static class Builder { private Path pluginDirectory; private Class lesson; + private final List loadedClasses = new ArrayList(); + + public Builder loadClasses(Map classes) { + for (Map.Entry clazz : classes.entrySet() ) { + loadClass(clazz.getKey(), clazz.getValue()); + } + return this; + } public Builder loadClass(String name, byte[] classFile) { ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); @@ -26,20 +48,27 @@ public class Plugin { if (AbstractLesson.class.isAssignableFrom(clazz)) { this.lesson = clazz; } + loadedClasses.add(clazz.getName()); } catch (ClassNotFoundException e) { - e.printStackTrace(); + logger.error("Unable to load class {}", name); } return this; } public Builder setBaseDirectory(Path pluginDirectory) { this.pluginDirectory = pluginDirectory; + //Find necessary files flag if something went wrong plugin should complain return this; } public Plugin build() { + if ( lesson == null ) { + throw new PluginLoadingFailure(String.format("Lesson class not found, following classes were detected in the plugin: %s", + StringUtils.collectionToCommaDelimitedString(loadedClasses))); + } return new Plugin(this.lesson, pluginDirectory); } + } public Plugin(Class lesson, Path pluginDirectory) { @@ -52,9 +81,9 @@ public class Plugin { try { Files.readAllLines(lesson_plans.resolve(this.lesson.getSimpleName() + ".html"), Charset.defaultCharset()); } catch (IOException e) { - e.printStackTrace(); + logger.error("No html found in directory {}", lesson_plans.toString()); } - return lesson_plans.resolve(this.lesson.getSimpleName() + ".html").toFile().toString(); + return ""; } public Class getLesson() { diff --git a/src/main/java/org/owasp/webgoat/plugins/PluginClassLoader.java b/src/main/java/org/owasp/webgoat/plugins/PluginClassLoader.java index 36bb92a4d..98b101b8b 100644 --- a/src/main/java/org/owasp/webgoat/plugins/PluginClassLoader.java +++ b/src/main/java/org/owasp/webgoat/plugins/PluginClassLoader.java @@ -13,10 +13,5 @@ public class PluginClassLoader extends ClassLoader { return defineClass(name, classFile, 0, classFile.length); } - public static void main(String[] args) { - - } - - } diff --git a/src/main/java/org/owasp/webgoat/plugins/PluginExtractor.java b/src/main/java/org/owasp/webgoat/plugins/PluginExtractor.java index daf69fd3e..abcf30350 100644 --- a/src/main/java/org/owasp/webgoat/plugins/PluginExtractor.java +++ b/src/main/java/org/owasp/webgoat/plugins/PluginExtractor.java @@ -13,60 +13,59 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.SimpleFileVisitor; -import java.nio.file.StandardCopyOption; import java.nio.file.attribute.BasicFileAttributes; -import java.util.ArrayList; import java.util.HashMap; -import java.util.List; +import java.util.Map; + +import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; /** - * Extract the zip file and place the files in a temp directory - * - * TODO: should only do the extraction of the zip file return should be the base directory of the extracted - * plugin. The PluginLoader should take care of the loading - * + * Extract the wpf file and collect the classes to load and remember the base directory in which we extracted + * the files (lesson plans etc) */ public class PluginExtractor { private static final String DIRECTORY = "webgoat"; private final Path pluginArchive; private final Logger logger = LoggerFactory.getLogger(getClass()); - private final List classes = new ArrayList(); + private final Map classes = new HashMap(); + private Path baseDirectory; public PluginExtractor(Path pluginArchive) { this.pluginArchive = pluginArchive; } - - public Plugin extract() { - final Plugin.Builder pluginBuilder = new Plugin.Builder(); + public void extract() { FileSystem zip = null; try { zip = createZipFileSystem(); final Path root = zip.getPath("/"); - final Path tmpDir = Paths.get(System.getProperty("java.io.tmpdir"), DIRECTORY); - pluginBuilder.setBaseDirectory(tmpDir); + baseDirectory = Paths.get(System.getProperty("java.io.tmpdir"), DIRECTORY); Files.walkFileTree(root, new SimpleFileVisitor() { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { if (file.toString().endsWith(".class")) { ByteArrayOutputStream bos = new ByteArrayOutputStream(); Files.copy(file, bos); - pluginBuilder.loadClass(file.toString(), bos.toByteArray()); + classes.put(file.toString(), bos.toByteArray()); } - - Files.copy(file, Paths.get(tmpDir.toString(), file.toString()), StandardCopyOption.REPLACE_EXISTING); + Files.copy(file, Paths.get(baseDirectory.toString(), file.toString()), REPLACE_EXISTING); return FileVisitResult.CONTINUE; } }); - return pluginBuilder.build(); } catch (IOException io) { logger.error(String.format("Unable to extract: %s", pluginArchive.getFileName()), io); } finally { closeZipFileSystem(zip); } + } - return pluginBuilder.build(); + public Map getClasses() { + return this.classes; + } + + public Path getBaseDirectory() { + return this.baseDirectory; } private FileSystem createZipFileSystem() throws IOException { diff --git a/src/main/java/org/owasp/webgoat/plugins/PluginsLoader.java b/src/main/java/org/owasp/webgoat/plugins/PluginsLoader.java index 7cb1b9904..3c80d4a8c 100644 --- a/src/main/java/org/owasp/webgoat/plugins/PluginsLoader.java +++ b/src/main/java/org/owasp/webgoat/plugins/PluginsLoader.java @@ -1,5 +1,8 @@ package org.owasp.webgoat.plugins; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.io.IOException; import java.nio.file.FileVisitResult; import java.nio.file.Files; @@ -11,6 +14,7 @@ import java.util.List; public class PluginsLoader { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); private final Path path; public PluginsLoader(Path path) { @@ -24,13 +28,22 @@ public class PluginsLoader { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { - plugins.add(new PluginExtractor(file).extract()); + try { + PluginExtractor extractor = new PluginExtractor(file); + extractor.extract(); + Plugin.Builder builder = new Plugin.Builder(); + builder.loadClasses(extractor.getClasses()); + builder.setBaseDirectory(extractor.getBaseDirectory()); + plugins.add(builder.build()); + } catch (Plugin.PluginLoadingFailure e) { + logger.error("Unable to load plugin, continue reading others..."); + } return FileVisitResult.CONTINUE; } }); } catch (IOException e) { - e.printStackTrace(); + logger.error("Loading plugins failed", e); } return plugins; }