Fixed server tests

Change-Id: I7b265323760ec2a0ee070ef4dee989fe43126b93
diff --git a/src/main/java/de/ids_mannheim/korap/KrillIndex.java b/src/main/java/de/ids_mannheim/korap/KrillIndex.java
index a425f36..cb604be 100644
--- a/src/main/java/de/ids_mannheim/korap/KrillIndex.java
+++ b/src/main/java/de/ids_mannheim/korap/KrillIndex.java
@@ -116,8 +116,8 @@
     // Last line of defense against DOS
     private int maxTermRelations = 100;
     private int autoCommit = 500;
-    private String version;
-    private String name;
+    private String version = "unknown";
+    private String name = "Krill";
 
     // Temp:
     private IndexReader reader;
diff --git a/src/main/java/de/ids_mannheim/korap/server/Node.java b/src/main/java/de/ids_mannheim/korap/server/Node.java
index 8b4de0f..b4d0068 100644
--- a/src/main/java/de/ids_mannheim/korap/server/Node.java
+++ b/src/main/java/de/ids_mannheim/korap/server/Node.java
@@ -10,6 +10,8 @@
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import java.util.logging.LogManager;
+import org.slf4j.bridge.SLF4JBridgeHandler;
 
 import java.net.URI;
 import java.beans.PropertyVetoException;
@@ -20,31 +22,37 @@
 import com.mchange.v2.c3p0.*;
 
 /**
- * Standalone REST-Service for the Lucene Search Backend.
+ * Standalone REST-Service for the Krill node.
+ * Reads a property file at <tt>krill.properties</tt>.
+ * Defaults to port <tt>9876</tt> if no information is given,
+ * and an unprotected in-memory SQLite database for collections.
  * 
  * @author diewald
  */
 public class Node {
 
     // Base URI the Grizzly HTTP server will listen on
-    public static String BASE_URI = "http://localhost:8080/";
+    public static String BASE_URI = "http://localhost:9876/";
+    private static String propFile = "krill.properties";
+
 
     // Logger
     private final static Logger log = LoggerFactory.getLogger(Node.class);
 
     // Index
     private static KrillIndex index;
+
+    // Database
     private static ComboPooledDataSource cpds;
-    private static String path, name = "unknown";
-
+    private static String path = null;
+    private static String name = "unknown";
     private static String dbUser, dbPwd;
-
-    private static String dbClass = "org.sqlite.JDBC", dbURL = "jdbc:sqlite:";
+    private static String dbClass = "org.sqlite.JDBC";
+    private static String dbURL = "jdbc:sqlite:";
 
 
     /*
-     * Todo: Add shutdown hook,
-     * Then also close cdps.close();
+     * Todo: Close cdps.close() on shutdown.
      * see: https://10.0.10.12/trac/korap/browser/KorAP-modules/KorAP-REST/src/main/java/de/ids_mannheim/korap/web/Application.java
      * https://10.0.10.12/trac/korap/browser/KorAP-modules/KorAP-REST/src/main/java/de/ids_mannheim/korap/web/ShutdownHook.java
      */
@@ -52,52 +60,38 @@
     /**
      * Starts Grizzly HTTP server exposing JAX-RS
      * resources defined in this application.
+     * This will load a <tt>krill.properties</tt> property file.
      * 
      * @return Grizzly HTTP server.
      */
     public static HttpServer startServer () {
-
-        // Load configuration
-        URL resUrl = Node.class.getClassLoader().getResource("krill.properties");
-        if (resUrl == null) {
-            log.error("Cannot find \"krill.properties\". Please create it "
-                      +"using \"krill.properties.info\" as template. Terminating.");
-            System.exit(1);
-        }
-        try {
-            InputStream file = new FileInputStream(resUrl.getFile());
-            Properties prop = new Properties();
-            prop.load(file);
-
-            // Node properties
-            path = prop.getProperty("krill.indexDir", path);
-            name = prop.getProperty("krill.server.name", name);
-            BASE_URI = prop.getProperty("krill.server.baseURI", BASE_URI);
-
-            // Database properties
-            dbUser = prop.getProperty("krill.db.user", dbUser);
-            dbPwd = prop.getProperty("krill.db.pwd", dbPwd);
-            dbClass = prop.getProperty("krill.db.class", dbClass);
-            dbURL = prop.getProperty("krill.db.jdbcURL", dbURL);
-
-        }
-        catch (IOException e) {
-            log.error(e.getLocalizedMessage());
-        };
+        _loadResourceProperties();
 
         // create a resource config that scans for JAX-RS resources and providers
         // in de.ids_mannheim.korap.server package
         final ResourceConfig rc = new ResourceConfig()
-                .packages("de.ids_mannheim.korap.server");
+            .packages("de.ids_mannheim.korap.server");
 
         // create and start a new instance of grizzly http server
         // exposing the Jersey application at BASE_URI
-        return GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI),
-                rc);
+        return GrizzlyHttpServerFactory.createHttpServer(
+            URI.create(BASE_URI), rc
+        );
     };
 
