LdapAuth3: factor out configuration class

including the renaming of some configuration properties

Change-Id: I0268c88a0bb7a3255debf045beab3faa71e9dce2
diff --git a/full/src/main/java/de/ids_mannheim/korap/authentication/LDAPConfig.java b/full/src/main/java/de/ids_mannheim/korap/authentication/LDAPConfig.java
new file mode 100644
index 0000000..7608761
--- /dev/null
+++ b/full/src/main/java/de/ids_mannheim/korap/authentication/LDAPConfig.java
@@ -0,0 +1,88 @@
+package de.ids_mannheim.korap.authentication;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+public class LDAPConfig {
+    public final boolean useSSL;
+    public final String host;
+    public final int port;
+    public final String searchBase;
+    public final String sLoginDN;
+    public final String searchFilter;
+    public final String sPwd;
+    public final String trustStorePath;
+    public final String additionalCipherSuites;
+    public final boolean useEmbeddedServer;
+    public final String emailAttribute;
+    public final String ldif;
+
+    public LDAPConfig(String ldapConfigFilename) throws LdapConfigurationException {
+        Map<String, String> ldapConfig = null;
+        try {
+            ldapConfig = loadProp(ldapConfigFilename);
+        } catch (IOException e) {
+            System.out.println("Error: LDAPAuth.login: cannot load Property file!");
+        }
+
+        useSSL = Boolean.parseBoolean(ldapConfig.getOrDefault("useSSL", "false"));
+        host = ldapConfig.getOrDefault("host", "localhost");
+        port = Integer.parseInt(ldapConfig.getOrDefault("port", (useSSL ? "636" : "389")));
+        searchBase = getConfigOrThrow(ldapConfig, "searchBase");
+        sLoginDN = getConfigOrThrow(ldapConfig, "sLoginDN");
+        searchFilter = getConfigOrThrow(ldapConfig, "searchFilter");
+        sPwd = ldapConfig.getOrDefault("pwd", "");
+        trustStorePath = ldapConfig.getOrDefault("trustStore", "");
+        additionalCipherSuites = ldapConfig.getOrDefault("additionalCipherSuites", "");
+        useEmbeddedServer = Boolean.parseBoolean(ldapConfig.getOrDefault("useEmbeddedServer", "false"));
+        emailAttribute = ldapConfig.getOrDefault("emailAttribute", "mail");
+        ldif = ldapConfig.getOrDefault("ldifFile", null);
+
+
+    }
+
+    static HashMap<String, String> typeCastConvert(Properties prop) {
+        Map<String, String> step2 = (Map<String, String>) (Map) prop;
+        return new HashMap<>(step2);
+    }
+
+    public static HashMap<String, String> loadProp(String sConfFile) throws IOException {
+        FileInputStream in;
+        Properties prop;
+
+        try {
+            in = new FileInputStream(sConfFile);
+        } catch (IOException ex) {
+            System.err.printf("Error: LDAP.loadProp: cannot load Property file '%s'!\n", sConfFile);
+            ex.printStackTrace();
+            return null;
+        }
+
+        prop = new Properties();
+
+        try {
+            prop.load(in);
+            return typeCastConvert(prop);
+        } catch (IOException ex) {
+            ex.printStackTrace();
+        }
+
+        return new HashMap<>();
+    }
+
+    private String getConfigOrThrow(Map<String, String> ldapConfig, String attribute) throws LdapConfigurationException {
+        String value = ldapConfig.get(attribute);
+        if (value != null) return value;
+        else throw new LdapConfigurationException(attribute + " is not set");
+    }
+
+    private class LdapConfigurationException extends RuntimeException {
+        public LdapConfigurationException(String s) {
+            super(s);
+        }
+    }
+
+}
diff --git a/full/src/main/java/de/ids_mannheim/korap/authentication/LdapAuth3.java b/full/src/main/java/de/ids_mannheim/korap/authentication/LdapAuth3.java
index bc091ad..bdfb2ad 100644
--- a/full/src/main/java/de/ids_mannheim/korap/authentication/LdapAuth3.java
+++ b/full/src/main/java/de/ids_mannheim/korap/authentication/LdapAuth3.java
@@ -15,13 +15,10 @@
 import org.apache.commons.text.StringSubstitutor;
 
 import javax.net.ssl.SSLSocketFactory;
