Added re-caching VC at closing-index service, resolved #44

Change-Id: I72bc0980da63f64f50b9bf92787550a9401fd1c3
diff --git a/core/Changes b/core/Changes
index 52ad813..62aa351 100644
--- a/core/Changes
+++ b/core/Changes
@@ -6,7 +6,9 @@
 25/04/2019
    - Updated Jetty version due to vulnerabilities (margaretha)
 27/06/2019
-   - Updated Jetty version, fixed server hanging problem (margaretha)  
+   - Updated Jetty version, fixed server hanging problem (margaretha)
+03/07/2019
+   - Added VCLoader interface (margaretha)
 
 # version 0.61.6
 06/02/2019
diff --git a/core/src/main/java/de/ids_mannheim/de/init/VCLoader.java b/core/src/main/java/de/ids_mannheim/de/init/VCLoader.java
new file mode 100644
index 0000000..5c19d97
--- /dev/null
+++ b/core/src/main/java/de/ids_mannheim/de/init/VCLoader.java
@@ -0,0 +1,6 @@
+package de.ids_mannheim.de.init;
+
+public interface VCLoader {
+
+    void recachePredefinedVC();
+}
diff --git a/core/src/main/java/de/ids_mannheim/korap/service/SearchService.java b/core/src/main/java/de/ids_mannheim/korap/service/SearchService.java
index 9d2ef02..5d3953f 100644
--- a/core/src/main/java/de/ids_mannheim/korap/service/SearchService.java
+++ b/core/src/main/java/de/ids_mannheim/korap/service/SearchService.java
@@ -18,6 +18,7 @@
 
 import com.sun.jersey.core.util.MultivaluedMapImpl;
 
+import de.ids_mannheim.de.init.VCLoader;
 import de.ids_mannheim.korap.authentication.AuthenticationManager;
 import de.ids_mannheim.korap.config.KustvaktConfiguration;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
@@ -39,7 +40,8 @@
 
     @Autowired
     private KustvaktConfiguration config;
-
+    @Autowired
+    private VCLoader vcLoader;
     @Autowired
     private AuthenticationManager authenticationManager;
 
