refactored so the extracting is not tangled with the loading the plugin
This commit is contained in:
parent
c39d673439
commit
34694b01c0
@ -1,21 +1,43 @@
|
|||||||
package org.owasp.webgoat.plugins;
|
package org.owasp.webgoat.plugins;
|
||||||
|
|
||||||
import org.owasp.webgoat.lessons.AbstractLesson;
|
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.io.IOException;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public class Plugin {
|
public class Plugin {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(Plugin.class);
|
||||||
private final Class<AbstractLesson> lesson;
|
private final Class<AbstractLesson> lesson;
|
||||||
private final Path pluginDirectory;
|
private final Path pluginDirectory;
|
||||||
|
|
||||||
|
public static class PluginLoadingFailure extends RuntimeException {
|
||||||
|
|
||||||
|
public PluginLoadingFailure(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
|
|
||||||
private Path pluginDirectory;
|
private Path pluginDirectory;
|
||||||
private Class lesson;
|
private Class lesson;
|
||||||
|
private final List<String> loadedClasses = new ArrayList<String>();
|
||||||
|
|
||||||
|
public Builder loadClasses(Map<String, byte[]> classes) {
|
||||||
|
for (Map.Entry<String, byte[]> clazz : classes.entrySet() ) {
|
||||||
|
loadClass(clazz.getKey(), clazz.getValue());
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public Builder loadClass(String name, byte[] classFile) {
|
public Builder loadClass(String name, byte[] classFile) {
|
||||||
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
|
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
|
||||||
@ -26,20 +48,27 @@ public class Plugin {
|
|||||||
if (AbstractLesson.class.isAssignableFrom(clazz)) {
|
if (AbstractLesson.class.isAssignableFrom(clazz)) {
|
||||||
this.lesson = clazz;
|
this.lesson = clazz;
|
||||||
}
|
}
|
||||||
|
loadedClasses.add(clazz.getName());
|
||||||
} catch (ClassNotFoundException e) {
|
} catch (ClassNotFoundException e) {
|
||||||
e.printStackTrace();
|
logger.error("Unable to load class {}", name);
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder setBaseDirectory(Path pluginDirectory) {
|
public Builder setBaseDirectory(Path pluginDirectory) {
|
||||||
this.pluginDirectory = pluginDirectory;
|
this.pluginDirectory = pluginDirectory;
|
||||||
|
//Find necessary files flag if something went wrong plugin should complain
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Plugin build() {
|
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);
|
return new Plugin(this.lesson, pluginDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Plugin(Class<AbstractLesson> lesson, Path pluginDirectory) {
|
public Plugin(Class<AbstractLesson> lesson, Path pluginDirectory) {
|
||||||
@ -52,9 +81,9 @@ public class Plugin {
|
|||||||
try {
|
try {
|
||||||
Files.readAllLines(lesson_plans.resolve(this.lesson.getSimpleName() + ".html"), Charset.defaultCharset());
|
Files.readAllLines(lesson_plans.resolve(this.lesson.getSimpleName() + ".html"), Charset.defaultCharset());
|
||||||
} catch (IOException e) {
|
} 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<AbstractLesson> getLesson() {
|
public Class<AbstractLesson> getLesson() {
|
||||||
|
@ -13,10 +13,5 @@ public class PluginClassLoader extends ClassLoader {
|
|||||||
return defineClass(name, classFile, 0, classFile.length);
|
return defineClass(name, classFile, 0, classFile.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,60 +13,59 @@ import java.nio.file.Files;
|
|||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.nio.file.SimpleFileVisitor;
|
import java.nio.file.SimpleFileVisitor;
|
||||||
import java.nio.file.StandardCopyOption;
|
|
||||||
import java.nio.file.attribute.BasicFileAttributes;
|
import java.nio.file.attribute.BasicFileAttributes;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
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
|
* Extract the wpf file and collect the classes to load and remember the base directory in which we extracted
|
||||||
*
|
* the files (lesson plans etc)
|
||||||
* 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
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class PluginExtractor {
|
public class PluginExtractor {
|
||||||
|
|
||||||
private static final String DIRECTORY = "webgoat";
|
private static final String DIRECTORY = "webgoat";
|
||||||
private final Path pluginArchive;
|
private final Path pluginArchive;
|
||||||
private final Logger logger = LoggerFactory.getLogger(getClass());
|
private final Logger logger = LoggerFactory.getLogger(getClass());
|
||||||
private final List<byte[]> classes = new ArrayList<byte[]>();
|
private final Map<String, byte[]> classes = new HashMap<String, byte[]>();
|
||||||
|
private Path baseDirectory;
|
||||||
|
|
||||||
public PluginExtractor(Path pluginArchive) {
|
public PluginExtractor(Path pluginArchive) {
|
||||||
this.pluginArchive = pluginArchive;
|
this.pluginArchive = pluginArchive;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void extract() {
|
||||||
public Plugin extract() {
|
|
||||||
final Plugin.Builder pluginBuilder = new Plugin.Builder();
|
|
||||||
FileSystem zip = null;
|
FileSystem zip = null;
|
||||||
try {
|
try {
|
||||||
zip = createZipFileSystem();
|
zip = createZipFileSystem();
|
||||||
final Path root = zip.getPath("/");
|
final Path root = zip.getPath("/");
|
||||||
final Path tmpDir = Paths.get(System.getProperty("java.io.tmpdir"), DIRECTORY);
|
baseDirectory = Paths.get(System.getProperty("java.io.tmpdir"), DIRECTORY);
|
||||||
pluginBuilder.setBaseDirectory(tmpDir);
|
|
||||||
Files.walkFileTree(root, new SimpleFileVisitor<Path>() {
|
Files.walkFileTree(root, new SimpleFileVisitor<Path>() {
|
||||||
@Override
|
@Override
|
||||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
||||||
if (file.toString().endsWith(".class")) {
|
if (file.toString().endsWith(".class")) {
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
Files.copy(file, bos);
|
Files.copy(file, bos);
|
||||||
pluginBuilder.loadClass(file.toString(), bos.toByteArray());
|
classes.put(file.toString(), bos.toByteArray());
|
||||||
}
|
}
|
||||||
|
Files.copy(file, Paths.get(baseDirectory.toString(), file.toString()), REPLACE_EXISTING);
|
||||||
Files.copy(file, Paths.get(tmpDir.toString(), file.toString()), StandardCopyOption.REPLACE_EXISTING);
|
|
||||||
return FileVisitResult.CONTINUE;
|
return FileVisitResult.CONTINUE;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return pluginBuilder.build();
|
|
||||||
} catch (IOException io) {
|
} catch (IOException io) {
|
||||||
logger.error(String.format("Unable to extract: %s", pluginArchive.getFileName()), io);
|
logger.error(String.format("Unable to extract: %s", pluginArchive.getFileName()), io);
|
||||||
} finally {
|
} finally {
|
||||||
closeZipFileSystem(zip);
|
closeZipFileSystem(zip);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return pluginBuilder.build();
|
public Map<String, byte[]> getClasses() {
|
||||||
|
return this.classes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Path getBaseDirectory() {
|
||||||
|
return this.baseDirectory;
|
||||||
}
|
}
|
||||||
|
|
||||||
private FileSystem createZipFileSystem() throws IOException {
|
private FileSystem createZipFileSystem() throws IOException {
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package org.owasp.webgoat.plugins;
|
package org.owasp.webgoat.plugins;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.FileVisitResult;
|
import java.nio.file.FileVisitResult;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
@ -11,6 +14,7 @@ import java.util.List;
|
|||||||
|
|
||||||
public class PluginsLoader {
|
public class PluginsLoader {
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||||
private final Path path;
|
private final Path path;
|
||||||
|
|
||||||
public PluginsLoader(Path path) {
|
public PluginsLoader(Path path) {
|
||||||
@ -24,13 +28,22 @@ public class PluginsLoader {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
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;
|
return FileVisitResult.CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
logger.error("Loading plugins failed", e);
|
||||||
}
|
}
|
||||||
return plugins;
|
return plugins;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user