-
+    /**
+     * Starts Grizzly HTTP server exposing JAX-RS
+     * resources defined in this application.
+     * Mainly used for testing.
+     * 
+     * @param nodeName The name of the node.
+     * @param indexPath The path of the Lucene index.
+     *
+     * @return Grizzly {@link HttpServer} server.
+     */
     public static HttpServer startServer (String nodeName, String indexPath) {
+        LogManager.getLogManager().reset();
+        SLF4JBridgeHandler.install();
 
         // create a resource config that scans for JAX-RS resources and providers
         // in de.ids_mannheim.korap.server package
@@ -115,25 +109,32 @@
 
 
     /**
-     * Main method.
+     * Runner method for Krill node.
      * 
-     * @param args
+     * @param args No special arguments required.
      * @throws IOException
      */
     public static void main (String[] args) throws IOException {
-        // WADL available at BASE_URI + application.wadl
 
+        // WADL available at BASE_URI + application.wadl
+        // Start the server with krill properties or given defaults
         final HttpServer server = startServer();
 
         // Establish shutdown hook
-        Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
-            @Override
-            public void run () {
-                log.info("Stop Server");
-                // staaahp!
-                server.stop();
-            }
-        }, "shutdownHook"));
+        Runtime.getRuntime().addShutdownHook(
+            new Thread(
+                new Runnable() {
+
+                    @Override
+                    public void run () {
+                        log.info("Stop Server");
+                        server.stop();
+                        if (cpds != null)
+                            cpds.close();
+                    };
+
+                }, "shutdownHook")
+        );
 
         // Start server
         try {
@@ -147,25 +148,49 @@
     };
 
 
-    // What's the servers name?
+    /**
+     * Get the name of the node.
+     * The name is unique in the cluster and should be persistent.
+     *
+     * @return The unique name of the node.
+     */
     public static String getName () {
         return name;
     };
 
 
-    // What is the server listening on?
+    /**
+     * Get the URI (incl. port) the node is listening on.
+     *
+     * @return The URI the node is listening on. 
+     */
     public static String getListener () {
         return BASE_URI;
     };
 
 