@@ -291,6 +293,7 @@
         if (token != null && !token.isEmpty()
                 && token.equals(context.getInitParameter("adminToken"))) {
             searchKrill.closeIndexReader();
+            vcLoader.recachePredefinedVC();
         }
         else {
             throw new KustvaktException(StatusCodes.INCORRECT_ADMIN_TOKEN,
diff --git a/full/Changes b/full/Changes
index cea6968..c4998cc 100644
--- a/full/Changes
+++ b/full/Changes
@@ -3,7 +3,7 @@
    - Removed old VC controllers and updated tests (margaretha, issue #34)
    - Updated VC access controllers (margaretha)
 19/03/2019
-  - Added close index controller (margaretha)
+   - Added close index controller (margaretha)
 11/04/2019
    - Fixed unknown authentication scheme, missing VC entity, and parameter 
      checker (margaretha)
@@ -11,7 +11,11 @@
      unique group name and unknown VC access (margaretha)
 27/06/2019
    - Handled LDAP errors, fixed #45 (margaretha)
-     
+03/07/2019
+   - Added re-caching VC at closing-index service, resolved #44 (margaretha)
+   - Changed the response media-type of authentication controllers (margaretha)
+   - Fixed bugs: allow guest to retrieve system VC, 
+     remove VC from cache when it is deleted (margaretha)
 
 # version 0.61.6
 04/02/2019
diff --git a/full/pom.xml b/full/pom.xml
index f8bf49b..ea825bc 100644
--- a/full/pom.xml
+++ b/full/pom.xml
@@ -192,7 +192,6 @@
 					<excludes>
 						<exclude>de/ids_mannheim/korap/authentication/*.java</exclude>
 						<exclude>de/ids_mannheim/korap/web/controller/TokenExpiryTest.java</exclude>
-						<exclude>**/VCReferenceTest.java</exclude>
 					</excludes>
 					<includes>
 						<include>de/ids_mannheim/korap/**/*.java</include>
diff --git a/full/src/main/java/de/ids_mannheim/de/init/VCLoaderImpl.java b/full/src/main/java/de/ids_mannheim/de/init/VCLoaderImpl.java
new file mode 100644
index 0000000..113a6cc
--- /dev/null
+++ b/full/src/main/java/de/ids_mannheim/de/init/VCLoaderImpl.java
@@ -0,0 +1,19 @@
+package de.ids_mannheim.de.init;
+
+import org.springframework.beans.factory.annotation.Autowired;
+
+import de.ids_mannheim.korap.KrillCollection;
+import de.ids_mannheim.korap.config.NamedVCLoader;
+
+public class VCLoaderImpl implements VCLoader{
+
+    @Autowired
+    private NamedVCLoader vcLoader;
+    
+    @Override
+    public void recachePredefinedVC () {
+        KrillCollection.cache.removeAll();
+        Thread t = new Thread(vcLoader);
+        t.start();
+    }
+}
diff --git a/full/src/main/java/de/ids_mannheim/korap/config/NamedVCLoader.java b/full/src/main/java/de/ids_mannheim/korap/config/NamedVCLoader.java
index de7ac08..014a057 100644
--- a/full/src/main/java/de/ids_mannheim/korap/config/NamedVCLoader.java
+++ b/full/src/main/java/de/ids_mannheim/korap/config/NamedVCLoader.java
@@ -98,6 +98,7 @@
                 }
                 catch (KustvaktException e) {
                     // ignore
+                    if (DEBUG) jlog.debug(e);
                 }
                 vcService.storeVC(filename, VirtualCorpusType.SYSTEM, json,
                         null, null, null, true, "system");
diff --git a/full/src/main/java/de/ids_mannheim/korap/service/VirtualCorpusService.java b/full/src/main/java/de/ids_mannheim/korap/service/VirtualCorpusService.java
index 187b738..6b530bc 100644
--- a/full/src/main/java/de/ids_mannheim/korap/service/VirtualCorpusService.java
+++ b/full/src/main/java/de/ids_mannheim/korap/service/VirtualCorpusService.java
@@ -15,6 +15,7 @@
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.JsonNode;
 
+import de.ids_mannheim.korap.KrillCollection;
 import de.ids_mannheim.korap.config.FullConfiguration;
 import de.ids_mannheim.korap.constant.GroupMemberStatus;
 import de.ids_mannheim.korap.constant.VirtualCorpusAccessStatus;
@@ -213,6 +214,9 @@
                 userGroupService.deleteAutoHiddenGroup(
                         access.getUserGroup().getId(), "system");
             }
+            if (KrillCollection.cache.get(vc.getName())!=null){
+                KrillCollection.cache.remove(vc.getName());
+            }
             vcDao.deleteVirtualCorpus(vc);
         }
         else {
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/controller/AuthenticationController.java b/full/src/main/java/de/ids_mannheim/korap/web/controller/AuthenticationController.java
index b3594fd..bca7dc2 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/controller/AuthenticationController.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/controller/AuthenticationController.java
@@ -58,15 +58,16 @@
  * @date 24/01/2014
  * 
  * @author margaretha
- * @last-update 28/08/2018
+ * @last-update 01/07/2019
  * 
  * - added user authentication time in token context
  * - added api version filter
+ * - changed the response media-type 
  */
 @Controller
 @Path("/{version}/auth")
 @ResourceFilters({APIVersionFilter.class, PiwikFilter.class })
-@Produces(MediaType.TEXT_HTML + ";charset=utf-8")
+@Produces(MediaType.APPLICATION_JSON + ";charset=utf-8")
 public class AuthenticationController {
 
     @Autowired
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/controller/VirtualCorpusController.java b/full/src/main/java/de/ids_mannheim/korap/web/controller/VirtualCorpusController.java
index 60beaea..87a98c8 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/controller/VirtualCorpusController.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/controller/VirtualCorpusController.java
@@ -33,6 +33,7 @@
 import de.ids_mannheim.korap.web.filter.APIVersionFilter;
 import de.ids_mannheim.korap.web.filter.AuthenticationFilter;
 import de.ids_mannheim.korap.web.filter.BlockingFilter;
+import de.ids_mannheim.korap.web.filter.DemoUserFilter;
 import de.ids_mannheim.korap.web.filter.PiwikFilter;
 import de.ids_mannheim.korap.web.input.VirtualCorpusJson;
 
@@ -115,6 +116,8 @@
     @GET
     @Path("{createdBy}/{vcName}")
     @Produces(MediaType.APPLICATION_JSON + ";charset=utf-8")
+    @ResourceFilters({ APIVersionFilter.class, AuthenticationFilter.class,
+        DemoUserFilter.class, PiwikFilter.class })
     public VirtualCorpusDto retrieveVCByName (
             @Context SecurityContext securityContext,
             @PathParam("createdBy") String createdBy,
diff --git a/full/src/main/resources/default-config.xml b/full/src/main/resources/default-config.xml
index a3de4ac..bd25718 100644
--- a/full/src/main/resources/default-config.xml
+++ b/full/src/main/resources/default-config.xml
@@ -193,7 +193,9 @@
 	<bean id="initializator" class="de.ids_mannheim.de.init.InitializatorImpl"
 		init-method="initAnnotation">
 	</bean>
-
+	
+	<bean id="vcLoader" class="de.ids_mannheim.de.init.VCLoaderImpl"/>
+	
 	<!-- Krill -->
 	<bean id="search_krill" class="de.ids_mannheim.korap.web.SearchKrill">
 		<constructor-arg value="${krill.indexDir}" />
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/IndexControllerTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/IndexControllerTest.java
new file mode 100644
index 0000000..fbf56e3
--- /dev/null
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/IndexControllerTest.java
@@ -0,0 +1,89 @@
+package de.ids_mannheim.korap.web.controller;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+
+import org.apache.http.HttpStatus;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.core.util.MultivaluedMapImpl;
+
+import de.ids_mannheim.korap.authentication.http.HttpAuthorizationHandler;
+import de.ids_mannheim.korap.config.Attributes;
+import de.ids_mannheim.korap.config.SpringJerseyTest;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.exceptions.StatusCodes;
+import de.ids_mannheim.korap.utils.JsonUtils;
+import de.ids_mannheim.korap.web.SearchKrill;
+
+/**
+ * @author margaretha
+ *
+ */
+public class IndexControllerTest extends SpringJerseyTest {
+
+    @Autowired
+    private SearchKrill searchKrill;
+
+    @Test
+    public void testCloseIndex () throws IOException, KustvaktException,
+            URISyntaxException, InterruptedException {
+        URI uri = IndexControllerTest.class.getClassLoader()
+                .getResource("vc/named-vc1.jsonld").toURI();
+        Path toLink = Paths.get(uri);
+        Path symLink = Paths.get("vc/named-vc1.jsonld");
+        Path vcPath = Paths.get("vc");
+        if (!Files.exists(vcPath)) {
+            Files.createDirectory(vcPath);
+        }
+        if (Files.exists(symLink)) {
+            Files.delete(symLink);
+        }
+        Files.createSymbolicLink(symLink, toLink);
+
+        searchKrill.getStatistics(null);
+        assertEquals(true, searchKrill.getIndex().isReaderOpen());
+
+        MultivaluedMap<String, String> m = new MultivaluedMapImpl();
+        m.add("token", "secret");
+
+        ClientResponse response = resource().path(API_VERSION).path("index")
+                .path("close").type(MediaType.APPLICATION_FORM_URLENCODED)
+                .post(ClientResponse.class, m);
+
+        assertEquals(HttpStatus.SC_OK, response.getStatus());
+        assertEquals(false, searchKrill.getIndex().isReaderOpen());
+
+        
+        // Cleaning database and cache
+        
+        Thread.sleep(200);
+
+        response = resource().path(API_VERSION).path("vc").path("system")
+                .path("named-vc1")
+                .header(Attributes.AUTHORIZATION, HttpAuthorizationHandler
+                        .createBasicAuthorizationHeaderValue("admin", "pass"))
+                .delete(ClientResponse.class);
+
+        response = resource().path(API_VERSION).path("vc").path("system")
+                .path("named-vc1")
+                .get(ClientResponse.class);
+        
+        String entity = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(entity);
+        assertEquals(StatusCodes.NO_RESOURCE_FOUND,node.at("/errors/0/0").asInt());
+    }
+
+}
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/SearchControllerTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/SearchControllerTest.java
index 7e118d1..1fb3915 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/SearchControllerTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/SearchControllerTest.java
@@ -6,20 +6,14 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
-import java.io.IOException;
-
 import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.MultivaluedMap;
 
-import org.apache.http.HttpStatus;
 import org.junit.Ignore;
 import org.junit.Test;
-import org.springframework.beans.factory.annotation.Autowired;
 
 import com.fasterxml.jackson.databind.JsonNode;
 import com.google.common.net.HttpHeaders;
 import com.sun.jersey.api.client.ClientResponse;
-import com.sun.jersey.core.util.MultivaluedMapImpl;
 
 import de.ids_mannheim.korap.authentication.http.HttpAuthorizationHandler;
 import de.ids_mannheim.korap.config.Attributes;
@@ -27,7 +21,6 @@
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.query.serialize.QuerySerializer;
 import de.ids_mannheim.korap.utils.JsonUtils;
-import de.ids_mannheim.korap.web.SearchKrill;
 
 /**
  * @author hanl, margaretha
@@ -36,9 +29,6 @@
  */
 public class SearchControllerTest extends SpringJerseyTest {
 
-    @Autowired
-    private SearchKrill searchKrill;
-    
     private JsonNode requestSearchWithFields(String fields) throws KustvaktException{
         ClientResponse response = resource().path(API_VERSION).path("search")
                 .queryParam("q", "[orth=das]").queryParam("ql", "poliqarp")
@@ -342,21 +332,4 @@
         assertNotEquals(0, node.path("matches").size());
         // assertEquals(10993, node.at("/meta/totalResults").asInt());
     }
-    
-    @Test
-    public void testCloseIndex () throws IOException {
-        searchKrill.getStatistics(null);
-        assertEquals(true, searchKrill.getIndex().isReaderOpen());
-
-        MultivaluedMap<String, String> m = new MultivaluedMapImpl();
-        m.add("token", "secret");
-
-        ClientResponse response = resource().path(API_VERSION).path("index")
-                .path("close").type(MediaType.APPLICATION_FORM_URLENCODED)
-                .post(ClientResponse.class, m);
-
-        assertEquals(HttpStatus.SC_OK, response.getStatus());
-        assertEquals(false, searchKrill.getIndex().isReaderOpen());
-    }
-
 }
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusControllerTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusControllerTest.java
index 53adca4..814799a 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusControllerTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusControllerTest.java
@@ -125,6 +125,18 @@
         assertEquals(VirtualCorpusType.SYSTEM.displayName(),
                 node.at("/type").asText());
     }
+    
+    @Test
+    public void testRetrieveSystemVCGuest () throws UniformInterfaceException,
+            ClientHandlerException, KustvaktException {
+
+        ClientResponse response = resource().path(API_VERSION).path("vc")
+                .path("system").path("system VC").get(ClientResponse.class);
+        JsonNode node = JsonUtils.readTree(response.getEntity(String.class));
+        assertEquals("system VC", node.at("/name").asText());
+        assertEquals(VirtualCorpusType.SYSTEM.displayName(),
+                node.at("/type").asText());
+    }
 
     @Test
     public void testRetrieveOwnerPrivateVCInfo ()
diff --git a/full/src/test/resources/kustvakt-test.conf b/full/src/test/resources/kustvakt-test.conf
index 066377c..585d43c 100644
--- a/full/src/test/resources/kustvakt-test.conf
+++ b/full/src/test/resources/kustvakt-test.conf
@@ -36,7 +36,7 @@
 default.foundry.dependency = malt
 default.foundry.constituent = corenlp
 default.foundry.morphology = marmot
-default.foundry.surface = base 
+default.foundry.surface = base
 
 ## delete configuration (default hard)
 # delete.auto.group = hard
diff --git a/full/src/test/resources/test-config.xml b/full/src/test/resources/test-config.xml
index 16f7ee3..82b314e 100644
--- a/full/src/test/resources/test-config.xml
+++ b/full/src/test/resources/test-config.xml
@@ -175,6 +175,7 @@
 		init-method="initTest">
 	</bean>
 
+	<bean id="vcLoader" class="de.ids_mannheim.de.init.VCLoaderImpl"/>	
 
 	<!-- Krill -->
 	<bean id="search_krill" class="de.ids_mannheim.korap.web.SearchKrill">
diff --git a/lite/src/main/java/de/ids_mannheim/de/init/VCLoaderImpl.java b/lite/src/main/java/de/ids_mannheim/de/init/VCLoaderImpl.java
new file mode 100644
index 0000000..b015e43
--- /dev/null
+++ b/lite/src/main/java/de/ids_mannheim/de/init/VCLoaderImpl.java
@@ -0,0 +1,11 @@
+package de.ids_mannheim.de.init;
+
+public class VCLoaderImpl implements VCLoader {
+
+    @Override
+    public void recachePredefinedVC () {
+        // TODO Auto-generated method stub
+        
+    }
+
+}
diff --git a/lite/src/main/resources/lite-config.xml b/lite/src/main/resources/lite-config.xml
index a180563..e474b65 100644
--- a/lite/src/main/resources/lite-config.xml
+++ b/lite/src/main/resources/lite-config.xml
@@ -131,6 +131,8 @@
 	<bean id="annotationParser" class="de.ids_mannheim.korap.annotation.AnnotationParser"
 		scope="singleton" />
 
+	<bean id="vcLoader" class="de.ids_mannheim.de.init.VCLoaderImpl"/>
+	
 	<!-- Krill -->
 	<bean id="search_krill" class="de.ids_mannheim.korap.web.SearchKrill">
 		<constructor-arg value="${krill.indexDir}" />
diff --git a/lite/src/test/resources/test-config.xml b/lite/src/test/resources/test-config.xml
index a012e26..ba6713b 100644
--- a/lite/src/test/resources/test-config.xml
+++ b/lite/src/test/resources/test-config.xml
@@ -129,6 +129,8 @@
 	<bean id="annotationParser" class="de.ids_mannheim.korap.annotation.AnnotationParser"
 		scope="singleton" />
 
+	<bean id="vcLoader" class="de.ids_mannheim.de.init.VCLoaderImpl"/>
+
 	<!-- Krill -->
 	<bean id="search_krill" class="de.ids_mannheim.korap.web.SearchKrill">
 		<constructor-arg value="${krill.indexDir}" />