Fixed KustvaktResponseHandler and missing exceptions in JsonUtils. 

Change-Id: I3a95361659cebf91dc9175d08891dd67815b1851
diff --git a/core/pom.xml b/core/pom.xml
index 51c7bab..465f0b9 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -3,7 +3,7 @@
 	<modelVersion>4.0.0</modelVersion>
 	<groupId>de.ids_mannheim.korap</groupId>
 	<artifactId>Kustvakt-core</artifactId>
-	<version>0.59.8</version>
+	<version>0.59.9</version>
 
 	<properties>
 		<java.version>1.7</java.version>
diff --git a/core/src/main/java/de/ids_mannheim/korap/auditing/AuditRecord.java b/core/src/main/java/de/ids_mannheim/korap/auditing/AuditRecord.java
index c2e0791..5370c9f 100644
--- a/core/src/main/java/de/ids_mannheim/korap/auditing/AuditRecord.java
+++ b/core/src/main/java/de/ids_mannheim/korap/auditing/AuditRecord.java
@@ -2,6 +2,8 @@
 
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.databind.JsonNode;
+
+import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.utils.JsonUtils;
 import de.ids_mannheim.korap.utils.TimeUtils;
 import lombok.Getter;
@@ -93,7 +95,7 @@
     }
 
 
-    public AuditRecord fromJson (String json) {
+    public AuditRecord fromJson (String json) throws KustvaktException {
         JsonNode n = JsonUtils.readTree(json);
         AuditRecord r = new AuditRecord();
         r.setCategory(CATEGORY.valueOf(n.path("category").asText()));
diff --git a/core/src/main/java/de/ids_mannheim/korap/config/BeanConfiguration.java b/core/src/main/java/de/ids_mannheim/korap/config/BeanConfiguration.java
index d924fd1..79dc884 100644
--- a/core/src/main/java/de/ids_mannheim/korap/config/BeanConfiguration.java
+++ b/core/src/main/java/de/ids_mannheim/korap/config/BeanConfiguration.java
@@ -106,7 +106,7 @@
             this.handler = new DefaultHandler();
             this.context = context;
             // todo: better method?!
-            KustvaktResponseHandler.init(getAuditingProvider());
+            new KustvaktResponseHandler(getAuditingProvider());
         }
 
 
diff --git a/core/src/main/java/de/ids_mannheim/korap/config/ContextHolder.java b/core/src/main/java/de/ids_mannheim/korap/config/ContextHolder.java
index c0126da..60324c0 100644
--- a/core/src/main/java/de/ids_mannheim/korap/config/ContextHolder.java
+++ b/core/src/main/java/de/ids_mannheim/korap/config/ContextHolder.java
@@ -40,7 +40,7 @@
         this.handler = new DefaultHandler();
         this.context = context;
         // todo: better method?!
-        KustvaktResponseHandler.init(getAuditingProvider());
+        new KustvaktResponseHandler(getAuditingProvider());
     }
 
 
diff --git a/core/src/main/java/de/ids_mannheim/korap/exceptions/KustvaktException.java b/core/src/main/java/de/ids_mannheim/korap/exceptions/KustvaktException.java
index 72e650c..e435b5b 100644
--- a/core/src/main/java/de/ids_mannheim/korap/exceptions/KustvaktException.java
+++ b/core/src/main/java/de/ids_mannheim/korap/exceptions/KustvaktException.java
@@ -20,7 +20,8 @@
     private String userid;
     private Integer statusCode;
     private String entity;
-
+    private String notification;
+    private boolean isNotification;
 
     public KustvaktException (int status) {
         this.statusCode = status;
@@ -31,6 +32,15 @@
         this.entity = Arrays.asList(args).toString();
     }
 
