refactoring; test inits
diff --git a/dependency-reduced-pom.xml b/dependency-reduced-pom.xml
index 9ebc5a9..e485c69 100644
--- a/dependency-reduced-pom.xml
+++ b/dependency-reduced-pom.xml
@@ -4,10 +4,34 @@
   <groupId>de.ids_mannheim.korap</groupId>

   <artifactId>Kustvakt-core</artifactId>

   <name>Kustvakt core</name>

-  <version>0.2</version>

+  <version>0.4</version>

   <description>Kustvakt core, basic rest api for testing purposes and default

         interfaces</description>

   <build>

+    <resources>

+      <resource>

+        <filtering>true</filtering>

+        <directory>src/main/resources</directory>

+        <includes>

+          <include>**/*.prop</include>

+          <include>**/*.xml</include>

+          <include>**/*.conf</include>

+          <include>**/*.properties</include>

+        </includes>

+      </resource>

+    </resources>

+    <testResources>

+      <testResource>

+        <filtering>true</filtering>

+        <directory>src/main/resources</directory>

+        <includes>

+          <include>**/*.prop</include>

+          <include>**/*.xml</include>

+          <include>**/*.conf</include>

+          <include>**/*.properties</include>

+        </includes>

+      </testResource>

+    </testResources>

     <plugins>

       <plugin>

         <artifactId>maven-jar-plugin</artifactId>

@@ -37,7 +61,7 @@
         <version>2.1</version>

         <executions>

           <execution>

-            <id>light</id>

+            <id>full</id>

             <phase>package</phase>

             <goals>

               <goal>shade</goal>

@@ -70,6 +94,52 @@
       </plugin>

     </plugins>

   </build>

+  <profiles>

+    <profile>

+      <id>light</id>

+      <build>

+        <plugins>

+          <plugin>

+            <artifactId>maven-shade-plugin</artifactId>

+            <version>2.1</version>

+            <executions>

+              <execution>

+                <id>light</id>

+                <phase>package</phase>

+                <goals>

+                  <goal>shade</goal>

+                </goals>

+                <configuration>

+                  <finalName>Kustvakt-core-${project.version}-light</finalName>

+                  <transformers>

+                    <transformer>

+                      <mainClass>de.ids_mannheim.korap.web.KustvaktBaseServer</mainClass>

+                    </transformer>

+                    <transformer>

+                      <resource>META-INF/spring.handlers</resource>

+                    </transformer>

+                    <transformer>

+                      <resource>META-INF/spring.schemas</resource>

+                    </transformer>

+                  </transformers>

+                  <filters>

+                    <filter>

+                      <artifact>*:*</artifact>

+                      <excludes>

+                        <exclude>META-INF/*.SF</exclude>

+                        <exclude>META-INF/*.DSA</exclude>

+                        <exclude>META-INF/*.RSA</exclude>

+                      </excludes>

+                    </filter>

+                  </filters>

+                </configuration>

+              </execution>

+            </executions>

+          </plugin>

+        </plugins>

+      </build>

+    </profile>

+  </profiles>

   <repositories>

     <repository>

       <id>codehaus-release-repo</id>

@@ -126,6 +196,12 @@
       <scope>test</scope>

     </dependency>

     <dependency>

+      <groupId>org.projectlombok</groupId>

+      <artifactId>lombok</artifactId>

+      <version>0.11.8</version>

+      <scope>provided</scope>

+    </dependency>

+    <dependency>

       <groupId>com.restfuse</groupId>

       <artifactId>com.eclipsesource.restfuse</artifactId>

       <version>1.0.0</version>

diff --git a/pom.xml b/pom.xml
index 42a59ab..afa274e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -41,7 +41,7 @@
                                         <transformer
                                                 implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                             <mainClass>
-                                                de.ids_mannheim.korap.web.KustvaktLightServer
+                                                de.ids_mannheim.korap.web.KustvaktBaseServer
                                             </mainClass>
                                         </transformer>
                                         <transformer
diff --git a/src/.DS_Store b/src/.DS_Store
index f62e292..b6a5951 100644
--- a/src/.DS_Store
+++ b/src/.DS_Store
Binary files differ
diff --git a/src/main/.DS_Store b/src/main/.DS_Store
index d4fd3e7..6f2c378 100644
--- a/src/main/.DS_Store
+++ b/src/main/.DS_Store
Binary files differ
diff --git a/src/main/java/.DS_Store b/src/main/java/.DS_Store
index e282944..175efa1 100644
--- a/src/main/java/.DS_Store
+++ b/src/main/java/.DS_Store
Binary files differ
diff --git a/src/main/java/de/.DS_Store b/src/main/java/de/.DS_Store
index b276992..dcbce40 100644
--- a/src/main/java/de/.DS_Store
+++ b/src/main/java/de/.DS_Store
Binary files differ
diff --git a/src/main/java/de/ids_mannheim/.DS_Store b/src/main/java/de/ids_mannheim/.DS_Store
index 07256f1..f61ad44 100644
--- a/src/main/java/de/ids_mannheim/.DS_Store
+++ b/src/main/java/de/ids_mannheim/.DS_Store
Binary files differ
diff --git a/src/main/java/de/ids_mannheim/korap/.DS_Store b/src/main/java/de/ids_mannheim/korap/.DS_Store
index e540d83..f8811c7 100644
--- a/src/main/java/de/ids_mannheim/korap/.DS_Store
+++ b/src/main/java/de/ids_mannheim/korap/.DS_Store
Binary files differ
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 028a9f4..c308e34 100644
--- a/src/main/java/de/ids_mannheim/korap/config/BeanConfiguration.java
+++ b/src/main/java/de/ids_mannheim/korap/config/BeanConfiguration.java
@@ -24,8 +24,13 @@
     public static final String KUSTVAKT_AUDITING = "kustvakt_auditing";
     public static final String KUSTVAKT_CONFIG = "kustvakt_config";
 
+    public static final String KUSTVAKT_AUTHENTICATION_MANAGER = "kustvakt_authenticationmanager";
+    public static final String KUSTVAKT_USERDB = "kustvakt_userdb";
+    public static final String KUSTVAKT_POLICIES = "kustvakt_policies";
+
     private static BeanHolderHelper beans;
 
+    //todo: allow this for external plugin systems that are not kustvakt specific
     public static void setCustomBeansHolder(BeanHolderHelper holder) {
         ApplicationContext context = beans.context;
         holder.context = context;
@@ -136,18 +141,37 @@
             return getBean(KUSTVAKT_DB);
         }
 
-        public AuthenticationManagerIface getAuthenticationManager() {
-            throw new RuntimeException("!Stub");
-        }
+        //        public AuthenticationManagerIface getAuthenticationManager() {
+        //            throw new RuntimeException("!Stub");
+        //        }
 
-        public EntityHandlerIface getUserDBHandler() {
-            throw new RuntimeException("!Stub");
-        }
+        //        public EntityHandlerIface getUserDBHandler() {
+        //            throw new RuntimeException("!Stub");
+        //        }
 
         public EncryptionIface getEncryption() {
             return getBean(KUSTVAKT_ENCRYPTION);
         }
 
+        public AuthenticationManagerIface getAuthenticationManager() {
+            return getBean(KUSTVAKT_AUTHENTICATION_MANAGER);
+        }
+
+        public EntityHandlerIface getUserDBHandler() {
+            return getBean(KUSTVAKT_USERDB);
+        }
+
+        public PolicyHandlerIface getPolicyDbProvider() {
+            return getBean(KUSTVAKT_POLICIES);
+        }
+
+        // todo: more specific --> collection provider, document provider, etc.
+        public ResourceOperationIface getResourceProvider() {
+            return getBean("resourceProvider");
+        }
+
+
+
         public void finish() {
             this.getAuditingProvider().finish();
             context = null;
diff --git a/src/main/java/de/ids_mannheim/korap/config/JWTSigner.java b/src/main/java/de/ids_mannheim/korap/config/JWTSigner.java
index be9e9ce..aa1e00b 100644
--- a/src/main/java/de/ids_mannheim/korap/config/JWTSigner.java
+++ b/src/main/java/de/ids_mannheim/korap/config/JWTSigner.java
@@ -137,8 +137,8 @@
     }
 
     // does not care about expiration times
-    public String retrieveContent(String signedContent) throws
-            KustvaktException {
+    public String retrieveContent(String signedContent)
+            throws KustvaktException {
         SignedJWT jwt;
         try {
             jwt = SignedJWT.parse(signedContent);
@@ -155,8 +155,8 @@
             throws ParseException, JOSEException, KustvaktException {
         SignedJWT signedJWT = verifyToken(idtoken);
 
-        TokenContext c = new TokenContext(
-                signedJWT.getJWTClaimsSet().getSubjectClaim());
+        TokenContext c = new TokenContext();
+        c.setUsername(signedJWT.getJWTClaimsSet().getSubjectClaim());
         if (signedJWT.getJWTClaimsSet().getAudienceClaim() != null)
             c.addContextParameter(Attributes.CLIENT_ID,
                     signedJWT.getJWTClaimsSet().getAudienceClaim()[0]);
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 49eb4df..36f5bb2 100644
--- a/src/main/java/de/ids_mannheim/korap/config/KustvaktConfiguration.java
+++ b/src/main/java/de/ids_mannheim/korap/config/KustvaktConfiguration.java
@@ -1,6 +1,8 @@
 package de.ids_mannheim.korap.config;
 
+import de.ids_mannheim.korap.interfaces.EncryptionIface;
 import de.ids_mannheim.korap.utils.KustvaktLogger;
+import de.ids_mannheim.korap.utils.TimeUtils;
 import lombok.Getter;
 import org.apache.log4j.PropertyConfigurator;
 import org.slf4j.Logger;
@@ -23,22 +25,42 @@
 @Getter
 public class KustvaktConfiguration {
 
-    private final Logger jlog = KustvaktLogger
+    private static final Logger jlog = KustvaktLogger
             .initiate(KustvaktConfiguration.class);
     private String indexDir;
     private int port;
     // todo: make exclusive so that the containg languages can really only be used then
     private List<String> queryLanguages;
 
-    private int maxhits;
-
-    private int returnhits;
     private String serverHost;
-
-    private String host;
-
     private URL issuer;
 
+    private int maxhits;
+    private int returnhits;
+    private String keystoreLocation;
+    private String keystorePassword;
+    private Properties mailProperties;
+    private String host;
+    private String shibUserMapping;
+    private String userConfig;
+    private int inactiveTime;
+    private int loginAttemptTTL;
+    private long loginAttemptNum;
+    private boolean allowMultiLogIn;
+    private int expiration;
+    private int loadFactor;
+    private int validationStringLength;
+    private int validationEmaillength;
+    // fixme: should move to base config?!
+    private EncryptionIface.Encryption encryption;
+    private byte[] sharedSecret;
+    private String adminToken;
+    private int longTokenTTL;
+    private int tokenTTL;
+    private int shortTokenTTL;
+    private String[] rewrite_strategies;
+    private String passcodeSaltField;
+
     private String default_pos;
     private String default_lemma;
     private String default_surface;
@@ -51,35 +73,71 @@
     /**
      * loading of the properties and mapping to parameter variables
      *
-     * @param korap
+     * @param properties
      * @return
      */
