From 010404d2e14a487e367768f1b65b8029b6986b09 Mon Sep 17 00:00:00 2001
From: Nanne Baars <nbaars@xebia.com>
Date: Fri, 28 Aug 2015 06:40:27 +0200
Subject: [PATCH] Increase performance while extracting the plugins

---
 .gitignore                                    |  4 +-
 .../owasp/webgoat/plugins/PluginsLoader.java  | 41 +++++++++++++++----
 2 files changed, 36 insertions(+), 9 deletions(-)

diff --git a/.gitignore b/.gitignore
index ca73a7e10..c785967b3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -32,4 +32,6 @@ classes/*
 
 /*.iml
 .extract/*
-UserDatabase.mv.db
\ No newline at end of file
+UserDatabase.mv.db
+webgoat-container/src/main/webapp/users/guest.org.owasp.webgoat.plugin.*.props
+webgoat-container/src/main/webapp/plugin_lessons/dist-*.pom
\ No newline at end of file
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 cdea39ee2..1a02be5fd 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
@@ -8,7 +8,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.io.IOException;
-import java.net.URISyntaxException;
 import java.net.URL;
 import java.nio.file.FileVisitResult;
 import java.nio.file.Files;
@@ -17,6 +16,11 @@ import java.nio.file.Paths;
 import java.nio.file.SimpleFileVisitor;
 import java.nio.file.attribute.BasicFileAttributes;
 import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CompletionService;
+import java.util.concurrent.ExecutorCompletionService;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
 
 public class PluginsLoader implements Runnable {
 
@@ -35,7 +39,7 @@ public class PluginsLoader implements Runnable {
     }
 
     public List<Plugin> loadPlugins(final boolean reload) {
-        final PluginClassLoader cl = (PluginClassLoader)Thread.currentThread().getContextClassLoader();
+        final PluginClassLoader cl = (PluginClassLoader) Thread.currentThread().getContextClassLoader();
         List<Plugin> plugins = Lists.newArrayList();
 
         try {
@@ -43,7 +47,7 @@ public class PluginsLoader implements Runnable {
             List<URL> jars = listJars();
             cl.addURL(jars);
             plugins = processPlugins(jars, reload);
-        } catch (IOException | URISyntaxException e) {
+        } catch (Exception e) {
             logger.error("Loading plugins failed", e);
         }
         return plugins;
@@ -64,13 +68,18 @@ public class PluginsLoader implements Runnable {
         return jars;
     }
 
-    private List<Plugin> processPlugins(List<URL> jars, boolean reload) throws URISyntaxException, IOException {
+    private List<Plugin> processPlugins(List<URL> jars, boolean reload) throws Exception {
         final List<Plugin> plugins = Lists.newArrayList();
-        for (URL jar : jars) {
-
-            PluginExtractor extractor = new PluginExtractor(Paths.get(jar.toURI()));
-            extractor.extract(pluginTarget);
+        final ExecutorService executorService = Executors.newFixedThreadPool(20);
+        final CompletionService<PluginExtractor> completionService = new ExecutorCompletionService<>(executorService);
+        final List<Callable<PluginExtractor>> callables = extractJars(jars);
 
+        for (Callable<PluginExtractor> s : callables) {
+            completionService.submit(s);
+        }
+        int n = callables.size();
+        for (int i = 0; i < n; i++) {
+            PluginExtractor extractor = completionService.take().get();
             Plugin plugin = new Plugin(pluginTarget, extractor.getClasses());
             if (plugin.getLesson().isPresent()) {
                 PluginFileUtils.createDirsIfNotExists(pluginTarget);
@@ -83,6 +92,22 @@ public class PluginsLoader implements Runnable {
         return plugins;
     }
 
+    private List<Callable<PluginExtractor>> extractJars(List<URL> jars) {
+        List<Callable<PluginExtractor>> extractorCallables = Lists.newArrayList();
+        for (final URL jar : jars) {
+            extractorCallables.add(new Callable<PluginExtractor>() {
+
+                @Override
+                public PluginExtractor call() throws Exception {
+                    PluginExtractor extractor = new PluginExtractor(Paths.get(jar.toURI()));
+                    extractor.extract(pluginTarget);
+                    return extractor;
+                }
+            });
+        }
+        return extractorCallables;
+    }
+
     @Override
     public void run() {
         loadPlugins(true);