Added Shutdown handler to Jetty server and fixed NamedVCLoader.

Change-Id: I18fe51031103deb966843cc248e154011efb8abe
diff --git a/full/Changes b/full/Changes
index 5d23f15..c742c97 100644
--- a/full/Changes
+++ b/full/Changes
@@ -14,7 +14,10 @@
     - Added "fields" parameter to search controllers (margaretha)
     - Integrated lite controllers, services and tests in full version (margaretha)
 29/10/2018
-    - Moved javax.servlet-api to core
+    - Moved javax.servlet-api to core (margaretha)
+13/11/2018
+    - Added Shutdown handler to Jetty server (margaretha)
+    - Fixed storing VC order in NamedVCLoader (margaretha)  
 
 # version 0.61.2
 12/09/2018
diff --git a/full/src/main/java/de/ids_mannheim/korap/config/FullConfiguration.java b/full/src/main/java/de/ids_mannheim/korap/config/FullConfiguration.java
index ba5a5a4..0b46164 100644
--- a/full/src/main/java/de/ids_mannheim/korap/config/FullConfiguration.java
+++ b/full/src/main/java/de/ids_mannheim/korap/config/FullConfiguration.java
@@ -63,8 +63,6 @@
     private boolean isSoftDeleteGroupMember;
 
     private EncryptionIface.Encryption secureHashAlgorithm;
-    private String secureRandomAlgorithm;
-    private String messageDigestAlgorithm;
 
     private AuthenticationMethod OAuth2passwordAuthentication;
     private String nativeClientHost;
@@ -83,7 +81,7 @@
     private RSAPrivateKey rsaPrivateKey;
     private JWKSet publicKeySet;
     private String rsaKeyId;
-    
+
     private String namedVCPath;
 
     public FullConfiguration (Properties properties) throws Exception {
@@ -107,9 +105,8 @@
         setOAuth2Configuration(properties);
         setOpenIdConfiguration(properties);
         setRSAKeys(properties);
-        
-        setNamedVCPath(properties
-                .getProperty("krill.namedVC", ""));
+
+        setNamedVCPath(properties.getProperty("krill.namedVC", ""));
     }
 
     private void setSecurityConfiguration (Properties properties) {
@@ -117,11 +114,6 @@
                 properties.getProperty("security.secure.hash.algorithm",
                         "BCRYPT")));
 
-        setSecureRandomAlgorithm(properties
-                .getProperty("security.secure.random.algorithm", "SHA1PRNG"));
-
-        setMessageDigestAlgorithm(
-                properties.getProperty("security.md.algorithm", "MD5"));
     }
 
     private void setOpenIdConfiguration (Properties properties)
@@ -321,7 +313,6 @@
         return list;
     }
 
-
     private Pattern compilePattern (String patternStr) {
         if (!patternStr.isEmpty()) {
             return Pattern.compile(patternStr);
@@ -634,22 +625,6 @@
         this.authorizationCodeExpiry = authorizationCodeExpiry;
     }
 
-    public String getSecureRandomAlgorithm () {
-        return secureRandomAlgorithm;
-    }
-
-    public void setSecureRandomAlgorithm (String secureRandomAlgorithm) {
-        this.secureRandomAlgorithm = secureRandomAlgorithm;
-    }
-
-    public String getMessageDigestAlgorithm () {
-        return messageDigestAlgorithm;
-    }
-
-    public void setMessageDigestAlgorithm (String messageDigestAlgorithm) {
-        this.messageDigestAlgorithm = messageDigestAlgorithm;
-    }
-
     public String getNamedVCPath () {
         return namedVCPath;
     }
diff --git a/full/src/main/java/de/ids_mannheim/korap/config/NamedVCLoader.java b/full/src/main/java/de/ids_mannheim/korap/config/NamedVCLoader.java
index 1e4c4c4..38f0fc9 100644
--- a/full/src/main/java/de/ids_mannheim/korap/config/NamedVCLoader.java
+++ b/full/src/main/java/de/ids_mannheim/korap/config/NamedVCLoader.java
@@ -61,7 +61,9 @@
             }
 
             String filename = file.getName();