-    protected Properties load(Properties korap) {
-        String log4jconfig = korap
+    protected Properties load(Properties properties) {
+        String log4jconfig = properties
                 .getProperty("log4jconfig", "log4j.properties");
         loadLog4jLogger(log4jconfig);
-        maxhits = new Integer(korap.getProperty("maxhits", "50000"));
-        returnhits = new Integer(korap.getProperty("returnhits", "50000"));
-        indexDir = korap.getProperty("lucene.indexDir", "");
-        port = new Integer(korap.getProperty("server.port", "8080"));
+        maxhits = new Integer(properties.getProperty("maxhits", "50000"));
+        returnhits = new Integer(properties.getProperty("returnhits", "50000"));
+        indexDir = properties.getProperty("lucene.indexDir", "");
+        port = new Integer(properties.getProperty("server.port", "8080"));
         // server options
         serverHost = String
-                .valueOf(korap.getProperty("server.host", "localhost"));
-        String queries = korap.getProperty("korap.ql", "");
+                .valueOf(properties.getProperty("server.host", "localhost"));
+        String queries = properties.getProperty("korap.ql", "");
         String[] qls = queries.split(",");
         queryLanguages = new ArrayList<>();
         for (String querylang : qls)
             queryLanguages.add(querylang.trim().toUpperCase());
         //        issuer = new URL(korap.getProperty("korap.issuer", ""));
 
-        default_const = korap.getProperty("kustvakt.default.const", "mate");
-        default_dep = korap.getProperty("kustvakt.default.dep", "mate");
-        default_lemma = korap.getProperty("kustvakt.default.lemma", "tt");
-        default_pos = korap.getProperty("kustvakt.default.pos", "tt");
-        default_surface = korap
+        default_const = properties
+                .getProperty("kustvakt.default.const", "mate");
+        default_dep = properties.getProperty("kustvakt.default.dep", "mate");
+        default_lemma = properties.getProperty("kustvakt.default.lemma", "tt");
+        default_pos = properties.getProperty("kustvakt.default.pos", "tt");
+        default_surface = properties
                 .getProperty("kustvakt.default.opennlp", "opennlp");
 
-        return korap;
+        // security configuration
+        expiration = TimeUtils.convertTimeToSeconds(properties
+                .getProperty("security.absoluteTimeoutDuration", "25M"));
+        inactiveTime = TimeUtils.convertTimeToSeconds(
+                properties.getProperty("security.idleTimeoutDuration", "10M"));
+        allowMultiLogIn = Boolean
+                .valueOf(properties.getProperty("security.multipleLogIn"));
+
+        loginAttemptNum = Long.parseLong(
+                properties.getProperty("security.loginAttemptNum", "3"));
+        loginAttemptTTL = TimeUtils.convertTimeToSeconds(
+                properties.getProperty("security.authAttemptTTL", "30M"));
+
+        loadFactor = Integer.valueOf(
+                properties.getProperty("security.encryption.loadFactor", "15"));
+        validationStringLength = Integer.valueOf(properties
+                .getProperty("security.validation.stringLength", "150"));
+        validationEmaillength = Integer.valueOf(properties
+                .getProperty("security.validation.emailLength", "40"));
+        encryption = Enum.valueOf(EncryptionIface.Encryption.class,
+                properties.getProperty("security.encryption", "BCRYPT"));
+        sharedSecret = properties.getProperty("security.sharedSecret", "")
+                .getBytes();
+        adminToken = properties.getProperty("security.adminToken");
+
+        longTokenTTL = TimeUtils.convertTimeToSeconds(
+                properties.getProperty("security.longTokenTTL", "100D"));
+        tokenTTL = TimeUtils.convertTimeToSeconds(
+                properties.getProperty("security.tokenTTL", "72H"));
+        shortTokenTTL = TimeUtils.convertTimeToSeconds(
+                properties.getProperty("security.shortTokenTTL", "3H"));
+
+        passcodeSaltField = properties
+                .getProperty("security.passcode.salt", "accountCreation");
+
+        return properties;
     }
 
     /**
@@ -124,14 +182,15 @@
                 jlog.info(
                         "using local logging properties file ({}) to configure logging system",
                         log4jconfig);
-            }else
-                loadClassLogger();
+                return;
+            }
         }catch (Exception e) {
-            loadClassLogger();
+            // do nothing
         }
+        loadClassLogger();
     }
 
-    public void loadClassLogger() {
+    private 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/EmptyResultException.java b/src/main/java/de/ids_mannheim/korap/exceptions/EmptyResultException.java
index 5541695..07acf8d 100644
--- a/src/main/java/de/ids_mannheim/korap/exceptions/EmptyResultException.java
+++ b/src/main/java/de/ids_mannheim/korap/exceptions/EmptyResultException.java
@@ -4,10 +4,14 @@
  * @author hanl
  * @date 25/03/2014
  */
-public class EmptyResultException extends BaseException {
+public class EmptyResultException extends KustvaktException {
+
+    public EmptyResultException(String message, String entity) {
+        super(StatusCodes.EMPTY_RESULTS, message, entity);
+    }
 
     public EmptyResultException(String entity) {
-        super(StatusCodes.EMPTY_RESULTS, entity);
+        super(StatusCodes.EMPTY_RESULTS, "", entity);
     }
 
 }
diff --git a/src/main/java/de/ids_mannheim/korap/exceptions/KustvaktException.java b/src/main/java/de/ids_mannheim/korap/exceptions/KustvaktException.java
index 1c0c5aa..3b078ff 100644
--- a/src/main/java/de/ids_mannheim/korap/exceptions/KustvaktException.java
+++ b/src/main/java/de/ids_mannheim/korap/exceptions/KustvaktException.java
@@ -11,8 +11,6 @@
  * @author hanl
  * @date 11/12/2013
  */
-//fixme: redundant with baseexception
-@Deprecated
 @Setter
 @Getter
 public class KustvaktException extends Exception {
@@ -22,31 +20,37 @@
     private Integer statusCode;
     private String entity;
 
-    public KustvaktException(Integer status) {
+    public KustvaktException(int status) {
         this.statusCode = status;
     }
 
-    public KustvaktException(Object userid, Integer status) {
+    public KustvaktException(Object userid, int status) {
         this(status);
         this.userid = String.valueOf(userid);
     }
 
-    public KustvaktException(Object userid, Integer status, String message,
+    public KustvaktException(Object userid, int status, String message,
             String entity) {
-        super(status, message, entity);
+        super(message);
+        this.statusCode = status;
+        this.entity = entity;
         this.userid = String.valueOf(userid);
     }
 
-    public KustvaktException(Integer status, String message, String entity) {
-        super(status, message, entity);
+    public KustvaktException(int status, String message, String entity) {
+        super(message);
+        this.statusCode = status;
+        this.entity = entity;
     }
 
-    public KustvaktException(Throwable cause, Integer status) {
-        super(cause, status);
+    public KustvaktException(Throwable cause, int status) {
+        super(cause);
+        this.statusCode = status;
     }
 
-    public KustvaktException(String message, Throwable cause, Integer status) {
-        super(message, cause, status);
+    public KustvaktException(String message, Throwable cause, int status) {
+        super(message, cause);
+        this.statusCode = status;
     }
 
     @Override
diff --git a/src/main/java/de/ids_mannheim/korap/exceptions/NotAuthorizedException.java b/src/main/java/de/ids_mannheim/korap/exceptions/NotAuthorizedException.java
index 2b499c7..8b8d2c5 100644
--- a/src/main/java/de/ids_mannheim/korap/exceptions/NotAuthorizedException.java
+++ b/src/main/java/de/ids_mannheim/korap/exceptions/NotAuthorizedException.java
@@ -9,7 +9,7 @@
 // a security table registers all these exceptions (failed authentication, failed access to a resource, etc.)
 @Data
 @Deprecated
-public class NotAuthorizedException extends BaseException {
+public class NotAuthorizedException extends KustvaktException {
 
     public NotAuthorizedException(int status) {
         super(status);
diff --git a/src/main/java/de/ids_mannheim/korap/exceptions/WrappedException.java b/src/main/java/de/ids_mannheim/korap/exceptions/WrappedException.java
index c180f1b..70702b7 100644
--- a/src/main/java/de/ids_mannheim/korap/exceptions/WrappedException.java
+++ b/src/main/java/de/ids_mannheim/korap/exceptions/WrappedException.java
@@ -10,7 +10,7 @@
  */
 // should be a http exception that responds to a service point
 // is the extension of the notauthorized exception!
-public class WrappedException extends KorAPException {
+public class WrappedException extends KustvaktException {
 
     private WrappedException(Object userid, Integer status, String message,
             String args) {
@@ -23,7 +23,7 @@
         this.records.add(record);
     }
 
-    public WrappedException(KorAPException e, Integer status, String... args) {
+    public WrappedException(KustvaktException e, Integer status, String... args) {
         this(e.getUserid(), e.getStatusCode(), e.getMessage(), e.getEntity());
         AuditRecord record = AuditRecord
                 .serviceRecord(e.getUserid(), status, args);
diff --git a/src/main/java/de/ids_mannheim/korap/exceptions/dbException.java b/src/main/java/de/ids_mannheim/korap/exceptions/dbException.java
index d505e13..9818648 100644
--- a/src/main/java/de/ids_mannheim/korap/exceptions/dbException.java
+++ b/src/main/java/de/ids_mannheim/korap/exceptions/dbException.java
@@ -8,7 +8,7 @@
  * @author hanl
  * @date 08/04/2015
  */
-public class dbException extends KorAPException {
+public class dbException extends KustvaktException {
 
     private dbException(Object userid, Integer status, String message,
             String args) {
@@ -27,7 +27,7 @@
         this.records.add(record);
     }
 
-    public dbException(KorAPException e, Integer status, String... args) {
+    public dbException(KustvaktException e, Integer status, String... args) {
         this(e.getUserid(), e.getStatusCode(), e.getMessage(), e.getEntity());
         AuditRecord record = AuditRecord
                 .dbRecord(e.getUserid(), status, args);
diff --git a/src/main/java/de/ids_mannheim/korap/handlers/CollectionDao.java b/src/main/java/de/ids_mannheim/korap/handlers/CollectionDao.java
index 7f4fb22..fceaf89 100644
--- a/src/main/java/de/ids_mannheim/korap/handlers/CollectionDao.java
+++ b/src/main/java/de/ids_mannheim/korap/handlers/CollectionDao.java
@@ -2,10 +2,10 @@
 
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.exceptions.StatusCodes;
-import de.ids_mannheim.korap.ext.interfaces.ResourceOperationIface;
-import de.ids_mannheim.korap.ext.resource.KorAPResource;
-import de.ids_mannheim.korap.ext.resource.VirtualCollection;
 import de.ids_mannheim.korap.interfaces.PersistenceClient;
+import de.ids_mannheim.korap.interfaces.ResourceOperationIface;
+import de.ids_mannheim.korap.resources.KustvaktResource;
+import de.ids_mannheim.korap.resources.VirtualCollection;
 import de.ids_mannheim.korap.user.User;
 import de.ids_mannheim.korap.utils.KustvaktLogger;
 import org.slf4j.Logger;
@@ -42,7 +42,7 @@
 
     // fixme: persistentid can be done, persistence is achieved by specifing a date until which documents
     // are to be included. this excludes documents that are part of the "sperreinträge"
-    public <T extends KorAPResource> T findbyId(String id, User user)
+    public <T extends KustvaktResource> T findbyId(String id, User user)
             throws KustvaktException {
         MapSqlParameterSource source = new MapSqlParameterSource();
         source.addValue("id", id);
diff --git a/src/main/java/de/ids_mannheim/korap/handlers/DocumentDao.java b/src/main/java/de/ids_mannheim/korap/handlers/DocumentDao.java
index 111c282..ce0475e 100644
--- a/src/main/java/de/ids_mannheim/korap/handlers/DocumentDao.java
+++ b/src/main/java/de/ids_mannheim/korap/handlers/DocumentDao.java
@@ -2,9 +2,9 @@
 
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.exceptions.StatusCodes;
-import de.ids_mannheim.korap.ext.interfaces.ResourceOperationIface;
-import de.ids_mannheim.korap.ext.resource.Document;
 import de.ids_mannheim.korap.interfaces.PersistenceClient;
+import de.ids_mannheim.korap.interfaces.ResourceOperationIface;
+import de.ids_mannheim.korap.resources.Document;
 import de.ids_mannheim.korap.user.User;
 import de.ids_mannheim.korap.utils.BooleanUtils;
 import org.springframework.dao.DataAccessException;
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 71ecbaf..c8d8281 100644
--- a/src/main/java/de/ids_mannheim/korap/handlers/OAuth2Handler.java
+++ b/src/main/java/de/ids_mannheim/korap/handlers/OAuth2Handler.java
@@ -9,6 +9,9 @@
 import net.sf.ehcache.Element;
 
 /**
+ * extends OAuthDb to allow temporary caching of tokens
+ * and authorizations (authorizations are not persisted in db)
+ *
  * @author hanl
  * @date 04/05/2015
  */
@@ -28,22 +31,26 @@
         return null;
     }
 
-    public void authorize(AuthCodeInfo code, User user) throws
-            KustvaktException {
+    public void authorize(AuthCodeInfo code, User user)
+            throws KustvaktException {
         code.setUserId(user.getId());
         cache.put(new Element(code.getCode(), code));
     }
 
-    public boolean addToken(String code, String token, int ttl)
+    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, info.getUserId(), info.getClientId(),
+            return super.addToken(token, refresh, info.getUserId(), info.getClientId(),
                     info.getScopes(), ttl);
         }
         return false;
     }
 
+    public void exchangeToken(String refresh) {
+
+    }
+
 }
diff --git a/src/main/java/de/ids_mannheim/korap/handlers/OAuthDb.java b/src/main/java/de/ids_mannheim/korap/handlers/OAuthDb.java
index b0bee5a..63485c9 100644
--- a/src/main/java/de/ids_mannheim/korap/handlers/OAuthDb.java
+++ b/src/main/java/de/ids_mannheim/korap/handlers/OAuthDb.java
@@ -103,10 +103,12 @@
         return true;
     }
 
-    public boolean addToken(String token, Integer userid, String client_id,
-            String scopes, int expiration) throws KustvaktException {
+    public boolean addToken(String token, String refresh, Integer userid,
+            String client_id, String scopes, int expiration)
+            throws KustvaktException {
         MapSqlParameterSource s = new MapSqlParameterSource();
         s.addValue("token", token);
+        s.addValue("rt", refresh);
         s.addValue("ex",
                 new Timestamp(TimeUtils.plusSeconds(expiration).getMillis()));
         s.addValue("us", userid);
@@ -114,8 +116,8 @@
         s.addValue("st", BooleanUtils.getBoolean(true));
         s.addValue("cli", client_id);
         String sql =
-                "insert into oauth2_access_token (access_token, scopes, client_id, user_id, expiration, status) "
-                        + "values (:token, :sc, :cli, :us, :ex, :st);";
+                "insert into oauth2_access_token (access_token, refresh_token, scopes, client_id, user_id, expiration, status) "
+                        + "values (:token, :rt, :sc, :cli, :us, :ex, :st);";
         try {
             return this.jdbcTemplate.update(sql, s) == 1;
         }catch (DataAccessException e) {
@@ -151,6 +153,10 @@
                 "select cl.* from oauth2_client as cl where cl.client_id in (select cd.client_id from oauth2_access_token as cd "
                         + "where cd.user_id=:user) or cl.is_confidential=:conf;";
 
+        //todo: test query
+        //        "select cl.* from oauth2_client as cl inner join oauth2_access_token as cd "
+        //                + "on cd.client_id=cl.client_id where cd.user_id=:user or cl.is_confidential=:conf;"
+
         MapSqlParameterSource s = new MapSqlParameterSource();
         s.addValue("user", userid);
         s.addValue("conf", BooleanUtils.getBoolean(true));
@@ -177,8 +183,9 @@
 
     }
 
-    public TokenContext getContext(final String token) throws
-            KustvaktException {
+    // todo: expired token must trigger an invalid token exception to trigger a refresh token
+    public TokenContext getContext(final String token)
+            throws KustvaktException {
         String sql =
                 "select ko.username, oa.expiration, oa.scopes from oauth2_access_token as oa inner join korap_users as ko "
                         + "on ko.id=oa.user_id where oa.access_token=:token and oa.expiration > :now;";
@@ -193,8 +200,8 @@
                         public TokenContext mapRow(ResultSet rs, int rowNum)
                                 throws SQLException {
                             long exp = rs.getTimestamp("expiration").getTime();
-                            TokenContext c = new TokenContext(
-                                    rs.getString(Attributes.USERNAME));
+                            TokenContext c = new TokenContext();
+                            c.setUsername(rs.getString(Attributes.USERNAME));
                             c.setExpirationTime(exp);
                             c.setToken(token);
                             c.setTokenType(Attributes.OAUTH2_AUTHORIZATION);
@@ -217,8 +224,8 @@
     }
 
     // subsequently delete all access and auth code tokens associated!
-    public void removeClient(ClientInfo info, User user) throws
-            KustvaktException {
+    public void removeClient(ClientInfo info, User user)
+            throws KustvaktException {
         MapSqlParameterSource p = new MapSqlParameterSource();
         p.addValue("url", info.getUrl());
         p.addValue("cls", info.getClient_secret());
diff --git a/src/main/java/de/ids_mannheim/korap/handlers/ResourceDao.java b/src/main/java/de/ids_mannheim/korap/handlers/ResourceDao.java
index 6039c79..3b51f5c 100644
--- a/src/main/java/de/ids_mannheim/korap/handlers/ResourceDao.java
+++ b/src/main/java/de/ids_mannheim/korap/handlers/ResourceDao.java
@@ -3,10 +3,10 @@
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.exceptions.StatusCodes;
 import de.ids_mannheim.korap.exceptions.dbException;
-import de.ids_mannheim.korap.ext.interfaces.ResourceOperationIface;
-import de.ids_mannheim.korap.ext.resource.KorAPResource;
-import de.ids_mannheim.korap.ext.resource.ResourceFactory;
 import de.ids_mannheim.korap.interfaces.PersistenceClient;
+import de.ids_mannheim.korap.interfaces.ResourceOperationIface;
+import de.ids_mannheim.korap.resources.KustvaktResource;
+import de.ids_mannheim.korap.resources.ResourceFactory;
 import de.ids_mannheim.korap.user.User;
 import de.ids_mannheim.korap.utils.KustvaktLogger;
 import de.ids_mannheim.korap.utils.TimeUtils;
@@ -26,7 +26,7 @@
  * Created by hanl on 7/21/14.
  */
 //todo: auditing // testing
-public class ResourceDao<T extends KorAPResource>
+public class ResourceDao<T extends KustvaktResource>
         implements ResourceOperationIface<T> {
 
     private static Logger log = KustvaktLogger.initiate(ResourceDao.class);
@@ -38,7 +38,7 @@
 
     @Override
     public Class<T> getType() {
-        return (Class<T>) KorAPResource.class;
+        return (Class<T>) KustvaktResource.class;
     }
 
     @Override
@@ -71,7 +71,7 @@
     }
 
     @Override
-    public <T extends KorAPResource> T findbyId(String id, User user)
+    public <T extends KustvaktResource> T findbyId(String id, User user)
             throws KustvaktException {
         MapSqlParameterSource source = new MapSqlParameterSource();
         source.addValue("pid", id);
@@ -86,7 +86,7 @@
         }
     }
 
-    public KorAPResource findbyPath(String path, User user)
+    public KustvaktResource findbyPath(String path, User user)
             throws KustvaktException {
         MapSqlParameterSource source = new MapSqlParameterSource();
         source.addValue("path", path);
@@ -103,7 +103,7 @@
     }
 
     @Override
-    public <T extends KorAPResource> T findbyId(Integer id, User user)
+    public <T extends KustvaktResource> T findbyId(Integer id, User user)
             throws KustvaktException {
         MapSqlParameterSource source = new MapSqlParameterSource();
         source.addValue("id", id);
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 600981f..82d6737 100644
--- a/src/main/java/de/ids_mannheim/korap/interfaces/AuthenticationIface.java
+++ b/src/main/java/de/ids_mannheim/korap/interfaces/AuthenticationIface.java
@@ -1,6 +1,6 @@
 package de.ids_mannheim.korap.interfaces;
 
-import de.ids_mannheim.korap.exceptions.KorAPException;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.user.TokenContext;
 import de.ids_mannheim.korap.user.User;
 
@@ -8,15 +8,16 @@
 
 public interface AuthenticationIface {
 
-    public TokenContext getUserStatus(String authToken) throws KorAPException;
+    TokenContext getUserStatus(String authToken) throws
+            KustvaktException;
 
-    public TokenContext createUserSession(User user, Map<String, Object> attr)
-            throws KorAPException;
+    TokenContext createUserSession(User user, Map<String, Object> attr)
+            throws KustvaktException;
 
-    public void removeUserSession(String token) throws KorAPException;
+    void removeUserSession(String token) throws KustvaktException;
 
-    public TokenContext refresh(TokenContext context) throws KorAPException;
+    TokenContext refresh(TokenContext context) throws KustvaktException;
 
-    public String getIdentifier();
+    String getIdentifier();
 
 }
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 45e5143..c6d1bee 100644
--- a/src/main/java/de/ids_mannheim/korap/interfaces/AuthenticationManagerIface.java
+++ b/src/main/java/de/ids_mannheim/korap/interfaces/AuthenticationManagerIface.java
@@ -1,6 +1,6 @@
 package de.ids_mannheim.korap.interfaces;
 
-import de.ids_mannheim.korap.exceptions.KorAPException;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.user.*;
 
 import java.util.HashMap;
@@ -34,48 +34,49 @@
     }
 
     public abstract TokenContext getTokenStatus(String token, String host,
-            String useragent) throws KorAPException;
+            String useragent) throws KustvaktException;
 
-    public abstract User getUser(String username) throws KorAPException;
+    public abstract User getUser(String username) throws KustvaktException;
 
     public abstract User authenticate(int type, String username,
             String password, Map<String, Object> attributes)
-            throws KorAPException;
+            throws KustvaktException;
 
     public abstract TokenContext createTokenContext(User user,
             Map<String, Object> attr, String provider_key)
-            throws KorAPException;
+            throws KustvaktException;
 
-    public abstract void logout(TokenContext context) throws KorAPException;
+    public abstract void logout(TokenContext context) throws KustvaktException;
 
-    public abstract void lockAccount(User user) throws KorAPException;
+    public abstract void lockAccount(User user) throws KustvaktException;
 
     public abstract User createUserAccount(Map<String, Object> attributes)
-            throws KorAPException;
+            throws KustvaktException;
 
-    public abstract boolean updateAccount(User user) throws KorAPException;
+    public abstract boolean updateAccount(User user) throws KustvaktException;
 
-    public abstract boolean deleteAccount(User user) throws KorAPException;
+    public abstract boolean deleteAccount(User user) throws KustvaktException;
 
-    public abstract UserDetails getUserDetails(User user) throws KorAPException;
+    public abstract UserDetails getUserDetails(User user) throws
+            KustvaktException;
 
     public abstract UserSettings getUserSettings(User user)
-            throws KorAPException;
+            throws KustvaktException;
 
     public abstract void updateUserDetails(User user, UserDetails details)
-            throws KorAPException;
+            throws KustvaktException;
 
     public abstract void updateUserSettings(User user, UserSettings settings)
-            throws KorAPException;
+            throws KustvaktException;
 
     public abstract Object[] validateResetPasswordRequest(String username,
-            String email) throws KorAPException;
+            String email) throws KustvaktException;
 
     public abstract void resetPassword(String uriFragment, String username,
-            String newPassphrase) throws KorAPException;
+            String newPassphrase) throws KustvaktException;
 
     public abstract void confirmRegistration(String uriFragment,
-            String username) throws KorAPException;
+            String username) throws KustvaktException;
 
     @Override
     public String toString() {
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 0b00b31..1dc864c 100644
--- a/src/main/java/de/ids_mannheim/korap/interfaces/EncryptionIface.java
+++ b/src/main/java/de/ids_mannheim/korap/interfaces/EncryptionIface.java
@@ -1,6 +1,6 @@
 package de.ids_mannheim.korap.interfaces;
 
-import de.ids_mannheim.korap.exceptions.KorAPException;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.user.User;
 
 import java.io.UnsupportedEncodingException;
@@ -24,11 +24,11 @@
      */
     public String produceSecureHash(String input, String salt)
             throws NoSuchAlgorithmException, UnsupportedEncodingException,
-            KorAPException;
+            KustvaktException;
 
     public String produceSecureHash(String input)
             throws NoSuchAlgorithmException, UnsupportedEncodingException,
-            KorAPException;
+            KustvaktException;
 
     public String hash(String value);
 
@@ -62,17 +62,17 @@
 
     public String encodeBase();
 
-    public String validateIPAddress(String ipaddress) throws KorAPException;
+    public String validateIPAddress(String ipaddress) throws KustvaktException;
 
-    public String validateEmail(String email) throws KorAPException;
+    public String validateEmail(String email) throws KustvaktException;
 
     public Map<String, Object> validateMap(Map<String, Object> map)
-            throws KorAPException;
+            throws KustvaktException;
 
-    public String validateString(String input) throws KorAPException;
+    public String validateString(String input) throws KustvaktException;
 
-    public void validate(Object instance) throws KorAPException;
+    public void validate(Object instance) throws KustvaktException;
 
-    public String validatePassphrase(String pw) throws KorAPException;
+    public String validatePassphrase(String pw) throws KustvaktException;
 
 }
diff --git a/src/main/java/de/ids_mannheim/korap/interfaces/EntityHandlerIface.java b/src/main/java/de/ids_mannheim/korap/interfaces/EntityHandlerIface.java
index fb8048b..aed2871 100644
--- a/src/main/java/de/ids_mannheim/korap/interfaces/EntityHandlerIface.java
+++ b/src/main/java/de/ids_mannheim/korap/interfaces/EntityHandlerIface.java
@@ -1,7 +1,7 @@
 package de.ids_mannheim.korap.interfaces;
 
 import de.ids_mannheim.korap.exceptions.EmptyResultException;
-import de.ids_mannheim.korap.exceptions.KorAPException;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.user.User;
 import de.ids_mannheim.korap.user.UserDetails;
 import de.ids_mannheim.korap.user.UserSettings;
@@ -12,13 +12,13 @@
  * Time: 11:04 AM
  */
 public interface EntityHandlerIface {
-    UserSettings getUserSettings(Integer userid) throws KorAPException;
+    UserSettings getUserSettings(Integer userid) throws KustvaktException;
 
-    int updateSettings(UserSettings settings) throws KorAPException;
+    int updateSettings(UserSettings settings) throws KustvaktException;
 
-    UserDetails getUserDetails(Integer userid) throws KorAPException;
+    UserDetails getUserDetails(Integer userid) throws KustvaktException;
 
-    int updateUserDetails(UserDetails details) throws KorAPException;
+    int updateUserDetails(UserDetails details) throws KustvaktException;
 
     //    List<UserQuery> getUserQueries(User user) throws KorAPException;
 
@@ -27,18 +27,18 @@
     //    void updateUserQueries(User user, List<UserQuery> newOnes) throws KorAPException;
 
     User getAccount(String username) throws
-            EmptyResultException, KorAPException;
+            EmptyResultException, KustvaktException;
 
-    int updateAccount(User user) throws KorAPException;
+    int updateAccount(User user) throws KustvaktException;
 
-    int createAccount(User user) throws KorAPException;
+    int createAccount(User user) throws KustvaktException;
 
-    int deleteAccount(Integer userid) throws KorAPException;
+    int deleteAccount(Integer userid) throws KustvaktException;
 
     int resetPassphrase(String username, String uriToken,
-            String passphrase) throws KorAPException;
+            String passphrase) throws KustvaktException;
 
     int activateAccount(String username, String uriToken)
-            throws KorAPException;
+            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 a79c82f..1465c06 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
@@ -2,7 +2,7 @@
 
 import de.ids_mannheim.korap.config.BeanConfiguration;
 import de.ids_mannheim.korap.config.Configurable;
-import de.ids_mannheim.korap.exceptions.KorAPException;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.interfaces.EncryptionIface;
 import de.ids_mannheim.korap.user.User;
 
@@ -28,14 +28,14 @@
     @Override
     public String produceSecureHash(String input, String salt)
             throws NoSuchAlgorithmException, UnsupportedEncodingException,
-            KorAPException {
+            KustvaktException {
         return null;
     }
 
     @Override
     public String produceSecureHash(String input)
             throws NoSuchAlgorithmException, UnsupportedEncodingException,
-            KorAPException {
+            KustvaktException {
         return null;
     }
 
@@ -81,33 +81,33 @@
     }
 
     @Override
-    public String validateIPAddress(String ipaddress) throws KorAPException {
+    public String validateIPAddress(String ipaddress) throws KustvaktException {
         return null;
     }
 
     @Override
-    public String validateEmail(String email) throws KorAPException {
+    public String validateEmail(String email) throws KustvaktException {
         return null;
     }
 
     @Override
     public Map<String, Object> validateMap(Map<String, Object> map)
-            throws KorAPException {
+            throws KustvaktException {
         return null;
     }
 
     @Override
-    public String validateString(String input) throws KorAPException {
+    public String validateString(String input) throws KustvaktException {
         return null;
     }
 
     @Override
-    public void validate(Object instance) throws KorAPException {
+    public void validate(Object instance) throws KustvaktException {
 
     }
 
     @Override
-    public String validatePassphrase(String pw) throws KorAPException {
+    public String validatePassphrase(String pw) throws KustvaktException {
         return null;
     }
 }
diff --git a/src/main/java/de/ids_mannheim/korap/resource/CollectionProcessor.java b/src/main/java/de/ids_mannheim/korap/resource/CollectionProcessor.java
index db1b995..b1e13d4 100644
--- a/src/main/java/de/ids_mannheim/korap/resource/CollectionProcessor.java
+++ b/src/main/java/de/ids_mannheim/korap/resource/CollectionProcessor.java
@@ -4,5 +4,6 @@
  * @author hanl
  * @date 19/06/2015
  */
+@Deprecated
 public class CollectionProcessor {
 }
diff --git a/src/main/java/de/ids_mannheim/korap/resource/LayerProcessor.java b/src/main/java/de/ids_mannheim/korap/resource/LayerProcessor.java
index 952e308..dab1914 100644
--- a/src/main/java/de/ids_mannheim/korap/resource/LayerProcessor.java
+++ b/src/main/java/de/ids_mannheim/korap/resource/LayerProcessor.java
@@ -10,6 +10,7 @@
  * @author hanl
  * @date 19/06/2015
  */
+@Deprecated
 public class LayerProcessor extends NodeProcessor {
 
     private LayerMapper mapper;
diff --git a/src/main/java/de/ids_mannheim/korap/resource/NodeProcessor.java b/src/main/java/de/ids_mannheim/korap/resource/NodeProcessor.java
index c7a9451..c2ed5b1 100644
--- a/src/main/java/de/ids_mannheim/korap/resource/NodeProcessor.java
+++ b/src/main/java/de/ids_mannheim/korap/resource/NodeProcessor.java
@@ -6,6 +6,7 @@
  * @author hanl
  * @date 19/06/2015
  */
+@Deprecated
 public abstract class NodeProcessor {
 
     public abstract JsonNode process(JsonNode node);
diff --git a/src/main/java/de/ids_mannheim/korap/resource/RewriteProcessor.java b/src/main/java/de/ids_mannheim/korap/resource/RewriteProcessor.java
index 4d2a2a4..af44cb8 100644
--- a/src/main/java/de/ids_mannheim/korap/resource/RewriteProcessor.java
+++ b/src/main/java/de/ids_mannheim/korap/resource/RewriteProcessor.java
@@ -11,6 +11,7 @@
  * @author hanl
  * @date 19/06/2015
  */
+@Deprecated
 public class RewriteProcessor {
 
     private KustvaktConfiguration config;
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 a703e39..d5e22da 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
@@ -111,7 +111,6 @@
      * @return User
      * @throws KustvaktException
      */
-
     public User authenticate(int type, String username, String password,
             Map<String, Object> attributes) throws KustvaktException {
         User user;
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 8f244d3..e877846 100644
--- a/src/main/java/de/ids_mannheim/korap/user/TokenContext.java
+++ b/src/main/java/de/ids_mannheim/korap/user/TokenContext.java
@@ -25,19 +25,13 @@
     // either "session_token " / "api_token
     private String tokenType;
     private String token;
-
     private boolean secureRequired;
 
     private Map<String, Object> parameters;
     private String hostAddress;
     private String userAgent;
 
-    public TokenContext(String username) {
-        this();
-        this.username = username;
-    }
-
-    private TokenContext() {
+    public TokenContext() {
         this.parameters = new HashMap<>();
         this.setUsername("");
         this.setToken("");
@@ -75,20 +69,28 @@
         this.expirationTime = new Date(date);
     }
 
+    //todo: complete
     public static TokenContext fromJSON(String s) {
         JsonNode node = JsonUtils.readTree(s);
-        TokenContext c = new TokenContext(
-                node.path(Attributes.USERNAME).asText());
-        c.setToken(node.path(Attributes.TOKEN).asText());
+        TokenContext c = new TokenContext();
+        if (node != null) {
+            c.setUsername(node.path(Attributes.USERNAME).asText());
+            c.setToken(node.path(Attributes.TOKEN).asText());
+        }
         return c;
     }
 
-    public static TokenContext fromOAuth(String s) {
+    public static TokenContext fromOAuth2(String s) {
         JsonNode node = JsonUtils.readTree(s);
         TokenContext c = new TokenContext();
-        c.setToken(node.path("token").asText());
-        c.setTokenType(node.path("token_type").asText());
-        c.setExpirationTime(node.path("expires_in").asLong());
+        if (node != null) {
+            c.setToken(node.path("token").asText());
+            c.setTokenType(node.path("token_type").asText());
+            c.setExpirationTime(node.path("expires_in").asLong());
+            c.addContextParameter("refresh_token",
+                    node.path("refresh_token").asText());
+
+        }
         return c;
     }
 
diff --git a/src/main/java/de/ids_mannheim/korap/utils/Benchmarker.java b/src/main/java/de/ids_mannheim/korap/utils/Benchmarker.java
index 2a4761a..309578d 100644
--- a/src/main/java/de/ids_mannheim/korap/utils/Benchmarker.java
+++ b/src/main/java/de/ids_mannheim/korap/utils/Benchmarker.java
@@ -1,14 +1,10 @@
 package de.ids_mannheim.korap.utils;
 
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
 /**
  * @author hanl
  * @date 29/04/2014
  */
 
+@Deprecated
 public class Benchmarker {
 }
diff --git a/src/main/java/de/ids_mannheim/korap/utils/CollectionQueryBuilder3.java b/src/main/java/de/ids_mannheim/korap/utils/CollectionQueryBuilder3.java
index 4d012b2..6b1ee91 100644
--- a/src/main/java/de/ids_mannheim/korap/utils/CollectionQueryBuilder3.java
+++ b/src/main/java/de/ids_mannheim/korap/utils/CollectionQueryBuilder3.java
@@ -1,10 +1,10 @@
 package de.ids_mannheim.korap.utils;
 
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
 import de.ids_mannheim.korap.query.serialize.CollectionQueryProcessor;
 
-import java.io.IOException;
-import java.util.*;
-
 /**
  * convenience builder class for collection query
  *
@@ -13,8 +13,12 @@
  */
 public class CollectionQueryBuilder3 {
 
+    public enum EQ {
+        EQUAL, UNEQUAL
+    }
+
     private boolean verbose;
-    private List<Map> rq;
+    private JsonNode base;
     private StringBuilder builder;
 
     public CollectionQueryBuilder3() {
@@ -24,12 +28,18 @@
     public CollectionQueryBuilder3(boolean verbose) {
         this.verbose = verbose;
         this.builder = new StringBuilder();
-        this.rq = new LinkedList<>();
+        this.base = null;
     }
 
-    public CollectionQueryBuilder3 addSegment(String field, String value) {
-        String f = field + "=" + value;
-        this.builder.append(f);
+    public CollectionQueryBuilder3 addSegment(String field, EQ eq,
+            String value) {
+        if (base == null)
+            this.builder
+                    .append(field + (eq.equals(EQ.EQUAL) ? "=" : "!=") + value);
+        else {
+            JsonNode node = Utils.buildDoc(field, value, eq);
+            appendToBaseGroup(node);
+        }
         return this;
     }
 
@@ -42,7 +52,16 @@
     public CollectionQueryBuilder3 addSub(String query) {
         if (!query.startsWith("(") && !query.endsWith(")"))
             query = "(" + query + ")";
-        this.builder.append(query);
+
+        if (base != null) {
+            CollectionQueryProcessor tree = new CollectionQueryProcessor(
+                    this.verbose);
+            tree.process(query);
+            JsonNode map = JsonUtils
+                    .valueToTree(tree.getRequestMap().get("collection"));
+            appendToBaseGroup(map);
+        }else
+            this.builder.append(query);
         return this;
     }
 
@@ -56,33 +75,70 @@
         return this;
     }
 
+    @Deprecated
     public CollectionQueryBuilder3 addRaw(String collection) {
-        try {
-            Map v = JsonUtils.read(collection, HashMap.class);
-            v.get("collection");
-        }catch (IOException e) {
-            throw new IllegalArgumentException("Conversion went wrong!");
-        }
         return this;
     }
 
-    public Map getRequest() {
-        //todo: adding another resource query doesnt work
+    public Object getRequest() {
+        Object request = base;
+        if (request == null) {
+            CollectionQueryProcessor tree = new CollectionQueryProcessor(
+                    this.verbose);
+            tree.process(this.builder.toString());
 
-        CollectionQueryProcessor tree = new CollectionQueryProcessor(
-                this.verbose);
-        tree.process(this.builder.toString());
-
-        Map request = tree.getRequestMap();
-        if (!this.rq.isEmpty()) {
-            List coll = (List) request.get("collection");
-            coll.addAll(this.rq);
+            request = tree.getRequestMap();
         }
         return request;
     }
 
+    /**
+     * sets base query. All consequent queries are added to the first koral:docGroup within the collection base query
+     * If no group in base query, consequent queries are skipped.
+     *
+     * @param query
+     */
+    public void setBaseQuery(String query) {
+        this.base = JsonUtils.readTree(query);
+    }
+
     public String toJSON() {
         return JsonUtils.toJSON(getRequest());
     }
 
+
+
+    private void appendToBaseGroup(JsonNode node) {
+        if (base.at("/collection/@type").asText().equals("koral:docGroup")) {
+            ArrayNode group = (ArrayNode) base.at("/collection/operands");
+            if (node instanceof ArrayNode)
+                group.addAll((ArrayNode) node);
+            else
+                group.add(node);
+        }else
+            throw new IllegalArgumentException("No group found to add to!");
+        // fixme: if base is a doc only, this function is not supported. requirement is a koral:docGroup, since
+        // combination operator is unknown otherwise
+    }
+
+    public static class Utils {
+
+        public static JsonNode buildDoc(String key, String value, EQ eq) {
+            ObjectNode node = JsonUtils.createObjectNode();
+            node.put("@type", "koral:doc");
+            node.put("match", eq.equals(EQ.EQUAL) ? "match:eq" : "match:ne");
+            node.put("key", key);
+            node.put("value", value);
+
+            return node;
+        }
+
+        public static JsonNode buildDocGroup() {
+            ObjectNode node = JsonUtils.createObjectNode();
+
+            return node;
+        }
+
+    }
+
 }
diff --git a/src/main/java/de/ids_mannheim/korap/web/.DS_Store b/src/main/java/de/ids_mannheim/korap/web/.DS_Store
index 32f11f9..1383f97 100644
--- a/src/main/java/de/ids_mannheim/korap/web/.DS_Store
+++ b/src/main/java/de/ids_mannheim/korap/web/.DS_Store
Binary files differ
diff --git a/src/main/java/de/ids_mannheim/korap/web/ClientsHandler.java b/src/main/java/de/ids_mannheim/korap/web/ClientsHandler.java
index 8b846eb..65fdafa 100644
--- a/src/main/java/de/ids_mannheim/korap/web/ClientsHandler.java
+++ b/src/main/java/de/ids_mannheim/korap/web/ClientsHandler.java
@@ -6,7 +6,7 @@
 import com.sun.jersey.api.client.config.ClientConfig;
 import com.sun.jersey.api.client.config.DefaultClientConfig;
 import com.sun.jersey.core.util.MultivaluedMapImpl;
-import de.ids_mannheim.korap.exceptions.KorAPException;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.exceptions.StatusCodes;
 
 import javax.ws.rs.core.MultivaluedMap;
@@ -27,17 +27,19 @@
         this.service = client.resource(address);
     }
 
-    public String getResponse(String path, String key, Object value) throws KorAPException {
+    public String getResponse(String path, String key, Object value) throws
+            KustvaktException {
         MultivaluedMap map = new MultivaluedMapImpl();
         map.add(key, value);
         try {
             return service.path(path).queryParams(map).get(String.class);
         } catch (UniformInterfaceException e) {
-            throw new KorAPException(StatusCodes.REQUEST_INVALID);
+            throw new KustvaktException(StatusCodes.REQUEST_INVALID);
         }
     }
 
-    public String getResponse(MultivaluedMap map, String... paths) throws KorAPException {
+    public String getResponse(MultivaluedMap map, String... paths) throws
+            KustvaktException {
         try {
             WebResource resource = service;
             for (String p : paths)
@@ -45,7 +47,7 @@
             resource = resource.queryParams(map);
             return resource.get(String.class);
         } catch (UniformInterfaceException e) {
-            throw new KorAPException(StatusCodes.REQUEST_INVALID);
+            throw new KustvaktException(StatusCodes.REQUEST_INVALID);
         }
     }
 
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 1e97bd8..c8961932 100644
--- a/src/main/java/de/ids_mannheim/korap/web/KustvaktBaseServer.java
+++ b/src/main/java/de/ids_mannheim/korap/web/KustvaktBaseServer.java
@@ -28,7 +28,7 @@
         else
             BeanConfiguration.loadClasspathContext();
 
-        kargs.setRootClasses(
+        kargs.setRootPackages(
                 new String[] { "de.ids_mannheim.korap.web.service.light" });
         startServer(kargs);
     }
@@ -71,7 +71,7 @@
 
             // http://stackoverflow.com/questions/9670363/how-do-i-programmatically-configure-jersey-to-use-jackson-for-json-deserializa
             final ResourceConfig rc = new PackagesResourceConfig(
-                    kargs.rootClasses);
+                    kargs.rootPackages);
 
             // from http://stackoverflow.com/questions/7421574/embedded-jetty-with-jersey-or-resteasy
             contextHandler
@@ -106,7 +106,7 @@
         private String config;
         private int port;
         private SslContextFactory sslContext;
-        private String[] rootClasses;
+        private String[] rootPackages;
 
         public KustvaktArgs() {
             this.port = -1;
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 8346e1f..eff8b57 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
@@ -9,6 +9,7 @@
 import de.ids_mannheim.korap.interfaces.AuthenticationManagerIface;
 import de.ids_mannheim.korap.user.TokenContext;
 import de.ids_mannheim.korap.web.utils.KorAPContext;
+import de.ids_mannheim.korap.web.utils.KustvaktResponseHandler;
 
 import javax.ws.rs.ext.Provider;
 
@@ -40,7 +41,7 @@
                         .getTokenStatus(authentication, host, ua);
 
             }catch (KustvaktException e) {
-                throw BeanConfiguration.getResponseHandler().throwit(e);
+                throw KustvaktResponseHandler.throwit(e);
             }
 
             if (context != null && (
diff --git a/src/main/java/de/ids_mannheim/korap/web/filter/DefaultFilter.java b/src/main/java/de/ids_mannheim/korap/web/filter/DefaultFilter.java
index a8ffe89..e28be03 100644
--- a/src/main/java/de/ids_mannheim/korap/web/filter/DefaultFilter.java
+++ b/src/main/java/de/ids_mannheim/korap/web/filter/DefaultFilter.java
@@ -39,7 +39,8 @@
 
     private TokenContext createShorterToken(String host, String agent) {
         User demo = User.UserFactory.getDemoUser();
-        TokenContext c = new TokenContext(demo.getUsername());
+        TokenContext c = new TokenContext();
+        c.setUsername(demo.getUsername());
         c.setHostAddress(host);
         c.setUserAgent(agent);
         c.setExpirationTime(TimeUtils.plusSeconds(
diff --git a/src/main/java/de/ids_mannheim/korap/web/service/AuthService.java b/src/main/java/de/ids_mannheim/korap/web/service/AuthService.java
index 5e76016..d4b98fc 100644
--- a/src/main/java/de/ids_mannheim/korap/web/service/AuthService.java
+++ b/src/main/java/de/ids_mannheim/korap/web/service/AuthService.java
@@ -18,6 +18,7 @@
 import de.ids_mannheim.korap.web.filter.AuthFilter;
 import de.ids_mannheim.korap.web.filter.DefaultFilter;
 import de.ids_mannheim.korap.web.filter.PiwikFilter;
+import de.ids_mannheim.korap.web.utils.KustvaktResponseHandler;
 import org.slf4j.Logger;
 
 import javax.ws.rs.*;
@@ -82,6 +83,7 @@
         return Response.ok(ctx.toJSON()).build();
     }
 
+    // todo: rename scope to scopes!
     @GET
     @Path("apiToken")
     public Response requestAPIToken(@Context HttpHeaders headers,
@@ -89,29 +91,29 @@
             @HeaderParam(ContainerRequest.USER_AGENT) String agent,
             @HeaderParam(ContainerRequest.HOST) String host,
             @HeaderParam("referer-url") String referer,
-            @QueryParam("scope") String scope) {
+            @QueryParam("scopes") String scopes) {
         List<String> auth = headers
                 .getRequestHeader(ContainerRequest.AUTHORIZATION);
 
         if (auth == null)
-            throw BeanConfiguration.getResponseHandler()
+            throw KustvaktResponseHandler
                     .throwit(StatusCodes.PERMISSION_DENIED);
         String[] values = BasicHttpAuth.decode(auth.get(0));
 
         // "Invalid syntax for username and password"
         if (values == null)
-            throw BeanConfiguration.getResponseHandler()
+            throw KustvaktResponseHandler
                     .throwit(StatusCodes.PERMISSION_DENIED);
 
         if (values[0].equalsIgnoreCase("null") | values[1]
                 .equalsIgnoreCase("null"))
             // is actual an invalid request
-            throw BeanConfiguration.getResponseHandler()
+            throw KustvaktResponseHandler
                     .throwit(StatusCodes.REQUEST_INVALID);
 
         Map<String, Object> attr = new HashMap<>();
-        if (scope != null && !scope.isEmpty())
-            attr.put(Attributes.SCOPES, scope);
+        if (scopes != null && !scopes.isEmpty())
+            attr.put(Attributes.SCOPES, scopes);
         attr.put(Attributes.HOST, host);
         attr.put(Attributes.USER_AGENT, agent);
         TokenContext context;
@@ -121,7 +123,7 @@
             context = controller.createTokenContext(user, attr,
                     Attributes.API_AUTHENTICATION);
         }catch (KustvaktException e) {
-            throw BeanConfiguration.getResponseHandler().throwit(e);
+            throw KustvaktResponseHandler.throwit(e);
         }
 
         return Response.ok(context.toResponse()).build();
@@ -140,7 +142,7 @@
         //            newContext = controller.refresh(ctx);
         //        }catch (KorAPException e) {
         //            KorAPLogger.ERROR_LOGGER.error("Exception encountered!", e);
-        //            throw BeanConfiguration.getResponseHandler().throwit(e);
+        //            throw KustvaktResponseHandler.throwit(e);
         //        }
         //        return Response.ok().entity(newContext.getToken()).build();
         return null;
@@ -156,7 +158,7 @@
                 .getRequestHeader(ContainerRequest.AUTHORIZATION);
 
         if (auth == null)
-            throw BeanConfiguration.getResponseHandler()
+            throw KustvaktResponseHandler
                     .throwit(StatusCodes.PERMISSION_DENIED);
 
         String[] values = BasicHttpAuth.decode(auth.get(0));
@@ -167,12 +169,12 @@
 
         // "Invalid syntax for username and password"
         if (values == null)
-            throw BeanConfiguration.getResponseHandler()
+            throw KustvaktResponseHandler
                     .throwit(StatusCodes.PERMISSION_DENIED);
 
         if (values[0].equalsIgnoreCase("null") | values[1]
                 .equalsIgnoreCase("null"))
-            throw BeanConfiguration.getResponseHandler()
+            throw KustvaktResponseHandler
                     .throwit(StatusCodes.REQUEST_INVALID);
 
         Map<String, Object> attr = new HashMap<>();
@@ -184,7 +186,7 @@
             context = controller.createTokenContext(user, attr,
                     Attributes.SESSION_AUTHENTICATION);
         }catch (KustvaktException e) {
-            throw BeanConfiguration.getResponseHandler().throwit(e);
+            throw KustvaktResponseHandler.throwit(e);
         }
         return Response.ok().entity(context.toJSON()).build();
     }
@@ -215,7 +217,7 @@
             User user = controller.authenticate(1, null, null, attr);
             context = controller.createTokenContext(user, attr, null);
         }catch (KustvaktException e) {
-            throw BeanConfiguration.getResponseHandler().throwit(e);
+            throw KustvaktResponseHandler.throwit(e);
         }
         return Response.ok().entity(context.toJSON()).build();
     }
diff --git a/src/main/java/de/ids_mannheim/korap/web/service/OAuthService.java b/src/main/java/de/ids_mannheim/korap/web/service/OAuthService.java
index 525eca9..ae4c57e 100644
--- a/src/main/java/de/ids_mannheim/korap/web/service/OAuthService.java
+++ b/src/main/java/de/ids_mannheim/korap/web/service/OAuthService.java
@@ -15,10 +15,11 @@
 import de.ids_mannheim.korap.utils.StringUtils;
 import de.ids_mannheim.korap.web.KustvaktServer;
 import de.ids_mannheim.korap.web.filter.AuthFilter;
-import de.ids_mannheim.korap.web.filter.BlockFilter;
+import de.ids_mannheim.korap.web.filter.BlockingFilter;
 import de.ids_mannheim.korap.web.filter.DefaultFilter;
 import de.ids_mannheim.korap.web.filter.PiwikFilter;
 import de.ids_mannheim.korap.web.utils.FormRequestWrapper;
+import de.ids_mannheim.korap.web.utils.KustvaktResponseHandler;
 import org.apache.oltu.oauth2.as.issuer.MD5Generator;
 import org.apache.oltu.oauth2.as.issuer.OAuthIssuer;
 import org.apache.oltu.oauth2.as.issuer.OAuthIssuerImpl;
@@ -75,7 +76,7 @@
 
     @POST
     @Path("unregister")
-    @ResourceFilters({ AuthFilter.class, BlockFilter.class })
+    @ResourceFilters({ AuthFilter.class, BlockingFilter.class })
     public Response unregisterClient(@Context SecurityContext context,
             @HeaderParam("Host") String host,
             @QueryParam("client_secret") String secret,
@@ -87,14 +88,14 @@
             this.handler.removeClient(info,
                     this.controller.getUser(ctx.getUsername()));
         }catch (KustvaktException e) {
-            throw BeanConfiguration.getResponseHandler().throwit(e);
+            throw KustvaktResponseHandler.throwit(e);
         }
         return Response.ok().build();
     }
 
     @POST
     @Path("register")
-    @ResourceFilters({ AuthFilter.class, BlockFilter.class })
+    @ResourceFilters({ AuthFilter.class, BlockingFilter.class })
     public Response registerClient(@Context SecurityContext context,
             @HeaderParam("Host") String host,
             @QueryParam("redirect_url") String rurl) {
@@ -102,7 +103,7 @@
                 crypto.createToken());
         info.setUrl(host);
         if (rurl == null)
-            throw BeanConfiguration.getResponseHandler()
+            throw KustvaktResponseHandler
                     .throwit(StatusCodes.ILLEGAL_ARGUMENT, "Missing parameter!",
                             "redirect_url");
         info.setRedirect_uri(rurl);
@@ -111,17 +112,18 @@
             this.handler.registerClient(info,
                     this.controller.getUser(ctx.getUsername()));
         }catch (KustvaktException e) {
-            throw BeanConfiguration.getResponseHandler().throwit(e);
+            throw KustvaktResponseHandler.throwit(e);
         }
         return Response.ok(info.toJSON()).build();
     }
 
+    // todo: change parameter to scopes!
     @GET
     @Path("info")
     @ResourceFilters({ AuthFilter.class, DefaultFilter.class,
             PiwikFilter.class })
     public Response getStatus(@Context SecurityContext context,
-            @QueryParam("scope") String scopes) {
+            @QueryParam("scopes") String scopes) {
         TokenContext ctx = (TokenContext) context.getUserPrincipal();
         User user;
         try {
@@ -133,7 +135,7 @@
             base_scope.retainAll(StringUtils.toSet(scopes));
             scopes = StringUtils.toString(base_scope);
         }catch (KustvaktException e) {
-            throw BeanConfiguration.getResponseHandler().throwit(e);
+            throw KustvaktResponseHandler.throwit(e);
         }
         // json format with scope callback parameter
         return Response.ok(JsonUtils.toJSON(Scopes
@@ -142,7 +144,7 @@
 
     @GET
     @Path("authorizations")
-    @ResourceFilters({ AuthFilter.class, BlockFilter.class })
+    @ResourceFilters({ AuthFilter.class, BlockingFilter.class })
     public Response getAuthorizations(@Context SecurityContext context,
             @HeaderParam(ContainerRequest.USER_AGENT) String agent,
             @HeaderParam(ContainerRequest.HOST) String host) {
@@ -156,18 +158,18 @@
                 return Response.noContent().build();
             return Response.ok(JsonUtils.toJSON(auths)).build();
         }catch (KustvaktException e) {
-            throw BeanConfiguration.getResponseHandler().throwit(e);
+            throw KustvaktResponseHandler.throwit(e);
         }
     }
 
     // todo: scopes for access_token are defined here
-    // todo: if user already has an access token registered for client and application, then redirect to token endpoint to retrive that token
+    // todo: if user already has an access token registered for client and application, then redirect to token endpoint to retrieve that token
     // todo: demo account should be disabled for this function --> if authentication failed, client must redirect to login url (little login window)
     @POST
     @Path("authorize")
     @Consumes("application/x-www-form-urlencoded")
     @Produces("application/json")
-    @ResourceFilters({ BlockFilter.class })
+    @ResourceFilters({ BlockingFilter.class })
     public Response authorize(@Context HttpServletRequest request,
             @Context SecurityContext context,
             @HeaderParam(ContainerRequest.USER_AGENT) String agent,
@@ -200,17 +202,13 @@
                 user = controller.getUser(c.getUsername());
                 controller.getUserDetails(user);
             }catch (KustvaktException e) {
-                throw BeanConfiguration.getResponseHandler().throwit(e);
+                throw KustvaktResponseHandler.throwit(e);
             }
 
             // register response according to response_type
             String responseType = oauthRequest
                     .getParam(OAuth.OAUTH_RESPONSE_TYPE);
 
-            OAuthASResponse.OAuthAuthorizationResponseBuilder builder = OAuthASResponse
-                    .authorizationResponse(request,
-                            HttpServletResponse.SC_FOUND);
-
             final String authorizationCode = oauthIssuerImpl
                     .authorizationCode();
             ClientInfo info = this.handler
@@ -240,8 +238,12 @@
 
             String accessToken = this.handler
                     .getToken(oauthRequest.getClientId(), user.getId());
-            //todo: test this with parameters
+
+            //todo: test correct redirect and parameters
             if (accessToken != null) {
+                // fixme: correct status code?
+                OAuthASResponse.OAuthResponseBuilder builder = OAuthASResponse
+                        .status(HttpServletResponse.SC_FOUND);
                 final OAuthResponse response = builder.location("/oauth2/token")
                         .setParam(OAuth.OAUTH_CLIENT_ID,
                                 oauthRequest.getClientId())
@@ -252,7 +254,21 @@
                         .location(new URI(response.getLocationUri())).build();
             }
 
+            final OAuthResponse response;
+            String redirectURI = oauthRequest.getRedirectURI();
+            if (OAuthUtils.isEmpty(redirectURI)) {
+                throw new WebApplicationException(
+                        Response.status(HttpServletResponse.SC_BAD_REQUEST)
+                                .entity("OAuth callback url needs to be provided by client!!!\n")
+                                .build());
+            }
+
             if (responseType.equals(ResponseType.CODE.toString())) {
+                OAuthASResponse.OAuthAuthorizationResponseBuilder builder = OAuthASResponse
+                        .authorizationResponse(request,
+                                HttpServletResponse.SC_FOUND);
+                builder.location(redirectURI);
+
                 try {
                     AuthCodeInfo codeInfo = new AuthCodeInfo(
                             info.getClient_id(), authorizationCode);
@@ -260,32 +276,30 @@
                             .toString(oauthRequest.getScopes(), " "));
                     this.handler.authorize(codeInfo, user);
                 }catch (KustvaktException e) {
-                    throw BeanConfiguration.getResponseHandler().throwit(e);
+                    throw KustvaktResponseHandler.throwit(e);
                 }
                 builder.setParam(OAuth.OAUTH_RESPONSE_TYPE,
                         ResponseType.CODE.toString());
                 builder.setCode(authorizationCode);
+                response = builder.buildBodyMessage();
 
             }else if (responseType.contains(ResponseType.TOKEN.toString())) {
-                try {
-                    AuthCodeInfo codeInfo = new AuthCodeInfo(
-                            info.getClient_id(), authorizationCode);
-                    codeInfo.setScopes(StringUtils
-                            .toString(oauthRequest.getScopes(), " "));
-                    this.handler.authorize(codeInfo, user);
-                }catch (KustvaktException e) {
-                    throw BeanConfiguration.getResponseHandler().throwit(e);
-                }
-
+                OAuthASResponse.OAuthTokenResponseBuilder builder = OAuthASResponse
+                        .tokenResponse(HttpServletResponse.SC_OK);
                 builder.setParam(OAuth.OAUTH_RESPONSE_TYPE,
                         ResponseType.TOKEN.toString());
-                builder.setCode(authorizationCode);
+                builder.location(redirectURI);
 
                 String token = oauthIssuerImpl.accessToken();
-                this.handler.addToken(authorizationCode, token,
+                String refresh = oauthIssuerImpl.refreshToken();
+
+                this.handler.addToken(token, refresh, user.getId(),
+                        oauthRequest.getClientId(),
+                        StringUtils.toString(oauthRequest.getScopes(), " "),
                         config.getLongTokenTTL());
                 builder.setAccessToken(token);
-                builder.setExpiresIn((long) config.getLongTokenTTL());
+                builder.setRefreshToken(refresh);
+                builder.setExpiresIn(String.valueOf(config.getLongTokenTTL()));
 
                 // skips authorization code type and returns id_token and access token directly
                 if (oauthRequest.getScopes().contains("openid")) {
@@ -295,9 +309,10 @@
                         builder.setParam(new_context.getTokenType(),
                                 new_context.getToken());
                     }catch (KustvaktException e) {
-                        throw BeanConfiguration.getResponseHandler().throwit(e);
+                        throw KustvaktResponseHandler.throwit(e);
                     }
                 }
+                response = builder.buildBodyMessage();
             }else {
                 OAuthResponse res = OAuthASResponse
                         .errorResponse(HttpServletResponse.SC_BAD_REQUEST)
@@ -308,23 +323,22 @@
                 return Response.status(res.getResponseStatus())
                         .entity(res.getBody()).build();
             }
-
-            String redirectURI = oauthRequest.getRedirectURI();
-
-            // enables state parameter to disable cross-site scripting attacks
-            final OAuthResponse response = builder.location(redirectURI)
-                    .buildQueryMessage();
-            if (OAuthUtils.isEmpty(redirectURI)) {
-                throw new WebApplicationException(
-                        Response.status(HttpServletResponse.SC_BAD_REQUEST)
-                                .entity("OAuth callback url needs to be provided by client!!!\n")
-                                .build());
-            }
+            //
+            //            String redirectURI = oauthRequest.getRedirectURI();
+            //
+            //            // enables state parameter to disable cross-site scripting attacks
+            //            final OAuthResponse response = builder.location(redirectURI)
+            //                    .buildQueryMessage();
+            //            if (OAuthUtils.isEmpty(redirectURI)) {
+            //                throw new WebApplicationException(
+            //                        Response.status(HttpServletResponse.SC_BAD_REQUEST)
+            //                                .entity("OAuth callback url needs to be provided by client!!!\n")
+            //                                .build());
+            //            }
 
             return Response.status(response.getResponseStatus())
                     .location(new URI(response.getLocationUri())).build();
         }catch (OAuthProblemException e) {
-            e.printStackTrace();
             final Response.ResponseBuilder responseBuilder = Response
                     .status(HttpServletResponse.SC_BAD_REQUEST);
             String redirectUri = e.getRedirectUri();
@@ -454,18 +468,20 @@
                     }else {
                         openid_valid = codeInfo.getScopes().contains("openid");
                         String accessToken = oauthIssuerImpl.accessToken();
+                        String refreshToken = oauthIssuerImpl.refreshToken();
                         // auth code posesses the user reference. native apps access_tokens are directly associated with the user
                         this.handler
                                 .addToken(oauthRequest.getCode(), accessToken,
-                                        config.getTokenTTL());
+                                        refreshToken, config.getTokenTTL());
 
                         builder.setTokenType(TokenType.BEARER.toString());
                         builder.setExpiresIn(
                                 String.valueOf(config.getLongTokenTTL()));
                         builder.setAccessToken(accessToken);
+                        builder.setRefreshToken(refreshToken);
                     }
                 }catch (KustvaktException e) {
-                    throw BeanConfiguration.getResponseHandler().throwit(e);
+                    throw KustvaktResponseHandler.throwit(e);
                 }
                 // todo: errors for invalid scopes or different scopes then during authorization request?
                 //todo ??
@@ -492,18 +508,22 @@
                             .authenticate(0, oauthRequest.getUsername(),
                                     oauthRequest.getPassword(), attr);
                 }catch (KustvaktException e) {
-                    throw BeanConfiguration.getResponseHandler().throwit(e);
+                    throw KustvaktResponseHandler.throwit(e);
                 }
 
                 try {
                     String accessToken = this.handler
                             .getToken(oauthRequest.getClientId(), user.getId());
                     if (accessToken == null) {
+                        String refresh = oauthIssuerImpl.refreshToken();
                         accessToken = oauthIssuerImpl.accessToken();
-                        this.handler.addToken(accessToken, user.getId(),
-                                oauthRequest.getClientId(), StringUtils
-                                        .toString(oauthRequest.getScopes(),
-                                                " "), config.getLongTokenTTL());
+                        this.handler
+                                .addToken(accessToken, refresh, user.getId(),
+                                        oauthRequest.getClientId(), StringUtils
+                                                .toString(oauthRequest
+                                                        .getScopes(), " "),
+                                        config.getLongTokenTTL());
+                        builder.setRefreshToken(refresh);
                     }
                     builder.setTokenType(TokenType.BEARER.toString());
                     builder.setExpiresIn(
@@ -511,7 +531,7 @@
                     builder.setAccessToken(accessToken);
 
                 }catch (KustvaktException e) {
-                    throw BeanConfiguration.getResponseHandler().throwit(e);
+                    throw KustvaktResponseHandler.throwit(e);
                 }
             }
 
@@ -529,7 +549,7 @@
                             Attributes.OPENID_AUTHENTICATION);
                     builder.setParam(c.getTokenType(), c.getToken());
                 }catch (KustvaktException e) {
-                    throw BeanConfiguration.getResponseHandler().throwit(e);
+                    throw KustvaktResponseHandler.throwit(e);
                 }
             }
 
diff --git a/src/main/java/de/ids_mannheim/korap/web/service/UserService.java b/src/main/java/de/ids_mannheim/korap/web/service/UserService.java
index befa736..d3bc6a2 100644
--- a/src/main/java/de/ids_mannheim/korap/web/service/UserService.java
+++ b/src/main/java/de/ids_mannheim/korap/web/service/UserService.java
@@ -20,9 +20,11 @@
 import de.ids_mannheim.korap.web.filter.AuthFilter;
 import de.ids_mannheim.korap.web.filter.DefaultFilter;
 import de.ids_mannheim.korap.web.filter.PiwikFilter;
-import de.ids_mannheim.korap.web.utils.FormWrapper;
+import de.ids_mannheim.korap.web.utils.FormRequestWrapper;
+import de.ids_mannheim.korap.web.utils.KustvaktResponseHandler;
 import org.slf4j.Logger;
 
+import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.*;
 import javax.ws.rs.core.*;
 import java.io.IOException;
@@ -60,18 +62,19 @@
     @Path("register")
     @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
     public Response signUp(
+            @Context HttpServletRequest request,
             @HeaderParam(ContainerRequest.USER_AGENT) String agent,
             @HeaderParam(ContainerRequest.HOST) String host,
             @Context Locale locale, MultivaluedMap form_values) {
 
-        FormWrapper wrapper = new FormWrapper(form_values);
+        FormRequestWrapper wrapper = new FormRequestWrapper(request, form_values);
 
         wrapper.put(Attributes.HOST, host);
         wrapper.put(Attributes.USER_AGENT, agent);
         UriBuilder uriBuilder;
         User user;
-        if (wrapper.get(Attributes.EMAIL) == null)
-            throw BeanConfiguration.getResponseHandler()
+        if (wrapper.getParameter(Attributes.EMAIL) == null)
+            throw KustvaktResponseHandler
                     .throwit(StatusCodes.ILLEGAL_ARGUMENT, "parameter missing",
                             "email");
 
@@ -80,10 +83,10 @@
             uriBuilder.path(KustvaktServer.API_VERSION).path("user")
                     .path("confirm");
 
-            user = controller.createUserAccount(wrapper);
+            user = controller.createUserAccount(wrapper.toMap(true));
 
         }catch (KustvaktException e) {
-            throw BeanConfiguration.getResponseHandler().throwit(e);
+            throw KustvaktResponseHandler.throwit(e);
         }
         URIParam uri = user.getField(URIParam.class);
         if (uri.hasValues()) {
@@ -124,7 +127,7 @@
             //                            node.path("new_password").asText());
             controller.updateAccount(user);
         }catch (KustvaktException e) {
-            throw BeanConfiguration.getResponseHandler().throwit(e);
+            throw KustvaktResponseHandler.throwit(e);
         }
         return Response.ok().build();
     }
@@ -135,18 +138,19 @@
     public Response confirmRegistration(@QueryParam("uri") String uritoken,
             @Context Locale locale, @QueryParam("user") String username) {
         if (uritoken == null)
-            throw BeanConfiguration.getResponseHandler()
+            throw KustvaktResponseHandler
                     .throwit(StatusCodes.ILLEGAL_ARGUMENT, "parameter missing",
                             "Uri-Token");
         if (username == null)
-            throw BeanConfiguration.getResponseHandler()
+            throw KustvaktResponseHandler
                     .throwit(StatusCodes.ILLEGAL_ARGUMENT, "parameter missing",
                             "Username");
 
         try {
             controller.confirmRegistration(uritoken, username);
         }catch (KustvaktException e) {
-            throw BeanConfiguration.getResponseHandler().throwit(e);
+            throw KustvaktResponseHandler
+                    .throwit(e);
         }
         return Response.ok("success").build();
     }
@@ -184,7 +188,7 @@
                     .append(username);
         }catch (KustvaktException e) {
             error.error("Eoxception encountered!", e);
-            throw BeanConfiguration.getResponseHandler().throwit(e);
+            throw KustvaktResponseHandler.throwit(e);
         }
 
         ObjectNode obj = JsonUtils.createObjectNode();
@@ -215,7 +219,7 @@
     @ResourceFilters({ AuthFilter.class, DefaultFilter.class,
             PiwikFilter.class })
     public Response getStatus(@Context SecurityContext context,
-            @QueryParam("scope") String scope) {
+            @QueryParam("scopes") String scope) {
         TokenContext ctx = (TokenContext) context.getUserPrincipal();
         User user;
         try {
@@ -227,7 +231,7 @@
             base_scope.retainAll(StringUtils.toSet(scope));
             scope = StringUtils.toString(base_scope);
         }catch (KustvaktException e) {
-            throw BeanConfiguration.getResponseHandler().throwit(e);
+            throw KustvaktResponseHandler.throwit(e);
         }
         return Response.ok(JsonUtils.toJSON(Scopes
                 .mapOpenIDConnectScopes(scope, user.getDetails()))).build();
@@ -247,7 +251,7 @@
 
         }catch (KustvaktException e) {
             error.error("Exception encountered!", e);
-            throw BeanConfiguration.getResponseHandler().throwit(e);
+            throw KustvaktResponseHandler.throwit(e);
         }
         return Response.ok(JsonUtils.toJSON(user.getSettings().toObjectMap()))
                 .build();
@@ -266,7 +270,7 @@
         try {
             settings = JsonUtils.read(values, Map.class);
         }catch (IOException e) {
-            throw BeanConfiguration.getResponseHandler()
+            throw KustvaktResponseHandler
                     .throwit(StatusCodes.REQUEST_INVALID,
                             "Could not read parameters", values);
         }
@@ -285,7 +289,7 @@
                 return Response.notModified().build();
         }catch (KustvaktException e) {
             error.error("Exception encountered!", e);
-            throw BeanConfiguration.getResponseHandler().throwit(e);
+            throw KustvaktResponseHandler.throwit(e);
         }
 
         return Response.ok().build();
@@ -304,7 +308,7 @@
             controller.getUserDetails(user);
         }catch (KustvaktException e) {
             error.error("Exception encountered!", e);
-            throw BeanConfiguration.getResponseHandler().throwit(e);
+            throw KustvaktResponseHandler.throwit(e);
         }
 
         return Response.ok(JsonUtils.toJSON(user.getDetails().toMap())).build();
@@ -325,7 +329,7 @@
             details = JsonUtils.read(values, Map.class);
         }catch (IOException e) {
             error.error("Exception encountered!", e);
-            throw BeanConfiguration.getResponseHandler()
+            throw KustvaktResponseHandler
                     .throwit(StatusCodes.REQUEST_INVALID,
                             "Could not read parameters", values);
         }
@@ -339,7 +343,7 @@
                 return Response.notModified().build();
         }catch (KustvaktException e) {
             error.error("Exception encountered!", e);
-            throw BeanConfiguration.getResponseHandler().throwit(e);
+            throw KustvaktResponseHandler.throwit(e);
         }
 
         return Response.ok().build();
@@ -394,7 +398,7 @@
             //            }
         }catch (KustvaktException e) {
             error.error("Exception encountered!", e);
-            throw BeanConfiguration.getResponseHandler().throwit(e);
+            throw KustvaktResponseHandler.throwit(e);
         }
         return Response.ok(JsonUtils.toJSON(add)).build();
     }
@@ -411,7 +415,7 @@
             controller.deleteAccount(user);
         }catch (KustvaktException e) {
             error.error("Exception encountered!", e);
-            throw BeanConfiguration.getResponseHandler().throwit(e);
+            throw KustvaktResponseHandler.throwit(e);
         }
         return Response.ok().build();
     }
@@ -433,7 +437,7 @@
             queryStr = "";
         }catch (KustvaktException e) {
             error.error("Exception encountered!", e);
-            throw BeanConfiguration.getResponseHandler().throwit(e);
+            throw KustvaktResponseHandler.throwit(e);
         }
         return Response.ok(queryStr).build();
     }
@@ -449,7 +453,7 @@
             controller.logout(context);
         }catch (KustvaktException e) {
             error.error("Logout Exception", e);
-            throw BeanConfiguration.getResponseHandler().throwit(e);
+            throw KustvaktResponseHandler.throwit(e);
         }
         return Response.ok().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 2f300be..b7463d9 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
@@ -8,7 +8,9 @@
 import de.ids_mannheim.korap.exceptions.StatusCodes;
 import de.ids_mannheim.korap.query.serialize.MetaQueryBuilder;
 import de.ids_mannheim.korap.query.serialize.QuerySerializer;
-import de.ids_mannheim.korap.resource.RewriteProcessor;
+import de.ids_mannheim.korap.resource.rewrite.FoundryInject;
+import de.ids_mannheim.korap.resource.rewrite.PublicCollection;
+import de.ids_mannheim.korap.resource.rewrite.RewriteHandler;
 import de.ids_mannheim.korap.utils.KustvaktLogger;
 import de.ids_mannheim.korap.web.ClientsHandler;
 import de.ids_mannheim.korap.web.SearchKrill;
@@ -37,7 +39,7 @@
 
     private SearchKrill searchKrill;
     private ClientsHandler graphDBhandler;
-    private RewriteProcessor processor;
+    private RewriteHandler processor;
     private KustvaktConfiguration config;
 
     public LightService() {
@@ -45,7 +47,9 @@
         this.searchKrill = new SearchKrill(config.getIndexDir());
         UriBuilder builder = UriBuilder.fromUri("http://10.0.10.13").port(9997);
         this.graphDBhandler = new ClientsHandler(builder.build());
-        this.processor = new RewriteProcessor(this.config);
+        this.processor = new RewriteHandler();
+        this.processor.add(new FoundryInject(this.config));
+        this.processor.add(new PublicCollection());
     }
 
     /**
@@ -92,14 +96,14 @@
         ss.setMeta(meta);
         if (cq != null)
             ss.setCollection(cq);
-        return Response.ok(processor.process(ss.toJSON())).build();
+        return Response.ok(processor.apply(ss.toJSON(), null)).build();
     }
 
     @POST
     @Path("search")
     public Response queryRaw(@QueryParam("engine") String engine,
             String jsonld) {
-        jsonld = processor.process(jsonld);
+        jsonld = processor.apply(jsonld, null);
         // todo: should be possible to add the meta part to the query serialization
         jlog.info("Serialized search: {}", jsonld);
 
@@ -133,7 +137,7 @@
         if (cq != null)
             serializer.setCollection(cq);
 
-        String query = processor.process(serializer.toJSON());
+        String query = processor.apply(serializer.toJSON(), null);
         jlog.info("the serialized query {}", query);
 
         // This may not work with the the KoralQuery
@@ -200,7 +204,7 @@
             //                meta.addEntry("itemsPerResource", 1);
             QuerySerializer s = new QuerySerializer().setQuery(query, ql, v)
                     .setMeta(meta);
-            query = processor.process(s.toJSON());
+            query = processor.apply(s.toJSON(), null);
         }
         String result;
         try {
diff --git a/src/main/java/de/ids_mannheim/korap/web/utils/FormRequestWrapper.java b/src/main/java/de/ids_mannheim/korap/web/utils/FormRequestWrapper.java
index 143aa04..05a1bb5 100644
--- a/src/main/java/de/ids_mannheim/korap/web/utils/FormRequestWrapper.java
+++ b/src/main/java/de/ids_mannheim/korap/web/utils/FormRequestWrapper.java
@@ -3,9 +3,7 @@
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletRequestWrapper;
 import javax.ws.rs.core.MultivaluedMap;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 /**
  * Helper class to wrapp multivaluedmap into a hashmap. Depending on the strict parameter,
@@ -59,6 +57,14 @@
         return map;
     }
 
+    public void put(String key, String value) {
+        this.form.putSingle(key, value);
+    }
+
+    public void put(String key, String... values) {
+        this.form.put(key, Arrays.asList(values));
+    }
+
 }
 
 
diff --git a/src/main/java/de/ids_mannheim/korap/web/utils/FormWrapper.java b/src/main/java/de/ids_mannheim/korap/web/utils/FormWrapper.java
index 913c848..f099158 100644
--- a/src/main/java/de/ids_mannheim/korap/web/utils/FormWrapper.java
+++ b/src/main/java/de/ids_mannheim/korap/web/utils/FormWrapper.java
@@ -12,6 +12,7 @@
  * @author hanl
  * @date 18/05/2015
  */
+@Deprecated
 public class FormWrapper extends HashMap<String, Object> {
 
     public FormWrapper(MultivaluedMap form, boolean strict) {
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 c35ce5b..1a52c3d 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
@@ -1,8 +1,7 @@
 package de.ids_mannheim.korap.web.utils;
 
 import de.ids_mannheim.korap.auditing.AuditRecord;
-import de.ids_mannheim.korap.exceptions.BaseException;
-import de.ids_mannheim.korap.exceptions.KorAPException;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.exceptions.StatusCodes;
 import de.ids_mannheim.korap.interfaces.AuditingIface;
 import de.ids_mannheim.korap.response.Notifications;
@@ -32,32 +31,24 @@
             throw new RuntimeException("Auditing handler must be set!");
     }
 
-    public static WebApplicationException throwit(BaseException e) {
-        //fixme: ??!
-        e.printStackTrace();
+    public static WebApplicationException throwit(KustvaktException e) {
         return new WebApplicationException(
                 Response.status(Response.Status.BAD_REQUEST)
                         .entity(buildNotification(e)).build());
     }
 
-    @Deprecated
     public static WebApplicationException throwit(int code) {
-        KorAPException e = new KorAPException(code);
-        return new WebApplicationException(
-                Response.status(Response.Status.OK).entity(buildNotification(e))
-                        .build());
+        return new WebApplicationException(Response.status(Response.Status.OK)
+                .entity(buildNotification(code, "", "")).build());
     }
 
-    @Deprecated
     public static WebApplicationException throwit(int code, String message,
             String entity) {
-        KorAPException e = new KorAPException(code, message, entity);
-        return new WebApplicationException(
-                Response.status(Response.Status.OK).entity(buildNotification(e))
-                        .build());
+        return new WebApplicationException(Response.status(Response.Status.OK)
+                .entity(buildNotification(code, message, entity)).build());
     }
 
-    private static String buildNotification(BaseException e) {
+    private static String buildNotification(KustvaktException e) {
         register(e.getRecords());
         return buildNotification(e.getStatusCode(), e.getMessage(),
                 e.getEntity());
@@ -71,7 +62,8 @@
     }
 
     public static WebApplicationException throwAuthenticationException() {
-        KorAPException e = new KorAPException(StatusCodes.BAD_CREDENTIALS);
+        KustvaktException e = new KustvaktException(
+                StatusCodes.BAD_CREDENTIALS);
         return new WebApplicationException(
                 Response.status(Response.Status.UNAUTHORIZED)
                         .header(HttpHeaders.WWW_AUTHENTICATE,
diff --git a/src/main/resources/.DS_Store b/src/main/resources/.DS_Store
index 51b3007..0f6288e 100644
--- a/src/main/resources/.DS_Store
+++ b/src/main/resources/.DS_Store
Binary files differ
diff --git a/src/main/resources/db/mysql/V1.2__oauth2_tables_mysql.sql b/src/main/resources/db/mysql/V1.2__oauth2_tables_mysql.sql
index 5e9c968..227d660 100644
--- a/src/main/resources/db/mysql/V1.2__oauth2_tables_mysql.sql
+++ b/src/main/resources/db/mysql/V1.2__oauth2_tables_mysql.sql
@@ -9,37 +9,6 @@
 url VARCHAR(200) UNIQUE
 );
 
-create table oauth2_auth_codes (
-id INTEGER PRIMARY KEY AUTO_INCREMENT,
-client_id VARCHAR(100),
-auth_code VARCHAR(250),
-status INTEGER DEFAULT 1,
-scopes VARCHAR (150),
-created TIMESTAMP DEFAULT CURRENT_TIMESTAMP
-);
-
--- define scopes?!
-create table oauth2_client_authorization (
-id INTEGER PRIMARY KEY AUTO_INCREMENT,
-fk_client_id VARCHAR(100),
-user_id INTEGER,
-FOREIGN KEY (fk_client_id)
-REFERENCES oauth2_client(client_id)
-ON DELETE CASCADE
-);
-
----- status 1 = valid, 0 = revoked
---create table oauth2_access_token (
---id INTEGER PRIMARY KEY AUTO_INCREMENT,
---access_token VARCHAR(300),
---auth_code VARCHAR(250),
---userID INTEGER,
---status INTEGER DEFAULT 1,
---expiration TIMESTAMP,
---scopes VARCHAR (150),
---FOREIGN KEY (userID)
---REFERENCES korap_users(id)
---);
 
 -- status 1 = valid, 0 = revoked, -1 = disabled
 create table oauth2_access_token (
@@ -61,3 +30,19 @@
 REFERENCES oauth2_client(client_id)
 ON DELETE CASCADE
 );
+
+
+-- also scopes?
+create table oauth2_refresh_token (
+id INTEGER PRIMARY KEY AUTO_INCREMENT,
+client_id VARCHAR(100),
+user_id INTEGER,
+expiration TIMESTAMP,
+scopes VARCHAR(350),
+FOREIGN KEY (user_id)
+REFERENCES korap_users(id)
+ON DELETE CASCADE,
+FOREIGN KEY (client_id)
+REFERENCES oauth2_client(client_id)
+ON DELETE CASCADE
+);
\ No newline at end of file
diff --git a/src/main/resources/db/sqlite/V1__Initial_version.sql b/src/main/resources/db/sqlite/V1__Initial_version.sql
index fbe252d..912e699 100644
--- a/src/main/resources/db/sqlite/V1__Initial_version.sql
+++ b/src/main/resources/db/sqlite/V1__Initial_version.sql
@@ -226,11 +226,17 @@
 url VARCHAR(200) UNIQUE
 );
 
+
+-- refresh token doesn't care about expiration.
+-- also narrower scopes for new access token with the refresh token are not supported
+-- otherwise i would require a comparison of all access_token to get the maximum scopes and compare to request
+
 -- status 1 = valid, 0 = revoked, -1 = disabled
 create table IF NOT EXISTS oauth2_access_token (
 id INTEGER PRIMARY KEY AUTOINCREMENT,
 access_token VARCHAR(300),
 auth_code VARCHAR(250),
+refresh_token VARCHAR(250),
 client_id VARCHAR(100),
 user_id INTEGER,
 -- make boolean --
@@ -240,10 +246,29 @@
 scopes VARCHAR(350),
 expiration TIMESTAMP,
 FOREIGN KEY (user_id)
-REFERENCES korap_users(id)
+REFERENCES korap_users(id),
+FOREIGN KEY (client_id)
+REFERENCES oauth2_client(client_id)
 );
 
 
+-- fixme: also scopes?
+create table oauth2_refresh_token (
+id INTEGER PRIMARY KEY AUTOINCREMENT,
+client_id VARCHAR(100),
+user_id INTEGER,
+expiration TIMESTAMP,
+scopes VARCHAR(350),
+FOREIGN KEY (user_id)
+REFERENCES korap_users(id)
+ON DELETE CASCADE,
+FOREIGN KEY (client_id)
+REFERENCES oauth2_client(client_id)
+ON DELETE CASCADE
+);
+
+
+
 -- a bit confusing. 1. creator is policy creator, 2. creator is resource creator --> different implications
 -- insert resource data from resource_store alltogether, so i dont have to retrieve anything from there?!
 create view if not exists policy_view as
diff --git a/src/main/resources/default-config.xml b/src/main/resources/default-config.xml
index 023f671..4f7d23b 100644
--- a/src/main/resources/default-config.xml
+++ b/src/main/resources/default-config.xml
@@ -64,29 +64,31 @@
     </bean>
 
     <bean id="kustvakt_db"
-          class="de.ids_mannheim.korap.ext.database.JDBCClient">
+          class="de.ids_mannheim.korap.handlers.JDBCClient">
         <constructor-arg index="0" ref="dataSource"/>
         <!-- deprecated property -->
         <property name="database" value="${jdbc.database}"/>
     </bean>
 
     <bean id="kustvakt_auditing"
-          class="de.ids_mannheim.korap.ext.database.JDBCAuditing">
+          class="de.ids_mannheim.korap.handlers.JDBCAuditing">
         <constructor-arg ref="kustvakt_db"/>
     </bean>
 
     <bean id="kustvakt_userdb"
-          class="de.ids_mannheim.korap.ext.database.EntityDao">
+          class="de.ids_mannheim.korap.handlers.EntityDao">
         <constructor-arg ref="kustvakt_db"/>
     </bean>
 
+    <!--fixme: change name according to convention -->
     <bean id="collectionProvider"
-          class="de.ids_mannheim.korap.ext.database.CollectionDao">
+          class="de.ids_mannheim.korap.handlers.CollectionDao">
         <constructor-arg ref="kustvakt_db"/>
     </bean>
 
+    <!--fixme: change name according to convention -->
     <bean id="resourceProvider"
-          class="de.ids_mannheim.korap.ext.database.ResourceDao">
+          class="de.ids_mannheim.korap.handlers.ResourceDao">
         <constructor-arg ref="kustvakt_db"/>
     </bean>
 
@@ -100,12 +102,7 @@
         <constructor-arg ref="kustvakt_config"/>
     </bean>
 
-    <bean id="resourceHandler"
-          class="de.ids_mannheim.korap.ext.security.accessControl.ResourceHandler"/>
-
-
     <!-- authentication providers to use -->
-
     <bean id="api_auth"
           class="de.ids_mannheim.korap.ext.security.authentication.APIAuthentication">
         <constructor-arg
@@ -160,14 +157,6 @@
         <property name="providers" ref="auth_providers"/>
     </bean>
 
-    <!--
-    <util:list id="providers"
-               value-type="de.ids_mannheim.korap.ext.interfaces.ResourceOperationIface">
-        <ref bean="resourceProvider"/>
-        <ref bean="collectionProvider"/>
-    </util:list>
--->
-
     <!-- todo: if db interfaces not loaded via spring, does transaction even work then? -->
     <!-- the transactional advice (i.e. what 'happens'; see the <aop:advisor/> bean below) -->
     <tx:advice id="txAdvice" transaction-manager="txManager">
diff --git a/src/test/.DS_Store b/src/test/.DS_Store
index c7f4961..b5e4a6e 100644
--- a/src/test/.DS_Store
+++ b/src/test/.DS_Store
Binary files differ
diff --git a/src/test/java/.DS_Store b/src/test/java/.DS_Store
index 9462fb8..f388377 100644
--- a/src/test/java/.DS_Store
+++ b/src/test/java/.DS_Store
Binary files differ
diff --git a/src/test/java/CollectionQueryBuilderTest.java b/src/test/java/CollectionQueryBuilderTest.java
index de9a089..aeb753f 100644
--- a/src/test/java/CollectionQueryBuilderTest.java
+++ b/src/test/java/CollectionQueryBuilderTest.java
@@ -13,67 +13,76 @@
     public void testsimpleAdd() {
         CollectionQueryBuilder3 b = new CollectionQueryBuilder3();
         b.addSegment("corpusID", CollectionQueryBuilder3.EQ.EQUAL, "WPD");
-        //        System.out.println(b.toJSON());
+
+        JsonNode node = JsonUtils.readTree(b.toJSON());
+
+        assert node != null;
+        assert node.at("/collection/@type").asText().equals("koral:doc");
+        assert node.at("/collection/key").asText().equals("corpusID");
+
     }
 
     @Test
-    public void testSimpleConjunctive() {
+    public void testSimpleConjunction() {
         CollectionQueryBuilder3 b = new CollectionQueryBuilder3();
         b.addSegment("corpusID", CollectionQueryBuilder3.EQ.EQUAL, "WPD").and()
                 .addSegment("textClass", CollectionQueryBuilder3.EQ.EQUAL,
                         "freizeit");
-        //        System.out.println(b.toJSON());
+        JsonNode node = JsonUtils.readTree(b.toJSON());
+
+        assert node != null;
+        assert node.at("/collection/@type").asText().equals("koral:docGroup");
+        assert node.at("/collection/operation").asText()
+                .equals("operation:and");
+        assert node.at("/collection/operands/0/key").asText()
+                .equals("corpusID");
+        assert node.at("/collection/operands/1/key").asText()
+                .equals("textClass");
     }
 
     @Test
-    public void testSimpleDisjunctive() {
+    public void testSimpleDisjunction() {
         CollectionQueryBuilder3 b = new CollectionQueryBuilder3();
-        b.addSegment("corpusID", CollectionQueryBuilder3.EQ.EQUAL, "WPD").and()
+        b.addSegment("corpusID", CollectionQueryBuilder3.EQ.EQUAL, "WPD").or()
                 .addSegment("textClass", CollectionQueryBuilder3.EQ.EQUAL,
                         "freizeit");
-        //        System.out.println(b.toJSON());
+        JsonNode node = JsonUtils.readTree(b.toJSON());
+
+        assert node != null;
+        assert node.at("/collection/operation").asText().equals("operation:or");
+        assert node.at("/collection/operands/0/key").asText()
+                .equals("corpusID");
+        assert node.at("/collection/operands/1/key").asText()
+                .equals("textClass");
     }
 
     @Test
     public void testComplexSubQuery() {
-
         CollectionQueryBuilder3 b = new CollectionQueryBuilder3();
-        b.addSegment("corpusID", CollectionQueryBuilder3.EQ.EQUAL, "ADF").and()
+        b.addSegment("corpusID", CollectionQueryBuilder3.EQ.EQUAL, "ADF").or()
                 .addSub("textClass=freizeit & corpusID=WPD");
-        //        System.out.println(b.toJSON());
-    }
 
-    @Test // basically joining two or more resource queries
-    public void testAddResourceQueryAfter() {
-        CollectionQueryBuilder3 b = new CollectionQueryBuilder3();
-        b.addSegment("corpusID", CollectionQueryBuilder3.EQ.EQUAL, "ADF").and()
-                .addSub("textClass=freizeit & corpusID=WPD");
-        //        System.out.println(b.toJSON());
+        JsonNode node = JsonUtils.readTree(b.toJSON());
 
-        //        join.addSegment("textClass", "politik");
-    }
+        assert node != null;
+        assert node.at("/collection/operation").asText().equals("operation:or");
+        assert node.at("/collection/operands/0/key").asText()
+                .equals("corpusID");
+        assert node.at("/collection/operands/1/@type").asText()
+                .equals("koral:docGroup");
 
-    @Test // basically joining two or more resource queries
-    public void testAddResourceQueryBefore() {
-        CollectionQueryBuilder3 b = new CollectionQueryBuilder3();
-        b.addSegment("corpusID", CollectionQueryBuilder3.EQ.EQUAL, "ADF").and()
-                .addSub("textClass!=freizeit & corpusID=WPD");
-
-        //        CollectionQueryBuilder3 join = new CollectionQueryBuilder3();
-        //        join.addRaw(b.toJSON());
-        //        join.addSegment("textClass", "politik");
-        //        System.out.println("JOINED " + join.toJSON());
     }
 
     @Test
-    public void test1() {
+    public void testAddResourceQueryAfter() {
         CollectionQueryBuilder3 b = new CollectionQueryBuilder3();
         b.addSegment("corpusID", CollectionQueryBuilder3.EQ.EQUAL, "ADF").or()
                 .addSub("textClass=freizeit & corpusID=WPD");
 
         CollectionQueryBuilder3 c = new CollectionQueryBuilder3();
         c.setBaseQuery(b.toJSON());
-        c.addSub("textClass=wissenschaft");
+        c.addSegment("textClass", CollectionQueryBuilder3.EQ.EQUAL,
+                "wissenschaft");
 
         JsonNode node = JsonUtils.readTree(c.toJSON());
 
@@ -84,4 +93,26 @@
                 .equals("wissenschaft");
     }
 
+    @Test
+    public void testAddComplexResourceQueryAfter() {
+        CollectionQueryBuilder3 b = new CollectionQueryBuilder3();
+        b.addSegment("corpusID", CollectionQueryBuilder3.EQ.EQUAL, "ADF").or()
+                .addSub("textClass=freizeit & corpusID=WPD");
+
+        CollectionQueryBuilder3 c = new CollectionQueryBuilder3();
+        c.setBaseQuery(b.toJSON());
+        c.addSub("(textClass=politik & corpusID=AZPS)");
+
+        JsonNode node = JsonUtils.readTree(c.toJSON());
+
+        assert node != null;
+        assert node.at("/collection/operands/2/@type").asText()
+                .equals("koral:docGroup");
+        assert node.at("/collection/operands/2/operands/0/value").asText()
+                .equals("politik");
+        assert node.at("/collection/operands/2/operands/1/value").asText()
+                .equals("AZPS");
+
+    }
+
 }
diff --git a/src/test/java/de/ids_mannheim/korap/web/service/AuthServiceTest.java b/src/test/java/de/ids_mannheim/korap/web/service/AuthServiceTest.java
index 2a4486e..10d5855 100644
--- a/src/test/java/de/ids_mannheim/korap/web/service/AuthServiceTest.java
+++ b/src/test/java/de/ids_mannheim/korap/web/service/AuthServiceTest.java
@@ -4,5 +4,10 @@
  * @author hanl
  * @date 24/09/2015
  */
-public class AuthServiceTest {
+public class AuthServiceTest extends FastJerseyTest {
+
+    //todo: test basicauth via secure connection
+
+
+
 }
diff --git a/src/test/java/de/ids_mannheim/korap/web/service/FastJerseyTest.java b/src/test/java/de/ids_mannheim/korap/web/service/FastJerseyTest.java
index f3a0a04..b77e4be 100644
--- a/src/test/java/de/ids_mannheim/korap/web/service/FastJerseyTest.java
+++ b/src/test/java/de/ids_mannheim/korap/web/service/FastJerseyTest.java
@@ -5,10 +5,10 @@
 import com.sun.jersey.api.core.DefaultResourceConfig;
 import com.sun.jersey.spi.inject.SingletonTypeInjectableProvider;
 import com.sun.jersey.test.framework.AppDescriptor;
-import com.sun.jersey.test.framework.LowLevelAppDescriptor;
+import com.sun.jersey.test.framework.WebAppDescriptor;
 import com.sun.jersey.test.framework.spi.container.TestContainer;
 import com.sun.jersey.test.framework.spi.container.TestContainerFactory;
-import com.sun.jersey.test.framework.spi.container.grizzly.GrizzlyTestContainerFactory;
+import com.sun.jersey.test.framework.spi.container.grizzly.web.GrizzlyWebTestContainerFactory;
 import org.junit.AfterClass;
 import org.junit.Before;
 import org.junit.BeforeClass;
@@ -68,11 +68,14 @@
     }
 
     public static void initServer() {
-        AppDescriptor ad = new LowLevelAppDescriptor.Builder(resourceConfig)
-                .build();
+
+        //        AppDescriptor ad = new LowLevelAppDescriptor.Builder(resourceConfig)
+        //                .build();
+        AppDescriptor ad = new WebAppDescriptor.Builder().build();
+
         TestContainerFactory tcf = testContainerFactory;
         if (tcf == null) {
-            tcf = new GrizzlyTestContainerFactory();
+            tcf = new GrizzlyWebTestContainerFactory();
         }
         testContainer = tcf
                 .create(UriBuilder.fromUri("http://localhost/").port(9998)
diff --git a/src/test/java/de/ids_mannheim/korap/web/service/KustvaktCoreRestTest.java b/src/test/java/de/ids_mannheim/korap/web/service/KustvaktCoreRestTest.java
index 88ad2bf..101da58 100644
--- a/src/test/java/de/ids_mannheim/korap/web/service/KustvaktCoreRestTest.java
+++ b/src/test/java/de/ids_mannheim/korap/web/service/KustvaktCoreRestTest.java
@@ -4,6 +4,7 @@
 import de.ids_mannheim.korap.config.BeanConfiguration;
 import de.ids_mannheim.korap.query.serialize.CollectionQueryProcessor;
 import de.ids_mannheim.korap.utils.JsonUtils;
+import de.ids_mannheim.korap.web.service.light.LightService;
 import org.junit.BeforeClass;
 import org.junit.Ignore;
 import org.junit.Test;
@@ -74,7 +75,7 @@
                 .queryParam("q", "[base=Haus & surface=Hauses]")
                 .queryParam("ql", "poliqarp").queryParam("cutOff", "true")
                 .queryParam("page", "1").get(ClientResponse.class);
-        System.out.println("RESPONSE " + response);
+        System.out.println("RESPONSE " + response.getEntity(String.class));
     }
 
 }
diff --git a/src/test/java/de/ids_mannheim/korap/web/service/OAuth2EndpointTest.java b/src/test/java/de/ids_mannheim/korap/web/service/OAuth2EndpointTest.java
index 19bb99e..4cd0ed5 100644
--- a/src/test/java/de/ids_mannheim/korap/web/service/OAuth2EndpointTest.java
+++ b/src/test/java/de/ids_mannheim/korap/web/service/OAuth2EndpointTest.java
@@ -1,8 +1,32 @@
 package de.ids_mannheim.korap.web.service;
 
+import com.sun.jersey.api.client.ClientResponse;
+import de.ids_mannheim.korap.config.BeanConfiguration;
+import de.ids_mannheim.korap.security.auth.BasicHttpAuth;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
 /**
  * @author hanl
  * @date 23/09/2015
  */
-public class OAuth2EndpointTest {
+public class OAuth2EndpointTest extends FastJerseyTest {
+
+    @BeforeClass
+    public static void configure() {
+        BeanConfiguration.loadClasspathContext();
+        addClass(OAuthService.class);
+        // todo: change korap user personal data!
+        String header = BasicHttpAuth.encode("test", "test1");
+    }
+
+    @Test
+    public void testAuthorizeClient() {
+        ClientResponse response = resource().path(API_VERSION).path("oauth2")
+                .path("register")
+                .queryParam("redirect_url", "korap.ids-mannheim.de/redirect")
+                .header("Host", "korap.ids-mannheim.de")
+                .post(ClientResponse.class);
+    }
+
 }
diff --git a/src/test/java/de/ids_mannheim/korap/web/service/OAuth2HandlerTest.java b/src/test/java/de/ids_mannheim/korap/web/service/OAuth2HandlerTest.java
index eadced8..7e982f7 100644
--- a/src/test/java/de/ids_mannheim/korap/web/service/OAuth2HandlerTest.java
+++ b/src/test/java/de/ids_mannheim/korap/web/service/OAuth2HandlerTest.java
@@ -4,10 +4,11 @@
 import de.ids_mannheim.korap.config.BeanConfiguration;
 import de.ids_mannheim.korap.config.ClientInfo;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
-import de.ids_mannheim.korap.ext.config.BeanHelperExtension;
-import de.ids_mannheim.korap.ext.security.oauth2.OAuth2Handler;
+import de.ids_mannheim.korap.handlers.OAuth2Handler;
 import de.ids_mannheim.korap.interfaces.EncryptionIface;
-import de.ids_mannheim.korap.user.*;
+import de.ids_mannheim.korap.user.KorAPUser;
+import de.ids_mannheim.korap.user.TokenContext;
+import de.ids_mannheim.korap.user.User;
 import org.junit.AfterClass;
 import org.junit.Assert;
 import org.junit.BeforeClass;
@@ -18,19 +19,17 @@
  * @date 13/05/2015
  */
 
-//works
 public class OAuth2HandlerTest {
 
     private static ClientInfo info;
     private static OAuth2Handler handler;
     private static EncryptionIface crypto;
-    private static final String SCOPE = "search preferences queries account";
+    private static final String SCOPES = "search preferences queries account";
     private static final KorAPUser user = User.UserFactory.getUser("test_user");
 
     @BeforeClass
     public static void setup() throws KustvaktException {
         BeanConfiguration.loadClasspathContext("classpath-config.xml");
-        BeanConfiguration.setCustomBeansHolder(new BeanHelperExtension());
         handler = new OAuth2Handler(
                 BeanConfiguration.getBeans().getPersistenceClient());
         crypto = BeanConfiguration.getBeans().getEncryption();
@@ -58,7 +57,7 @@
         String auth_code = crypto.createToken();
         AuthCodeInfo codeInfo = new AuthCodeInfo(info.getClient_id(),
                 auth_code);
-        codeInfo.setScopes(SCOPE);
+        codeInfo.setScopes(SCOPES);
 
         handler.authorize(codeInfo, user);
         codeInfo = handler.getAuthorization(auth_code);
@@ -71,11 +70,12 @@
         String auth_code = crypto.createToken();
         AuthCodeInfo codeInfo = new AuthCodeInfo(info.getClient_id(),
                 auth_code);
-        codeInfo.setScopes(SCOPE);
+        codeInfo.setScopes(SCOPES);
 
         handler.authorize(codeInfo, user);
         String t = crypto.createToken();
-        handler.addToken(codeInfo.getCode(), t, 7200);
+        String refresh = crypto.createToken();
+        handler.addToken(codeInfo.getCode(), t, refresh, 7200);
 
         TokenContext ctx = handler.getContext(t);
         Assert.assertNotNull("context is null", ctx);
@@ -85,7 +85,16 @@
     }
 
     @Test
+    public void testTokenEndpointRedirect() {
+
+    }
+
+    @Test
     public void testStoreAccessCodeViaAuthCodeThrowsNoException() {
+        String auth_code = crypto.createToken();
+        AuthCodeInfo codeInfo = new AuthCodeInfo(info.getClient_id(),
+                auth_code);
+        codeInfo.setScopes(SCOPES);
 
     }
 
@@ -98,4 +107,15 @@
     public void testAccessTokenbyUserDeleteCascade() {
 
     }
+
+    @Test
+    public void testRefreshToken() {
+
+    }
+
+    // fixme: exception thrown?!
+    @Test
+    public void testAccessTokenExpired() {
+
+    }
 }