diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/plugins/Plugin.java b/webgoat-container/src/main/java/org/owasp/webgoat/plugins/Plugin.java index 5c57e9139..7cd012d05 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/plugins/Plugin.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/plugins/Plugin.java @@ -2,12 +2,12 @@ package org.owasp.webgoat.plugins; import com.google.common.base.Optional; import com.google.common.collect.Lists; +import org.apache.catalina.loader.WebappClassLoader; import org.owasp.webgoat.lessons.AbstractLesson; import org.springframework.util.StringUtils; import java.io.File; import java.io.IOException; -import java.net.URLClassLoader; import java.nio.file.Path; import java.util.Arrays; import java.util.HashMap; @@ -43,10 +43,10 @@ public class Plugin { private void findLesson(String name) { String realClassName = StringUtils.trimLeadingCharacter(name, '/').replaceAll("/", ".").replaceAll(".class", ""); //TODO should be passed in (refactor) - URLClassLoader cl = (URLClassLoader) Thread.currentThread().getContextClassLoader(); + WebappClassLoader cl = (WebappClassLoader) Thread.currentThread().getContextClassLoader(); try { - Class clazz = cl.loadClass(realClassName); + Class clazz = cl.loadClass(realClassName, true); if (AbstractLesson.class.isAssignableFrom(clazz)) { this.lesson = clazz; diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginContextListener.java b/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginContextListener.java new file mode 100644 index 000000000..43e58d07f --- /dev/null +++ b/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginContextListener.java @@ -0,0 +1,36 @@ +package org.owasp.webgoat.plugins; + +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; +import javax.servlet.annotation.WebListener; +import java.nio.file.Paths; + +/** + * Created by nanne_000 on 9/29/2015. + */ +@WebListener +public class PluginContextListener implements ServletContextListener { + @Override + public void contextInitialized(ServletContextEvent event) { + String pluginPath = event.getServletContext().getRealPath("plugin_lessons"); + String targetPath = event.getServletContext().getRealPath("plugin_extracted"); + + if (event.getServletContext().getInitParameter("plugins_loaded") == null) { + new PluginsLoader(Paths.get(pluginPath), Paths.get(targetPath)).copyJars(); + } + event.getServletContext().setInitParameter("plugins_loaded", ""); + } + + @Override + public void contextDestroyed(ServletContextEvent event) { +// String targetPath = event.getServletContext().getRealPath("plugin_extracted"); +// WebappClassLoader cl = (WebappClassLoader)Thread.currentThread().getContextClassLoader(); +// cl.closeJARs(true); +// Path webInfLib = Paths.get(targetPath).getParent().resolve(cl.getJarPath().replaceFirst("\\/", "")); +// try { +// FileUtils.cleanDirectory(webInfLib.toFile()); +// } catch (IOException e) { +// e.printStackTrace(); +// } + } +} diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginsLoader.java b/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginsLoader.java index b725d9d9f..930ebbf30 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginsLoader.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginsLoader.java @@ -13,7 +13,9 @@ import java.net.URL; import java.nio.file.FileVisitResult; 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.List; import java.util.Objects; @@ -46,6 +48,25 @@ public class PluginsLoader implements Runnable { this.pluginTarget = Objects.requireNonNull(pluginTarget, "plugin target cannot be null"); } + public void copyJars() { + try { + WebappClassLoader cl = (WebappClassLoader) Thread.currentThread().getContextClassLoader(); + cl.setAntiJARLocking(true); + + List jars = listJars(); + + cl.closeJARs(true); + Path webInfLib = pluginTarget.getParent().resolve(cl.getJarPath().replaceFirst("\\/", "")); + for (URL jar : jars) { + Path sourceJarFile = Paths.get(jar.toURI()); + Files.copy(sourceJarFile, webInfLib.resolve(sourceJarFile.getFileName()), + StandardCopyOption.REPLACE_EXISTING); + } + } catch (Exception e) { + logger.error("Loading plugins failed", e); + } + } + /** *

loadPlugins.

* @@ -59,9 +80,6 @@ public class PluginsLoader implements Runnable { PluginFileUtils.createDirsIfNotExists(pluginTarget); cleanupExtractedPluginsDirectory(); List jars = listJars(); - for (URL url : jars) { - cl.addRepository(url.toString()); - } plugins = processPlugins(jars); } catch (Exception e) { @@ -71,13 +89,12 @@ public class PluginsLoader implements Runnable { } - private void cleanupExtractedPluginsDirectory() { Path i18nDirectory = pluginTarget.resolve("plugin/i18n/"); FileUtils.deleteQuietly(i18nDirectory.toFile()); } - private List listJars() throws IOException { + public List listJars() throws IOException { final List jars = Lists.newArrayList(); Files.walkFileTree(pluginSource, new SimpleFileVisitor() { @@ -127,7 +144,9 @@ public class PluginsLoader implements Runnable { return extractorCallables; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ @Override public void run() { loadPlugins(); diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/service/PluginReloadService.java b/webgoat-container/src/main/java/org/owasp/webgoat/service/PluginReloadService.java index 9415446cc..83ece5a64 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/service/PluginReloadService.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/service/PluginReloadService.java @@ -30,6 +30,7 @@ */ package org.owasp.webgoat.service; +import org.owasp.webgoat.plugins.PluginsLoader; import org.owasp.webgoat.session.WebSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -40,6 +41,7 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpSession; +import java.nio.file.Paths; /** *

PluginReloadService class.

@@ -61,6 +63,11 @@ public class PluginReloadService extends BaseService { public @ResponseBody ResponseEntity reloadPlugins(HttpSession session) { WebSession webSession = (WebSession) session.getAttribute(WebSession.SESSION); + logger.debug("Loading plugins into cache"); + String pluginPath = session.getServletContext().getRealPath("plugin_lessons"); + String targetPath = session.getServletContext().getRealPath("plugin_extracted"); + new PluginsLoader(Paths.get(pluginPath), Paths.get(targetPath)).copyJars(); + webSession.getCourse().loadLessonFromPlugin(session.getServletContext()); return new ResponseEntity("Plugins reload refresh the WebGoat page!",HttpStatus.OK); }