caching framework cleanup and test extension

Change-Id: I472b0a465e3d2217835ffb1f49e07a1b65a08976
diff --git a/src/main/java/de/ids_mannheim/korap/config/BeanConfiguration.java b/src/main/java/de/ids_mannheim/korap/config/BeanConfiguration.java
index 4d777b0..d924fd1 100644
--- a/src/main/java/de/ids_mannheim/korap/config/BeanConfiguration.java
+++ b/src/main/java/de/ids_mannheim/korap/config/BeanConfiguration.java
@@ -2,13 +2,16 @@
 
 import de.ids_mannheim.korap.interfaces.AuthenticationManagerIface;
 import de.ids_mannheim.korap.interfaces.EncryptionIface;
+import de.ids_mannheim.korap.interfaces.ValidatorIface;
 import de.ids_mannheim.korap.interfaces.db.*;
+import de.ids_mannheim.korap.interfaces.defaults.ApacheValidator;
 import de.ids_mannheim.korap.web.utils.KustvaktResponseHandler;
 import org.springframework.beans.factory.NoSuchBeanDefinitionException;
 import org.springframework.context.ApplicationContext;
 import org.springframework.context.support.ClassPathXmlApplicationContext;
 import org.springframework.context.support.FileSystemXmlApplicationContext;
 
+import java.io.IOException;
 import java.util.HashSet;
 import java.util.Set;
 
@@ -178,6 +181,14 @@
         }
 
 
+        public ValidatorIface getValidator()  {
+            try {
+                return new ApacheValidator();
+            } catch (IOException e) {
+                throw new RuntimeException("validator could not be loaded!");
+            }
+        }
+
         // todo: !!!!!!!!!!!!!!!!!!!!!!!!!!
         // todo: more specific --> collection provider, document provider, etc.
         public ResourceOperationIface getResourceProvider () {
diff --git a/src/main/java/de/ids_mannheim/korap/config/ContextHolder.java b/src/main/java/de/ids_mannheim/korap/config/ContextHolder.java
index f3f256c..e142def 100644
--- a/src/main/java/de/ids_mannheim/korap/config/ContextHolder.java
+++ b/src/main/java/de/ids_mannheim/korap/config/ContextHolder.java
@@ -3,11 +3,14 @@
 import de.ids_mannheim.korap.interfaces.AuthenticationIface;
 import de.ids_mannheim.korap.interfaces.AuthenticationManagerIface;
 import de.ids_mannheim.korap.interfaces.EncryptionIface;
+import de.ids_mannheim.korap.interfaces.ValidatorIface;
 import de.ids_mannheim.korap.interfaces.db.*;
+import de.ids_mannheim.korap.interfaces.defaults.ApacheValidator;
 import de.ids_mannheim.korap.web.utils.KustvaktResponseHandler;
 import org.springframework.beans.factory.NoSuchBeanDefinitionException;
 import org.springframework.context.ApplicationContext;
 
+import java.io.IOException;
 import java.util.Collection;
 
 /**
@@ -120,7 +123,15 @@
     }
 
 
-    private void finish () {
+    public ValidatorIface getValidator()  {
+        try {
+            return new ApacheValidator();
+        } catch (IOException e) {
+            throw new RuntimeException("validator could not be loaded!");
+        }
+    }
+
+    private void close () {
         this.getAuditingProvider().finish();
         this.context = null;
     }
diff --git a/src/main/java/de/ids_mannheim/korap/config/ExceptionBuilder.java b/src/main/java/de/ids_mannheim/korap/config/ExceptionBuilder.java
index 4eb2725..84b2046 100644
--- a/src/main/java/de/ids_mannheim/korap/config/ExceptionBuilder.java
+++ b/src/main/java/de/ids_mannheim/korap/config/ExceptionBuilder.java
@@ -4,6 +4,7 @@
  * @author hanl
  * @date 10/02/2016
  */
+// todo:
 // run simple queries to determine the exception cause (e.g. policy could not be created because resource doesnt exist, etc.)
 public class ExceptionBuilder {
     // use sqlbuilder to build the respective query (one instance per dao interface)
diff --git a/src/main/java/de/ids_mannheim/korap/config/KustvaktCacheManager.java b/src/main/java/de/ids_mannheim/korap/config/KustvaktCacheManager.java
deleted file mode 100644
index f3bcc53..0000000
--- a/src/main/java/de/ids_mannheim/korap/config/KustvaktCacheManager.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package de.ids_mannheim.korap.config;
-
-import net.sf.ehcache.CacheManager;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.InputStream;
-
-/**
- * @author hanl
- * @date 03/02/2016
- */
-public class KustvaktCacheManager {
-
-    private static boolean loaded = false;
-
-
-    public static void init () {
-        if (!loaded) {
-            InputStream in = null;
-            try {
-                in = new FileInputStream(new File("./ehcache.xml"));
-            }
-            catch (FileNotFoundException e) {
-                // do nothing
-            }
-
-            if (in == null) {
-                in = KustvaktCacheManager.class.getClassLoader()
-                        .getResourceAsStream("ehcache.xml");
-            }
-            CacheManager.newInstance(in);
-            loaded = true;
-        }
-    }
-}
diff --git a/src/main/java/de/ids_mannheim/korap/config/KustvaktConfiguration.java b/src/main/java/de/ids_mannheim/korap/config/KustvaktConfiguration.java
index a657c87..9e025e4 100644
--- a/src/main/java/de/ids_mannheim/korap/config/KustvaktConfiguration.java
+++ b/src/main/java/de/ids_mannheim/korap/config/KustvaktConfiguration.java
@@ -64,7 +64,9 @@
     private boolean allowMultiLogIn;
     private int expiration;
     private int loadFactor;
+    @Deprecated
     private int validationStringLength;
+    @Deprecated
     private int validationEmaillength;
     // fixme: should move to base config?!
     private EncryptionIface.Encryption encryption;
@@ -197,6 +199,16 @@
     }
 
 
+
+    public static void loadLogger () {
+        InputStream stream = ConfigLoader.loadConfigStream("log4j.properties");
+        PropertyConfigurator.configure(stream);
+        jlog.info("Done loading logging framework Log4j!");
+    }
+
+
+
+    @Deprecated
     public static void loadLog4jLogger () {
         /** loadSubTypes log4j configuration file programmatically */
         Properties log4j = new Properties();
@@ -219,6 +231,7 @@
     }
 
 
+    @Deprecated
     private static void loadClassLogger () {
         Properties log4j = new Properties();
         jlog.info("using class path logging properties file to configure logging system");
diff --git a/src/main/java/de/ids_mannheim/korap/exceptions/StatusCodes.java b/src/main/java/de/ids_mannheim/korap/exceptions/StatusCodes.java
index abc4d22..14cb52a 100644
--- a/src/main/java/de/ids_mannheim/korap/exceptions/StatusCodes.java
+++ b/src/main/java/de/ids_mannheim/korap/exceptions/StatusCodes.java
@@ -1,5 +1,12 @@
 package de.ids_mannheim.korap.exceptions;
 
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import de.ids_mannheim.korap.config.ConfigLoader;
+
+import java.io.IOException;
+import java.util.Properties;
+
 /**
  * @author hanl
  * @date 07/09/2014
@@ -23,7 +30,7 @@
     public static final int NOT_SUPPORTED = 110;
 
     /**
-     * 400 status codes for account/authentication relevant components
+     * 200 status codes for account/authentication relevant components
      */
 
     public static final int ACCOUNT_DEACTIVATED = 200;
@@ -31,6 +38,7 @@
     public static final int ALREADY_LOGGED_IN = 202;
     public static final int EXPIRED = 204;
     public static final int BAD_CREDENTIALS = 205;
+    @Deprecated // fixme: duplicate to account deactivated
     public static final int UNCONFIRMED_ACCOUNT = 206;
     public static final int NAME_EXISTS = 207;
     public static final int PASSWORD_RESET_FAILED = 208;
@@ -48,7 +56,11 @@
     public static final int CLIENT_AUTHORIZATION_FAILURE = 216;
 
 
+    /**
+     *  400 status codes for authorization and rewrite functions
+     */
 
+    // fixme: use unsupported resource and include type in return message
     public static final int PERMISSION_DENIED = 401;
     public static final int UNSUPPORTED_RESOURCE = 402;
     public static final int UNSUPPORTED_FOUNDRY = 403;
@@ -106,4 +118,10 @@
 
     public static final int NO_QUERY = 301;
 
+
+
+    private StatusCodes() {
+
+    }
+
 }
diff --git a/src/main/java/de/ids_mannheim/korap/handlers/EntityDao.java b/src/main/java/de/ids_mannheim/korap/handlers/EntityDao.java
index 5d58b46..46b0544 100644
--- a/src/main/java/de/ids_mannheim/korap/handlers/EntityDao.java
+++ b/src/main/java/de/ids_mannheim/korap/handlers/EntityDao.java
@@ -117,7 +117,6 @@
             jlog.error(
                     "Could not update user account for user: " + user.getId(),
                     e);
-            //            throw new KorAPException(e, StatusCodes.CONNECTION_ERROR);
             throw new dbException(user.getId(), "korap_users",
                     StatusCodes.DB_UPDATE_FAILED, user.toString());
         }
diff --git a/src/main/java/de/ids_mannheim/korap/handlers/OAuth2Handler.java b/src/main/java/de/ids_mannheim/korap/handlers/OAuth2Handler.java
index c1ce959..8ddeb33 100644
--- a/src/main/java/de/ids_mannheim/korap/handlers/OAuth2Handler.java
+++ b/src/main/java/de/ids_mannheim/korap/handlers/OAuth2Handler.java
@@ -1,53 +1,54 @@
 package de.ids_mannheim.korap.handlers;
 
 import de.ids_mannheim.korap.config.AuthCodeInfo;
+import de.ids_mannheim.korap.config.ClientInfo;
+import de.ids_mannheim.korap.config.KustvaktCacheable;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.interfaces.db.PersistenceClient;
 import de.ids_mannheim.korap.user.User;
-import net.sf.ehcache.Cache;
-import net.sf.ehcache.CacheManager;
-import net.sf.ehcache.Element;
 
 /**
  * extends OAuthDb to allow temporary caching of tokens
- * and authorizations (authorizations are not persisted in db)
+ * and authorization codes.
+ * Authorization codes are not persisted in db,
+ * but stored in file of ehcache
  * 
  * @author hanl
  * @date 04/05/2015
  */