-            String json = readFile(file, filename);
+            String[] strArr = readFile(file, filename);
+            filename = strArr[0];
+            String json = strArr[1];
             if (json != null) {
                 cacheVC(json, filename);
                 vcService.storeVC(filename, VirtualCorpusType.SYSTEM, json, null,
@@ -70,7 +72,7 @@
         }
     }
 
-    private String readFile (File file, String filename) throws IOException {
+    private String[] readFile (File file, String filename) throws IOException, KustvaktException {
         String json = null;
         long start = System.currentTimeMillis();
         if (filename.endsWith(".jsonld")) {
@@ -92,17 +94,22 @@
         }
         long end = System.currentTimeMillis();
         jlog.debug("READ " + filename + " duration: " + (end - start));
-        return json;
+        
+        return new String[]{filename, json};
     }
 
     private void cacheVC (String json, String filename)
             throws IOException, QueryException {
+        jlog.info("Create KrillCollection: "+filename);
         long start, end;
         start = System.currentTimeMillis();
 
         KrillCollection collection = new KrillCollection(json);
+        jlog.debug("Finished creating KrillCollection");
+        jlog.debug("Set Index to collection");
         collection.setIndex(searchKrill.getIndex());
-
+                
+        jlog.debug("StoreInCache "+filename);
         if (collection != null) {
             collection.storeInCache(filename);
         }
diff --git a/full/src/main/java/de/ids_mannheim/korap/encryption/RandomCodeGenerator.java b/full/src/main/java/de/ids_mannheim/korap/encryption/RandomCodeGenerator.java
index 2b85f94..ea451aa 100644
--- a/full/src/main/java/de/ids_mannheim/korap/encryption/RandomCodeGenerator.java
+++ b/full/src/main/java/de/ids_mannheim/korap/encryption/RandomCodeGenerator.java
@@ -1,7 +1,5 @@
 package de.ids_mannheim.korap.encryption;
 
-import java.io.UnsupportedEncodingException;
-import java.net.URLEncoder;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.security.SecureRandom;
@@ -14,7 +12,7 @@
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
-import de.ids_mannheim.korap.config.FullConfiguration;
+import de.ids_mannheim.korap.config.KustvaktConfiguration;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.exceptions.StatusCodes;
 
@@ -29,7 +27,7 @@
 public class RandomCodeGenerator {
 
     @Autowired
-    private FullConfiguration config;
+    public KustvaktConfiguration config;
 
     public static SecureRandom secureRandom;
 
@@ -39,6 +37,13 @@
                 SecureRandom.getInstance(config.getSecureRandomAlgorithm());
     }
 
+    public String createRandomCode (KustvaktConfiguration c)
+            throws KustvaktException, NoSuchAlgorithmException {
+        config = c;
+        init();
+        return createRandomCode();
+    }
+
     public String createRandomCode () throws KustvaktException {
         UUID randomUUID = UUID.randomUUID();
         byte[] uuidBytes = randomUUID.toString().getBytes();
diff --git a/full/src/main/java/de/ids_mannheim/korap/server/KustvaktBaseServer.java b/full/src/main/java/de/ids_mannheim/korap/server/KustvaktBaseServer.java
new file mode 100644
index 0000000..2af1912
--- /dev/null
+++ b/full/src/main/java/de/ids_mannheim/korap/server/KustvaktBaseServer.java
@@ -0,0 +1,139 @@
+package de.ids_mannheim.korap.server;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.nio.charset.StandardCharsets;
+import java.security.NoSuchAlgorithmException;
+
+import javax.servlet.ServletContextListener;
+
+import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.server.handler.HandlerList;
+import org.eclipse.jetty.server.handler.ShutdownHandler;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.springframework.web.context.ContextLoaderListener;
+
+import com.sun.jersey.spi.spring.container.servlet.SpringServlet;
+
+import de.ids_mannheim.korap.config.KustvaktConfiguration;
+import de.ids_mannheim.korap.encryption.RandomCodeGenerator;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @author hanl
+ * @date 01/06/2015
+ */
+public abstract class KustvaktBaseServer {
+
+    protected static KustvaktConfiguration config;
+
+    protected static String rootPackages;
+    protected static KustvaktArgs kargs;
+
+    public KustvaktBaseServer () {}
+
+    protected KustvaktArgs readAttributes (String[] args) {
+        KustvaktArgs kargs = new KustvaktArgs();
+        for (int i = 0; i < args.length; i++) {
+            switch ((args[i])) {
+                case "--spring-config":
+                    kargs.setSpringConfig(args[i + 1]);
+                    break;
+                case "--port":
+                    kargs.setPort(Integer.valueOf(args[i + 1]));
+                    break;
+                case "--help":
+                    StringBuffer b = new StringBuffer();
+
+                    b.append("Parameter description: \n")
+                            .append("--spring-config  <Spring XML configuration filename in classpath>\n")
+                            .append("--port  <Server port number>\n")
+                            .append("--help : This help menu\n");
+                    System.out.println(b.toString());
+                    System.out.println();
+                    return (KustvaktArgs) null;
+            }
+        }
+        return kargs;
+    }
+
+    protected void start ()
+            throws KustvaktException, IOException, NoSuchAlgorithmException {
+
+        if (kargs.port == -1) {
+            kargs.setPort(config.getPort());
+        }
+
+        Server server = new Server();
+
+        ServletContextHandler contextHandler =
+                new ServletContextHandler(ServletContextHandler.NO_SESSIONS);
+        contextHandler.setContextPath("/");
+        contextHandler.setInitParameter("contextConfigLocation",
+                "classpath:" + kargs.getSpringConfig());
+
+        ServletContextListener listener = new ContextLoaderListener();
+        contextHandler.addEventListener(listener);
+
+        ServletHolder servletHolder = new ServletHolder(new SpringServlet());
+        servletHolder.setInitParameter(
+                "com.sun.jersey.config.property.packages", rootPackages);
+        servletHolder.setInitParameter(
+                "com.sun.jersey.api.json.POJOMappingFeature", "true");
+        servletHolder.setInitOrder(1);
+        contextHandler.addServlet(servletHolder, config.getBaseURL());
+
+        ServerConnector connector = new ServerConnector(server);
+        connector.setPort(kargs.port);
+        connector.setIdleTimeout(60000);
+
+        RandomCodeGenerator random = new RandomCodeGenerator();
+        String shutdownToken = random.createRandomCode(config);
+        ShutdownHandler shutdownHandler = new ShutdownHandler(shutdownToken,true,true);
+
+        FileOutputStream fos = new FileOutputStream(new File("shutdownToken"));
+        OutputStreamWriter writer =
+                new OutputStreamWriter(fos, StandardCharsets.UTF_8.name());
+        writer.write(shutdownToken);
+        writer.flush();
+        writer.close();
+
+        HandlerList handlers = new HandlerList();
+        handlers.addHandler(shutdownHandler);
+        handlers.addHandler(contextHandler);
+
+        server.setHandler(handlers);
+
+        server.setConnectors(new Connector[] { connector });
+        try {
+            server.start();
+            server.join();
+        }
+        catch (Exception e) {
+            System.out.println("Server could not be started!");
+            System.out.println(e.getMessage());
+            e.printStackTrace();
+            System.exit(-1);
+        }
+    }
+
+    @Setter
+    public static class KustvaktArgs {
+
+        @Getter
+        private String springConfig;
+        private int port;
+
+        public KustvaktArgs () {
+            this.port = -1;
+            this.springConfig = null;
+        }
+    }
+}
diff --git a/full/src/main/java/de/ids_mannheim/korap/server/KustvaktLiteServer.java b/full/src/main/java/de/ids_mannheim/korap/server/KustvaktLiteServer.java
index 448d4f6..b2510ec 100644
--- a/full/src/main/java/de/ids_mannheim/korap/server/KustvaktLiteServer.java
+++ b/full/src/main/java/de/ids_mannheim/korap/server/KustvaktLiteServer.java
@@ -6,7 +6,6 @@
 import java.util.Properties;
 
 import de.ids_mannheim.korap.config.KustvaktConfiguration;
-import de.ids_mannheim.korap.web.KustvaktBaseServer;
 
 public class KustvaktLiteServer extends KustvaktBaseServer {
 
diff --git a/full/src/main/java/de/ids_mannheim/korap/server/KustvaktServer.java b/full/src/main/java/de/ids_mannheim/korap/server/KustvaktServer.java
index 5e97ea1..9b2f8ee 100644
--- a/full/src/main/java/de/ids_mannheim/korap/server/KustvaktServer.java
+++ b/full/src/main/java/de/ids_mannheim/korap/server/KustvaktServer.java
@@ -6,7 +6,6 @@
 import java.util.Properties;
 
 import de.ids_mannheim.korap.config.FullConfiguration;
-import de.ids_mannheim.korap.web.KustvaktBaseServer;
 
 /**
  * pu
diff --git a/full/src/main/java/de/ids_mannheim/korap/service/VirtualCorpusService.java b/full/src/main/java/de/ids_mannheim/korap/service/VirtualCorpusService.java
index 5d2ce4b..a9a1fb4 100644
--- a/full/src/main/java/de/ids_mannheim/korap/service/VirtualCorpusService.java
+++ b/full/src/main/java/de/ids_mannheim/korap/service/VirtualCorpusService.java
@@ -258,7 +258,7 @@
         }
 
         CorpusAccess requiredAccess = determineRequiredAccess(koralQuery);
-
+        jlog.debug("Storing VC");
         int vcId = 0;
         try {
             vcId = vcDao.createVirtualCorpus(name, type, requiredAccess,
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/JettyServerTest.java b/full/src/test/java/de/ids_mannheim/korap/web/JettyServerTest.java
new file mode 100644
index 0000000..e2127ea
--- /dev/null
+++ b/full/src/test/java/de/ids_mannheim/korap/web/JettyServerTest.java
@@ -0,0 +1,36 @@
+package de.ids_mannheim.korap.web;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+import org.eclipse.jetty.server.Handler;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.handler.HandlerList;
+import org.eclipse.jetty.server.handler.ShutdownHandler;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class JettyServerTest {
+
+    @BeforeClass
+    public static void testServerStarts () throws Exception {
+        Server server = new Server(8000);
+        HandlerList handlers = new HandlerList();
+        handlers.setHandlers(
+                new Handler[] { new ShutdownHandler("secret", true, true) });
+        server.setHandler(handlers);
+        server.start();
+    }
+    
+    @Test
+    public void testShutdown () throws IOException {
+        URL url = new URL(
+                "http://localhost:8000/shutdown?token=secret");
+        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+        connection.setRequestMethod("POST");
+        assertEquals(200, connection.getResponseCode());
+    }
+}
diff --git a/full/src/test/resources/test-jdbc.properties b/full/src/test/resources/test-jdbc.properties
index db40081..bbf5f6b 100644
--- a/full/src/test/resources/test-jdbc.properties
+++ b/full/src/test/resources/test-jdbc.properties
@@ -8,4 +8,4 @@
 jdbc.username=pc
 jdbc.password=pc
 #jdbc.schemaPath=classpath:db.sqlite
-jdbc.schemaPath=classpath:db.new-sqlite, db.insert, db.predefined
\ No newline at end of file
+jdbc.schemaPath=classpath:db.sqlite, db.insert, db.predefined
\ No newline at end of file