-    // Get database pool
+    /**
+     * Shut down the database pool.
+     */
+    public static void closeDBPool () {
+        if (cpds != null)
+            cpds.close();
+    };
+
+
+    /**
+     * Get the associated database pool
+     * for match collection.
+     *
+     * @return The CPDS {@link ComboPooledDataSource} object.
+     */
     public static ComboPooledDataSource getDBPool () {
 
         // Pool already initiated
         if (cpds != null)
             return cpds;
 
+        // Initiate pool
         try {
 
             // Parameters are defined in the property file
@@ -186,7 +211,11 @@
     };
 
 
-    // Get Lucene Index
+    /**
+     * Get the associuated {@link KrillIndex}.
+     *
+     * @return The associated {@link KrillIndex}.
+     */
     public static KrillIndex getIndex () {
 
         // Index already instantiated
@@ -196,10 +225,13 @@
         try {
 
             // Get a temporary index
-            if (path == null)
+            if (path == null) {
+
                 // Temporary index
                 index = new KrillIndex();
+            }
 
+            // Get a MMap directory index
             else {
                 File file = new File(path);
 
@@ -219,4 +251,45 @@
         };
         return null;
     };
+
+
+    // Load properties from file
+    private static Properties _loadProperties (String propFile) {
+        try {
+            InputStream file = new FileInputStream(propFile);
+            Properties prop = new Properties();
+            prop.load(file);
+
+            // Node properties
+            path = prop.getProperty("krill.indexDir", path);
+            name = prop.getProperty("krill.server.name", name);
+            BASE_URI = prop.getProperty("krill.server.baseURI", BASE_URI);
+
+            // Database properties
+            dbUser = prop.getProperty("krill.db.user", dbUser);
+            dbPwd = prop.getProperty("krill.db.pwd", dbPwd);
+            dbClass = prop.getProperty("krill.db.class", dbClass);
+            dbURL = prop.getProperty("krill.db.jdbcURL", dbURL);
+            return prop;
+        }
+        catch (IOException e) {
+            log.error(e.getLocalizedMessage());
+        };
+        return null;
+    };
+
+
+    // Load properties from resource file
+    private static Properties _loadResourceProperties () {
+
+        // Load configuration
+        URL resUrl = Node.class.getClassLoader().getResource(propFile);
+        if (resUrl == null) {
+            log.error("Cannot find {}. Please create it using \"{}.info\" as template.",
+                      propFile, propFile);
+            return null;
+        };
+
+        return _loadProperties(resUrl.getFile());
+    };
 };
diff --git a/src/main/java/de/ids_mannheim/korap/server/Resource.java b/src/main/java/de/ids_mannheim/korap/server/Resource.java
index 4b4fa31..be13ee7 100644
--- a/src/main/java/de/ids_mannheim/korap/server/Resource.java
+++ b/src/main/java/de/ids_mannheim/korap/server/Resource.java
@@ -20,16 +20,16 @@
 import javax.ws.rs.WebApplicationException;
 
 import de.ids_mannheim.korap.server.Node;
-import de.ids_mannheim.korap.KrillIndex;
 import de.ids_mannheim.korap.Krill;
+import de.ids_mannheim.korap.KrillIndex;
 import de.ids_mannheim.korap.KrillCollection;
 import de.ids_mannheim.korap.response.Result;
 import de.ids_mannheim.korap.response.Match;
 import de.ids_mannheim.korap.response.Response;
-import de.ids_mannheim.korap.index.FieldDocument;
-import de.ids_mannheim.korap.util.QueryException;
 import de.ids_mannheim.korap.response.MatchCollector;
 import de.ids_mannheim.korap.response.collector.MatchCollectorDB;
+import de.ids_mannheim.korap.util.QueryException;
+import de.ids_mannheim.korap.index.FieldDocument;
 
 import java.util.List;
 import java.util.regex.Pattern;
@@ -45,16 +45,14 @@
 
 
 /**
- * Root resource (exposed at root path)
+ * Root resource (exposed at root path) of the Krill node.
  * The responses only represent JSON responses, although HTML
- * responses
- * may be handy.
+ * responses may be handy.
  * 
- * @author Nils Diewald
- * 
- *         Look at
- *         http://www.mkyong.com/webservices/jax-rs/json-example
- *         -with-jersey-jackson/
+ * @author diewald
+ */
+/* Look at
+ * http://www.mkyong.com/webservices/jax-rs/json-example-with-jersey-jackson/
  */
 @Path("/")
 public class Resource {
@@ -69,20 +67,8 @@
 
     // Slightly based on String::BooleanSimple
     static Pattern p = Pattern
-            .compile("\\s*(?i:false|no|inactive|disabled|off|n|neg(?:ative)?|not|null|undef)\\s*");
-
-
-    // Check if a string is meant to represent null
-    private static boolean isNull (String value) {
-        if (value == null)
-            return true;
-
-        Matcher m = p.matcher(value);
-        if (m.matches())
-            return true;
-
-        return false;
-    };
+        .compile("\\s*(?i:false|no|inactive|disabled|" +
+                 "off|n|neg(?:ative)?|not|null|undef)\\s*");
 
 
     /**
@@ -91,19 +77,19 @@
     @GET
     @Produces(MediaType.APPLICATION_JSON)
     public String info () {
-        KrillIndex index = Node.getIndex();
         Response kresp = new Response();
         kresp.setNode(Node.getName());
+        kresp.setListener(Node.getListener());
+
+        // Get index
+        KrillIndex index = Node.getIndex();
         kresp.setName(index.getName());
         kresp.setVersion(index.getVersion());
-
-        kresp.setListener(Node.getListener());
-        long texts = -1;
         /*
-          kresp.addMessage(
+        kresp.addMessage(
           "Number of documents in the index",
           String.parseLong(index.numberOf("documents"))
-          );
+        );
         */
         kresp.addMessage(680, "Server is up and running!");
         return kresp.toJsonString();
@@ -134,7 +120,6 @@
          */
 
         // Todo: Parameter for server node
-
         if (DEBUG)
             log.trace("Added new document with unique identifier {}", uid);
 
@@ -197,6 +182,7 @@
         // There are documents to commit
         try {
             index.commit();
+            kresp.addMessage(683, "Staged data committed");
         }
         catch (IOException e) {
             // Set HTTP to ???
@@ -373,22 +359,22 @@
             boolean includeSpans = false, includeHighlights = true, extendToSentence = false, info = false;
 
             // Optional query parameter "info" for more information on the match
-            if (!isNull(qp.getFirst("info")))
+            if (!_isNull(qp.getFirst("info")))
                 info = true;
 
             // Optional query parameter "spans" for span information inclusion
-            if (!isNull(qp.getFirst("spans"))) {
+            if (!_isNull(qp.getFirst("spans"))) {
                 includeSpans = true;
                 info = true;
             };
 
             // Optional query parameter "highlights" for highlight information inclusion
             String highlights = qp.getFirst("highlights");
-            if (highlights != null && isNull(highlights))
+            if (highlights != null && _isNull(highlights))
                 includeHighlights = false;
 
             // Optional query parameter "extended" for sentence expansion
-            if (!isNull(qp.getFirst("extended")))
+            if (!_isNull(qp.getFirst("extended")))
                 extendToSentence = true;
 
             List<String> foundries = qp.get("foundry");
@@ -468,4 +454,17 @@
             context.proceed();
         };
     };
+
+
+    // Check if a string is meant to represent null
+    private static boolean _isNull (String value) {
+        if (value == null)
+            return true;
+
+        Matcher m = p.matcher(value);
+        if (m.matches())
+            return true;
+        
+        return false;
+    };
 };
diff --git a/src/main/resources/log4j.properties b/src/main/resources/log4j.properties
index 9bd7ad2..5fed33b 100644
--- a/src/main/resources/log4j.properties
+++ b/src/main/resources/log4j.properties
@@ -1,4 +1,4 @@
-# log4j.rootLogger = ERROR, stdout
+log4j.rootLogger = ERROR, stdout
 
 # Queries:
 # log4j.logger.de.ids_mannheim.korap.query.SpanNextQuery = TRACE, stdout
@@ -35,8 +35,11 @@
 # Tests:
 # log4j.logger.de.ids_mannheim.korap.index.TestSegmentIndex = TRACE, stdout
 
-log4j.appender.stdout=org.apache.log4j.ConsoleAppender
-log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+# Server
+# log4j.category.org.glassfish.jersey = TRACE, stdout
+
+log4j.appender.stdout = org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
 log4j.appender.stdout.layout.ConversionPattern = %5p (%F:%L) -> %m%n
 
 # log4j.appender.stdout.Target=System.out