-import java.io.IOException;
 import java.net.UnknownHostException;
 import java.security.GeneralSecurityException;
 import java.util.*;
 
-import static de.ids_mannheim.korap.server.EmbeddedLdapServer.loadProp;
-
 
 /**
  * LDAP Login
@@ -72,76 +69,62 @@
         }
     }
 
-    public static int login(String sUserDN, String sUserPwd, String ldapConfigFilename) throws LDAPException {
+    public static int login(String login, String password, String ldapConfigFilename) throws LDAPException {
+        LDAPConfig ldapConfig = new LDAPConfig(ldapConfigFilename);
 
-        sUserDN = Filter.encodeValue(sUserDN);
-        sUserPwd = Filter.encodeValue(sUserPwd);
+        login = Filter.encodeValue(login);
+        password = Filter.encodeValue(password);
 
-        SearchResult srchRes = search(sUserDN, sUserPwd, ldapConfigFilename);
+        if (ldapConfig.useEmbeddedServer) {
+            try {
+                EmbeddedLdapServer.startIfNotRunning(ldapConfig);
+            } catch (GeneralSecurityException | UnknownHostException | LDAPException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        SearchResult srchRes = search(login, password, ldapConfig);
 
         if (srchRes == null || srchRes.getEntryCount() == 0) {
-            if (DEBUGLOG) System.out.printf("Finding '%s': no entry found!\n", sUserDN);
+            if (DEBUGLOG) System.out.printf("Finding '%s': no entry found!\n", login);
             return LDAP_AUTH_RNAUTH;
         }
         return LDAP_AUTH_ROK;
     }
 
-    public static SearchResult search(String sUserDN, String sUserPwd, String ldapConfigFilename) throws LDAPException {
-        Map<String, String> ldapConfig;
-        try {
-            ldapConfig = loadProp(ldapConfigFilename);
-        } catch (IOException e) {
-            System.out.println("Error: LDAPAuth.login: cannot load Property file!");
-            return null;
-        }
-
-        assert ldapConfig != null;
-        final boolean ldapS = Boolean.parseBoolean(ldapConfig.getOrDefault("ldapS", "false"));
-        final String ldapHost = ldapConfig.getOrDefault("ldapHost", "localhost");
-        final int ldapPort = Integer.parseInt(ldapConfig.getOrDefault("ldapPort", (ldapS ? "636" : "389")));
-        final String ldapBase = ldapConfig.getOrDefault("ldapBase", "dc=example,dc=com");
-        final String sLoginDN = ldapConfig.getOrDefault("sLoginDN", "cn=admin,dc=example,dc=com");
-        final String ldapFilter = ldapConfig.getOrDefault("ldapFilter", "(&(|(&(mail=${username})(idsC2Password=${password}))(&(idsC2Profile=${username})(idsC2Password=${password})))(&(idsC2=TRUE)(|(idsStatus=1)(|(idsStatus=0)(xidsStatus=\00)))))");
-        final String sPwd = ldapConfig.getOrDefault("pwd", "");
-        final String trustStorePath = ldapConfig.getOrDefault("trustStore", "");
-        final String additionalCipherSuites = ldapConfig.getOrDefault("additionalCipherSuites", "");
-        final boolean useEmbeddedServer = Boolean.parseBoolean(ldapConfig.getOrDefault("useEmbeddedServer", "false"));
-
-        if (useEmbeddedServer && EmbeddedLdapServer.server == null) {
-            try {
-                EmbeddedLdapServer.start(ldapConfigFilename);
-            } catch (GeneralSecurityException | UnknownHostException e) {
-                throw new RuntimeException(e);
-            }
-        }
-
+    public static SearchResult search(String login, String password, LDAPConfig ldapConfig) throws LDAPException {
         Map<String, String> valuesMap = new HashMap<>();
-        valuesMap.put("username", sUserDN);
-        valuesMap.put("password", sUserPwd);
+        valuesMap.put("login", login);
+        valuesMap.put("password", password);
         StringSubstitutor sub = new StringSubstitutor(valuesMap);
-        String ldapFilterInstance = sub.replace(ldapFilter);
+        String searchFilterInstance = sub.replace(ldapConfig.searchFilter);
+
+        valuesMap.clear();
+        valuesMap.put("login", login);
+        sub = new StringSubstitutor(valuesMap);
+        String insensitiveSearchFilter = sub.replace(ldapConfig.searchFilter);
 
         if (DEBUGLOG) {
             //System.out.printf("LDAP Version      = %d.\n", LDAPConnection.LDAP_V3);
-            System.out.printf("LDAP Host & Port  = '%s':%d.\n", ldapHost, ldapPort);
-            System.out.printf("Login User = '%s'\n", sUserDN);
+            System.out.printf("LDAP Host & Port  = '%s':%d.\n", ldapConfig.host, ldapConfig.port);
+            System.out.printf("Login User = '%s'\n", login);
         }
 
         // LDAP Connection:
-        if (DEBUGLOG) System.out.println("LDAPS " + ldapS);
+        if (DEBUGLOG) System.out.println("LDAPS " + ldapConfig.useSSL);
 
         LDAPConnection lc;
 
-        if (ldapS) {
+        if (ldapConfig.useSSL) {
             try {
                 SSLUtil sslUtil;
-                if (trustStorePath != null && !trustStorePath.isEmpty()) {
-                    sslUtil = new SSLUtil(new TrustStoreTrustManager(trustStorePath));
+                if (ldapConfig.trustStorePath != null && !ldapConfig.trustStorePath.isEmpty()) {
+                    sslUtil = new SSLUtil(new TrustStoreTrustManager(ldapConfig.trustStorePath));
                 } else {
                     sslUtil = new SSLUtil(new TrustAllTrustManager());
                 }
-                if (additionalCipherSuites != null && !additionalCipherSuites.isEmpty()) {
-                    addSSLCipherSuites(additionalCipherSuites);
+                if (ldapConfig.additionalCipherSuites != null && !ldapConfig.additionalCipherSuites.isEmpty()) {
+                    addSSLCipherSuites(ldapConfig.additionalCipherSuites);
                 }
                 SSLSocketFactory socketFactory = sslUtil.createSSLSocketFactory();
                 lc = new LDAPConnection(socketFactory);
@@ -154,9 +137,9 @@
             lc = new LDAPConnection();
         }
         try {
-            lc.connect(ldapHost, ldapPort);
-            if (DEBUGLOG && ldapS) System.out.println("LDAPS Connection = OK\n");
-            if (DEBUGLOG && !ldapS) System.out.println("LDAP Connection = OK\n");
+            lc.connect(ldapConfig.host, ldapConfig.port);
+            if (DEBUGLOG && ldapConfig.useSSL) System.out.println("LDAPS Connection = OK\n");
+            if (DEBUGLOG && !ldapConfig.useSSL) System.out.println("LDAP Connection = OK\n");
         } catch (LDAPException e) {
             String fullStackTrace = org.apache.commons.lang.exception.ExceptionUtils.getFullStackTrace(e);
             System.err.printf("Error: login: Connecting to LDAP Server: failed: '%s'!\n", fullStackTrace);
@@ -169,8 +152,8 @@
 
         try {
             // bind to server:
-            if (DEBUGLOG) System.out.printf("Binding with '%s' ...\n", sLoginDN);
-            lc.bind(sLoginDN, sPwd);
+            if (DEBUGLOG) System.out.printf("Binding with '%s' ...\n", ldapConfig.sLoginDN);
+            lc.bind(ldapConfig.sLoginDN, ldapConfig.sPwd);
             if (DEBUGLOG) System.out.print("Binding: OK.\n");
         } catch (LDAPException e) {
             System.err.printf("Error: login: Binding failed: '%s'!\n", e);
@@ -180,16 +163,16 @@
 
         if (DEBUGLOG) System.out.printf("Debug: isConnected=%d\n", lc.isConnected() ? 1 : 0);
 
-        if (DEBUGLOG) System.out.printf("Finding user '%s'...\n", sUserDN);
+        if (DEBUGLOG) System.out.printf("Finding user '%s'...\n", login);
 
         SearchResult srchRes;
         try {
             // SCOPE_SUB = Scope Subtree.
-            if (DEBUGLOG) System.out.printf("Finding Filter: '%s'.\n", ldapFilterInstance);
+            if (DEBUGLOG) System.out.printf("Finding Filter: '%s'.\n", insensitiveSearchFilter);
 
-            srchRes = lc.search(ldapBase, SearchScope.SUB, ldapFilterInstance);
+            srchRes = lc.search(ldapConfig.searchBase, SearchScope.SUB, searchFilterInstance);
 
-            if (DEBUGLOG) System.out.printf("Finding '%s': %d entries.\n", sUserDN, srchRes.getEntryCount());
+            if (DEBUGLOG) System.out.printf("Finding '%s': %d entries.\n", login, srchRes.getEntryCount());
         } catch (LDAPSearchException e) {
             System.err.printf("Error: login: Search for User failed: '%s'!\n", e);
             ldapTerminate(lc);
@@ -197,7 +180,7 @@
         }
 
         if (srchRes.getEntryCount() == 0) {
-            if (DEBUGLOG) System.out.printf("Finding '%s': no entry found!\n", sUserDN);
+            if (DEBUGLOG) System.out.printf("Finding '%s': no entry found!\n", login);
             return null;
         }
 
@@ -207,16 +190,10 @@
 
     public static String getEmail(String sUserDN, String ldapConfigFilename) throws LDAPException {
         String sUserPwd = "*";
-        Map<String, String> ldapConfig;
-        try {
-            ldapConfig = loadProp(ldapConfigFilename);
-        } catch (IOException e) {
-            System.out.println("Error: LDAPAuth.login: cannot load Property file!");
-            return null;
-        }
-        final String emailAttribute = ldapConfig.getOrDefault("emailAttribute", "mail");
+        LDAPConfig ldapConfig = new LDAPConfig(ldapConfigFilename);
+        final String emailAttribute = ldapConfig.emailAttribute;
 
-        SearchResult searchResult = search(sUserDN, sUserPwd, ldapConfigFilename);
+        SearchResult searchResult = search(sUserDN, sUserPwd, ldapConfig);
 
         if (searchResult == null) {
             return null;
diff --git a/full/src/main/java/de/ids_mannheim/korap/server/EmbeddedLdapServer.java b/full/src/main/java/de/ids_mannheim/korap/server/EmbeddedLdapServer.java
index e6bd261..76f6494 100644
--- a/full/src/main/java/de/ids_mannheim/korap/server/EmbeddedLdapServer.java
+++ b/full/src/main/java/de/ids_mannheim/korap/server/EmbeddedLdapServer.java
@@ -6,82 +6,46 @@
 import com.unboundid.ldap.sdk.LDAPException;
 import com.unboundid.util.ssl.SSLUtil;
 import com.unboundid.util.ssl.TrustAllTrustManager;
+import de.ids_mannheim.korap.authentication.LDAPConfig;
 
-import java.io.FileInputStream;
-import java.io.IOException;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.security.GeneralSecurityException;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Properties;
 
 public class EmbeddedLdapServer {
-    public static InMemoryDirectoryServer server;
+    static InMemoryDirectoryServer server;
 
-    public static void start(String ldapConfigFilename) throws LDAPException, GeneralSecurityException, UnknownHostException {
-        Map<String, String> ldapConfig = null;
-        try {
-            ldapConfig = loadProp(ldapConfigFilename);
-        } catch (IOException e) {
-            System.out.println("Error: LDAPAuth.login: cannot load Property file!");
+    public static void startIfNotRunning(LDAPConfig ldapConfig) throws LDAPException, GeneralSecurityException, UnknownHostException {
+        if (server != null) {
+            return;
         }
 
-        final int ldapPort = Integer.parseInt(ldapConfig.getOrDefault("ldapPort", "3268"));
-        final String ldapBase = ldapConfig.getOrDefault("ldapBase", "dc=example,dc=com");
-        final String sLoginDN = ldapConfig.getOrDefault("sLoginDN", "cn=admin,dc=example,dc=com");
-        final String sPwd = ldapConfig.getOrDefault("pwd", "");
-        final String ldif = ldapConfig.getOrDefault("ldifFile", "");
-
-        InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig(ldapBase);
-        config.addAdditionalBindCredentials(sLoginDN, sPwd);
+        InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig(ldapConfig.searchBase);
+        config.addAdditionalBindCredentials(ldapConfig.sLoginDN, ldapConfig.sPwd);
         config.setSchema(null);
 
         final SSLUtil clientSslUtil = new SSLUtil(new TrustAllTrustManager());
 
         config.setListenerConfigs(InMemoryListenerConfig.createLDAPConfig("LDAP", // Listener name
                 InetAddress.getByName("localhost"), // Listen address. (null = listen on all interfaces)
-                ldapPort, // Listen port (0 = automatically choose an available port)
+                ldapConfig.port, // Listen port (0 = automatically choose an available port)
                 clientSslUtil.createSSLSocketFactory()));
         server = new InMemoryDirectoryServer(config);
 
-        server.importFromLDIF(true, ldif);
+        server.importFromLDIF(true, ldapConfig.ldif);
         server.startListening();
     }
 
+    public static void startIfNotRunning(String ldapConfigFilename) throws LDAPException, GeneralSecurityException, UnknownHostException {
+        LDAPConfig ldapConfig = new LDAPConfig(ldapConfigFilename);
+        startIfNotRunning(ldapConfig);
+    }
+
     public static void stop() {
         if (server != null) {
             server.shutDown(true);
+            server = null;
         }
     }
 
-    static HashMap<String, String> typeCastConvert(Properties prop) {
-        Map<String, String> step2 = (Map<String, String>) (Map) prop;
-        return new HashMap<>(step2);
-    }
-
-    public static HashMap<String, String> loadProp(String sConfFile) throws IOException {
-        FileInputStream in;
-        Properties prop;
-
-        try {
-            in = new FileInputStream(sConfFile);
-        } catch (IOException ex) {
-            System.err.printf("Error: LDAP.loadProp: cannot load Property file '%s'!\n", sConfFile);
-            ex.printStackTrace();
-            return null;
-        }
-
-        prop = new Properties();
-
-        try {
-            prop.load(in);
-            return typeCastConvert(prop);
-        } catch (IOException ex) {
-            ex.printStackTrace();
-        }
-
-        return new HashMap<>();
-    }
-
 }
diff --git a/full/src/main/resources/embedded-ldap-default.conf b/full/src/main/resources/embedded-ldap-default.conf
index ccb912e..becf6e0 100644
--- a/full/src/main/resources/embedded-ldap-default.conf
+++ b/full/src/main/resources/embedded-ldap-default.conf
@@ -1,10 +1,10 @@
 # default and sample configuration for an automatically starting
 # embedded LDAP server
-ldapHost=localhost
-ldapPort=3267
-ldapBase=dc=example,dc=com
+host=localhost
+port=3267
+searchBase=dc=example,dc=com
 sLoginDN=cn=admin,dc=example,dc=com
 pwd=admin
-ldapFilter=(&(uid=${username})(userPassword=${password}))
+searchFilter=(&(uid=${login})(userPassword=${password}))
 useEmbeddedServer=true
 ldifFile=src/main/resources/korap-users.ldif