+    public KustvaktException (int status, String notification, boolean isNotification) {
+        this.statusCode = status;
+        this.notification = notification;
+        this.isNotification = isNotification;
+    }
+    
+    public boolean hasNotification () {
+        return isNotification;
+    }
 
     public KustvaktException (Object userid, int status) {
         this(status);
diff --git a/core/src/main/java/de/ids_mannheim/korap/exceptions/StatusCodes.java b/core/src/main/java/de/ids_mannheim/korap/exceptions/StatusCodes.java
index 1bbe4ce..b555efb 100644
--- a/core/src/main/java/de/ids_mannheim/korap/exceptions/StatusCodes.java
+++ b/core/src/main/java/de/ids_mannheim/korap/exceptions/StatusCodes.java
@@ -28,19 +28,24 @@
      */
 
     public static final int NO_QUERY = 301;
-    public static final int SERIALIZATION_FAILED = 302;
+    // EM: e.g. vc type
+    public static final int INVALID_TYPE = 302;
     public static final int MISSING_ATTRIBUTE = 303;
     public static final int INVALID_ATTRIBUTE = 304;
     public static final int UNSUPPORTED_VALUE = 305;
-
+    public static final int SERIALIZATION_FAILED = 306;
+    public static final int DESERIALIZATION_FAILED = 307;
+    
     /**
      *  400 status codes for authorization and rewrite functions
      */
 
     // fixme: use unsupported resource and include type in return message
     public static final int POLICY_ERROR_DEFAULT = 400;
+    public static final int UNAUTHORIZED_OPERATION = 401;
+    
     public static final int UNSUPPORTED_RESOURCE = 402;
-    public static final int REWRITE_FAILED = 403;
+//    public static final int REWRITE_FAILED = 403;
     //public static final int UNSUPPORTED_FOUNDRY = 403;
     //public static final int UNSUPPORTED_CORPUS = 404;
     //public static final int UNSUPPORTED_LAYER = 405;
@@ -49,13 +54,14 @@
     //public static final int CORPUS_REWRITE = 407;
     //public static final int FOUNDRY_REWRITE = 408;
     //public static final int FOUNDRY_INJECTION = 409;
-    public static final int MISSING_RESOURCE = 405;
+//    public static final int MISSING_RESOURCE = 405;
     public static final int NO_POLICY_TARGET = 406;
     public static final int NO_POLICY_CONDITION = 407;
     public static final int NO_POLICY_PERMISSION = 408;
     public static final int NO_POLICIES = 409;
 
-
+    
+    
     /**
      * 500 status codes for access control related components (also
      * policy rewrite)
diff --git a/core/src/main/java/de/ids_mannheim/korap/resources/KustvaktResource.java b/core/src/main/java/de/ids_mannheim/korap/resources/KustvaktResource.java
index 7bbb43f..20908ad 100644
--- a/core/src/main/java/de/ids_mannheim/korap/resources/KustvaktResource.java
+++ b/core/src/main/java/de/ids_mannheim/korap/resources/KustvaktResource.java
@@ -2,6 +2,8 @@
 
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.databind.JsonNode;
+
+import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.utils.JsonUtils;
 import de.ids_mannheim.korap.utils.TimeUtils;
 import lombok.AccessLevel;
@@ -9,6 +11,7 @@
 import lombok.Setter;
 import org.joda.time.DateTime;
 
+import java.io.IOException;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -86,11 +89,15 @@
 
 
     public void setFields (String fields) {
-        Map s = JsonUtils.readSimple(fields, Map.class);
-        if (s == null)
+        Map s = null;
+        try {
+            s = JsonUtils.convertToClass(fields, Map.class);
+        }
+        catch (KustvaktException e) {
             throw new RuntimeException(
                     "Fields could not be read for resource '" + persistentID
                             + "'!");
+        }
         this.fields = s;
     }
 
diff --git a/core/src/main/java/de/ids_mannheim/korap/user/DataFactory.java b/core/src/main/java/de/ids_mannheim/korap/user/DataFactory.java
index 5d3f85f..e9b1387 100644
--- a/core/src/main/java/de/ids_mannheim/korap/user/DataFactory.java
+++ b/core/src/main/java/de/ids_mannheim/korap/user/DataFactory.java
@@ -93,7 +93,12 @@
         public Object convertData (String data) {
             if (data == null)
                 return JsonUtils.createObjectNode();
-            return JsonUtils.readTree(data);
+            try {
+                return JsonUtils.readTree(data);
+            }
+            catch (KustvaktException e) {
+                return null;
+            }
         }
 
 
diff --git a/core/src/main/java/de/ids_mannheim/korap/user/TokenContext.java b/core/src/main/java/de/ids_mannheim/korap/user/TokenContext.java
index 6a7f92e..d3b1944 100644
--- a/core/src/main/java/de/ids_mannheim/korap/user/TokenContext.java
+++ b/core/src/main/java/de/ids_mannheim/korap/user/TokenContext.java
@@ -3,6 +3,7 @@
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import de.ids_mannheim.korap.config.Attributes;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.utils.JsonUtils;
 import de.ids_mannheim.korap.utils.TimeUtils;
 import lombok.AccessLevel;
@@ -98,7 +99,7 @@
 
 
     //todo: complete
-    public static TokenContext fromJSON (String s) {
+    public static TokenContext fromJSON (String s) throws KustvaktException {
         JsonNode node = JsonUtils.readTree(s);
         TokenContext c = new TokenContext();
         if (node != null) {
@@ -109,7 +110,7 @@
     }
 
 
-    public static TokenContext fromOAuth2 (String s) {
+    public static TokenContext fromOAuth2 (String s) throws KustvaktException {
         JsonNode node = JsonUtils.readTree(s);
         TokenContext c = new TokenContext();
         if (node != null) {
diff --git a/core/src/main/java/de/ids_mannheim/korap/user/User.java b/core/src/main/java/de/ids_mannheim/korap/user/User.java
index 1792682..1de5d5d 100644
--- a/core/src/main/java/de/ids_mannheim/korap/user/User.java
+++ b/core/src/main/java/de/ids_mannheim/korap/user/User.java
@@ -3,6 +3,7 @@
 import com.fasterxml.jackson.databind.JsonNode;
 import de.ids_mannheim.korap.config.Attributes;
 import de.ids_mannheim.korap.config.ParamFields;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.utils.JsonUtils;
 import de.ids_mannheim.korap.utils.TimeUtils;
 import de.ids_mannheim.korap.web.utils.KustvaktMap;
@@ -293,7 +294,7 @@
         }
 
 
-        public static KorAPUser toUser (String value) {
+        public static KorAPUser toUser (String value) throws KustvaktException {
             JsonNode node = JsonUtils.readTree(value);
             KorAPUser user = UserFactory.getUser(node.path(Attributes.USERNAME)
                     .asText());
diff --git a/core/src/main/java/de/ids_mannheim/korap/utils/JsonUtils.java b/core/src/main/java/de/ids_mannheim/korap/utils/JsonUtils.java
index c9f0a25..d011ba7 100644
--- a/core/src/main/java/de/ids_mannheim/korap/utils/JsonUtils.java
+++ b/core/src/main/java/de/ids_mannheim/korap/utils/JsonUtils.java
@@ -1,11 +1,5 @@
 package de.ids_mannheim.korap.utils;
 
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-
 import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
@@ -13,6 +7,15 @@
 import java.util.List;
 import java.util.Map;
 
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.exceptions.StatusCodes;
+
 /**
  * @author hanl
  * @date 28/01/2014
@@ -33,12 +36,13 @@
     }
 
 
-    public static JsonNode readTree (String s) {
+    public static JsonNode readTree (String json) throws KustvaktException {
         try {
-            return mapper.readTree(s);
+            return mapper.readTree(json);
         }
         catch (IOException e) {
-            return null;
+            throw new KustvaktException(StatusCodes.DESERIALIZATION_FAILED,
+                    "Failed deserializing json object: " + json, json, e);
         }
     }
 
@@ -57,10 +61,11 @@
         return mapper.valueToTree(value);
     }
 
-    public static <T> T convert (JsonNode json, Class<T> cl) throws IOException {
+    public static <T> T convert (JsonNode json, Class<T> cl)
+            throws IOException {
         return mapper.convertValue(json, cl);
     }
-    
+
     public static <T> T read (String json, Class<T> cl) throws IOException {
         return mapper.readValue(json, cl);
     }
@@ -78,25 +83,28 @@
     }
 
 
-    public static <T> T readSimple (String json, Class<T> cl) {
+    public static <T> T convertToClass (String json, Class<T> cl) throws KustvaktException {
+        T t = null;
         try {
-            return mapper.readValue(json, cl);
+            t = mapper.readValue(json, cl);
         }
         catch (IOException e) {
-            return null;
+            throw new KustvaktException(StatusCodes.DESERIALIZATION_FAILED,
+                    "Failed deserializing json object: " + json, json, e);
         }
+        return t;
     }
 
 
     public static List<Map<String, Object>> convertToList (String json)
-            throws JsonProcessingException {
+            throws JsonProcessingException, KustvaktException {
         List d = new ArrayList();
         JsonNode node = JsonUtils.readTree(json);
         if (node.isArray()) {
             Iterator<JsonNode> nodes = node.iterator();
             while (nodes.hasNext()) {
-                Map<String, Object> map = mapper.treeToValue(nodes.next(),
-                        Map.class);
+                Map<String, Object> map =
+                        mapper.treeToValue(nodes.next(), Map.class);
                 d.add(map);
             }
         }
diff --git a/core/src/main/java/de/ids_mannheim/korap/utils/KoralCollectionQueryBuilder.java b/core/src/main/java/de/ids_mannheim/korap/utils/KoralCollectionQueryBuilder.java
index d2671be..361ab2b 100644
--- a/core/src/main/java/de/ids_mannheim/korap/utils/KoralCollectionQueryBuilder.java
+++ b/core/src/main/java/de/ids_mannheim/korap/utils/KoralCollectionQueryBuilder.java
@@ -2,10 +2,15 @@
 
 import java.util.List;
 
+import javax.ws.rs.WebApplicationException;
+
+import org.springframework.beans.factory.annotation.Autowired;
+
 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.exceptions.KustvaktException;
 import de.ids_mannheim.korap.exceptions.StatusCodes;
 import de.ids_mannheim.korap.query.serialize.CollectionQueryProcessor;
 import de.ids_mannheim.korap.response.Notifications;
@@ -28,6 +33,8 @@
     private JsonNode base;
     private StringBuilder builder;
     private String mergeOperator;
+    @Autowired
+    private KustvaktResponseHandler responseHandler;
 
 
     public KoralCollectionQueryBuilder () {
@@ -84,8 +91,7 @@
 
 
     public KoralCollectionQueryBuilder and () {
-        if (this.builder.length() != 0)
-            this.builder.append(" & ");
+        if (this.builder.length() != 0) this.builder.append(" & ");
         if (this.base != null && this.mergeOperator == null)
             this.mergeOperator = "AND";
         return this;
@@ -93,37 +99,37 @@
 
 
     public KoralCollectionQueryBuilder or () {
-        if (this.builder.length() != 0)
-            this.builder.append(" | ");
+        if (this.builder.length() != 0) this.builder.append(" | ");
         if (this.base != null && this.mergeOperator == null)
             this.mergeOperator = "OR";
         return this;
     }
 
 
-    public Object rebaseCollection (){
-        if (this.builder.length() == 0 && this.base == null)
-            return null;
+    public JsonNode rebaseCollection () throws KustvaktException {
+        if (this.builder.length() == 0 && this.base == null) return null;
 
         JsonNode request = null;
         if (this.builder.length() != 0) {
-            CollectionQueryProcessor tree = new CollectionQueryProcessor(
-                    this.verbose);
+            CollectionQueryProcessor tree =
+                    new CollectionQueryProcessor(this.verbose);
             tree.process(this.builder.toString());
-            if (tree.getErrors().size() > 0){
+            if (tree.getErrors().size() > 0) {
                 Notifications notif = new Notifications();
-                int code; 
-                for (List<Object> e : tree.getErrors()){
+                int code;
+                for (List<Object> e : tree.getErrors()) {
                     code = (int) e.get(0);
-                    if (e.get(1) instanceof String){
+                    if (e.get(1) instanceof String) {
                         notif.addError(code, (String) e.get(1));
                     }
-                    else{
+                    else {
                         notif.addError(code, (String[]) e.get(1));
                     }
                 }
-                
-                throw KustvaktResponseHandler.throwit(StatusCodes.SERIALIZATION_FAILED,notif.toJsonString());
+
+                String notificationStr = notif.toJsonString();
+                throw new KustvaktException(StatusCodes.SERIALIZATION_FAILED,
+                        notificationStr, true);
             }
             request = JsonUtils.valueToTree(tree.getRequestMap());
         }
@@ -153,8 +159,9 @@
                     return base;
                 else {
                     result = JsonBuilder.buildDocGroup(
-                            this.mergeOperator != null ? this.mergeOperator
-                                    .toLowerCase() : "and", result, tobase);
+                            this.mergeOperator != null
+                                    ? this.mergeOperator.toLowerCase() : "and",
+                            result, tobase);
                 }
                 ((ObjectNode) base).put("collection", result);
                 return base;
@@ -171,8 +178,9 @@
      * If no group in base query, consequent queries are skipped.
      * 
      * @param query
+     * @throws KustvaktException 
      */
-    public KoralCollectionQueryBuilder setBaseQuery (String query) {
+    public KoralCollectionQueryBuilder setBaseQuery (String query) throws KustvaktException {
         this.base = JsonUtils.readTree(query);
         return this;
     }
@@ -184,7 +192,7 @@
     }
 
 
-    public String toJSON () {
+    public String toJSON () throws KustvaktException {
         return JsonUtils.toJSON(rebaseCollection());
     }
 
@@ -208,7 +216,8 @@
         }
 
 
-        public static ObjectNode buildDocGroup (String op, JsonNode ... groups) {
+        public static ObjectNode buildDocGroup (String op,
+                JsonNode ... groups) {
             ObjectNode node = JsonUtils.createObjectNode();
             node.put("@type", "koral:docGroup");
             node.put("operation", "operation:" + op);
diff --git a/core/src/main/java/de/ids_mannheim/korap/web/filter/AdminFilter.java b/core/src/main/java/de/ids_mannheim/korap/web/filter/AdminFilter.java
index 377efaa..f78b1a1 100644
--- a/core/src/main/java/de/ids_mannheim/korap/web/filter/AdminFilter.java
+++ b/core/src/main/java/de/ids_mannheim/korap/web/filter/AdminFilter.java
@@ -13,7 +13,6 @@
 import com.sun.jersey.spi.container.ResourceFilter;
 
 import de.ids_mannheim.korap.config.Attributes;
-import de.ids_mannheim.korap.config.BeansFactory;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.interfaces.AuthenticationManagerIface;
 import de.ids_mannheim.korap.security.auth.BasicHttpAuth;
@@ -32,12 +31,15 @@
 
     @Autowired
 	private AuthenticationManagerIface authManager;
+    
+    @Autowired
+    KustvaktResponseHandler kustvaktResponseHandler;
 
 	@Override
 	public ContainerRequest filter(ContainerRequest cr) {
 		String authentication = cr.getHeaderValue(ContainerRequest.AUTHORIZATION);
 		if (authentication == null) {
-			throw KustvaktResponseHandler.throwAuthenticationException("The authorization header value is missing.");
+			throw kustvaktResponseHandler.throwAuthenticationException("The authorization header value is missing.");
 		}
 
 		// decode password
@@ -60,12 +62,12 @@
 		try {
 			User user = authManager.authenticate(tokenType, username, token, attributes);
 			if (!user.isAdmin()){
-				throw KustvaktResponseHandler.throwAuthenticationException("Admin authentication failed.");
+				throw kustvaktResponseHandler.throwAuthenticationException("Admin authentication failed.");
 			}
 			Map<String, Object> properties = cr.getProperties();
 			properties.put("user", user);
 		} catch (KustvaktException e) {
-			throw KustvaktResponseHandler.throwAuthenticationException("User authentication failed.");
+			throw kustvaktResponseHandler.throwAuthenticationException("User authentication failed.");
 		}
 
 		TokenContext c = new TokenContext();
diff --git a/core/src/main/java/de/ids_mannheim/korap/web/filter/BlockingFilter.java b/core/src/main/java/de/ids_mannheim/korap/web/filter/BlockingFilter.java
index 976c051..b8faf76 100644
--- a/core/src/main/java/de/ids_mannheim/korap/web/filter/BlockingFilter.java
+++ b/core/src/main/java/de/ids_mannheim/korap/web/filter/BlockingFilter.java
@@ -9,6 +9,9 @@
 
 import javax.ws.rs.ext.Provider;
 
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
 /**
  * @author hanl
  * @date 11/12/2014
@@ -16,9 +19,13 @@
  *       endpoint filter to block access to an endpoint, in case no
  *       anonymous access should be allowed!
  */
+@Component
 @Provider
 public class BlockingFilter implements ContainerRequestFilter, ResourceFilter {
 
+    @Autowired
+    KustvaktResponseHandler kustvaktResponseHandler;
+    
     @Override
     public ContainerRequest filter (ContainerRequest request) {
         TokenContext context;
@@ -26,11 +33,11 @@
             context = (TokenContext) request.getUserPrincipal();
         }
         catch (UnsupportedOperationException e) {
-            throw KustvaktResponseHandler.throwAuthenticationException("");
+            throw kustvaktResponseHandler.throwAuthenticationException("");
         }
 
         if(context == null || context.isDemo())
-            throw KustvaktResponseHandler.throwAuthenticationException("");
+            throw kustvaktResponseHandler.throwAuthenticationException("");
 
         return request;
     }
diff --git a/core/src/main/java/de/ids_mannheim/korap/web/filter/NonDemoBlockingFilter.java b/core/src/main/java/de/ids_mannheim/korap/web/filter/NonDemoBlockingFilter.java
index 3724fc5..95cb077 100644
--- a/core/src/main/java/de/ids_mannheim/korap/web/filter/NonDemoBlockingFilter.java
+++ b/core/src/main/java/de/ids_mannheim/korap/web/filter/NonDemoBlockingFilter.java
@@ -9,6 +9,9 @@
 
 import javax.ws.rs.ext.Provider;
 
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
 /**
  * @author hanl
  * @date 11/12/2014
@@ -16,10 +19,14 @@
  *       endpoint filter to block access to an endpoint, in case no
  *       anonymous access should be allowed!
  */
+@Component
 @Provider
 public class NonDemoBlockingFilter implements ContainerRequestFilter,
         ResourceFilter {
 
+    @Autowired
+    KustvaktResponseHandler kustvaktResponseHandler;
+    
     @Override
     public ContainerRequest filter (ContainerRequest request) {
         TokenContext context;
@@ -27,11 +34,11 @@
             context = (TokenContext) request.getUserPrincipal();
         }
         catch (UnsupportedOperationException e) {
-            throw KustvaktResponseHandler.throwAuthenticationException("");
+            throw kustvaktResponseHandler.throwAuthenticationException("");
         }
 
         if (context == null || context.isDemo())
-            throw KustvaktResponseHandler
+            throw kustvaktResponseHandler
                     .throwAuthenticationException("Service not available for non-authenticated "
                             + "or demo account users!");
         return request;
diff --git a/core/src/main/java/de/ids_mannheim/korap/web/filter/PiwikFilter.java b/core/src/main/java/de/ids_mannheim/korap/web/filter/PiwikFilter.java
deleted file mode 100644
index 26cde36..0000000
--- a/core/src/main/java/de/ids_mannheim/korap/web/filter/PiwikFilter.java
+++ /dev/null
@@ -1,148 +0,0 @@
-package de.ids_mannheim.korap.web.filter;
-
-import com.sun.jersey.api.client.Client;
-import com.sun.jersey.api.client.WebResource;
-import com.sun.jersey.api.client.config.ClientConfig;
-import com.sun.jersey.api.client.config.DefaultClientConfig;
-import com.sun.jersey.api.client.filter.LoggingFilter;
-import com.sun.jersey.core.util.MultivaluedMapImpl;
-import com.sun.jersey.spi.container.ContainerRequest;
-import com.sun.jersey.spi.container.ContainerRequestFilter;
-import com.sun.jersey.spi.container.ContainerResponseFilter;
-import com.sun.jersey.spi.container.ResourceFilter;
-import de.ids_mannheim.korap.config.Attributes;
-import de.ids_mannheim.korap.config.BeansFactory;
-import de.ids_mannheim.korap.exceptions.KustvaktException;
-import de.ids_mannheim.korap.interfaces.AuthenticationManagerIface;
-import de.ids_mannheim.korap.user.*;
-import net.minidev.json.JSONArray;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.core.UriBuilder;
-import javax.ws.rs.ext.Provider;
-import java.security.SecureRandom;
-import java.util.*;
-
-/**
- * @author hanl
- * @date 13/05/2014
- */
-@Provider
-public class PiwikFilter implements ContainerRequestFilter, ResourceFilter {
-
-    private WebResource service;
-    //    private static final String SERVICE = "http://localhost:8888";
-    private static final String SERVICE = "http://10.0.10.13";
-    private static Logger jlog = LoggerFactory.getLogger(PiwikFilter.class);
-    public static boolean ENABLED = false;
-    private Map<String, String> customVars;
-    private AuthenticationManagerIface controller;
-
-
-    public PiwikFilter () {
-        controller = BeansFactory.getKustvaktContext()
-                .getAuthenticationManager();
-        ClientConfig config = new DefaultClientConfig();
-        Client client = Client.create(config);
-        if (jlog.isDebugEnabled())
-            client.addFilter(new LoggingFilter());
-        UriBuilder b = UriBuilder.fromUri(SERVICE);
-        service = client.resource(b.build());
-        this.customVars = new HashMap<>();
-    }
-
-
-    private void send (ContainerRequest request) {
-        Random random = new SecureRandom();
-        MultivaluedMap<String, String> params = new MultivaluedMapImpl();
-        params.add("idsite", "2");
-        params.add("rec", "1");
-        if (!customVars.isEmpty())
-            params.add("_cvar", translateCustomData());
-        params.add("cip", request.getHeaderValue("Host"));
-        params.add("cookie", "false");
-        params.add("r", String.valueOf(random.nextDouble()));
-        params.add("action_name", request.getRequestUri().toASCIIString());
-
-        Locale l = null;
-        if (request.getAcceptableLanguages() != null)
-            l = request.getAcceptableLanguages().get(0);
-        try {
-            service.path("piwik/piwik.php")
-                    .queryParam("idsite", "2")
-                    .queryParam("rec", "1")
-                    //todo check for empty container
-                    .queryParam("_cvar", translateCustomData())
-                    .queryParam("cip", request.getHeaderValue("Host"))
-                    .queryParam("cookie", "false")
-                    .queryParam("r", String.valueOf(random.nextDouble()))
-                    .queryParam("action_name",
-                            request.getRequestUri().toASCIIString())
-                    .queryParams(params).accept("text/html")
-                    .header("Host", request.getHeaderValue("Host"))
-                    .header("User-Agent", request.getHeaderValue("User-Agent"))
-                    .acceptLanguage(l).method("GET");
-        }
-        catch (Exception e) {
-            // do nothing if piwik not available!
-        }
-    }
-
-
-    private String translateCustomData () {
-        final Map<String, List<String>> customVariables = new HashMap<String, List<String>>();
-        int i = 0;
-        for (final Map.Entry<String, String> entry : this.customVars.entrySet()) {
-            i++;
-            final List<String> list = new ArrayList<String>();
-            list.add(entry.getKey());
-            list.add(entry.getValue());
-            customVariables.put(Integer.toString(i), list);
-        }
-
-        final JSONArray json = new JSONArray();
-        json.add(customVariables);
-
-        // remove unnecessary parent square brackets from JSON-string
-        String jsonString = json.toString().substring(1,
-                json.toString().length() - 1);
-        customVars.clear();
-        return jsonString;
-    }
-
-
-    @Override
-    public ContainerRequest filter (ContainerRequest request) {
-        if (ENABLED) {
-            try {
-                TokenContext context = (TokenContext) request
-                        .getUserPrincipal();
-                // since this is cached, not very expensive!
-                User user = controller.getUser(context.getUsername());
-                Userdata data = controller
-                        .getUserData(user, UserSettings.class);
-                if ((Boolean) data.get(Attributes.COLLECT_AUDITING_DATA))
-                    customVars.put("username", context.getUsername());
-            }
-            catch (KustvaktException | UnsupportedOperationException e) {
-                //do nothing
-            }
-            send(request);
-        }
-        return request;
-    }
-
-
-    @Override
-    public ContainerRequestFilter getRequestFilter () {
-        return this;
-    }
-
-
-    @Override
-    public ContainerResponseFilter getResponseFilter () {
-        return null;
-    }
-}
diff --git a/core/src/main/java/de/ids_mannheim/korap/web/utils/KustvaktResponseHandler.java b/core/src/main/java/de/ids_mannheim/korap/web/utils/KustvaktResponseHandler.java
index 44fb085..e5517b6 100644
--- a/core/src/main/java/de/ids_mannheim/korap/web/utils/KustvaktResponseHandler.java
+++ b/core/src/main/java/de/ids_mannheim/korap/web/utils/KustvaktResponseHandler.java
@@ -1,32 +1,31 @@
 package de.ids_mannheim.korap.web.utils;
 
+import java.util.List;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+
 import de.ids_mannheim.korap.auditing.AuditRecord;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.exceptions.StatusCodes;
 import de.ids_mannheim.korap.interfaces.db.AuditingIface;
 import de.ids_mannheim.korap.response.Notifications;
 
-import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.Response;
-import java.util.List;
-
 /**
- * @author hanl
+ * @author hanl, margaretha
  * @date 29/01/2014
+ * @last 08/11/2017
  */
 public class KustvaktResponseHandler {
 
-    private static AuditingIface auditing;
+    private AuditingIface auditing;
 
-
-    public static void init (AuditingIface iface) {
-        if (auditing == null)
-            auditing = iface;
+    public KustvaktResponseHandler (AuditingIface iface) {
+        this.auditing = iface;
     }
-
-
-    private static void register (List<AuditRecord> records) {
+    
+    private void register (List<AuditRecord> records) {
         if (auditing != null && !records.isEmpty())
             auditing.audit(records);
         else if (auditing == null)
@@ -34,37 +33,44 @@
     }
 
 
-    public static WebApplicationException throwit (KustvaktException e) {
-        Response s = Response.status(getStatus(e.getStatusCode()))
-                .entity(buildNotification(e)).build();
+    public WebApplicationException throwit (KustvaktException e) {
+        Response s;
+        if (e.hasNotification()){
+            s = Response.status(getStatus(e.getStatusCode()))
+                    .entity(e.getNotification()).build();
+        }
+        else{
+            s = Response.status(getStatus(e.getStatusCode()))
+                    .entity(buildNotification(e)).build();
+        }
         return new WebApplicationException(s);
     }
 
-    public static WebApplicationException throwit (int code) {
+    public WebApplicationException throwit (int code) {
         return new WebApplicationException(Response.status(getStatus(code))
                 .entity(buildNotification(code, "", "")).build());
     }
 
 
-    public static WebApplicationException throwit (int code, String message,
+    public WebApplicationException throwit (int code, String message,
             String entity) {
         return new WebApplicationException(Response.status(getStatus(code))
                 .entity(buildNotification(code, message, entity)).build());
     }
 
-    public static WebApplicationException throwit (int code, String notification) {
+    public WebApplicationException throwit (int code, String notification) {
         return new WebApplicationException(Response.status(getStatus(code))
                 .entity(notification).build());
     }
     
-    private static String buildNotification (KustvaktException e) {
+    private String buildNotification (KustvaktException e) {
         register(e.getRecords());
         return buildNotification(e.getStatusCode(), e.getMessage(),
                 e.getEntity());
     }
 
 
-    public static String buildNotification (int code, String message,
+    public String buildNotification (int code, String message,
             String entity) {
         Notifications notif = new Notifications();
         notif.addError(code, message, entity);
@@ -73,7 +79,7 @@
 
 
     //todo:  if exception, make exception message and error code available if not masked!
-    public static WebApplicationException throwAuthenticationException (String username) {
+    public WebApplicationException throwAuthenticationException (String username) {
         return new WebApplicationException(Response
                 .status(Response.Status.UNAUTHORIZED)
                 .header(HttpHeaders.WWW_AUTHENTICATE,
@@ -84,7 +90,7 @@
 
 
 
-    private static Response.Status getStatus (int code) {
+    private Response.Status getStatus (int code) {
         Response.Status status = Response.Status.BAD_REQUEST;
         switch (code) {
 //            case StatusCodes.NO_VALUE_FOUND: