DS-3484: Refactoring builders and extended Browse by title test

This commit is contained in:
Tom Desair
2017-10-16 23:24:22 +02:00
committed by Tom Desair
parent 9529e5634f
commit 6a7c60c121
29 changed files with 614 additions and 289 deletions

1
.gitignore vendored
View File

@@ -25,7 +25,6 @@ dist/
nbdist/
nbactions.xml
nb-configuration.xml
META-INF/
## Ignore all *.properties file in root folder, EXCEPT build.properties (the default)
## KEPT FOR BACKWARDS COMPATIBILITY WITH 5.x (build.properties is now replaced with local.cfg)

View File

@@ -506,31 +506,6 @@
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.dspace</groupId>
<artifactId>dspace-solr</artifactId>
<classifier>classes</classifier>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-analyzers-icu</artifactId>
<version>${solr.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-analyzers-smartcn</artifactId>
<version>${solr.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-analyzers-stempel</artifactId>
<version>${solr.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.rometools</groupId>
@@ -698,7 +673,6 @@
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>javax.inject</groupId>

View File

@@ -81,7 +81,7 @@ public class AbstractDSpaceTest
if (!kernelImpl.isRunning())
{
// NOTE: the "dspace.dir" system property MUST be specified via Maven
kernelImpl.start(System.getProperty("dspace.dir")); // init the kernel
kernelImpl.start(getDspaceDir()); // init the kernel
}
// Initialize mock Util class (allows Util.getSourceVersion() to work in Unit tests)
@@ -111,4 +111,8 @@ public class AbstractDSpaceTest
}
kernelImpl = null;
}
public static String getDspaceDir(){
return System.getProperty("dspace.dir");
}
}

View File

@@ -92,9 +92,9 @@ public class GoogleBitstreamComparatorTest extends AbstractUnitTest{
when(bitstreamFormat1.getMIMEType()).thenReturn("application/pdf");
when(bitstreamFormat2.getMIMEType()).thenReturn("application/pdf");
when(bitstreamFormat3.getMIMEType()).thenReturn("application/pdf");
when(bitstream1.getSize()).thenReturn(new Long(100));
when(bitstream2.getSize()).thenReturn(new Long(200));
when(bitstream3.getSize()).thenReturn(new Long(300));
when(bitstream1.getSize()).thenReturn(Long.valueOf(100));
when(bitstream2.getSize()).thenReturn(Long.valueOf(200));
when(bitstream3.getSize()).thenReturn(Long.valueOf(300));
List<Bitstream> toSort = bundle.getBitstreams();
Collections.sort(toSort, new GoogleBitstreamComparator(context, settings));
@@ -130,9 +130,9 @@ public class GoogleBitstreamComparatorTest extends AbstractUnitTest{
when(bitstreamFormat1.getMIMEType()).thenReturn("text/richtext");
when(bitstreamFormat2.getMIMEType()).thenReturn("text/richtext");
when(bitstreamFormat3.getMIMEType()).thenReturn("application/postscript");
when(bitstream1.getSize()).thenReturn(new Long(100));
when(bitstream2.getSize()).thenReturn(new Long(200));
when(bitstream3.getSize()).thenReturn(new Long(300));
when(bitstream1.getSize()).thenReturn(Long.valueOf(100));
when(bitstream2.getSize()).thenReturn(Long.valueOf(200));
when(bitstream3.getSize()).thenReturn(Long.valueOf(300));
List<Bitstream> toSort = bundle.getBitstreams();
Collections.sort(toSort, new GoogleBitstreamComparator(context, settings));
@@ -150,9 +150,9 @@ public class GoogleBitstreamComparatorTest extends AbstractUnitTest{
when(bitstreamFormat1.getMIMEType()).thenReturn("application/pdf");
when(bitstreamFormat2.getMIMEType()).thenReturn("application/pdf");
when(bitstreamFormat3.getMIMEType()).thenReturn("application/pdf");
when(bitstream1.getSize()).thenReturn(new Long(200));
when(bitstream2.getSize()).thenReturn(new Long(200));
when(bitstream3.getSize()).thenReturn(new Long(200));
when(bitstream1.getSize()).thenReturn(Long.valueOf(200));
when(bitstream2.getSize()).thenReturn(Long.valueOf(200));
when(bitstream3.getSize()).thenReturn(Long.valueOf(200));
List<Bitstream> toSort = bundle.getBitstreams();
Collections.sort(toSort, new GoogleBitstreamComparator(context, settings));
@@ -170,9 +170,9 @@ public class GoogleBitstreamComparatorTest extends AbstractUnitTest{
when(bitstreamFormat1.getMIMEType()).thenReturn("unknown");
when(bitstreamFormat2.getMIMEType()).thenReturn("text/richtext");
when(bitstreamFormat3.getMIMEType()).thenReturn("text/richtext");
when(bitstream1.getSize()).thenReturn(new Long(400));
when(bitstream2.getSize()).thenReturn(new Long(200));
when(bitstream3.getSize()).thenReturn(new Long(300));
when(bitstream1.getSize()).thenReturn(Long.valueOf(400));
when(bitstream2.getSize()).thenReturn(Long.valueOf(200));
when(bitstream3.getSize()).thenReturn(Long.valueOf(300));
List<Bitstream> toSort = bundle.getBitstreams();
Collections.sort(toSort, new GoogleBitstreamComparator(context, settings));
@@ -190,9 +190,9 @@ public class GoogleBitstreamComparatorTest extends AbstractUnitTest{
when(bitstreamFormat1.getMIMEType()).thenReturn("unknown");
when(bitstreamFormat2.getMIMEType()).thenReturn("unknown");
when(bitstreamFormat3.getMIMEType()).thenReturn("unknown");
when(bitstream1.getSize()).thenReturn(new Long(200));
when(bitstream2.getSize()).thenReturn(new Long(300));
when(bitstream3.getSize()).thenReturn(new Long(100));
when(bitstream1.getSize()).thenReturn(Long.valueOf(200));
when(bitstream2.getSize()).thenReturn(Long.valueOf(300));
when(bitstream3.getSize()).thenReturn(Long.valueOf(100));
List<Bitstream> toSort = bundle.getBitstreams();
Collections.sort(toSort, new GoogleBitstreamComparator(context, settings));
@@ -223,9 +223,9 @@ public class GoogleBitstreamComparatorTest extends AbstractUnitTest{
*/
@Test
public void testNoMimeType() throws Exception{
when(bitstream1.getSize()).thenReturn(new Long(200));
when(bitstream2.getSize()).thenReturn(new Long(300));
when(bitstream3.getSize()).thenReturn(new Long(100));
when(bitstream1.getSize()).thenReturn(Long.valueOf(200));
when(bitstream2.getSize()).thenReturn(Long.valueOf(300));
when(bitstream3.getSize()).thenReturn(Long.valueOf(100));
List<Bitstream> toSort = bundle.getBitstreams();
Collections.sort(toSort, new GoogleBitstreamComparator(context, settings));
@@ -272,9 +272,9 @@ public class GoogleBitstreamComparatorTest extends AbstractUnitTest{
when(bitstreamFormat1.getMIMEType()).thenReturn("text/richtext");
when(bitstreamFormat2.getMIMEType()).thenReturn("application/msword");
when(bitstreamFormat3.getMIMEType()).thenReturn("application/postscript");
when(bitstream1.getSize()).thenReturn(new Long(100));
when(bitstream2.getSize()).thenReturn(new Long(200));
when(bitstream3.getSize()).thenReturn(new Long(300));
when(bitstream1.getSize()).thenReturn(Long.valueOf(100));
when(bitstream2.getSize()).thenReturn(Long.valueOf(200));
when(bitstream3.getSize()).thenReturn(Long.valueOf(300));
List<Bitstream> toSort = bundle.getBitstreams();
Collections.sort(toSort, new GoogleBitstreamComparator(context, settings));
@@ -295,9 +295,9 @@ public class GoogleBitstreamComparatorTest extends AbstractUnitTest{
when(bitstreamFormat1.getMIMEType()).thenReturn("text/richtext");
when(bitstreamFormat2.getMIMEType()).thenReturn("application/msword");
when(bitstreamFormat3.getMIMEType()).thenReturn("application/postscript");
when(bitstream1.getSize()).thenReturn(new Long(100));
when(bitstream2.getSize()).thenReturn(new Long(200));
when(bitstream3.getSize()).thenReturn(new Long(300));
when(bitstream1.getSize()).thenReturn(Long.valueOf(100));
when(bitstream2.getSize()).thenReturn(Long.valueOf(200));
when(bitstream3.getSize()).thenReturn(Long.valueOf(300));
List<Bitstream> toSort = bundle.getBitstreams();
Collections.sort(toSort, new GoogleBitstreamComparator(context, settings));
@@ -315,9 +315,9 @@ public class GoogleBitstreamComparatorTest extends AbstractUnitTest{
when(bitstreamFormat1.getMIMEType()).thenReturn("text/richtext");
when(bitstreamFormat2.getMIMEType()).thenReturn("application/msword");
when(bitstreamFormat3.getMIMEType()).thenReturn("application/postscript");
when(bitstream1.getSize()).thenReturn(new Long(100));
when(bitstream2.getSize()).thenReturn(new Long(200));
when(bitstream3.getSize()).thenReturn(new Long(300));
when(bitstream1.getSize()).thenReturn(Long.valueOf(100));
when(bitstream2.getSize()).thenReturn(Long.valueOf(200));
when(bitstream3.getSize()).thenReturn(Long.valueOf(300));
List<Bitstream> toSort = bundle.getBitstreams();
Collections.sort(toSort, new GoogleBitstreamComparator(context, settings));
@@ -335,9 +335,9 @@ public class GoogleBitstreamComparatorTest extends AbstractUnitTest{
when(bitstreamFormat1.getMIMEType()).thenReturn("text/richtext");
when(bitstreamFormat2.getMIMEType()).thenReturn("application/msword");
when(bitstreamFormat3.getMIMEType()).thenReturn("audio/x-wav");
when(bitstream1.getSize()).thenReturn(new Long(300));
when(bitstream2.getSize()).thenReturn(new Long(200));
when(bitstream3.getSize()).thenReturn(new Long(100));
when(bitstream1.getSize()).thenReturn(Long.valueOf(300));
when(bitstream2.getSize()).thenReturn(Long.valueOf(200));
when(bitstream3.getSize()).thenReturn(Long.valueOf(100));
List<Bitstream> toSort = bundle.getBitstreams();
Collections.sort(toSort, new GoogleBitstreamComparator(context, settings));

View File

@@ -7,8 +7,6 @@
*/
package org.dspace.discovery;
import org.dspace.solr.MockSolrServer;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service;
@@ -16,16 +14,12 @@ import org.springframework.stereotype.Service;
* Mock SOLR service for the Search Core
*/
@Service
public class MockSolrServiceImpl extends SolrServiceImpl implements InitializingBean, DisposableBean {
private MockSolrServer mockSolrServer;
public class MockSolrServiceImpl extends SolrServiceImpl implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
mockSolrServer = new MockSolrServer("search");
solr = mockSolrServer.getSolrServer();
//We don't use SOLR in the tests of this module
solr = null;
}
public void destroy() throws Exception {
mockSolrServer.destroy();
}
}

View File

@@ -7,12 +7,18 @@
*/
package org.dspace.eperson;
import static org.junit.Assert.*;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import org.apache.commons.codec.DecoderException;
import org.dspace.AbstractDSpaceTest;
import org.junit.*;
import static org.junit.Assert.*;
import org.dspace.core.Constants;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
/**
*
@@ -77,14 +83,13 @@ public class PasswordHashTest extends AbstractDSpaceTest
*/
@Test
public void testMatches()
throws NoSuchAlgorithmException
{
throws NoSuchAlgorithmException, UnsupportedEncodingException {
System.out.println("matches");
final String secret = "Clark Kent is Superman";
// Test old 1-trip MD5 hash
MessageDigest digest = MessageDigest.getInstance("MD5");
PasswordHash hash = new PasswordHash(null, null, digest.digest(secret.getBytes()));
PasswordHash hash = new PasswordHash(null, null, digest.digest(secret.getBytes(Constants.DEFAULT_ENCODING)));
boolean result = hash.matches(secret);
assertTrue("Old unsalted 1-trip MD5 hash", result);

View File

@@ -13,6 +13,8 @@ import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;
import org.apache.commons.lang.ObjectUtils;
import org.apache.log4j.Logger;
import org.dspace.AbstractUnitTest;
import org.dspace.authorize.AuthorizeException;
@@ -411,7 +413,7 @@ public class DOIIdentifierProviderTest
DSpaceObject dso = provider.getObjectByDOI(context, doi);
assertNotNull("Failed to load DSpaceObject by DOI.", dso);
if (item.getType() != dso.getType() || item.getID() != dso.getID())
if (item.getType() != dso.getType() || ObjectUtils.notEqual(item.getID(), dso.getID()))
{
fail("Object loaded by DOI was another object then expected!");
}
@@ -428,7 +430,7 @@ public class DOIIdentifierProviderTest
DSpaceObject dso = provider.resolve(context, doi);
assertNotNull("Failed to resolve DOI.", dso);
if (item.getType() != dso.getType() || item.getID() != dso.getID())
if (item.getType() != dso.getType() || ObjectUtils.notEqual(item.getID(), dso.getID()))
{
fail("Object return by DOI lookup was another object then expected!");
}

View File

@@ -1,57 +0,0 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.solr;
import java.io.File;
import java.io.IOException;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.embedded.EmbeddedSolrServer;
import org.apache.solr.core.CoreContainer;
/**
* Abstract class to mock a service that uses SOLR
*/
public class MockSolrServer {
private String coreName;
private SolrServer solrServer = null;
public MockSolrServer(final String coreName) throws Exception {
this.coreName = coreName;
initSolrServer();
}
public SolrServer getSolrServer() {
return solrServer;
}
protected void initSolrServer() throws Exception {
CoreContainer container = new CoreContainer(System.getProperty("dspace.dir") + File.separator + "solr");
container.load();
solrServer = new EmbeddedSolrServer(container, coreName);
//Start with an empty index
try {
solrServer.deleteByQuery("*:*");
solrServer.commit();
} catch (SolrServerException | IOException e) {
e.printStackTrace();
}
}
public void destroy() throws Exception {
if(solrServer != null) {
solrServer.shutdown();
}
}
}

View File

@@ -12,6 +12,7 @@ import java.io.IOException;
import com.maxmind.geoip.Location;
import com.maxmind.geoip.LookupService;
import org.dspace.AbstractDSpaceTest;
/**
* Mock service to mock the location Lookup Service used by the SOLR statistics logger
@@ -20,7 +21,7 @@ public class MockLookupService extends LookupService {
public MockLookupService() throws IOException {
//Just give our super class a file so that he's happy. We'll mock all responses anyway.
super(System.getProperty("dspace.dir") + File.separator + "config" + File.separator + "dspace.cfg");
super(AbstractDSpaceTest.getDspaceDir() + File.separator + "config" + File.separator + "dspace.cfg");
}
@Override

View File

@@ -8,31 +8,23 @@
package org.dspace.statistics;
import org.dspace.services.ConfigurationService;
import org.dspace.solr.MockSolrServer;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
/**
* Mock service that uses an embedded SOLR server for the statistics core
*/
public class MockSolrLoggerServiceImpl extends SolrLoggerServiceImpl implements InitializingBean, DisposableBean {
private MockSolrServer mockSolrServer;
public class MockSolrLoggerServiceImpl extends SolrLoggerServiceImpl implements InitializingBean {
@Autowired(required = true)
private ConfigurationService configurationService;
@Override
public void afterPropertiesSet() throws Exception {
mockSolrServer = new MockSolrServer("statistics");
solr = mockSolrServer.getSolrServer();
//We don' use SOLR in the tests of this module
solr = null;
locationService = new MockLookupService();
useProxies = configurationService.getBooleanProperty("useProxies");
}
public void destroy() throws Exception {
mockSolrServer.destroy();
}
}

View File

@@ -252,6 +252,10 @@
<artifactId>commons-collections4</artifactId>
<version>4.1</version>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
</dependency>
<!-- TEST DEPENDENCIES -->
<dependency> <!-- Keep jmockit before junit -->

View File

@@ -6,25 +6,28 @@
* http://www.dspace.org/license/
*/
package org.dspace.app.rest;
import static org.hamcrest.Matchers.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import org.dspace.app.rest.builder.CollectionBuilder;
import org.dspace.app.rest.builder.CommunityBuilder;
import org.dspace.app.rest.builder.GroupBuilder;
import org.dspace.app.rest.builder.ItemBuilder;
import org.dspace.app.rest.matcher.BrowseIndexMatchers;
import org.dspace.app.rest.matcher.BrowseIndexMatcher;
import org.dspace.app.rest.matcher.ItemMatcher;
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
import org.dspace.content.Collection;
import org.dspace.content.Community;
import org.dspace.content.Item;
import org.dspace.eperson.Group;
import org.junit.Test;
/**
* Integration test to test the /api/discover/browses endpoint
* (Class has to start or end with IT to be picked up by the failsafe plugin)
*/
public class BrowsesResourceControllerTest extends AbstractControllerIntegrationTest {
public class BrowsesResourceControllerIT extends AbstractControllerIntegrationTest {
@Test
public void findAll() throws Exception {
@@ -46,10 +49,10 @@ public class BrowsesResourceControllerTest extends AbstractControllerIntegration
//Check that all (and only) the default browse indexes are present
.andExpect(jsonPath("$._embedded.browses", containsInAnyOrder(
BrowseIndexMatchers.dateIssuedBrowseIndex("asc"),
BrowseIndexMatchers.contributorBrowseIndex("asc"),
BrowseIndexMatchers.titleBrowseIndex("asc"),
BrowseIndexMatchers.subjectBrowseIndex("asc")
BrowseIndexMatcher.dateIssuedBrowseIndex("asc"),
BrowseIndexMatcher.contributorBrowseIndex("asc"),
BrowseIndexMatcher.titleBrowseIndex("asc"),
BrowseIndexMatcher.subjectBrowseIndex("asc")
)))
;
}
@@ -64,7 +67,7 @@ public class BrowsesResourceControllerTest extends AbstractControllerIntegration
.andExpect(content().contentType(contentType))
//Check that the JSON root matches the expected browse index
.andExpect(jsonPath("$", BrowseIndexMatchers.titleBrowseIndex("asc")))
.andExpect(jsonPath("$", BrowseIndexMatcher.titleBrowseIndex("asc")))
;
}
@@ -78,7 +81,7 @@ public class BrowsesResourceControllerTest extends AbstractControllerIntegration
.andExpect(content().contentType(contentType))
//Check that the JSON root matches the expected browse index
.andExpect(jsonPath("$", BrowseIndexMatchers.dateIssuedBrowseIndex("asc")))
.andExpect(jsonPath("$", BrowseIndexMatcher.dateIssuedBrowseIndex("asc")))
;
}
@@ -92,7 +95,7 @@ public class BrowsesResourceControllerTest extends AbstractControllerIntegration
.andExpect(content().contentType(contentType))
//Check that the JSON root matches the expected browse index
.andExpect(jsonPath("$", BrowseIndexMatchers.contributorBrowseIndex("asc")))
.andExpect(jsonPath("$", BrowseIndexMatcher.contributorBrowseIndex("asc")))
;
}
@@ -106,57 +109,111 @@ public class BrowsesResourceControllerTest extends AbstractControllerIntegration
.andExpect(content().contentType(contentType))
//Check that the JSON root matches the expected browse index
.andExpect(jsonPath("$", BrowseIndexMatchers.subjectBrowseIndex("asc")))
.andExpect(jsonPath("$", BrowseIndexMatcher.subjectBrowseIndex("asc")))
;
}
@Test
public void findBrowseByTitleItems() throws Exception {
context.turnOffAuthorisationSystem();
//** GIVEN **
//1. A community-collection structure with one parent community with sub-community and two collections.
parentCommunity = new CommunityBuilder().createCommunity(context)
.withName("Parent Community")
.build();
Community child1 = new CommunityBuilder().createSubCommunity(context, parentCommunity)
.withName("Sub Community")
.build();
Collection col1 = new CollectionBuilder().createCollection(context, child1).withName("Collection 1").build();
Collection col2 = new CollectionBuilder().createCollection(context, child1).withName("Collection 2").build();
Item item1 = new ItemBuilder().createItem(context, col1)
.withTitle("My first test item")
//2. Two public items that are readable by Anonymous
Item publicItem1 = new ItemBuilder().createItem(context, col1)
.withTitle("Public item 1")
.withIssueDate("2017-10-17")
.withAuthor("Smith, Donald")
.withAuthor("Doe, John")
.withSubject("Java")
.withSubject("Unit Testing")
.withAuthor("Smith, Donald").withAuthor("Doe, John")
.withSubject("Java").withSubject("Unit Testing")
.build();
Item item2 = new ItemBuilder().createItem(context, col2)
.withTitle("My second test item")
Item publicItem2 = new ItemBuilder().createItem(context, col2)
.withTitle("Public item 2")
.withIssueDate("2016-02-13")
.withAuthor("Smith, Maria")
.withAuthor("Doe, Jane")
.withSubject("Angular")
.withSubject("Unit Testing")
.withAuthor("Smith, Maria").withAuthor("Doe, Jane")
.withSubject("Angular").withSubject("Unit Testing")
.build();
//3. An item that has been made private
Item privateItem = new ItemBuilder().createItem(context, col1)
.withTitle("This is a private item")
.withIssueDate("2015-03-12")
.withAuthor("Duck, Donald")
.withSubject("Cartoons").withSubject("Ducks")
.makePrivate()
.build();
//4. An item with an item-level embargo
Item embargoedItem = new ItemBuilder().createItem(context, col2)
.withTitle("An embargoed publication")
.withIssueDate("2017-08-10")
.withAuthor("Mouse, Mickey")
.withSubject("Cartoons").withSubject("Mice")
.withEmbargoPeriod("12 months")
.build();
//5. An item that is only readable for an internal groups
Group internalGroup = new GroupBuilder().createGroup(context)
.withName("Internal Group")
.build();
Item internalItem = new ItemBuilder().createItem(context, col2)
.withTitle("Internal publication")
.withIssueDate("2016-09-19")
.withAuthor("Doe, John")
.withSubject("Unknown")
.withReaderGroup(internalGroup)
.build();
context.restoreAuthSystemState();
//When we browse the items in the Browse by item endpoint
mockMvc.perform(get("/api/discover/browses/title/items"))
//** WHEN **
//An anonymous user browses the items in the Browse by item endpoint
//sorted descending by tile
mockMvc.perform(get("/api/discover/browses/title/items")
.param("sort", "title,desc"))
//** THEN **
//The status has to be 200 OK
.andExpect(status().isOk())
//We expect the content type to be "application/hal+json;charset=UTF-8"
.andExpect(content().contentType(contentType))
//We expect our two created items to be present
//We expect only the two public items and the embargoed item to be present
.andExpect(jsonPath("$.page.size", is(20)))
.andExpect(jsonPath("$.page.totalElements", is(2)))
.andExpect(jsonPath("$.page.totalElements", is(3)))
.andExpect(jsonPath("$.page.totalPages", is(1)))
.andExpect(jsonPath("$.page.number", is(0)))
//Verify that the title of the public and embargoed items are present and sorted descending
.andExpect(jsonPath("$._embedded.items",
contains(ItemMatcher.matchItemWithTitleAndDateIssued(publicItem2,
"Public item 2", "2016-02-13"),
ItemMatcher.matchItemWithTitleAndDateIssued(publicItem1,
"Public item 1", "2017-10-17"),
ItemMatcher.matchItemWithTitleAndDateIssued(embargoedItem,
"An embargoed publication", "2017-08-10"))))
//The private item must not be present
.andExpect(jsonPath("$._embedded.items[*].metadata[?(@.key=='dc.title')].value",
not(hasItem("This is a private item"))))
//The internal item must not be present
.andExpect(jsonPath("$._embedded.items[*].metadata[?(@.key=='dc.title')].value",
not(hasItem("Internal publication"))))
;
//** CLEANUP **
context.turnOffAuthorisationSystem();
new GroupBuilder().delete(context, internalGroup);
}
}

View File

@@ -18,7 +18,7 @@ import org.junit.Test;
/**
* Integration test for the {@link RootRestResourceController}
*/
public class RootRestResourceControllerTest extends AbstractControllerIntegrationTest {
public class RootRestResourceControllerIT extends AbstractControllerIntegrationTest {
@Test
public void listDefinedEndpoint() throws Exception {

View File

@@ -1,46 +1,152 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.rest.builder;
import org.apache.log4j.Logger;
import org.dspace.authorize.AuthorizeException;
import org.dspace.authorize.ResourcePolicy;
import org.dspace.authorize.factory.AuthorizeServiceFactory;
import org.dspace.authorize.service.AuthorizeService;
import org.dspace.authorize.service.ResourcePolicyService;
import org.dspace.content.DSpaceObject;
import org.dspace.content.Item;
import org.dspace.content.factory.ContentServiceFactory;
import org.dspace.content.service.BitstreamService;
import org.dspace.content.service.BundleService;
import org.dspace.content.service.CollectionService;
import org.dspace.content.service.CommunityService;
import org.dspace.content.service.InstallItemService;
import org.dspace.content.service.ItemService;
import org.dspace.content.service.WorkspaceItemService;
import org.dspace.content.service.*;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.discovery.IndexingService;
import org.dspace.eperson.Group;
import org.dspace.eperson.factory.EPersonServiceFactory;
import org.dspace.eperson.service.EPersonService;
import org.dspace.eperson.service.GroupService;
import org.dspace.services.factory.DSpaceServicesFactory;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.MutablePeriod;
import org.joda.time.format.PeriodFormat;
import java.io.IOException;
import java.sql.SQLException;
import java.util.Date;
/**
* TODO TOM UNIT TEST
* Abstract builder to construct DSpace Objects
*/
public class AbstractBuilder {
public abstract class AbstractBuilder<T extends DSpaceObject> {
protected CommunityService communityService = ContentServiceFactory.getInstance().getCommunityService();
protected CollectionService collectionService = ContentServiceFactory.getInstance().getCollectionService();
protected ItemService itemService = ContentServiceFactory.getInstance().getItemService();
protected InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService();
protected WorkspaceItemService workspaceItemService = ContentServiceFactory.getInstance().getWorkspaceItemService();
protected EPersonService ePersonService = EPersonServiceFactory.getInstance().getEPersonService();
protected GroupService groupService = EPersonServiceFactory.getInstance().getGroupService();
protected BundleService bundleService = ContentServiceFactory.getInstance().getBundleService();
protected BitstreamService bitstreamService = ContentServiceFactory.getInstance().getBitstreamService();
protected IndexingService indexingService = DSpaceServicesFactory.getInstance().getServiceManager().getServiceByName(IndexingService.class.getName(),IndexingService.class);
static CommunityService communityService;
static CollectionService collectionService;
static ItemService itemService;
static InstallItemService installItemService;
static WorkspaceItemService workspaceItemService;
static EPersonService ePersonService;
static GroupService groupService;
static BundleService bundleService;
static BitstreamService bitstreamService;
static AuthorizeService authorizeService;
static ResourcePolicyService resourcePolicyService;
static IndexingService indexingService;
protected Context context;
/** log4j category */
private static final Logger log = Logger.getLogger(AbstractBuilder.class);
protected <T> T handleException(final Exception e) {
public static void init() {
communityService = ContentServiceFactory.getInstance().getCommunityService();
collectionService = ContentServiceFactory.getInstance().getCollectionService();
itemService = ContentServiceFactory.getInstance().getItemService();
installItemService = ContentServiceFactory.getInstance().getInstallItemService();
workspaceItemService = ContentServiceFactory.getInstance().getWorkspaceItemService();
ePersonService = EPersonServiceFactory.getInstance().getEPersonService();
groupService = EPersonServiceFactory.getInstance().getGroupService();
bundleService = ContentServiceFactory.getInstance().getBundleService();
bitstreamService = ContentServiceFactory.getInstance().getBitstreamService();
authorizeService = AuthorizeServiceFactory.getInstance().getAuthorizeService();
resourcePolicyService = AuthorizeServiceFactory.getInstance().getResourcePolicyService();
indexingService = DSpaceServicesFactory.getInstance().getServiceManager().getServiceByName(IndexingService.class.getName(),IndexingService.class);
}
public static void destroy() {
communityService = null;
collectionService = null;
itemService = null;
installItemService = null;
workspaceItemService = null;
ePersonService = null;
groupService = null;
bundleService = null;
bitstreamService = null;
authorizeService = null;
resourcePolicyService = null;
indexingService = null;
}
protected <B> B handleException(final Exception e) {
log.error(e);
return null;
}
protected abstract DSpaceObjectService<T> getDsoService();
protected <B extends AbstractBuilder<T>> B addMetadataValue(final T dso, final String schema, final String element, final String qualifier, final String value) {
try {
getDsoService().addMetadata(context, dso, schema, element, qualifier, Item.ANY, value);
} catch (SQLException e) {
return handleException(e);
}
return (B) this;
}
protected <B extends AbstractBuilder<T>> B setMetadataSingleValue(final T dso, final String schema, final String element, final String qualifier, final String value) {
try {
getDsoService().setMetadataSingleValue(context, dso, schema, element, qualifier, Item.ANY, value);
} catch (SQLException e) {
return handleException(e);
}
return (B) this;
}
protected <B extends AbstractBuilder<T>> B setEmbargo(String embargoPeriod, DSpaceObject dso) {
// add policy just for anonymous
try {
MutablePeriod period = PeriodFormat.getDefault().parseMutablePeriod(embargoPeriod);
Date embargoDate = DateTime.now(DateTimeZone.UTC).plus(period).toDate();
return setOnlyReadPermission(dso, groupService.findByName(context, Group.ANONYMOUS), embargoDate);
} catch (Exception e) {
return handleException(e);
}
}
protected <B extends AbstractBuilder<T>> B setOnlyReadPermission(DSpaceObject dso, Group group, Date startDate) {
// add policy just for anonymous
try {
authorizeService.removeAllPolicies(context, dso);
ResourcePolicy rp = authorizeService.createOrModifyPolicy(null, context, null, group,
null, startDate, Constants.READ, "Integration Test", dso);
if (rp != null) {
resourcePolicyService.update(context, rp);
}
} catch (Exception e) {
return handleException(e);
}
return (B) this;
}
public abstract T build();
public void delete(Context context, T dso) throws SQLException, IOException, AuthorizeException {
T attachedDso = context.reloadEntity(dso);
if(attachedDso != null) {
getDsoService().delete(context, attachedDso);
}
}
}

View File

@@ -1,21 +1,28 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.rest.builder;
import java.sql.SQLException;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.Collection;
import org.dspace.content.Community;
import org.dspace.content.Item;
import org.dspace.content.MetadataSchema;
import org.dspace.content.service.DSpaceObjectService;
import org.dspace.core.Context;
import org.dspace.discovery.SearchServiceException;
import java.sql.SQLException;
/**
* TODO TOM UNIT TEST
* Builder to construct Collection objects
*/
public class CollectionBuilder extends AbstractBuilder {
public class CollectionBuilder extends AbstractBuilder<Collection> {
private Collection collection;
private Context context;
public CollectionBuilder createCollection(final Context context, final Community parent) {
this.context = context;
@@ -29,22 +36,24 @@ public class CollectionBuilder extends AbstractBuilder {
}
public CollectionBuilder withName(final String name) {
try {
collectionService.setMetadataSingleValue(context, collection, MetadataSchema.DC_SCHEMA, "title", null, Item.ANY, name);
} catch (SQLException e) {
return handleException(e);
}
return this;
return setMetadataSingleValue(collection, MetadataSchema.DC_SCHEMA, "title", null, name);
}
@Override
public Collection build() {
context.dispatchEvents();
try {
collectionService.update(context, collection);
context.dispatchEvents();
indexingService.commit();
} catch (SearchServiceException e) {
} catch (Exception e) {
return handleException(e);
}
return collection;
}
@Override
protected DSpaceObjectService<Collection> getDsoService() {
return collectionService;
}
}

View File

@@ -1,27 +1,24 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.rest.builder;
import java.sql.SQLException;
import org.dspace.content.Community;
import org.dspace.content.Item;
import org.dspace.content.MetadataSchema;
import org.dspace.content.factory.ContentServiceFactory;
import org.dspace.content.service.CommunityService;
import org.dspace.content.service.DSpaceObjectService;
import org.dspace.core.Context;
import org.dspace.discovery.IndexingService;
import org.dspace.discovery.SearchServiceException;
import org.dspace.services.factory.DSpaceServicesFactory;
/**
* TODO TOM UNIT TEST
* Builder to construct Community objects
*/
public class CommunityBuilder {
protected CommunityService communityService = ContentServiceFactory.getInstance().getCommunityService();
protected IndexingService indexingService = DSpaceServicesFactory.getInstance().getServiceManager().getServiceByName(IndexingService.class.getName(),IndexingService.class);
public class CommunityBuilder extends AbstractBuilder<Community> {
private Community community;
private Context context;
public CommunityBuilder createCommunity(final Context context) {
return createSubCommunity(context, null);
@@ -40,24 +37,25 @@ public class CommunityBuilder {
}
public CommunityBuilder withName(final String communityName) {
try {
communityService.setMetadataSingleValue(context, community, MetadataSchema.DC_SCHEMA, "title", null, Item.ANY, communityName);
} catch (SQLException e) {
e.printStackTrace();
return null;
}
return this;
return setMetadataSingleValue(community, MetadataSchema.DC_SCHEMA, "title", null, communityName);
}
@Override
public Community build() {
context.dispatchEvents();
try {
communityService.update(context, community);
context.dispatchEvents();
indexingService.commit();
} catch (SearchServiceException e) {
} catch (Exception e) {
e.printStackTrace();
return null;
}
return community;
}
@Override
protected DSpaceObjectService<Community> getDsoService() {
return communityService;
}
}

View File

@@ -0,0 +1,68 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.rest.builder;
import org.dspace.content.service.DSpaceObjectService;
import org.dspace.core.Context;
import org.dspace.eperson.EPerson;
import org.dspace.eperson.Group;
/**
* Builder to construct Group objects
*/
public class GroupBuilder extends AbstractBuilder<Group> {
private Group group;
@Override
protected DSpaceObjectService<Group> getDsoService() {
return groupService;
}
@Override
public Group build() {
return group;
}
public GroupBuilder createGroup(final Context context) {
this.context = context;
try {
group = groupService.create(context);
} catch (Exception e) {
return handleException(e);
}
return this;
}
public GroupBuilder withName(String groupName) {
try {
groupService.setName(group, groupName);
} catch (Exception e) {
return handleException(e);
}
return this;
}
public GroupBuilder withParent(Group parent) {
try {
groupService.addMember(context, parent, group);
} catch (Exception e) {
return handleException(e);
}
return this;
}
public GroupBuilder addMember(EPerson eperson) {
try {
groupService.addMember(context, group, eperson);
} catch (Exception e) {
return handleException(e);
}
return this;
}
}

View File

@@ -1,20 +1,24 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.rest.builder;
import java.sql.SQLException;
import org.dspace.content.Collection;
import org.dspace.content.DCDate;
import org.dspace.content.Item;
import org.dspace.content.MetadataSchema;
import org.dspace.content.WorkspaceItem;
import org.dspace.content.*;
import org.dspace.content.service.DSpaceObjectService;
import org.dspace.core.Context;
import org.dspace.eperson.Group;
/**
* TODO TOM UNIT TEST
* Builder to construct Item objects
*/
public class ItemBuilder extends AbstractBuilder {
public class ItemBuilder extends AbstractBuilder<Item> {
private WorkspaceItem workspaceItem;
private Group readerGroup = null;
public ItemBuilder createItem(final Context context, final Collection col1) {
this.context = context;
@@ -29,46 +33,58 @@ public class ItemBuilder extends AbstractBuilder {
}
public ItemBuilder withTitle(final String title) {
try {
itemService.setMetadataSingleValue(context, workspaceItem.getItem(), MetadataSchema.DC_SCHEMA, "title", null, Item.ANY, title);
} catch (SQLException e) {
return handleException(e);
}
return this;
return setMetadataSingleValue(workspaceItem.getItem(), MetadataSchema.DC_SCHEMA, "title", null, title);
}
public ItemBuilder withIssueDate(final String issueDate) {
return addMetadataValueToItem(MetadataSchema.DC_SCHEMA, "date", "issued", new DCDate(issueDate).toString());
return addMetadataValue(workspaceItem.getItem(), MetadataSchema.DC_SCHEMA, "date", "issued", new DCDate(issueDate).toString());
}
public ItemBuilder withAuthor(final String authorName) {
return addMetadataValueToItem(MetadataSchema.DC_SCHEMA, "date", "issued", authorName);
return addMetadataValue(workspaceItem.getItem(), MetadataSchema.DC_SCHEMA, "contributor", "author", authorName);
}
public ItemBuilder withSubject(final String subject) {
return addMetadataValueToItem(MetadataSchema.DC_SCHEMA, "subject", null, subject);
return addMetadataValue(workspaceItem.getItem(), MetadataSchema.DC_SCHEMA, "subject", null, subject);
}
public ItemBuilder makePrivate() {
workspaceItem.getItem().setDiscoverable(false);
return this;
}
public ItemBuilder withEmbargoPeriod(String embargoPeriod) {
return setEmbargo(embargoPeriod, workspaceItem.getItem());
}
public ItemBuilder withReaderGroup(Group group) {
readerGroup = group;
return this;
}
@Override
public Item build() {
try {
Item item = installItemService.installItem(context, workspaceItem);
context.dispatchEvents();
indexingService.commit();
itemService.update(context, item);
//Check if we need to make this item private. This has to be done after item install.
if(readerGroup != null) {
setOnlyReadPermission(workspaceItem.getItem(), readerGroup, null);
}
context.dispatchEvents();
indexingService.commit();
return item;
} catch (Exception e) {
return handleException(e);
}
}
private ItemBuilder addMetadataValueToItem(final String schema, final String element, final String qualifier, final String value) {
try {
itemService.addMetadata(context, workspaceItem.getItem(), schema, element, qualifier, Item.ANY, value);
} catch (SQLException e) {
return handleException(e);
@Override
protected DSpaceObjectService<Item> getDsoService() {
return itemService;
}
return this;
}
}

View File

@@ -1,3 +1,10 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.rest.matcher;
import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasJsonPath;
@@ -8,8 +15,13 @@ import static org.hamcrest.text.IsEqualIgnoringCase.equalToIgnoringCase;
import org.hamcrest.Matcher;
import org.hamcrest.Matchers;
public class BrowseIndexMatchers {
public BrowseIndexMatchers() {
/**
* Utility class to construct a Matcher for a browse index
*/
public class BrowseIndexMatcher {
public BrowseIndexMatcher() {
}
public static Matcher<? super Object> subjectBrowseIndex(final String order) {

View File

@@ -0,0 +1,63 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.rest.matcher;
import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasJsonPath;
import static org.dspace.app.rest.test.AbstractControllerIntegrationTest.REST_SERVER_URL;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.startsWith;
import org.dspace.content.Item;
import org.hamcrest.Matcher;
/**
* Utility class to construct a Matcher for an item
*/
public class ItemMatcher {
public static Matcher<? super Object> matchItemWithTitleAndDateIssued(Item item, String title, String dateIssued) {
return allOf(
//Check item properties
matchItemProperties(item),
//Check core metadata (the JSON Path expression evaluates to a collection so we have to use contains)
hasJsonPath("$.metadata[?(@.key=='dc.title')].value", contains(title)),
hasJsonPath("$.metadata[?(@.key=='dc.date.issued')].value", contains(dateIssued)),
//Check links
matchItemLinks(item)
);
}
public static Matcher<? super Object> matchItemLinks(Item item) {
return allOf(
hasJsonPath("$._links.self.href", startsWith(REST_SERVER_URL)),
hasJsonPath("$._links.bitstreams.href", startsWith(REST_SERVER_URL)),
hasJsonPath("$._links.owningCollection.href", startsWith(REST_SERVER_URL)),
hasJsonPath("$._links.templateItemOf.href", startsWith(REST_SERVER_URL)),
hasJsonPath("$._links.self.href", startsWith(REST_SERVER_URL))
);
}
public static Matcher<? super Object> matchItemProperties(Item item) {
return allOf(
hasJsonPath("$.uuid", is(item.getID().toString())),
hasJsonPath("$.name", is(item.getName())),
hasJsonPath("$.handle", is(item.getHandle())),
hasJsonPath("$.inArchive", is(item.isArchived())),
hasJsonPath("$.discoverable", is(item.isDiscoverable())),
hasJsonPath("$.withdrawn", is(item.isWithdrawn())),
hasJsonPath("$.lastModified", is(notNullValue())),
hasJsonPath("$.type", is("item"))
);
}
}

View File

@@ -47,7 +47,7 @@ import org.springframework.web.context.WebApplicationContext;
TransactionalTestExecutionListener.class})
@DirtiesContext
@WebAppConfiguration
public class AbstractControllerIntegrationTest extends AbstractUnitTestWithDatabase {
public class AbstractControllerIntegrationTest extends AbstractIntegrationTestWithDatabase {
public static final String REST_SERVER_URL = "http://localhost/api/";

View File

@@ -16,6 +16,7 @@ import java.util.Properties;
import java.util.TimeZone;
import org.apache.log4j.Logger;
import org.dspace.app.rest.builder.AbstractBuilder;
import org.dspace.servicemanager.DSpaceKernelImpl;
import org.dspace.servicemanager.DSpaceKernelInit;
import org.junit.AfterClass;
@@ -24,10 +25,11 @@ import org.junit.BeforeClass;
/**
* Abstract Test class copied from DSpace API
*/
public class AbstractDSpaceTest
public class AbstractDSpaceIntegrationTest
{
/** log4j category */
private static final Logger log = Logger.getLogger(AbstractDSpaceTest.class);
private static final Logger log = Logger.getLogger(AbstractDSpaceIntegrationTest.class);
/**
* Test properties. These configure our general test environment
@@ -57,7 +59,7 @@ public class AbstractDSpaceTest
//load the properties of the tests
testProps = new Properties();
URL properties = AbstractDSpaceTest.class.getClassLoader()
URL properties = AbstractDSpaceIntegrationTest.class.getClassLoader()
.getResource("test-config.properties");
testProps.load(properties.openStream());
@@ -66,8 +68,9 @@ public class AbstractDSpaceTest
if (!kernelImpl.isRunning())
{
// NOTE: the "dspace.dir" system property MUST be specified via Maven
kernelImpl.start(System.getProperty("dspace.dir")); // init the kernel
kernelImpl.start(getDspaceDir()); // init the kernel
}
AbstractBuilder.init();
}
catch (IOException ex)
{
@@ -76,7 +79,6 @@ public class AbstractDSpaceTest
}
}
/**
* This method will be run after all tests finish as per @AfterClass. It
* will clean resources initialized by the @BeforeClass methods.
@@ -87,11 +89,18 @@ public class AbstractDSpaceTest
testProps.clear();
testProps = null;
AbstractBuilder.destroy();
//Also clear out the kernel & nullify (so JUnit will clean it up)
if (kernelImpl != null) {
kernelImpl.destroy();
}
kernelImpl = null;
}
public static String getDspaceDir(){
return System.getProperty("dspace.dir");
}
}

View File

@@ -28,9 +28,9 @@ import org.junit.BeforeClass;
/**
* Abstract Test class that will initialize the in-memory database
*/
public class AbstractUnitTestWithDatabase extends AbstractDSpaceTest {
public class AbstractIntegrationTestWithDatabase extends AbstractDSpaceIntegrationTest {
/** log4j category */
private static final Logger log = Logger.getLogger(AbstractUnitTestWithDatabase.class);
private static final Logger log = Logger.getLogger(AbstractIntegrationTestWithDatabase.class);
/**
* Context mock object to use in the tests.
@@ -54,7 +54,7 @@ public class AbstractUnitTestWithDatabase extends AbstractDSpaceTest {
* NOTE: Per JUnit, "The @BeforeClass methods of superclasses will be run before those the current class."
* http://junit.org/apidocs/org/junit/BeforeClass.html
* <p>
* This method builds on the initialization in AbstractDSpaceTest, and
* This method builds on the initialization in AbstractDSpaceIntegrationTest, and
* initializes the in-memory database for tests that need it.
*/
@BeforeClass

View File

@@ -1,3 +1,10 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.app.rest.test;
import java.util.List;

View File

@@ -9,21 +9,32 @@ package org.dspace.solr;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicLong;
import org.apache.log4j.Logger;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.embedded.EmbeddedSolrServer;
import org.apache.solr.core.CoreContainer;
import org.dspace.app.rest.test.AbstractDSpaceIntegrationTest;
/**
* Abstract class to mock a service that uses SOLR
*/
public class MockSolrServer {
private static final Logger log = Logger.getLogger(MockSolrServer.class);
private static final ConcurrentMap<String, SolrServer> loadedCores = new ConcurrentHashMap<>();
private static final ConcurrentMap<String, AtomicLong> usersPerCore = new ConcurrentHashMap<>();
private static CoreContainer container = null;
private String coreName;
private SolrServer solrServer = null;
public MockSolrServer(final String coreName) throws Exception {
this.coreName = coreName;
initSolrServer();
@@ -34,24 +45,65 @@ public class MockSolrServer {
}
protected void initSolrServer() throws Exception {
CoreContainer container = new CoreContainer(System.getProperty("dspace.dir") + File.separator + "solr");
container.load();
solrServer = loadedCores.get(coreName);
if(solrServer == null) {
solrServer = initSolrServerForCore(coreName);
}
solrServer = new EmbeddedSolrServer(container, coreName);
usersPerCore.putIfAbsent(coreName, new AtomicLong(0));
usersPerCore.get(coreName).incrementAndGet();
}
private static synchronized SolrServer initSolrServerForCore(final String coreName) {
SolrServer server = loadedCores.get(coreName);
if(server == null) {
initSolrContainer();
server = new EmbeddedSolrServer(container, coreName);
//Start with an empty index
try {
solrServer.deleteByQuery("*:*");
solrServer.commit();
server.deleteByQuery("*:*");
server.commit();
} catch (SolrServerException | IOException e) {
e.printStackTrace();
}
loadedCores.put(coreName, server);
log.info("SOLR Server for core " + coreName + " initialized");
}
return server;
}
public void destroy() throws Exception {
if(solrServer != null) {
long remainingUsers = usersPerCore.get(coreName).decrementAndGet();
if(remainingUsers <= 0) {
solrServer.shutdown();
usersPerCore.remove(coreName);
loadedCores.remove(coreName);
log.info("SOLR Server for core " + coreName + " destroyed");
}
if(usersPerCore.isEmpty()) {
destroyContainer();
}
}
}
private static synchronized void initSolrContainer() {
if(container == null) {
String solrDir = AbstractDSpaceIntegrationTest.getDspaceDir() + File.separator + "solr";
log.info("Initializing SOLR CoreContainer with directory " + solrDir);
container = new CoreContainer(solrDir);
container.load();
log.info("SOLR CoreContainer initialized");
}
}
private static synchronized void destroyContainer() {
container = null;
log.info("SOLR CoreContainer destroyed");
}
}

View File

@@ -12,6 +12,7 @@ import java.io.IOException;
import com.maxmind.geoip.Location;
import com.maxmind.geoip.LookupService;
import org.dspace.app.rest.test.AbstractDSpaceIntegrationTest;
/**
* Mock service to mock the location Lookup Service used by the SOLR statistics logger
@@ -20,7 +21,7 @@ public class MockLookupService extends LookupService {
public MockLookupService() throws IOException {
//Just give our super class a file so that he's happy. We'll mock all responses anyway.
super(System.getProperty("dspace.dir") + File.separator + "config" + File.separator + "dspace.cfg");
super(AbstractDSpaceIntegrationTest.getDspaceDir() + File.separator + "config" + File.separator + "dspace.cfg");
}
@Override

View File

@@ -0,0 +1,2 @@
org.springframework.test.context.ContextCustomizerFactory= \
org.dspace.app.rest.test.DSpaceKernelContextCustomizerFactory

View File

@@ -1,7 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml"/>
<!-- Set custom log levels for Spring REST integration tests here -->
<logger name="org.springframework.web" level="INFO"/>
<logger name="org.hibernate" level="INFO"/>
<logger name="org.hibernate" level="WARN"/>
<logger name="net.sf.ehcache" level="INFO"/>
<logger name="org.apache.solr" level="WARN"/>
</configuration>

View File

@@ -1147,6 +1147,11 @@
<artifactId>commons-validator</artifactId>
<version>1.5.0</version>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>