-public class OAuth2Handler extends OAuthDb {
+public class OAuth2Handler extends KustvaktCacheable {
 
-    private Cache cache;
-
+    private OAuthDb oauthdb;
 
     public OAuth2Handler (PersistenceClient client) {
-        super(client);
-        this.cache = CacheManager.getInstance().getCache("auth_codes");
+        super("auth_codes", "key:auth_codes");
+        this.oauthdb = new OAuthDb(client);
     }
 
 
+    // fixme: caching should not be obligatory here. alternative to caching if not available?
     public AuthCodeInfo getAuthorization (String code) {
-        Element e = this.cache.get(code);
-        if (e != null)
-            return (AuthCodeInfo) e.getObjectValue();
+        Object value = this.getCacheValue(code);
+        if (value != null)
+            return (AuthCodeInfo) value;
         return null;
     }
 
 
-    public void authorize (AuthCodeInfo code, User user)
+    public void authorize (AuthCodeInfo info, User user)
             throws KustvaktException {
-        code.setUserId(user.getId());
-        cache.put(new Element(code.getCode(), code));
+        info.setUserId(user.getId());
+        this.storeInCache(info.getCode(), info);
     }
 
 
     public boolean addToken (String code, String token, String refresh, int ttl)
             throws KustvaktException {
-        Element e = cache.get(code);
-        if (e != null) {
-            AuthCodeInfo info = (AuthCodeInfo) e.getObjectValue();
-            cache.remove(code);
-            return super.addToken(token, refresh, info.getUserId(),
+        Object o = this.getCacheValue(code);
+        if (o != null) {
+            AuthCodeInfo info = (AuthCodeInfo) o;
+            this.removeCacheEntry(code);
+            return oauthdb.addToken(token, refresh, info.getUserId(),
                     info.getClientId(), info.getScopes(), ttl);
         }
         return false;
@@ -55,7 +56,11 @@
 
 
     public void exchangeToken (String refresh) {
+        // todo:
+    }
 
+    public OAuthDb getPersistenceHandler(){
+        return this.oauthdb;
     }
 
 }
diff --git a/src/main/java/de/ids_mannheim/korap/handlers/UserDetailsDao.java b/src/main/java/de/ids_mannheim/korap/handlers/UserDetailsDao.java
index a85383e..ddfe851 100644
--- a/src/main/java/de/ids_mannheim/korap/handlers/UserDetailsDao.java
+++ b/src/main/java/de/ids_mannheim/korap/handlers/UserDetailsDao.java
@@ -36,7 +36,7 @@
     public int store (UserDetails data) throws KustvaktException {
         String sql = "INSERT INTO user_details (user_id, data) VALUES (:userid, :data);";
         MapSqlParameterSource source = new MapSqlParameterSource();
-        source.addValue("userid", data.getUserID());
+        source.addValue("userid", data.getUserId());
         source.addValue("data", data.serialize());
 
         GeneratedKeyHolder gen = new GeneratedKeyHolder();
@@ -56,7 +56,7 @@
     public int update (UserDetails data) throws KustvaktException {
         String sql = "UPDATE user_details SET data = :data WHERE user_id=:userid;";
         MapSqlParameterSource source = new MapSqlParameterSource();
-        source.addValue("userid", data.getUserID());
+        source.addValue("userid", data.getUserId());
         source.addValue("data", data.serialize());
 
         try {
@@ -82,8 +82,8 @@
                         @Override
                         public UserDetails mapRow (ResultSet rs, int rowNum)
                                 throws SQLException {
-                            UserDetails details = new UserDetails(rs
-                                    .getInt("user_id"));
+                            UserDetails details = new UserDetails();
+                            details.setUserId(rs.getInt("user_id"));
                             details.setId(rs.getInt("id"));
                             details.setData(rs.getString("data"));
                             return details;
@@ -114,8 +114,8 @@
                         @Override
                         public UserDetails mapRow (ResultSet rs, int rowNum)
                                 throws SQLException {
-                            UserDetails details = new UserDetails(rs
-                                    .getInt("user_id"));
+                            UserDetails details = new UserDetails();
+                            details.setUserId(rs.getInt("user_id"));
                             details.setId(rs.getInt("id"));
                             details.setData(rs.getString("data"));
                             return details;
diff --git a/src/main/java/de/ids_mannheim/korap/handlers/UserSettingsDao.java b/src/main/java/de/ids_mannheim/korap/handlers/UserSettingsDao.java
index 266d39f..fdc6ba5 100644
--- a/src/main/java/de/ids_mannheim/korap/handlers/UserSettingsDao.java
+++ b/src/main/java/de/ids_mannheim/korap/handlers/UserSettingsDao.java
@@ -41,7 +41,7 @@
     public int store (UserSettings data) throws KustvaktException {
         String sql = "INSERT INTO user_settings (user_id, data) VALUES (:userid, :data);";
         MapSqlParameterSource source = new MapSqlParameterSource();
-        source.addValue("userid", data.getUserID());
+        source.addValue("userid", data.getUserId());
         source.addValue("data", data.serialize());
 
         GeneratedKeyHolder gen = new GeneratedKeyHolder();
@@ -53,7 +53,7 @@
         }
         catch (DataAccessException e) {
             jlog.error("couldn't store data in db for user with id '{}'",
-                    data.getUserID());
+                    data.getUserId());
             return -1;
         }
     }
@@ -63,7 +63,7 @@
     public int update (UserSettings data) throws KustvaktException {
         String sql = "UPDATE user_settings SET data = :data WHERE user_id=:userid;";
         MapSqlParameterSource source = new MapSqlParameterSource();
-        source.addValue("userid", data.getUserID());
+        source.addValue("userid", data.getUserId());
         source.addValue("data", data.serialize());
 
         try {
diff --git a/src/main/java/de/ids_mannheim/korap/interfaces/AuthenticationIface.java b/src/main/java/de/ids_mannheim/korap/interfaces/AuthenticationIface.java
index 5c5a9e8..d15c4c4 100644
--- a/src/main/java/de/ids_mannheim/korap/interfaces/AuthenticationIface.java
+++ b/src/main/java/de/ids_mannheim/korap/interfaces/AuthenticationIface.java
@@ -8,10 +8,10 @@
 
 public interface AuthenticationIface {
 
-    TokenContext getUserStatus (String authToken) throws KustvaktException;
+    TokenContext getTokenContext(String authToken) throws KustvaktException;
 
 
-    TokenContext createUserSession (User user, Map<String, Object> attr)
+    TokenContext createTokenContext(User user, Map<String, Object> attr)
             throws KustvaktException;
 
 
diff --git a/src/main/java/de/ids_mannheim/korap/interfaces/AuthenticationManagerIface.java b/src/main/java/de/ids_mannheim/korap/interfaces/AuthenticationManagerIface.java
index ab39aca..1d77605 100644
--- a/src/main/java/de/ids_mannheim/korap/interfaces/AuthenticationManagerIface.java
+++ b/src/main/java/de/ids_mannheim/korap/interfaces/AuthenticationManagerIface.java
@@ -1,5 +1,6 @@
 package de.ids_mannheim.korap.interfaces;
 
+import de.ids_mannheim.korap.config.KustvaktCacheable;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.user.TokenContext;
 import de.ids_mannheim.korap.user.User;
@@ -13,12 +14,13 @@
  * @author hanl
  * @date 15/06/2015
  */
-public abstract class AuthenticationManagerIface {
+public abstract class AuthenticationManagerIface extends KustvaktCacheable {
 
     private Map<String, AuthenticationIface> providers;
 
 
     public AuthenticationManagerIface () {
+        super("id_tokens", "key:id_tokens");
         this.providers = new HashMap<>();
     }
 
@@ -45,6 +47,8 @@
 
     public abstract User getUser (String username) throws KustvaktException;
 
+    public abstract boolean isRegistered(String id);
+
 
     public abstract User authenticate (int type, String username,
             String password, Map<String, Object> attributes)
diff --git a/src/main/java/de/ids_mannheim/korap/interfaces/EncryptionIface.java b/src/main/java/de/ids_mannheim/korap/interfaces/EncryptionIface.java
index 9f95d6f..1042992 100644
--- a/src/main/java/de/ids_mannheim/korap/interfaces/EncryptionIface.java
+++ b/src/main/java/de/ids_mannheim/korap/interfaces/EncryptionIface.java
@@ -10,6 +10,7 @@
 public interface EncryptionIface {
 
     public enum Encryption {
+                @Deprecated
         SIMPLE, ESAPICYPHER, BCRYPT
     }
 
@@ -66,11 +67,13 @@
     public String encodeBase ();
 
 
-    public Map<String, Object> validateMap (Map<String, Object> map)
-            throws KustvaktException;
+   // @Deprecated
+    //public Map<String, Object> validateMap (Map<String, Object> map)
+    //        throws KustvaktException;
 
 
-    public String validateEntry (String input, String type)
-            throws KustvaktException;
+    //@Deprecated
+    //public String validateEntry (String input, String type)
+    //        throws KustvaktException;
 
 }
diff --git a/src/main/java/de/ids_mannheim/korap/interfaces/defaults/DefaultEncryption.java b/src/main/java/de/ids_mannheim/korap/interfaces/defaults/DefaultEncryption.java
index dbf07ac..d870e24 100644
--- a/src/main/java/de/ids_mannheim/korap/interfaces/defaults/DefaultEncryption.java
+++ b/src/main/java/de/ids_mannheim/korap/interfaces/defaults/DefaultEncryption.java
@@ -78,17 +78,4 @@
         return null;
     }
 
-
-    @Override
-    public Map validateMap (Map map) throws KustvaktException {
-        return null;
-    }
-
-
-    @Override
-    public String validateEntry (String input, String type)
-            throws KustvaktException {
-        return input;
-    }
-
 }
diff --git a/src/main/java/de/ids_mannheim/korap/interfaces/defaults/KustvaktEncryption.java b/src/main/java/de/ids_mannheim/korap/interfaces/defaults/KustvaktEncryption.java
index 5927f83..1539cfc 100644
--- a/src/main/java/de/ids_mannheim/korap/interfaces/defaults/KustvaktEncryption.java
+++ b/src/main/java/de/ids_mannheim/korap/interfaces/defaults/KustvaktEncryption.java
@@ -10,12 +10,8 @@
 import edu.emory.mathcs.backport.java.util.Collections;
 import org.apache.commons.codec.EncoderException;
 import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.lang.RandomStringUtils;
 import org.mindrot.jbcrypt.BCrypt;
-import org.owasp.esapi.ESAPI;
-import org.owasp.esapi.Randomizer;
-import org.owasp.esapi.Validator;
-import org.owasp.esapi.errors.ValidationException;
-import org.owasp.esapi.reference.DefaultValidator;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -36,17 +32,11 @@
     private static Logger jlog = LoggerFactory
             .getLogger(KustvaktEncryption.class);
 
-    private final boolean nullable;
-    private final Validator validator;
-    private final Randomizer randomizer;
     private final KustvaktConfiguration config;
 
 
     public KustvaktEncryption (KustvaktConfiguration config) {
         jlog.info("initializing KorAPEncryption implementation");
-        this.nullable = false;
-        this.validator = DefaultValidator.getInstance();
-        this.randomizer = ESAPI.randomizer();
         this.config = config;
     }
 
@@ -86,17 +76,6 @@
         String hashString = "";
         switch (config.getEncryption()) {
             case ESAPICYPHER:
-                try {
-                    hashString = hash(input, salt);
-                }
-                catch (NoSuchAlgorithmException e) {
-                    jlog.error("there was an encryption error!", e);
-                    return null;
-                }
-                catch (Exception e) {
-                    jlog.error("there was an error!", e);
-                    return null;
-                }
                 break;
             case SIMPLE:
                 try {
@@ -123,30 +102,11 @@
 
 
 
-    public String hash (String text, String salt) throws Exception {
-        byte[] bytes;
-
-        MessageDigest md = MessageDigest.getInstance(ALGORITHM);
-        md.reset();
-        md.update(ESAPI.securityConfiguration().getMasterSalt());
-        md.update(salt.getBytes());
-        md.update(text.getBytes());
-
-        bytes = md.digest();
-        for (int i = 0; i < 234; ++i) {
-            md.reset();
-            bytes = md.digest(bytes);
-        }
-        String coding = ESAPI.encoder().encodeForBase64(bytes, false);
-        return coding;
-    }
-
-
     public String hash (String input) {
         String hashString = "";
         MessageDigest md;
         try {
-            md = MessageDigest.getInstance("SHA-256");
+            md = MessageDigest.getInstance(ALGORITHM);
             md.update(input.getBytes("UTF-8"));
         }
         catch (NoSuchAlgorithmException e) {
@@ -188,6 +148,12 @@
     }
 
 
+    /**
+     * does this need to be equal for every iteration?!
+     * @param hash
+     * @param obj
+     * @return
+     */
     @Override
     public String createToken (boolean hash, Object ... obj) {
         StringBuffer b = new StringBuffer();
@@ -211,9 +177,7 @@
     @Override
     public String createToken () {
         String encoded;
-        String v = randomizer.getRandomString(
-                SecureRGenerator.TOKEN_RANDOM_SIZE,
-                SecureRGenerator.toHex(createSecureRandom(64)).toCharArray());
+        String v = RandomStringUtils.randomAlphanumeric(64);
         encoded = hash(v);
         jlog.trace("creating new token {}", encoded);
         return encoded;
@@ -224,12 +188,7 @@
     public String createRandomNumber (Object ... obj) {
         final byte[] rNumber = SecureRGenerator
                 .getNextSecureRandom(SecureRGenerator.CORPUS_RANDOM_SIZE);
-        if (obj.length != 0) {
-            ArrayList s = new ArrayList();
-            Collections.addAll(s, obj);
-            obj = s.toArray();
-        }
-        else {
+        if (obj.length == 0) {
             obj = new Object[1];
             obj[0] = rNumber;
         }
@@ -278,166 +237,6 @@
     }
 
 
-    // todo: where applied?
-    @Override
-    public Map<String, Object> validateMap (Map<String, Object> map)
-            throws KustvaktException {
-        Map<String, Object> safeMap = new HashMap<>();
-        KustvaktMap kmap = new KustvaktMap(map);
-
-        if (map != null) {
-            if (!kmap.isGeneric()) {
-                for (String key : kmap.keySet()) {
-                    String value = validateEntry(kmap.get(key), key);
-                    safeMap.put(key, value);
-                }
-            }
-            else {
-                for (String key : kmap.keySet()) {
-                    Object value = kmap.getRaw(key);
-                    if (value instanceof String) {
-                        value = validateEntry((String) value, key);
-
-                    }
-                    else if (value instanceof List) {
-                        List list = (List) value;
-                        for (Object v : list) {
-                            if (v instanceof String)
-                                validateEntry((String) v, key);
-                        }
-
-                        if (list.size() == 1)
-                            value = list.get(0);
-                        else
-                            value = list;
-                    }
-                    safeMap.put(key, value);
-                }
-            }
-        }
-        return safeMap;
-    }
-
-
-    @Deprecated
-    private String validateString (String descr, String input, String type,
-            int length, boolean nullable) throws KustvaktException {
-        String s;
-        try {
-            s = validator.getValidInput(descr, input, type, length, nullable);
-        }
-        catch (ValidationException e) {
-            jlog.error(
-                    "String value did not validate ('{}') with validation type {}",
-                    new Object[] { input, type, e.getMessage() });
-            throw new KustvaktException(StatusCodes.ILLEGAL_ARGUMENT,
-                    "invalid string of type " + type, input);
-        }
-        return s;
-    }
-
-
-    @Override
-    public String validateEntry (String input, String type)
-            throws KustvaktException {
-        try {
-            if (type != null) {
-                type = type.toLowerCase();
-                if (type.equals(Attributes.EMAIL)) {
-                    jlog.debug("validating email entry '{}'", input.hashCode());
-                    return validator.getValidInput("Email", input, "email",
-                            config.getValidationEmaillength(), false);
-                }
-                else if (type.equals(Attributes.USERNAME)) {
-                    jlog.debug("validating username entry '{}'",
-                            input.hashCode());
-                    return validator.getValidInput("Username", input,
-                            "username", config.getValidationEmaillength(),
-                            false);
-                }
-                else if (type.equals(Attributes.IP_RANG)) {
-                    jlog.debug("validating ip address entry '{}'",
-                            input.hashCode());
-                    return validator.getValidInput("IP Address", input,
-                            "ipaddress", config.getValidationStringLength(),
-                            nullable);
-                }
-                else if (type.equals(Attributes.PASSWORD)) {
-                    jlog.debug("validating password entry '{}'",
-                            input.hashCode());
-                    return validator.getValidInput("Password", input,
-                            "password", config.getValidationStringLength(),
-                            nullable);
-                }
-            }
-            jlog.debug("validating string entry '{}'", input.hashCode());
-            return validator.getValidInput("Safe String", input, "SafeString",
-                    config.getValidationStringLength(), nullable);
-        }
-        catch (ValidationException ex) {
-            jlog.error("Validation failed! Value '{}' with type '{}'",
-                    new Object[] { input, type });
-            throw new KustvaktException(StatusCodes.PARAMETER_VALIDATION_ERROR,
-                    "invalid value of type " + type, input);
-        }
-    }
-
-
-    public void validate (Object instance) throws KustvaktException {
-        if (instance == null)
-            return;
-        try {
-            validateStringField(instance.getClass().getDeclaredFields(),
-                    instance);
-            validateStringField(instance.getClass().getSuperclass()
-                    .getDeclaredFields(), instance);
-        }
-        catch (IllegalAccessException e) {
-            jlog.error("object value did not validate", e.getMessage());
-            throw new KustvaktException(StatusCodes.PARAMETER_VALIDATION_ERROR,
-                    "object could not be validated", instance.toString());
-        }
-    }
-
-
-    //FIXME: currently all sets are skipped during validation (since users should not be allowed to edit those sets anyway,
-    //I think we will be safe here
-    @Deprecated
-    private void validateStringField (Field[] fields, Object instance)
-            throws KustvaktException, IllegalAccessException {
-        for (Field field : fields) {
-            boolean priv = false;
-            if (field.getType().isAssignableFrom(String.class)) {
-                if (Modifier.isPrivate(field.getModifiers())) {
-                    priv = true;
-                    field.setAccessible(true);
-                }
-                if (field.getName().equals("password")
-                        | Modifier.isFinal(field.getModifiers()))
-                    continue;
-                String val = (String) field.get(instance);
-                if (val != null) {
-                    String[] set = val.split(";");
-                    if (set.length > 1)
-                        continue;
-                }
-                String safe;
-                if (!field.getName().equals("email"))
-                    safe = validateString("Safe String", val, "SafeString",
-                            config.getValidationStringLength(), true);
-                else
-                    safe = validateString("User Email", val, "Email",
-                            config.getValidationEmaillength(), true);
-                field.set(instance, safe == null ? "" : safe);
-
-                if (priv) {
-                    field.setAccessible(false);
-                }
-            }
-        }
-    }
-
-
     private String bcryptHash (String text, String salt) {
         if (salt == null || salt.isEmpty())
             salt = BCrypt.gensalt(config.getLoadFactor());
diff --git a/src/main/java/de/ids_mannheim/korap/resource/LayerMapper.java b/src/main/java/de/ids_mannheim/korap/resource/LayerMapper.java
index 44e367d..fa6459b 100644
--- a/src/main/java/de/ids_mannheim/korap/resource/LayerMapper.java
+++ b/src/main/java/de/ids_mannheim/korap/resource/LayerMapper.java
@@ -55,7 +55,7 @@
                 default:
                     // if the layer is not in this specific listing, assume a default layer
                     // like orth or other tokenization layers
-                    return "opennlp";
+                    return null;
             }
         }
         else {
@@ -76,7 +76,7 @@
                 default:
                     // if the layer is not in this specific listing, assume a default layer
                     // like orth or other tokenization layers
-                    return "opennlp";
+                    return null;
             }
         }
     }
diff --git a/src/main/java/de/ids_mannheim/korap/resource/rewrite/DocMatchRewrite.java b/src/main/java/de/ids_mannheim/korap/resource/rewrite/DocMatchRewrite.java
index 5c8e568..8cfebc8 100644
--- a/src/main/java/de/ids_mannheim/korap/resource/rewrite/DocMatchRewrite.java
+++ b/src/main/java/de/ids_mannheim/korap/resource/rewrite/DocMatchRewrite.java
@@ -3,28 +3,22 @@
 import com.fasterxml.jackson.databind.JsonNode;
 import de.ids_mannheim.korap.config.*;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
-import de.ids_mannheim.korap.handlers.DocumentDao;
 import de.ids_mannheim.korap.interfaces.db.ResourceOperationIface;
 import de.ids_mannheim.korap.resources.Document;
 import de.ids_mannheim.korap.user.User;
-import net.sf.ehcache.Cache;
-import net.sf.ehcache.CacheManager;
-import net.sf.ehcache.Element;
 
 /**
  * @author hanl
  * @date 12/11/2015
  */
 //todo : test
-public class DocMatchRewrite implements RewriteTask.IterableRewritePath,
+public class DocMatchRewrite extends KustvaktCacheable implements RewriteTask.IterableRewritePath,
         BeanInjectable {
 
     private ResourceOperationIface<Document> docDao;
-    private Cache cache;
-
 
     public DocMatchRewrite () {
-        this.cache = CacheManager.getInstance().getCache("documents");
+        super("documents", "key:doc");
     }
 
 
@@ -44,14 +38,14 @@
 
         if (node.has(Attributes.TEXT_SIGLE)) {
             String textSigle = node.get(Attributes.TEXT_SIGLE);
-            Element e = this.cache.get(textSigle);
-            if (e == null) {
+            Object o = this.getCacheValue(textSigle);
+            if (o == null) {
                 doc = docDao.findbyId(textSigle, null);
                 if (doc != null)
-                    this.cache.put(new Element(textSigle, doc));
+                    this.storeInCache(textSigle, doc);
             }
             else
-                doc = (Document) e.getObjectValue();
+                doc = (Document) o;
 
             if (doc != null && doc.isDisabled())
                 node.removeNode(new KoralNode.RewriteIdentifier(
diff --git a/src/main/java/de/ids_mannheim/korap/resource/rewrite/FoundryInject.java b/src/main/java/de/ids_mannheim/korap/resource/rewrite/FoundryInject.java
index 923e7a2..f308827 100644
--- a/src/main/java/de/ids_mannheim/korap/resource/rewrite/FoundryInject.java
+++ b/src/main/java/de/ids_mannheim/korap/resource/rewrite/FoundryInject.java
@@ -49,7 +49,8 @@
             else
                 layer = node.get("key");
             String foundry = mapper.findFoundry(layer);
-            node.put("foundry", foundry);
+            if (foundry != null)
+                node.put("foundry", foundry);
         }
         return node.rawNode();
     }
diff --git a/src/main/java/de/ids_mannheim/korap/security/ac/ResourceHandler.java b/src/main/java/de/ids_mannheim/korap/security/ac/ResourceHandler.java
index 7d34efa..fb27b4d 100644
--- a/src/main/java/de/ids_mannheim/korap/security/ac/ResourceHandler.java
+++ b/src/main/java/de/ids_mannheim/korap/security/ac/ResourceHandler.java
@@ -1,5 +1,6 @@
 package de.ids_mannheim.korap.security.ac;
 
+import de.ids_mannheim.korap.config.KustvaktCacheable;
 import de.ids_mannheim.korap.exceptions.EmptyResultException;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.exceptions.NotAuthorizedException;
@@ -23,15 +24,18 @@
 //todo: use interface (maybe a cachable interface?) and bean instanceing
 // todo: if cachable, data integrity needs to be checked! either remove caching or check integrity!
 @SuppressWarnings("all")
-public class ResourceHandler {
+public class ResourceHandler extends KustvaktCacheable {
 
     private static Logger jlog = LoggerFactory.getLogger(ResourceHandler.class);
 
 
-    public ResourceHandler () {}
+    public ResourceHandler () {
+        super("resources", "key:resources");
+    }
 
 
-    public <T extends KustvaktResource> T getCache (Object id, Class<T> clazz) {
+    @Deprecated
+    public <T extends KustvaktResource> T getCache (Object id, Class<T> cz) {
         Element e = CacheManager.getInstance().getCache("resources").get(id);
         if (e != null)
             return (T) e.getObjectValue();
@@ -40,6 +44,7 @@
     }
 
 
+    @Deprecated
     public <R extends KustvaktResource> void cache (R resource) {
         CacheManager.getInstance().getCache("resources")
                 .put(new Element(resource.getPersistentID(), resource));
diff --git a/src/main/java/de/ids_mannheim/korap/security/auth/APIAuthentication.java b/src/main/java/de/ids_mannheim/korap/security/auth/APIAuthentication.java
index 977f797..aed87d5 100644
--- a/src/main/java/de/ids_mannheim/korap/security/auth/APIAuthentication.java
+++ b/src/main/java/de/ids_mannheim/korap/security/auth/APIAuthentication.java
@@ -3,6 +3,7 @@
 import com.nimbusds.jose.JOSEException;
 import com.nimbusds.jwt.SignedJWT;
 import de.ids_mannheim.korap.config.JWTSigner;
+import de.ids_mannheim.korap.config.KustvaktCacheable;
 import de.ids_mannheim.korap.config.KustvaktConfiguration;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.exceptions.StatusCodes;
@@ -27,25 +28,20 @@
     private JWTSigner signedToken;
     private Cache invalided = CacheManager.getInstance().getCache(
             "id_tokens_inv");
-    private Cache id_tokens = CacheManager.getInstance().getCache("id_tokens");
+    //private Cache id_tokens = CacheManager.getInstance().getCache("id_tokens");
 
 
-    public APIAuthentication (KustvaktConfiguration bconfig) {
-        KustvaktConfiguration config = bconfig;
+    public APIAuthentication (KustvaktConfiguration config) {
         this.signedToken = new JWTSigner(config.getSharedSecret(),
                 config.getIssuer(), config.getTokenTTL());
     }
 
 
-    //    @Cacheable(value = "id_tokens", key = "#authToken")
-    // todo: test
     @Override
-    public TokenContext getUserStatus (String authToken)
+    public TokenContext getTokenContext(String authToken)
             throws KustvaktException {
         TokenContext context;
-        Element e = id_tokens.get(authToken);
-        Element ein = invalided.get(authToken);
-        if (e == null && ein == null) {
+        //Element ein = invalided.get(authToken);
             try {
                 authToken = StringUtils.stripTokenType(authToken);
                 context = signedToken.getTokenContext(authToken);
@@ -54,18 +50,14 @@
             catch (JOSEException | ParseException ex) {
                 throw new KustvaktException(StatusCodes.ILLEGAL_ARGUMENT);
             }
-        }
-        else if (ein == null) {
-            context = (TokenContext) e.getObjectValue();
-        }
-        else
-            throw new KustvaktException(StatusCodes.EXPIRED);
+        //context = (TokenContext) e.getObjectValue();
+        //throw new KustvaktException(StatusCodes.EXPIRED);
         return context;
     }
 
 
     @Override
-    public TokenContext createUserSession (User user, Map<String, Object> attr)
+    public TokenContext createTokenContext(User user, Map<String, Object> attr)
             throws KustvaktException {
         TokenContext c = new TokenContext();
         c.setUsername(user.getUsername());
@@ -78,14 +70,12 @@
         }
         c.setTokenType(Attributes.API_AUTHENTICATION);
         c.setToken(jwt.serialize());
-        id_tokens.put(new Element(c.getToken(), c));
-
+        //id_tokens.put(new Element(c.getToken(), c));
         return c;
     }
 
 
     // todo: cache and set expiration to token expiration. if token in that cache, it is not to be used anymore!
-    // fixme: dont use annotations but function calls
     //    @CacheEvict(value = "id_tokens", key = "#token")
     @Override
     public void removeUserSession (String token) throws KustvaktException {
diff --git a/src/main/java/de/ids_mannheim/korap/security/auth/BasicHttpAuth.java b/src/main/java/de/ids_mannheim/korap/security/auth/BasicHttpAuth.java
index 8c1ad22..0d828cb 100644
--- a/src/main/java/de/ids_mannheim/korap/security/auth/BasicHttpAuth.java
+++ b/src/main/java/de/ids_mannheim/korap/security/auth/BasicHttpAuth.java
@@ -1,6 +1,7 @@
 package de.ids_mannheim.korap.security.auth;
 
 import de.ids_mannheim.korap.config.BeansFactory;
+import de.ids_mannheim.korap.config.KustvaktConfiguration;
 import de.ids_mannheim.korap.config.Scopes;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.exceptions.StatusCodes;
@@ -13,9 +14,11 @@
 import de.ids_mannheim.korap.user.User;
 import de.ids_mannheim.korap.utils.NamingUtils;
 import de.ids_mannheim.korap.utils.StringUtils;
+import de.ids_mannheim.korap.utils.TimeUtils;
 import org.apache.commons.codec.binary.Base64;
 import org.apache.oltu.oauth2.common.utils.OAuthUtils;
 
+import java.beans.Beans;
 import java.util.Map;
 
 /**
@@ -24,6 +27,17 @@
  */
 public class BasicHttpAuth implements AuthenticationIface {
 
+    private KustvaktConfiguration config;
+
+    public BasicHttpAuth() {
+
+    }
+
+    public BasicHttpAuth(KustvaktConfiguration config) {
+        this.config = config;
+    }
+
+
     public static String[] decode (String token) {
         return OAuthUtils.decodeClientAuthenticationHeader(token);
     }
@@ -37,8 +51,10 @@
 
 
     @Override
-    public TokenContext getUserStatus (String authToken)
+    public TokenContext getTokenContext(String authToken)
             throws KustvaktException {
+        //fixme: handled via constructor
+        this.config = BeansFactory.getKustvaktContext().getConfiguration();
         EncryptionIface crypto = BeansFactory.getKustvaktContext()
                 .getEncryption();
         EntityHandlerIface dao = BeansFactory.getKustvaktContext()
@@ -55,6 +71,7 @@
                     return null;
             }
             c.setUsername(values[0]);
+            c.setExpirationTime(TimeUtils.plusSeconds(this.config.getExpiration()).getMillis());
             c.setTokenType(Attributes.BASIC_AUTHENTICATION);
             // todo: for production mode, set true
             c.setSecureRequired(false);
@@ -70,7 +87,7 @@
 
     // not supported!
     @Override
-    public TokenContext createUserSession (User user, Map<String, Object> attr)
+    public TokenContext createTokenContext(User user, Map<String, Object> attr)
             throws KustvaktException {
         return null;
     }
diff --git a/src/main/java/de/ids_mannheim/korap/security/auth/KustvaktAuthenticationManager.java b/src/main/java/de/ids_mannheim/korap/security/auth/KustvaktAuthenticationManager.java
index ccb8092..1184ac8 100644
--- a/src/main/java/de/ids_mannheim/korap/security/auth/KustvaktAuthenticationManager.java
+++ b/src/main/java/de/ids_mannheim/korap/security/auth/KustvaktAuthenticationManager.java
@@ -9,20 +9,18 @@
 import de.ids_mannheim.korap.interfaces.AuthenticationIface;
 import de.ids_mannheim.korap.interfaces.AuthenticationManagerIface;
 import de.ids_mannheim.korap.interfaces.EncryptionIface;
+import de.ids_mannheim.korap.interfaces.ValidatorIface;
 import de.ids_mannheim.korap.interfaces.db.AuditingIface;
 import de.ids_mannheim.korap.interfaces.db.EntityHandlerIface;
 import de.ids_mannheim.korap.interfaces.db.UserDataDbIface;
+import de.ids_mannheim.korap.interfaces.defaults.ApacheValidator;
 import de.ids_mannheim.korap.user.*;
 import de.ids_mannheim.korap.utils.StringUtils;
 import de.ids_mannheim.korap.utils.TimeUtils;
-import net.sf.ehcache.Cache;
-import net.sf.ehcache.CacheManager;
-import net.sf.ehcache.Element;
-import org.joda.time.DateTime;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.springframework.cache.annotation.CachePut;
 
+import java.io.IOException;
 import java.io.UnsupportedEncodingException;
 import java.security.NoSuchAlgorithmException;
 import java.util.Collection;
@@ -38,7 +36,6 @@
  */
 public class KustvaktAuthenticationManager extends AuthenticationManagerIface {
 
-    private static String KEY = "kustvakt:key";
     private static Logger jlog = LoggerFactory
             .getLogger(KustvaktAuthenticationManager.class);
     private EncryptionIface crypto;
@@ -47,21 +44,25 @@
     private KustvaktConfiguration config;
     private Collection userdatadaos;
     private LoginCounter counter;
-    private Cache user_cache;
-
+    private ValidatorIface validator;
 
     public KustvaktAuthenticationManager (EntityHandlerIface userdb,
                                           EncryptionIface crypto,
                                           KustvaktConfiguration config,
                                           AuditingIface auditer,
                                           Collection<UserDataDbIface> userdatadaos) {
-        this.user_cache = CacheManager.getInstance().getCache("users");
         this.entHandler = userdb;
         this.config = config;
         this.crypto = crypto;
         this.auditing = auditer;
         this.counter = new LoginCounter(config);
         this.userdatadaos = userdatadaos;
+        // todo: load via beancontext
+        try {
+            this.validator = new ApacheValidator();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
     }
 
 
@@ -74,6 +75,7 @@
      * @return
      * @throws KustvaktException
      */
+    @Override
     public TokenContext getTokenStatus (String token, String host,
             String useragent) throws KustvaktException {
         jlog.info("getting session status of token type '{}'",
@@ -82,41 +84,46 @@
                 StringUtils.getTokenType(token), null);
 
         if (provider == null)
-            // throw exception for missing type paramter
+            // throw exception for missing type parameter
             throw new KustvaktException(StatusCodes.ILLEGAL_ARGUMENT,
                     "token type not defined or found", "token_type");
 
-        TokenContext context = provider.getUserStatus(token);
+        TokenContext context = provider.getTokenContext(token);
+        System.out.println("CONTEXT "+ context.toResponse());
+        if (context != null && TimeUtils.isExpired(context.getExpirationTime()))
+            throw new KustvaktException(StatusCodes.EXPIRED);
+
         //        if (!matchStatus(host, useragent, context))
         //            provider.removeUserSession(token);
         return context;
     }
 
 
+    @Override
     public User getUser (String username) throws KustvaktException {
-        User user;
-        String key = cache_key(username);
-        Element e = user_cache.get(key);
+        //User user;
+        //Object value = this.getCacheValue(username);
 
         if (User.UserFactory.isDemo(username))
             return User.UserFactory.getDemoUser();
 
-        if (e != null) {
-            Map map = (Map) e.getObjectValue();
-            user = User.UserFactory.toUser(map);
-        }
-        else {
-            user = entHandler.getAccount(username);
-            user_cache.put(new Element(key, user.toCache()));
+        //if (value != null) {
+         //   Map map = (Map) value;
+          //  user = User.UserFactory.toUser(map);
+        //}
+       // else {
+        //    user = entHandler.getAccount(username);
+        //    this.storeInCache(username, user.toCache());
             // todo: not valid. for the duration of the session, the host should not change!
-        }
+        //}
         //todo:
         //        user.addField(Attributes.HOST, context.getHostAddress());
         //        user.addField(Attributes.USER_AGENT, context.getUserAgent());
-        return user;
+        return entHandler.getAccount(username);
     }
 
 
+
     public TokenContext refresh (TokenContext context) throws KustvaktException {
         AuthenticationIface provider = getProvider(context.getTokenType(), null);
         if (provider == null) {
@@ -126,7 +133,7 @@
         try {
             provider.removeUserSession(context.getToken());
             User user = getUser(context.getUsername());
-            return provider.createUserSession(user, context.params());
+            return provider.createTokenContext(user, context.params());
         }
         catch (KustvaktException e) {
             throw new WrappedException(e, StatusCodes.LOGIN_FAILED);
@@ -163,9 +170,7 @@
     }
 
 
-    // todo: dont use annotations for caching
     @Override
-    @CachePut(value = "users", key = "#user.getUsername()")
     public TokenContext createTokenContext (User user,
             Map<String, Object> attr, String provider_key)
             throws KustvaktException {
@@ -175,7 +180,7 @@
         if (attr.get(Attributes.SCOPES) != null)
             this.getUserData(user, UserDetails.class);
 
-        TokenContext context = provider.createUserSession(user, attr);
+        TokenContext context = provider.createTokenContext(user, attr);
         if (context == null)
             throw new KustvaktException(StatusCodes.NOT_SUPPORTED);
         context.setUserAgent((String) attr.get(Attributes.USER_AGENT));
@@ -205,12 +210,11 @@
             throw new KustvaktException(StatusCodes.REQUEST_INVALID);
 
         if (!attributes.containsKey(Attributes.EMAIL)
-                && crypto.validateEntry(eppn, Attributes.EMAIL) != null)
+                && validator.isValid(eppn, Attributes.EMAIL))
             attributes.put(Attributes.EMAIL, eppn);
 
-        // fixme?!
-        User user = isRegistered(eppn);
-        if (user == null)
+        User user = null;
+        if (isRegistered(eppn))
             user = createShibbUserAccount(attributes);
         return user;
     }
@@ -219,32 +223,30 @@
     //todo: what if attributes null?
     private User authenticate (String username, String password,
             Map<String, Object> attr) throws KustvaktException {
-        Map<String, Object> attributes = crypto.validateMap(attr);
-        String safeUS;
+        Map<String, Object> attributes = validator.validateMap(attr);
         User unknown;
         // just to make sure that the plain password does not appear anywhere in the logs!
 
         try {
-            safeUS = crypto.validateEntry(username, Attributes.USERNAME);
-        }
-        catch (KustvaktException e) {
+            validator.validateEntry(username, Attributes.USERNAME);
+        } catch (KustvaktException e) {
             throw new WrappedException(e, StatusCodes.LOGIN_FAILED, username);
         }
 
-        if (safeUS == null || safeUS.isEmpty())
+        if (username == null || username.isEmpty())
             throw new WrappedException(new KustvaktException(username,
                     StatusCodes.BAD_CREDENTIALS), StatusCodes.LOGIN_FAILED);
         else {
             try {
-                unknown = entHandler.getAccount(safeUS);
-            }
-            catch (EmptyResultException e) {
+                unknown = entHandler.getAccount(username);
+            } catch (EmptyResultException e) {
                 // mask exception to disable user guessing in possible attacks
                 throw new WrappedException(new KustvaktException(username,
                         StatusCodes.BAD_CREDENTIALS), StatusCodes.LOGIN_FAILED,
                         username);
             }
             catch (KustvaktException e) {
+                jlog.error("Error: {}", e);
                 throw new WrappedException(e, StatusCodes.LOGIN_FAILED,
                         attributes.toString());
             }
@@ -302,43 +304,44 @@
         else if (unknown instanceof ShibUser) {
             //todo
         }
-        jlog.debug("Authentication done: " + safeUS);
+        jlog.debug("Authentication done: " + username);
         return unknown;
     }
 
 
-    public User isRegistered (String username) throws KustvaktException {
+    public boolean isRegistered (String username) {
         User user;
         if (username == null || username.isEmpty())
-            throw new KustvaktException(username, StatusCodes.ILLEGAL_ARGUMENT,
-                    "username must be set", username);
+            return false;
+        //    throw new KustvaktException(username, StatusCodes.ILLEGAL_ARGUMENT,
+        //            "username must be set", username);
 
         try {
             user = entHandler.getAccount(username);
         }
         catch (EmptyResultException e) {
             jlog.debug("user does not exist ({})", username);
-            return null;
+            return false;
 
         }
         catch (KustvaktException e) {
-            jlog.error("KorAPException", e);
-            throw new KustvaktException(username, StatusCodes.ILLEGAL_ARGUMENT,
-                    "username invalid", username);
+            jlog.error("KorAPException", e.string());
+            return false;
+            //throw new KustvaktException(username, StatusCodes.ILLEGAL_ARGUMENT,
+             //       "username invalid", username);
         }
-        return user;
+        return user != null;
     }
 
 
     public void logout (TokenContext context) throws KustvaktException {
-        String key = cache_key(context.getUsername());
         try {
             AuthenticationIface provider = getProvider(context.getTokenType(),
                     null);
 
             if (provider == null) {
-                //todo:
-                return;
+                throw new KustvaktException(StatusCodes.ILLEGAL_ARGUMENT,
+                        "provider not supported!", context.getTokenType());
             }
             provider.removeUserSession(context.getToken());
         }
@@ -348,7 +351,7 @@
         }
         auditing.audit(AuditRecord.serviceRecord(context.getUsername(),
                 StatusCodes.LOGOUT_SUCCESSFUL, context.toString()));
-        user_cache.remove(key);
+        this.removeCacheEntry(context.getToken());
     }
 
 
@@ -359,7 +362,7 @@
                 this.lockAccount(user);
             }
             catch (KustvaktException e) {
-                jlog.error("user account could not be locked!", e);
+                jlog.error("user account could not be locked", e);
                 throw new WrappedException(e, StatusCodes.UPDATE_ACCOUNT_FAILED);
             }
             throw new WrappedException(new KustvaktException(user.getId(),
@@ -401,8 +404,6 @@
             user.setPassword(crypto.secureHash(newPassword));
         }
         catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
-            //            throw new KorAPException(StatusCodes.ILLEGAL_ARGUMENT,
-            //                    "Creating password hash failed!", "password");
             throw new WrappedException(new KustvaktException(user.getId(),
                     StatusCodes.ILLEGAL_ARGUMENT, "password invalid",
                     newPassword), StatusCodes.PASSWORD_RESET_FAILED,
@@ -416,14 +417,11 @@
     @Override
     public void resetPassword (String uriFragment, String username,
             String newPassphrase) throws KustvaktException {
-        String safeUser, safePass;
-
         try {
-            safeUser = crypto.validateEntry(username, Attributes.USERNAME);
-            safePass = crypto.validateEntry(newPassphrase, Attributes.PASSWORD);
-        }
-        catch (KustvaktException e) {
-            jlog.error("Error", e);
+            validator.validateEntry(username, Attributes.USERNAME);
+            validator.validateEntry(newPassphrase, Attributes.PASSWORD);
+        } catch (KustvaktException e) {
+            jlog.error("Error: {}", e.string());
             throw new WrappedException(new KustvaktException(username,
                     StatusCodes.ILLEGAL_ARGUMENT, "password invalid",
                     newPassphrase), StatusCodes.PASSWORD_RESET_FAILED,
@@ -431,9 +429,8 @@
         }
 
         try {
-            safePass = crypto.secureHash(safePass);
-        }
-        catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
+            newPassphrase= crypto.secureHash(newPassphrase);
+        } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
             jlog.error("Encoding/Algorithm Error", e);
             throw new WrappedException(new KustvaktException(username,
                     StatusCodes.ILLEGAL_ARGUMENT, "password invalid",
@@ -441,30 +438,28 @@
                     username, uriFragment, newPassphrase);
         }
         int result = entHandler
-                .resetPassphrase(safeUser, uriFragment, safePass);
+                .resetPassphrase(username, uriFragment, newPassphrase);
 
         if (result == 0)
             throw new WrappedException(new KustvaktException(username,
                     StatusCodes.EXPIRED, "URI fragment expired", uriFragment),
                     StatusCodes.PASSWORD_RESET_FAILED, username, uriFragment);
         else if (result == 1)
-            jlog.info("successfully reset password for user {}", safeUser);
+            jlog.info("successfully reset password for user {}", username);
     }
 
 
     public void confirmRegistration (String uriFragment, String username)
             throws KustvaktException {
-        String safeUser;
         try {
-            safeUser = crypto.validateEntry(username, Attributes.USERNAME);
-        }
-        catch (KustvaktException e) {
-            jlog.error("error", e);
+            validator.validateEntry(username, Attributes.USERNAME);
+        } catch (KustvaktException e) {
+            jlog.error("Error: {}", e.string());
             throw new WrappedException(e,
                     StatusCodes.ACCOUNT_CONFIRMATION_FAILED, username,
                     uriFragment);
         }
-        int r = entHandler.activateAccount(safeUser, uriFragment);
+        int r = entHandler.activateAccount(username, uriFragment);
         if (r == 0) {
             User user;
             try {
@@ -484,7 +479,7 @@
         }
         else if (r == 1)
             jlog.info("successfully confirmed user registration for user {}",
-                    safeUser);
+                    username);
         // register successful audit!
     }
 
@@ -497,7 +492,8 @@
     //fixme: remove clientinfo object (not needed), use json representation to get stuff
     public User createUserAccount (Map<String, Object> attributes,
             boolean confirmation_required) throws KustvaktException {
-        Map<String, Object> safeMap = crypto.validateMap(attributes);
+        Map<String, Object> safeMap = validator.validateMap(attributes);
+
         if (safeMap.get(Attributes.USERNAME) == null
                 || ((String) safeMap.get(Attributes.USERNAME)).isEmpty())
             throw new KustvaktException(StatusCodes.ILLEGAL_ARGUMENT,
@@ -508,13 +504,13 @@
                     StatusCodes.ILLEGAL_ARGUMENT, "password must be set",
                     "password");
 
-        String username = crypto.validateEntry(
+        String username = validator.validateEntry(
                 (String) safeMap.get(Attributes.USERNAME), Attributes.USERNAME);
-        String safePass = crypto.validateEntry(
+        String password = validator.validateEntry(
                 (String) safeMap.get(Attributes.PASSWORD), Attributes.PASSWORD);
         String hash;
         try {
-            hash = crypto.secureHash(safePass);
+            hash = crypto.secureHash(password);
         }
         catch (UnsupportedEncodingException | NoSuchAlgorithmException e) {
             jlog.error("Encryption error", e);
@@ -534,19 +530,21 @@
         }
         user.setPassword(hash);
         try {
+            UserDetails details = new UserDetails();
+            details.read(safeMap, true);
+
+            UserSettings settings = new UserSettings();
+            settings.read(safeMap, true);
+
             jlog.info("Creating new user account for user {}",
                     user.getUsername());
             entHandler.createAccount(user);
-            UserDetails details = new UserDetails(user.getId());
-            details.read(safeMap, true);
-            details.checkRequired();
-
-            UserSettings settings = new UserSettings(user.getId());
-            settings.read(safeMap, true);
-            settings.checkRequired();
+            details.setUserId(user.getId());
+            settings.setUserId(user.getId());
 
             UserDataDbIface dao = BeansFactory.getTypeFactory()
                     .getTypeInterfaceBean(userdatadaos, UserDetails.class);
+            //todo: remove this
             assert dao != null;
             dao.store(details);
             dao = BeansFactory.getTypeFactory().getTypeInterfaceBean(
@@ -555,6 +553,7 @@
             dao.store(settings);
         }
         catch (KustvaktException e) {
+            jlog.error("Error: {}", e.string());
             throw new WrappedException(e, StatusCodes.CREATE_ACCOUNT_FAILED,
                     user.toString());
         }
@@ -570,7 +569,7 @@
             throws KustvaktException {
         jlog.debug("creating shibboleth user account for user attr: {}",
                 attributes);
-        Map<String, Object> safeMap = crypto.validateMap(attributes);
+        Map<String, Object> safeMap = validator.validateMap(attributes);
 
         //todo eppn non-unique.join with idp or use persistent_id as username identifier
         ShibUser user = User.UserFactory.getShibInstance(
@@ -579,21 +578,24 @@
                 (String) safeMap.get(Attributes.CN));
         user.setAffiliation((String) safeMap.get(Attributes.EDU_AFFIL));
         user.setAccountCreation(TimeUtils.getNow().getMillis());
+
+
+        UserDetails d = new UserDetails();
+        d.read(attributes, true);
+
+        UserSettings s = new UserSettings();
+        s.read(attributes, true);
+
         entHandler.createAccount(user);
 
-        UserDetails d = new UserDetails(user.getId());
-        d.read(attributes, true);
-        d.checkRequired();
+        s.setUserId(user.getId());
+        d.setUserId(user.getId());
 
         UserDataDbIface dao = BeansFactory.getTypeFactory()
                 .getTypeInterfaceBean(userdatadaos, UserDetails.class);
         assert dao != null;
         dao.store(d);
 
-        UserSettings s = new UserSettings(user.getId());
-        s.read(attributes, true);
-        s.checkRequired();
-
         dao = BeansFactory.getTypeFactory().getTypeInterfaceBean(userdatadaos,
                 UserSettings.class);
         assert dao != null;
@@ -648,9 +650,9 @@
     }
 
 
+    // todo: test and rest usage?!
     public boolean updateAccount (User user) throws KustvaktException {
         boolean result;
-        String key = cache_key(user.getUsername());
         if (user instanceof DemoUser)
             throw new KustvaktException(user.getId(),
                     StatusCodes.REQUEST_INVALID,
@@ -661,12 +663,12 @@
                 result = entHandler.updateAccount(user) > 0;
             }
             catch (KustvaktException e) {
-                jlog.error("Error ", e);
+                jlog.error("Error: {}", e.string());
                 throw new WrappedException(e, StatusCodes.UPDATE_ACCOUNT_FAILED);
             }
         }
         if (result) {
-            user_cache.remove(key);
+            // this.removeCacheEntry(user.getUsername());
             auditing.audit(AuditRecord.serviceRecord(user.getId(),
                     StatusCodes.UPDATE_ACCOUNT_SUCCESSFUL, user.toString()));
         }
@@ -676,7 +678,6 @@
 
     public boolean deleteAccount (User user) throws KustvaktException {
         boolean result;
-        String key = cache_key(user.getUsername());
         if (user instanceof DemoUser)
             return true;
         else {
@@ -684,12 +685,12 @@
                 result = entHandler.deleteAccount(user.getId()) > 0;
             }
             catch (KustvaktException e) {
-                jlog.error("Error ", e);
+                jlog.error("Error: {}", e.string());
                 throw new WrappedException(e, StatusCodes.DELETE_ACCOUNT_FAILED);
             }
         }
         if (result) {
-            user_cache.remove(key);
+            // this.removeCacheEntry(user.getUsername());
             auditing.audit(AuditRecord.serviceRecord(user.getUsername(),
                     StatusCodes.DELETE_ACCOUNT_SUCCESSFUL, user.toString()));
         }
@@ -699,8 +700,8 @@
 
     public Object[] validateResetPasswordRequest (String username, String email)
             throws KustvaktException {
-        String mail, uritoken;
-        mail = crypto.validateEntry(email, Attributes.EMAIL);
+        String uritoken;
+        validator.validateEntry(email, Attributes.EMAIL);
         User ident;
         try {
             ident = entHandler.getAccount(username);
@@ -719,7 +720,7 @@
         Userdata data = this.getUserData(ident, UserDetails.class);
         KorAPUser user = (KorAPUser) ident;
 
-        if (!mail.equals(data.get(Attributes.EMAIL)))
+        if (!email.equals(data.get(Attributes.EMAIL)))
             //            throw new NotAuthorizedException(StatusCodes.ILLEGAL_ARGUMENT,
             //                    "invalid parameter: email", "email");
             throw new WrappedException(new KustvaktException(user.getId(),
@@ -734,10 +735,10 @@
             entHandler.updateAccount(user);
         }
         catch (KustvaktException e) {
-            jlog.error("Error ", e);
+            jlog.error("Error ", e.string());
             throw new WrappedException(e, StatusCodes.PASSWORD_RESET_FAILED);
         }
-        return new Object[] { uritoken, new DateTime(param.getUriExpiration()) };
+        return new Object[] { uritoken, TimeUtils.format(param.getUriExpiration()) };
     }
 
 
@@ -771,8 +772,7 @@
     @Override
     public void updateUserData (Userdata data) throws WrappedException {
         try {
-
-            data.validate(this.crypto);
+            data.validate(this.validator);
             UserDataDbIface dao = BeansFactory.getTypeFactory()
                     .getTypeInterfaceBean(
                             BeansFactory.getKustvaktContext()
@@ -785,16 +785,4 @@
             throw new WrappedException(e, StatusCodes.UPDATE_ACCOUNT_FAILED);
         }
     }
-
-
-    private String cache_key (String input) throws KustvaktException {
-        try {
-            return crypto.secureHash(KEY + "@" + input);
-        }
-        catch (Exception e) {
-            jlog.error("illegal cache key input '{}'", input);
-            throw new KustvaktException(StatusCodes.ILLEGAL_ARGUMENT,
-                    "missing or illegal cache key", input);
-        }
-    }
 }
diff --git a/src/main/java/de/ids_mannheim/korap/security/auth/LoginCounter.java b/src/main/java/de/ids_mannheim/korap/security/auth/LoginCounter.java
index 1ae589b..5f0a0e4 100644
--- a/src/main/java/de/ids_mannheim/korap/security/auth/LoginCounter.java
+++ b/src/main/java/de/ids_mannheim/korap/security/auth/LoginCounter.java
@@ -53,7 +53,7 @@
     public boolean validate (String username) {
         Long[] set = failedLogins.get(username);
         if (set != null) {
-            if (TimeUtils.isPassed(set[1])) {
+            if (TimeUtils.isExpired(set[1])) {
                 failedLogins.remove(username);
                 return true;
             }
diff --git a/src/main/java/de/ids_mannheim/korap/security/auth/OpenIDconnectAuthentication.java b/src/main/java/de/ids_mannheim/korap/security/auth/OpenIDconnectAuthentication.java
index 9515c93..75a25f6 100644
--- a/src/main/java/de/ids_mannheim/korap/security/auth/OpenIDconnectAuthentication.java
+++ b/src/main/java/de/ids_mannheim/korap/security/auth/OpenIDconnectAuthentication.java
@@ -38,9 +38,8 @@
     }
 
 
-    @Cacheable(value = "id_tokens", key = "#authToken")
     @Override
-    public TokenContext getUserStatus (String authToken)
+    public TokenContext getTokenContext(String authToken)
             throws KustvaktException {
         authToken = StringUtils.stripTokenType(authToken);
         return this.database.getContext(authToken);
@@ -48,7 +47,7 @@
 
 
     @Override
-    public TokenContext createUserSession (User user, Map<String, Object> attr)
+    public TokenContext createTokenContext(User user, Map<String, Object> attr)
             throws KustvaktException {
         String cl_secret = (String) attr.get(Attributes.CLIENT_SECRET);
         if (cl_secret == null)
@@ -73,7 +72,6 @@
     }
 
 
-    @CacheEvict(value = "id_tokens", key = "#token")
     @Override
     public void removeUserSession (String token) throws KustvaktException {
         // emit token from cache only
diff --git a/src/main/java/de/ids_mannheim/korap/security/auth/SessionAuthentication.java b/src/main/java/de/ids_mannheim/korap/security/auth/SessionAuthentication.java
index 5caab24..e0b3f51 100644
--- a/src/main/java/de/ids_mannheim/korap/security/auth/SessionAuthentication.java
+++ b/src/main/java/de/ids_mannheim/korap/security/auth/SessionAuthentication.java
@@ -49,7 +49,7 @@
 
 
     @Override
-    public TokenContext getUserStatus (String authenticationToken)
+    public TokenContext getTokenContext(String authenticationToken)
             throws KustvaktException {
         jlog.debug("retrieving user session for user '{}'", authenticationToken);
         if (authenticationToken == null)
@@ -59,7 +59,7 @@
 
 
     @Override
-    public TokenContext createUserSession (User user, Map<String, Object> attr)
+    public TokenContext createTokenContext(User user, Map<String, Object> attr)
             throws KustvaktException {
         DateTime now = TimeUtils.getNow();
         DateTime ex = TimeUtils.getExpiration(now.getMillis(),
diff --git a/src/main/java/de/ids_mannheim/korap/user/DataFactory.java b/src/main/java/de/ids_mannheim/korap/user/DataFactory.java
index be6f02f..354fcd6 100644
--- a/src/main/java/de/ids_mannheim/korap/user/DataFactory.java
+++ b/src/main/java/de/ids_mannheim/korap/user/DataFactory.java
@@ -5,9 +5,11 @@
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.exceptions.StatusCodes;
+import de.ids_mannheim.korap.interfaces.ValidatorIface;
 import de.ids_mannheim.korap.interfaces.db.UserDataDbIface;
 import de.ids_mannheim.korap.utils.JsonUtils;
 
+import java.io.IOException;
 import java.util.*;
 
 /**
@@ -48,6 +50,7 @@
 
     public abstract Collection<Object> values (Object data);
 
+    public abstract Object validate(Object data, ValidatorIface validator);
 
     @Deprecated
     public abstract Map<String, Object> fields (Object data);
@@ -118,6 +121,19 @@
             return new HashSet<>();
         }
 
+        @Override
+        public Object validate(Object data, ValidatorIface validator) {
+            if (checkDataType(data) && ((JsonNode) data).isObject()) {
+                try {
+                    Map mdata = JsonUtils.read(toStringValue(data), HashMap.class);
+                    return validator.validateMap(mdata);
+                } catch (IOException e) {
+                    // do nothing
+                }
+            }
+            return JsonUtils.createObjectNode();
+        }
+
 
         @Override
         public Map<String, Object> fields (Object data) {
diff --git a/src/main/java/de/ids_mannheim/korap/user/TokenContext.java b/src/main/java/de/ids_mannheim/korap/user/TokenContext.java
index c7da851..3c8ad0d 100644
--- a/src/main/java/de/ids_mannheim/korap/user/TokenContext.java
+++ b/src/main/java/de/ids_mannheim/korap/user/TokenContext.java
@@ -4,6 +4,7 @@
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import de.ids_mannheim.korap.config.Attributes;
 import de.ids_mannheim.korap.utils.JsonUtils;
+import de.ids_mannheim.korap.utils.TimeUtils;
 import lombok.AccessLevel;
 import lombok.Data;
 import lombok.Getter;
@@ -26,7 +27,7 @@
      * session relevant data. Are never persisted into a database
      */
     private String username;
-    private Date expirationTime;
+    private long expirationTime;
     // either "session_token " / "api_token
     private String tokenType;
     private String token;
@@ -44,6 +45,7 @@
         this.setUsername("");
         this.setToken("");
         this.setSecureRequired(false);
+        this.setExpirationTime(-1);
     }
 
 
@@ -90,7 +92,7 @@
 
 
     public void setExpirationTime (long date) {
-        this.expirationTime = new Date(date);
+        this.expirationTime = date;
     }
 
 
@@ -141,7 +143,7 @@
     public String toResponse () {
         ObjectNode node = JsonUtils.createObjectNode();
         node.put("token", this.getToken());
-        node.put("expires", this.getExpirationTime().getTime());
+        node.put("expires", TimeUtils.format(this.getExpirationTime()));
         node.put("token_type", this.getTokenType());
         return JsonUtils.toJSON(node);
     }
diff --git a/src/main/java/de/ids_mannheim/korap/user/User.java b/src/main/java/de/ids_mannheim/korap/user/User.java
index af1e90a..7cf211d 100644
--- a/src/main/java/de/ids_mannheim/korap/user/User.java
+++ b/src/main/java/de/ids_mannheim/korap/user/User.java
@@ -225,7 +225,7 @@
                     : (Integer) kmap.get(Attributes.ID, Integer.class);
 
             if (map.get(Attributes.ACCOUNT_CREATION) != null)
-                created = DateTime.parse(kmap.get(Attributes.ACCOUNT_CREATION))
+                created = TimeUtils.getTime(kmap.get(Attributes.ACCOUNT_CREATION))
                         .getMillis();
             switch (type) {
                 case 0:
diff --git a/src/main/java/de/ids_mannheim/korap/user/UserDetails.java b/src/main/java/de/ids_mannheim/korap/user/UserDetails.java
index d4e84c6..9901592 100644
--- a/src/main/java/de/ids_mannheim/korap/user/UserDetails.java
+++ b/src/main/java/de/ids_mannheim/korap/user/UserDetails.java
@@ -9,11 +9,16 @@
  */
 public class UserDetails extends Userdata {
 
-    public UserDetails (Integer userid) {
+
+    public UserDetails() {
+
+    }
+
+    public UserDetails(Integer userid) {
         super(userid);
     }
 
-
+    //todo: make configurable!
     @Override
     public String[] requiredFields () {
         return new String[] { Attributes.EMAIL, Attributes.ADDRESS,
diff --git a/src/main/java/de/ids_mannheim/korap/user/UserSettings.java b/src/main/java/de/ids_mannheim/korap/user/UserSettings.java
index 7149b4b..5ab7c7e 100644
--- a/src/main/java/de/ids_mannheim/korap/user/UserSettings.java
+++ b/src/main/java/de/ids_mannheim/korap/user/UserSettings.java
@@ -8,7 +8,11 @@
  */
 public class UserSettings extends Userdata {
 
-    public UserSettings (Integer userid) {
+    public UserSettings() {
+
+    }
+
+    public UserSettings(Integer userid) {
         super(userid);
     }
 
diff --git a/src/main/java/de/ids_mannheim/korap/user/Userdata.java b/src/main/java/de/ids_mannheim/korap/user/Userdata.java
index e14a3fb..60d851e 100644
--- a/src/main/java/de/ids_mannheim/korap/user/Userdata.java
+++ b/src/main/java/de/ids_mannheim/korap/user/Userdata.java
@@ -2,7 +2,7 @@
 
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.exceptions.StatusCodes;
-import de.ids_mannheim.korap.interfaces.EncryptionIface;
+import de.ids_mannheim.korap.interfaces.ValidatorIface;
 import lombok.AccessLevel;
 import lombok.Getter;
 import lombok.Setter;
@@ -22,12 +22,16 @@
     @Setter(AccessLevel.PRIVATE)
     private Object data;
     @Getter
-    @Setter(AccessLevel.PRIVATE)
-    private Integer userID;
+    @Setter
+    private Integer userId;
 
 
-    public Userdata (Integer userid) {
-        this.userID = userid;
+    public Userdata () {
+        this(-1);
+    }
+
+    public Userdata(Integer userid) {
+        this.userId = userid;
         this.id = -1;
         this.data = DataFactory.getFactory().convertData(null);
     }
@@ -64,9 +68,9 @@
 
 
     public void checkRequired () throws KustvaktException {
-        if (!isValid()) {
-            String[] fields = missing();
-            throw new KustvaktException(userID, StatusCodes.MISSING_ARGUMENTS,
+        String[] fields = missing();
+        if (missing().length != 0) {
+            throw new KustvaktException(userId, StatusCodes.MISSING_ARGUMENTS,
                     "User data object not valid. Object has missing fields!",
                     Arrays.asList(fields).toString());
         }
@@ -106,10 +110,9 @@
         DataFactory.getFactory().addValue(this.data, key, value);
     }
 
-
-    // todo:
-    public void validate (EncryptionIface crypto) throws KustvaktException {
-        //this.fields = crypto.validateMap(this.fields);
+    // todo: test
+    public void validate (ValidatorIface validator) throws KustvaktException {
+        DataFactory.getFactory().validate(this.data, validator);
     }
 
 
diff --git a/src/main/java/de/ids_mannheim/korap/user/UserdataFactory.java b/src/main/java/de/ids_mannheim/korap/user/UserdataFactory.java
deleted file mode 100644
index c2768b4..0000000
--- a/src/main/java/de/ids_mannheim/korap/user/UserdataFactory.java
+++ /dev/null
@@ -1,93 +0,0 @@
-package de.ids_mannheim.korap.user;
-
-import de.ids_mannheim.korap.config.BeansFactory;
-import de.ids_mannheim.korap.config.KustvaktClassLoader;
-import de.ids_mannheim.korap.exceptions.KustvaktException;
-import de.ids_mannheim.korap.exceptions.StatusCodes;
-import de.ids_mannheim.korap.interfaces.db.PersistenceClient;
-import de.ids_mannheim.korap.interfaces.db.UserDataDbIface;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author hanl
- * @date 27/01/2016
- */
-@Deprecated
-public class UserdataFactory {
-
-    private static final Map<Class<? extends Userdata>, UserDataDbIface> instances = new HashMap<>();
-
-
-    private UserdataFactory () {}
-
-
-    public static UserDataDbIface getDaoInstanceFromBean (
-            Class<? extends Userdata> type) {
-        Collection<UserDataDbIface> daos = BeansFactory.getKustvaktContext()
-                .getUserDataProviders();
-        for (UserDataDbIface o : daos) {
-            Type gtype = o.getClass().getGenericInterfaces()[0];
-            if (gtype instanceof ParameterizedType) {
-                ParameterizedType ptype = (ParameterizedType) gtype;
-                Class ctype = (Class) ptype.getActualTypeArguments()[0];
-                if (ctype.equals(type))
-                    return o;
-            }
-        }
-        return null;
-    }
-
-
-    public static Class<? extends UserDataDbIface> getClassFromAnno (
-            Class<? extends Userdata> data) {
-        Set<Class<? extends UserDataDbIface>> c = KustvaktClassLoader
-                .loadSubTypes(UserDataDbIface.class);
-        for (Class<? extends UserDataDbIface> o : c) {
-            Type type = o.getGenericInterfaces()[0];
-            if (type instanceof ParameterizedType) {
-                ParameterizedType ptype = (ParameterizedType) type;
-                Class ctype = (Class) ptype.getActualTypeArguments()[0];
-                if (ctype.equals(data))
-                    return o;
-            }
-        }
-        return null;
-    }
-
-
-    // todo: remove and load userdata via bean context
-    @Deprecated
-    public static UserDataDbIface getDaoInstance (Class<? extends Userdata> data)
-            throws KustvaktException {
-        if (instances.get(data) == null) {
-            Class<? extends UserDataDbIface> cl = getClassFromAnno(data);
-            if (cl != null) {
-                try {
-                    Constructor c = cl.getConstructor(PersistenceClient.class);
-                    UserDataDbIface iface = (UserDataDbIface) c
-                            .newInstance(BeansFactory.getKustvaktContext()
-                                    .getPersistenceClient());
-                    instances.put(data, iface);
-                    return iface;
-                }
-                catch (NoSuchMethodException | InvocationTargetException
-                        | InstantiationException | IllegalAccessException e) {
-                    return null;
-                }
-            }
-            throw new KustvaktException(StatusCodes.NOT_SUPPORTED,
-                    "No database handler found for type "
-                            + data.getSimpleName());
-        }
-        else
-            return instances.get(data);
-    }
-}
diff --git a/src/main/java/de/ids_mannheim/korap/utils/ServiceInfo.java b/src/main/java/de/ids_mannheim/korap/utils/ServiceInfo.java
index a30c8be..947f69d 100644
--- a/src/main/java/de/ids_mannheim/korap/utils/ServiceInfo.java
+++ b/src/main/java/de/ids_mannheim/korap/utils/ServiceInfo.java
@@ -1,5 +1,6 @@
 package de.ids_mannheim.korap.utils;
 
+import de.ids_mannheim.korap.config.ConfigLoader;
 import lombok.Getter;
 
 import java.io.IOException;
@@ -14,12 +15,20 @@
 
     private static final ServiceInfo info = new ServiceInfo();
 
-    private static String UNKNOWN = "UNKNOWN";
+    public static final String UNKNOWN = "UNKNOWN";
 
     @Getter
     private String name;
     @Getter
     private String version;
+    @Getter
+    private String config;
+    @Getter
+    private String logger;
+    @Getter
+    private Boolean cacheable;
+    @Getter
+    private String cache_store;
 
 
     private ServiceInfo () {
@@ -35,17 +44,25 @@
             stream.close();
             this.version = (String) props.get("kustvakt.version");
             this.name = (String) props.get("kustvakt.name");
+            this.config = (String) props.get("kustvakt.properties");
+            this.logger = (String) props.get("kustvakt.logging");
+            this.cacheable = Boolean.valueOf((String) props.get("kustvakt.cache"));
+            this.cache_store = (String) props.get("kustvakt.cache_store");
         }
         catch (IOException e) {
             this.version = UNKNOWN;
             this.name = UNKNOWN;
+            this.logger = UNKNOWN;
+            this.config = UNKNOWN;
+            this.cacheable = false;
+            this.cache_store = UNKNOWN;
         }
     }
 
 
     private static InputStream getStream () throws IOException {
-        String path = "/kustvakt.info";
-        InputStream stream = ServiceInfo.class.getResourceAsStream(path);
+        String path = "kustvakt.info";
+        InputStream stream = ConfigLoader.loadConfigStream(path);
         if (stream == null)
             throw new IOException("stream for resource " + path
                     + " could not be found...");
diff --git a/src/main/java/de/ids_mannheim/korap/utils/StringUtils.java b/src/main/java/de/ids_mannheim/korap/utils/StringUtils.java
index f942250..08ceeba 100644
--- a/src/main/java/de/ids_mannheim/korap/utils/StringUtils.java
+++ b/src/main/java/de/ids_mannheim/korap/utils/StringUtils.java
@@ -4,6 +4,8 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
 import java.util.*;
 
 public class StringUtils {
@@ -204,5 +206,20 @@
             return null;
     }
 
+    public static String toSHAHash(String input) {
+        try {
+            MessageDigest md = MessageDigest.getInstance("SHA-256");
+            md.update(input.getBytes());
+            byte[] mdbytes = md.digest();
+
+            StringBuffer sb = new StringBuffer();
+            for (int i = 0; i < mdbytes.length; i++)
+                sb.append(Integer.toString((mdbytes[i] & 0xff) + 0x100, 16).substring(1));
+            return sb.toString();
+        } catch (NoSuchAlgorithmException e) {
+            return null;
+        }
+    }
+
 
 }
diff --git a/src/main/java/de/ids_mannheim/korap/utils/TimeUtils.java b/src/main/java/de/ids_mannheim/korap/utils/TimeUtils.java
index e632c50..cac76bb 100644
--- a/src/main/java/de/ids_mannheim/korap/utils/TimeUtils.java
+++ b/src/main/java/de/ids_mannheim/korap/utils/TimeUtils.java
@@ -3,6 +3,7 @@
 import org.joda.time.DateTime;
 import org.joda.time.DateTimeZone;
 import org.joda.time.LocalDate;
+import org.joda.time.format.DateTimeFormat;
 import org.joda.time.format.DateTimeFormatter;
 import org.joda.time.format.ISODateTimeFormat;
 import org.slf4j.Logger;
@@ -26,6 +27,8 @@
 public class TimeUtils {
 
     private static DecimalFormat df = new DecimalFormat("#.#############");
+    private static DateTimeFormatter dtf = DateTimeFormat
+            .forPattern("dd/MM/yyyy");
     private static final DateTimeZone dtz = DateTimeZone.forID("Europe/Berlin");
     private static Logger jlog = LoggerFactory.getLogger(TimeUtils.class);
 
@@ -53,12 +56,17 @@
 
     }
 
-
-    //todo: time zone is wrong!
     public static DateTime getNow () {
-        return DateTime.now().withZone(dtz);
+        return DateTime.now(dtz);
     }
 
+    public static DateTime getTime(String time) {
+        return DateTime.parse(time).withZone(dtz);
+    }
+
+    public static DateTime getTime(long time) {
+        return new DateTime(time).withZone(dtz);
+    }
 
     //returns difference in milliseconds
     public static long calcDiff (DateTime now, DateTime future) {
@@ -68,17 +76,12 @@
     }
 
 
-    public static boolean isPassed (long time) {
+    public static boolean isExpired(long time) {
         return getNow().isAfter(time);
 
     }
 
 
-    public static boolean isPassed (DateTime time) {
-        return isPassed(time.getMillis());
-    }
-
-
     // returns difference in seconds in floating number
     public static float floating (DateTime past, DateTime now) {
         long diff = (now.withZone(dtz).getMillis() - past.withZone(dtz)
@@ -125,13 +128,13 @@
      */
     public static String format (DateTime time) {
         DateTimeFormatter fmt = ISODateTimeFormat.dateTime();
-        return fmt.print(time);
+        return fmt.withZone(dtz).print(time);
     }
 
 
     public static String format (long time) {
         DateTimeFormatter fmt = ISODateTimeFormat.dateTime();
-        return fmt.print(time);
+        return fmt.withZone(dtz).print(time);
     }
 
 
@@ -214,19 +217,4 @@
 
     private static final List<DateTime> times = new ArrayList<>();
 
-
-    @Deprecated
-    public static float benchmark (boolean getFinal) {
-        float value = 0;
-        times.add(getNow());
-        if (getFinal && times.size() > 1) {
-            value = floating(times.get(0), times.get(times.size() - 1));
-            times.clear();
-        }
-        else if (times.size() > 1)
-            value = floating(times.get(times.size() - 2),
-                    times.get(times.size() - 1));
-        return value;
-    }
-
 }
diff --git a/src/main/java/de/ids_mannheim/korap/utils/UserPropertyReader.java b/src/main/java/de/ids_mannheim/korap/utils/UserPropertyReader.java
index df9a1c4..544ceef 100644
--- a/src/main/java/de/ids_mannheim/korap/utils/UserPropertyReader.java
+++ b/src/main/java/de/ids_mannheim/korap/utils/UserPropertyReader.java
@@ -4,6 +4,7 @@
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.exceptions.StatusCodes;
 import de.ids_mannheim.korap.interfaces.EncryptionIface;
+import de.ids_mannheim.korap.interfaces.ValidatorIface;
 import de.ids_mannheim.korap.interfaces.db.EntityHandlerIface;
 import de.ids_mannheim.korap.interfaces.db.UserDataDbIface;
 import de.ids_mannheim.korap.user.*;
@@ -23,18 +24,22 @@
  */
 public class UserPropertyReader extends PropertyReader {
 
+    private static Logger jlog = LoggerFactory
+            .getLogger(UserPropertyReader.class);
+
+
     private Map<String, Properties> props;
     private String path;
     private EntityHandlerIface iface;
     private EncryptionIface crypto;
-    private static Logger jlog = LoggerFactory
-            .getLogger(UserPropertyReader.class);
+    private ValidatorIface validator;
 
 
     public UserPropertyReader (String path) {
         this.path = path;
         this.iface = BeansFactory.getKustvaktContext().getUserDBHandler();
         this.crypto = BeansFactory.getKustvaktContext().getEncryption();
+        this.validator = BeansFactory.getKustvaktContext().getValidator();
     }
 
 
@@ -107,13 +112,15 @@
             //todo: make sure uri is set to 0, so sql queries work with the null value
             //            user.setURIExpiration(0L);
             iface.createAccount(user);
-            UserDetails det = new UserDetails(user.getId());
+            UserDetails det = new UserDetails();
+            det.setUserId(user.getId());
             det.read(vals, true);
-            det.validate(crypto);
+            det.validate(this.validator);
 
-            Userdata set = new UserSettings(user.getId());
+            Userdata set = new UserSettings();
+            set.setUserId(user.getId());
             set.read(vals, true);
-            set.validate(crypto);
+            set.validate(this.validator);
 
             UserDataDbIface dao = BeansFactory.getTypeFactory()
                     .getTypeInterfaceBean(
diff --git a/src/main/java/de/ids_mannheim/korap/web/Arg.java b/src/main/java/de/ids_mannheim/korap/web/Arg.java
deleted file mode 100644
index 1fe8bf3..0000000
--- a/src/main/java/de/ids_mannheim/korap/web/Arg.java
+++ /dev/null
@@ -1,124 +0,0 @@
-package de.ids_mannheim.korap.web;
-
-import de.ids_mannheim.korap.config.KustvaktClassLoader;
-import lombok.Getter;
-
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * @author hanl
- * @date 11/02/2016
- */
-public abstract class Arg<T> {
-
-    @Getter
-    protected T value;
-
-
-    protected Arg () {}
-
-
-    public abstract void setValue (String value);
-
-
-    public String toString () {
-        return "--" + getName();
-    }
-
-
-    public abstract String getName ();
-
-
-    public abstract void run ();
-
-
-    public static Set<Arg> loadArgs (String[] args) {
-        Set<Arg> argSet = new HashSet<>();
-        Set<Class<? extends Arg>> set = KustvaktClassLoader
-                .loadSubTypes(Arg.class);
-
-        for (int idx = 0; idx < args.length; idx++) {
-            for (Class aClass : new HashSet<>(set)) {
-                if (!argSet.contains(aClass)) {
-                    Arg arg;
-                    try {
-                        arg = (Arg) aClass.newInstance();
-                    }
-                    catch (InstantiationException | IllegalAccessException e) {
-                        continue;
-                    }
-                    if (arg.toString().equals(args[idx])) {
-                        int i = args.length - 1;
-                        if (i > idx + 1)
-                            i = idx + 1;
-                        arg.setValue(args[i]);
-                        arg.run();
-                        argSet.add(arg);
-                        set.remove(aClass);
-                    }
-                }
-            }
-        }
-        return argSet;
-    }
-
-    public static class ConfigArg extends Arg<String> {
-
-        @Override
-        public void setValue (String value) {
-            this.value = value;
-        }
-
-
-        @Override
-        public String getName () {
-            return "config";
-        }
-
-
-        @Override
-        public void run () {
-
-        }
-    }
-
-    public static class InitArg extends Arg<Boolean> {
-
-        @Override
-        public void setValue (String value) {
-            this.value = true;
-        }
-
-
-        @Override
-        public String getName () {
-            return "init";
-        }
-
-
-        @Override
-        public void run () {
-
-        }
-    }
-
-    public static class PortArg extends Arg<Integer> {
-
-        @Override
-        public void setValue (String value) {
-            this.value = Integer.valueOf(value);
-        }
-
-
-        @Override
-        public String getName () {
-            return "port";
-        }
-
-
-        @Override
-        public void run () {}
-    }
-
-}
diff --git a/src/main/java/de/ids_mannheim/korap/web/KustvaktBaseServer.java b/src/main/java/de/ids_mannheim/korap/web/KustvaktBaseServer.java
index 48d5030..2939a2a 100644
--- a/src/main/java/de/ids_mannheim/korap/web/KustvaktBaseServer.java
+++ b/src/main/java/de/ids_mannheim/korap/web/KustvaktBaseServer.java
@@ -4,8 +4,6 @@
 import com.sun.jersey.api.core.ResourceConfig;
 import com.sun.jersey.spi.container.servlet.ServletContainer;
 import de.ids_mannheim.korap.config.*;
-import de.ids_mannheim.korap.exceptions.KustvaktException;
-import de.ids_mannheim.korap.web.service.BootableBeanInterface;
 import lombok.Getter;
 import lombok.Setter;
 import org.eclipse.jetty.server.Connector;
@@ -16,19 +14,18 @@
 import org.eclipse.jetty.servlet.ServletHolder;
 import org.eclipse.jetty.util.ssl.SslContextFactory;
 
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
 /**
  * @author hanl
  * @date 01/06/2015
  */
 public abstract class KustvaktBaseServer {
 
+    public KustvaktBaseServer () {
+        KustvaktConfiguration.loadLogger();
+    }
+
+
     public static void main (String[] args) throws Exception {
-        KustvaktConfiguration.loadLog4jLogger();
         KustvaktBaseServer server = new KustvaktBaseServer() {
             @Override
             protected void setup () {}
@@ -40,8 +37,6 @@
         else
             BeansFactory.loadClasspathContext();
 
-        KustvaktCacheManager.init();
-
         kargs.setRootPackages(new String[] { "de.ids_mannheim.korap.web.service.light" });
 
         server.startServer(kargs);
diff --git a/src/main/java/de/ids_mannheim/korap/web/filter/AdminFilter.java b/src/main/java/de/ids_mannheim/korap/web/filter/AdminFilter.java
index c06c3fe..dc60e89 100644
--- a/src/main/java/de/ids_mannheim/korap/web/filter/AdminFilter.java
+++ b/src/main/java/de/ids_mannheim/korap/web/filter/AdminFilter.java
@@ -49,7 +49,7 @@
             }
         }
         else
-            throw KustvaktResponseHandler.throwAuthenticationException();
+            throw KustvaktResponseHandler.throwAuthenticationException("");
         return cr;
     }
 
diff --git a/src/main/java/de/ids_mannheim/korap/web/filter/AuthFilter.java b/src/main/java/de/ids_mannheim/korap/web/filter/AuthFilter.java
index 194d76d..b142a9b 100644
--- a/src/main/java/de/ids_mannheim/korap/web/filter/AuthFilter.java
+++ b/src/main/java/de/ids_mannheim/korap/web/filter/AuthFilter.java
@@ -43,7 +43,7 @@
                         ua);
             }
             catch (KustvaktException e) {
-                throw KustvaktResponseHandler.throwAuthenticationException();
+                throw KustvaktResponseHandler.throwAuthenticationException("");
             }
             // fixme: give reason why access is not granted?
             if (context != null
@@ -52,7 +52,7 @@
                             .isSecureRequired()))
                 request.setSecurityContext(new KustvaktContext(context));
             else
-                throw KustvaktResponseHandler.throwAuthenticationException();
+                throw KustvaktResponseHandler.throwAuthenticationException("");
         }
         return request;
     }
diff --git a/src/main/java/de/ids_mannheim/korap/web/filter/BlockingFilter.java b/src/main/java/de/ids_mannheim/korap/web/filter/BlockingFilter.java
index 4bdaa07..ee0648c 100644
--- a/src/main/java/de/ids_mannheim/korap/web/filter/BlockingFilter.java
+++ b/src/main/java/de/ids_mannheim/korap/web/filter/BlockingFilter.java
@@ -4,6 +4,7 @@
 import com.sun.jersey.spi.container.ContainerRequestFilter;
 import com.sun.jersey.spi.container.ContainerResponseFilter;
 import com.sun.jersey.spi.container.ResourceFilter;
+import de.ids_mannheim.korap.user.TokenContext;
 import de.ids_mannheim.korap.web.utils.KustvaktResponseHandler;
 
 import javax.ws.rs.ext.Provider;
@@ -20,12 +21,17 @@
 
     @Override
     public ContainerRequest filter (ContainerRequest request) {
+        TokenContext context;
         try {
-            request.getUserPrincipal();
+            context = (TokenContext) request.getUserPrincipal();
         }
         catch (UnsupportedOperationException e) {
-            throw KustvaktResponseHandler.throwAuthenticationException();
+            throw KustvaktResponseHandler.throwAuthenticationException("");
         }
+
+        if(context == null)
+            throw KustvaktResponseHandler.throwAuthenticationException("");
+
         return request;
     }
 
diff --git a/src/main/java/de/ids_mannheim/korap/web/service/full/AdminService.java b/src/main/java/de/ids_mannheim/korap/web/service/full/AdminService.java
index cef07ae..de63612 100644
--- a/src/main/java/de/ids_mannheim/korap/web/service/full/AdminService.java
+++ b/src/main/java/de/ids_mannheim/korap/web/service/full/AdminService.java
@@ -44,9 +44,7 @@
 public class AdminService {
 
     private static Logger jlog = LoggerFactory.getLogger(AdminService.class);
-    // todo: map in timeutils
-    private static DateTimeFormatter dtf = DateTimeFormat
-            .forPattern("dd/MM/yyyy");
+
     private AuthenticationManagerIface controller;
     private AuditingIface auditingController;
     private DocumentDao documentDao;
@@ -71,13 +69,13 @@
         DateTime from_date, until_date;
 
         if (from == null)
-            from_date = new DateTime();
+            from_date = TimeUtils.getNow();
         else
-            from_date = DateTime.parse(from, dtf);
+            from_date = TimeUtils.getTime(from);
         if (until == null)
-            until_date = new DateTime();
+            until_date = TimeUtils.getNow();
         else
-            until_date = DateTime.parse(until, dtf);
+            until_date = TimeUtils.getTime(until);
 
         int integer_limit;
         boolean dayOnly = Boolean.valueOf(day);
diff --git a/src/main/java/de/ids_mannheim/korap/web/service/full/OAuthService.java b/src/main/java/de/ids_mannheim/korap/web/service/full/OAuthService.java
index 82bc5ab..02d9f7f 100644
--- a/src/main/java/de/ids_mannheim/korap/web/service/full/OAuthService.java
+++ b/src/main/java/de/ids_mannheim/korap/web/service/full/OAuthService.java
@@ -37,10 +37,7 @@
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.ws.rs.*;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.SecurityContext;
+import javax.ws.rs.core.*;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.util.Collection;
@@ -55,7 +52,6 @@
 //todo: only allow oauth2 access_token requests GET methods?
 //todo: allow refresh tokens
 @Path(KustvaktServer.API_VERSION + "/oauth2")
-//@ResourceFilters({ AccessLevelFilter.class, PiwikFilter.class })
 public class OAuthService {
 
     private OAuth2Handler handler;
@@ -85,7 +81,7 @@
         info.setUrl(host);
         TokenContext ctx = (TokenContext) context.getUserPrincipal();
         try {
-            this.handler.removeClient(info,
+            this.handler.getPersistenceHandler().removeClient(info,
                     this.controller.getUser(ctx.getUsername()));
         }
         catch (KustvaktException e) {
@@ -110,8 +106,8 @@
         info.setRedirect_uri(rurl);
         TokenContext ctx = (TokenContext) context.getUserPrincipal();
         try {
-            this.handler.registerClient(info,
-                    this.controller.getUser(ctx.getUsername()));
+            User user = this.controller.getUser(ctx.getUsername());
+            this.handler.getPersistenceHandler().registerClient(info, user);
         }
         catch (KustvaktException e) {
             throw KustvaktResponseHandler.throwit(e);
@@ -155,7 +151,7 @@
         TokenContext ctx = (TokenContext) context.getUserPrincipal();
         try {
             User user = this.controller.getUser(ctx.getUsername());
-            Collection auths = this.handler.getAuthorizedClients(user.getId());
+            Collection auths = this.handler.getPersistenceHandler().getAuthorizedClients(user.getId());
             if (auths.isEmpty())
                 return Response.noContent().build();
             return Response.ok(JsonUtils.toJSON(auths)).build();
@@ -217,7 +213,7 @@
 
             final String authorizationCode = oauthIssuerImpl
                     .authorizationCode();
-            ClientInfo info = this.handler
+            ClientInfo info = this.handler.getPersistenceHandler()
                     .getClient(oauthRequest.getClientId());
 
             if (info == null
@@ -242,7 +238,7 @@
                         .entity(res.getBody()).build();
             }
 
-            String accessToken = this.handler.getToken(
+            String accessToken = this.handler.getPersistenceHandler().getToken(
                     oauthRequest.getClientId(), user.getId());
 
             //todo: test correct redirect and parameters
@@ -302,7 +298,7 @@
                 String token = oauthIssuerImpl.accessToken();
                 String refresh = oauthIssuerImpl.refreshToken();
 
-                this.handler.addToken(token, refresh, user.getId(),
+                this.handler.getPersistenceHandler().addToken(token, refresh, user.getId(),
                         oauthRequest.getClientId(),
                         StringUtils.toString(oauthRequest.getScopes(), " "),
                         config.getLongTokenTTL());
@@ -384,7 +380,7 @@
         TokenContext ctx = (TokenContext) context.getUserPrincipal();
         try {
 
-            if (!this.handler.revokeToken(ctx.getToken())) {
+            if (!this.handler.getPersistenceHandler().revokeToken(ctx.getToken())) {
                 OAuthResponse res = OAuthASResponse
                         .errorResponse(HttpServletResponse.SC_BAD_REQUEST)
                         .setError(OAuthError.TokenResponse.UNAUTHORIZED_CLIENT)
@@ -437,7 +433,7 @@
             oauthRequest = new OAuthTokenRequest(new FormRequestWrapper(
                     request, form));
 
-            if ((info = this.handler.getClient(oauthRequest.getClientId())) == null) {
+            if ((info = this.handler.getPersistenceHandler().getClient(oauthRequest.getClientId())) == null) {
                 OAuthResponse res = OAuthASResponse
                         .errorResponse(HttpServletResponse.SC_BAD_REQUEST)
                         .setError(OAuthError.TokenResponse.INVALID_CLIENT)
@@ -537,12 +533,12 @@
                 }
 
                 try {
-                    String accessToken = this.handler.getToken(
+                    String accessToken = this.handler.getPersistenceHandler().getToken(
                             oauthRequest.getClientId(), user.getId());
                     if (accessToken == null) {
                         String refresh = oauthIssuerImpl.refreshToken();
                         accessToken = oauthIssuerImpl.accessToken();
-                        this.handler.addToken(accessToken, refresh, user
+                        this.handler.getPersistenceHandler().addToken(accessToken, refresh, user
                                 .getId(), oauthRequest.getClientId(),
                                 StringUtils.toString(oauthRequest.getScopes(),
                                         " "), config.getLongTokenTTL());
diff --git a/src/main/java/de/ids_mannheim/korap/web/service/full/UserService.java b/src/main/java/de/ids_mannheim/korap/web/service/full/UserService.java
index 6750073..9ed2fa4 100644
--- a/src/main/java/de/ids_mannheim/korap/web/service/full/UserService.java
+++ b/src/main/java/de/ids_mannheim/korap/web/service/full/UserService.java
@@ -181,13 +181,13 @@
                     .append(username);
         }
         catch (KustvaktException e) {
-            jlog.error("Eoxception encountered!", e);
+            jlog.error("Eoxception encountered!", e.string());
             throw KustvaktResponseHandler.throwit(e);
         }
 
         ObjectNode obj = JsonUtils.createObjectNode();
         obj.put(Attributes.URI, builder.toString());
-        obj.put(Attributes.URI_EXPIRATION, String.valueOf(objects[1]));
+        obj.put(Attributes.URI_EXPIRATION, objects[1].toString());
         return Response.ok(JsonUtils.toJSON(obj)).build();
     }
 
@@ -213,7 +213,7 @@
 
     @GET
     @Path("info")
-    @ResourceFilters({ AuthFilter.class, DefaultFilter.class,
+    @ResourceFilters({ AuthFilter.class,
             PiwikFilter.class, BlockingFilter.class })
     public Response getStatus (@Context SecurityContext context,
             @QueryParam("scopes") String scopes) {
@@ -230,7 +230,7 @@
             m = Scopes.mapScopes(scopes, data);
         }
         catch (KustvaktException e) {
-            throw KustvaktResponseHandler.throwit(e);
+            throw KustvaktResponseHandler.throwAuthenticationException(ctx.getUsername());
         }
         return Response.ok(m.toEntity()).build();
     }
diff --git a/src/main/java/de/ids_mannheim/korap/web/service/light/LightService.java b/src/main/java/de/ids_mannheim/korap/web/service/light/LightService.java
index fbe670f..ca6ef34 100644
--- a/src/main/java/de/ids_mannheim/korap/web/service/light/LightService.java
+++ b/src/main/java/de/ids_mannheim/korap/web/service/light/LightService.java
@@ -124,10 +124,15 @@
         }
         // todo: should be possible to add the meta part to the query serialization
         jlog.info("Serialized search: {}", jsonld);
-
-        String result = searchKrill.search(jsonld);
-        KustvaktLogger.QUERY_LOGGER.trace("The result set: {}", result);
-        return Response.ok(result).build();
+        try {
+            String result = searchKrill.search(jsonld);
+            KustvaktLogger.QUERY_LOGGER.trace("The result set: {}", result);
+            return Response.ok(result).build();
+        } catch(Exception e) {
+            System.out.println("_____________________________________" );
+            e.printStackTrace();
+        }
+        return Response.ok().build();
     }
 
 
diff --git a/src/main/java/de/ids_mannheim/korap/web/utils/KustvaktMap.java b/src/main/java/de/ids_mannheim/korap/web/utils/KustvaktMap.java
index d657149..8e9de8a 100644
--- a/src/main/java/de/ids_mannheim/korap/web/utils/KustvaktMap.java
+++ b/src/main/java/de/ids_mannheim/korap/web/utils/KustvaktMap.java
@@ -10,13 +10,13 @@
  */
 public class KustvaktMap {
 
-    private boolean mono;
+    private boolean monoTyped;
     private Map<String, Object> values;
 
 
     public KustvaktMap () {
         this.values = new HashMap<>();
-        this.mono = false;
+        this.monoTyped = false;
     }
 
 
@@ -27,13 +27,13 @@
 
 
     public void setMap (Map<String, Object> m) {
-        if (!isGeneric(m) | !this.mono)
+        if (!isGeneric(m) | !this.monoTyped)
             this.values.putAll(m);
     }
 
 
     public boolean isGeneric () {
-        return !this.mono && isGeneric(this.values);
+        return !this.monoTyped && isGeneric(this.values);
     }
 
 
@@ -48,7 +48,7 @@
 
 
     public void setMonoValue (boolean monovalue) {
-        this.mono = monovalue;
+        this.monoTyped = monovalue;
     }
 
 
diff --git a/src/main/java/de/ids_mannheim/korap/web/utils/KustvaktResponseHandler.java b/src/main/java/de/ids_mannheim/korap/web/utils/KustvaktResponseHandler.java
index 6b66d54..66eb5c3 100644
--- a/src/main/java/de/ids_mannheim/korap/web/utils/KustvaktResponseHandler.java
+++ b/src/main/java/de/ids_mannheim/korap/web/utils/KustvaktResponseHandler.java
@@ -69,13 +69,13 @@
     }
 
 
-    public static WebApplicationException throwAuthenticationException () {
+    public static WebApplicationException throwAuthenticationException (String username) {
         return new WebApplicationException(Response
                 .status(Response.Status.UNAUTHORIZED)
                 .header(HttpHeaders.WWW_AUTHENTICATE,
                         "Basic realm=Kustvakt Authentication Service")
                 .entity(buildNotification(StatusCodes.BAD_CREDENTIALS,
-                        "Unauthorized access", "")).build());
+                        "Unauthorized access", username)).build());
     }
 
 
diff --git a/src/main/resources/codes.kustvakt b/src/main/resources/codes.kustvakt
index 01fa0d8..b2fa1fb 100644
--- a/src/main/resources/codes.kustvakt
+++ b/src/main/resources/codes.kustvakt
@@ -1,2 +1,36 @@
-[{code=100, message=}
-]
\ No newline at end of file
+# generic non localized messages for API error codes
+
+# standard system errors #
+100 : "No Entry found!"
+101 : "The request could not be processed!"
+102 : "Entry exists already!"
+103 : "Status ok!"
+104 : "Unsupported Overation!"
+105 : "Illegal argument found. Request could not be processed!"
+106 : "Connection Error"
+107 : "No changes"
+108 : "Parameter Validation failed!"
+109 : ""
+110 : "Not supported!"
+
+
+# 200 codes for user account/ authenticaation services
+200 : "Account deactivated. Please verify account before using this API"
+201 : "Account confirmation failed. Please contact an adminstrator"
+202 : "Already logged in!"
+203 : ""
+204 : "Authentication credentials expired!"
+205 : "Bad credentials!"
+206 : ""
+207 : "Username already exists"
+208 : "Password reset failed"
+209 : ""
+210 : "Login successful!"
+211 : "Login failed!"
+212 : "Logout successful!"
+213 : "Logout failed!"
+214 : "Client registration failed!"
+215 : "Deleting client information failed!"
+216 : "Client could not be authorized!"
+
+
diff --git a/src/main/resources/ehcache.xml b/src/main/resources/ehcache.xml
index 1bbb213..3d999e1 100644
--- a/src/main/resources/ehcache.xml
+++ b/src/main/resources/ehcache.xml
@@ -42,6 +42,7 @@
            memoryStoreEvictionPolicy="LRU"
            maxEntriesLocalHeap="100"
            overflowToDisk='false'/>
+
     <cache name='resources'
            eternal='false'
            overflowToDisk='false'
diff --git a/src/main/resources/kustvakt.info b/src/main/resources/kustvakt.info
index 32b65d1..c1c6cea 100644
--- a/src/main/resources/kustvakt.info
+++ b/src/main/resources/kustvakt.info
@@ -1,2 +1,8 @@
 kustvakt.version=${project.version}
 kustvakt.name=${project.name}
+
+# use this file to define the properties and logging file names
+kustvakt.properties=./kustvakt.conf
+kustvakt.logging=./log4j.properties
+kustvakt.caching=true
+kustvakt.cache_store=./store
\ No newline at end of file
diff --git a/src/main/resources/log4j.properties b/src/main/resources/log4j.properties
index 9754e92..cba69e9 100644
--- a/src/main/resources/log4j.properties
+++ b/src/main/resources/log4j.properties
@@ -1,7 +1,7 @@
 
 # Root logger option
 #log4j.threshold=ALL
-log4j.rootLogger=WARN, stdout, debugLog
+log4j.rootLogger=INFO, stdout, debugLog
 log4j.logger.log=ERROR, errorLog
 
 # Direct log messages to stdout
diff --git a/src/main/resources/validation.properties b/src/main/resources/validation.properties
index 1e9d896..22f27c5 100644
--- a/src/main/resources/validation.properties
+++ b/src/main/resources/validation.properties
@@ -20,14 +20,17 @@
 # try {
 #    someObject.setEmail(ESAPI.validator().getValidInput("User Email", input, "Email", maxLength, allowNull));
 #
-#Validator.SafeString=^[.;:\\-\\p{Alnum}\\p{Space}]{0,1024}$
-Validator.username=^[;=\\*\/\/_()\\-0-9\\p{L}\\p{Space}]{0,15}$
-Validator.password_cap=((?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{8,20})
-Validator.password=((?=.*\\d)(?=.*[a-zA-Z]).{8,20})
+# Validator.SafeString=^[.;:\\-\\p{Alnum}\\p{Space}]{0,1024}$
+# Validator.password_cap=((?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{8,20})
 Validator.SafeString=^[.;:,=\\*\/\/_()\\-0-9\\p{L}\\p{Space}]{0,1024}$
 Validator.email=^[A-Za-z0-9._%'-]+@[A-Za-z0-9.-]+\\.[a-zA-Z]{2,4}$
 Validator.ipddress=^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$
 Validator.url=^(ht|f)tp(s?)\\:\\/\\/[0-9a-zA-Z]([-.\\w]*[0-9a-zA-Z])*(:(0-9)*)*(\\/?)([a-zA-Z0-9\\-\\.\\?\\,\\:\\'\\/\\\\\\+=&amp;%\\$#_]*)?$
-Validator.CreditCard=^(\\d{4}[- ]?){3}\\d{4}$
-Validator.SSN=^(?!000)([0-6]\\d{2}|7([0-6]\\d|7[012]))([ -]?)(?!00)\\d\\d\\3(?!0000)\\d{4}$
+# Validator.CreditCard=^(\\d{4}[- ]?){3}\\d{4}$
+# Validator.SSN=^(?!000)([0-6]\\d{2}|7([0-6]\\d|7[012]))([ -]?)(?!00)\\d\\d\\3(?!0000)\\d{4}$
 
+# as used by apache commons validator for strings
+# Validator.string=^[\\.;:,\\=&\\*\\/\\/_()\\[\\]@\\|\\-0-9\\p{L}\\p{Space}]{0,1024}$
+
+Validator.username=^[A-Za-z_.\\d]{6,15}$
+Validator.password=^((?=.*\\d)(?=.*[A-Za-z])(?!.*[\\(\\)-]).{8,20})$
\ No newline at end of file