mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-19 16:03:07 +00:00
DS-3484: Added SOLR integration for the REST integration tests
This commit is contained in:
@@ -506,6 +506,32 @@
|
||||
<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>
|
||||
<artifactId>rome-modules</artifactId>
|
||||
|
@@ -7,6 +7,29 @@
|
||||
*/
|
||||
package org.dspace.discovery;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.sql.SQLException;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TimeZone;
|
||||
import java.util.UUID;
|
||||
import java.util.Vector;
|
||||
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.collections.MapUtils;
|
||||
import org.apache.commons.collections.Transformer;
|
||||
@@ -14,14 +37,12 @@ import org.apache.commons.lang.ArrayUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.lang.time.DateFormatUtils;
|
||||
import org.apache.commons.validator.routines.UrlValidator;
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.params.ClientPNames;
|
||||
import org.apache.http.client.utils.URIBuilder;
|
||||
import org.apache.http.impl.client.DefaultHttpClient;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.apache.solr.client.solrj.SolrQuery;
|
||||
import org.apache.solr.client.solrj.SolrServer;
|
||||
import org.apache.solr.client.solrj.SolrServerException;
|
||||
import org.apache.solr.client.solrj.impl.HttpSolrServer;
|
||||
import org.apache.solr.client.solrj.request.AbstractUpdateRequest;
|
||||
@@ -32,11 +53,23 @@ import org.apache.solr.client.solrj.util.ClientUtils;
|
||||
import org.apache.solr.common.SolrDocument;
|
||||
import org.apache.solr.common.SolrDocumentList;
|
||||
import org.apache.solr.common.SolrInputDocument;
|
||||
import org.apache.solr.common.params.*;
|
||||
import org.apache.solr.common.params.CommonParams;
|
||||
import org.apache.solr.common.params.FacetParams;
|
||||
import org.apache.solr.common.params.HighlightParams;
|
||||
import org.apache.solr.common.params.ModifiableSolrParams;
|
||||
import org.apache.solr.common.params.MoreLikeThisParams;
|
||||
import org.apache.solr.common.params.SpellingParams;
|
||||
import org.apache.solr.common.util.NamedList;
|
||||
import org.apache.solr.handler.extraction.ExtractingParams;
|
||||
import org.dspace.content.*;
|
||||
import org.dspace.authorize.ResourcePolicy;
|
||||
import org.dspace.authorize.factory.AuthorizeServiceFactory;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.Community;
|
||||
import org.dspace.content.DSpaceObject;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.content.MetadataField;
|
||||
import org.dspace.content.MetadataSchema;
|
||||
import org.dspace.content.MetadataValue;
|
||||
import org.dspace.content.authority.Choices;
|
||||
import org.dspace.content.authority.service.ChoiceAuthorityService;
|
||||
import org.dspace.content.authority.service.MetadataAuthorityService;
|
||||
@@ -44,8 +77,25 @@ import org.dspace.content.factory.ContentServiceFactory;
|
||||
import org.dspace.content.service.CollectionService;
|
||||
import org.dspace.content.service.CommunityService;
|
||||
import org.dspace.content.service.ItemService;
|
||||
import org.dspace.core.*;
|
||||
import org.dspace.discovery.configuration.*;
|
||||
import org.dspace.core.ConfigurationManager;
|
||||
import org.dspace.core.Constants;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.core.Email;
|
||||
import org.dspace.core.I18nUtil;
|
||||
import org.dspace.core.LogManager;
|
||||
import org.dspace.discovery.configuration.DiscoveryConfiguration;
|
||||
import org.dspace.discovery.configuration.DiscoveryConfigurationParameters;
|
||||
import org.dspace.discovery.configuration.DiscoveryHitHighlightFieldConfiguration;
|
||||
import org.dspace.discovery.configuration.DiscoveryHitHighlightingConfiguration;
|
||||
import org.dspace.discovery.configuration.DiscoveryMoreLikeThisConfiguration;
|
||||
import org.dspace.discovery.configuration.DiscoveryRecentSubmissionsConfiguration;
|
||||
import org.dspace.discovery.configuration.DiscoverySearchFilter;
|
||||
import org.dspace.discovery.configuration.DiscoverySearchFilterFacet;
|
||||
import org.dspace.discovery.configuration.DiscoverySortConfiguration;
|
||||
import org.dspace.discovery.configuration.DiscoverySortFieldConfiguration;
|
||||
import org.dspace.discovery.configuration.HierarchicalSidebarFacetConfiguration;
|
||||
import org.dspace.eperson.Group;
|
||||
import org.dspace.eperson.factory.EPersonServiceFactory;
|
||||
import org.dspace.handle.service.HandleService;
|
||||
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||
import org.dspace.storage.rdbms.DatabaseUtils;
|
||||
@@ -53,21 +103,6 @@ import org.dspace.util.MultiFormatDateParser;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.sql.SQLException;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import org.dspace.authorize.ResourcePolicy;
|
||||
import org.dspace.authorize.factory.AuthorizeServiceFactory;
|
||||
import org.dspace.eperson.Group;
|
||||
import org.dspace.eperson.factory.EPersonServiceFactory;
|
||||
|
||||
/**
|
||||
* SolrIndexer contains the methods that index Items and their metadata,
|
||||
* collections, communities, etc. It is meant to either be invoked from the
|
||||
@@ -122,9 +157,9 @@ public class SolrServiceImpl implements SearchService, IndexingService {
|
||||
protected MetadataAuthorityService metadataAuthorityService;
|
||||
|
||||
/**
|
||||
* Non-Static CommonsHttpSolrServer for processing indexing events.
|
||||
* Non-Static SolrServer for processing indexing events.
|
||||
*/
|
||||
private HttpSolrServer solr = null;
|
||||
protected SolrServer solr = null;
|
||||
|
||||
|
||||
protected SolrServiceImpl()
|
||||
@@ -132,7 +167,7 @@ public class SolrServiceImpl implements SearchService, IndexingService {
|
||||
|
||||
}
|
||||
|
||||
protected HttpSolrServer getSolr()
|
||||
protected SolrServer getSolr()
|
||||
{
|
||||
if ( solr == null)
|
||||
{
|
||||
@@ -143,10 +178,10 @@ public class SolrServiceImpl implements SearchService, IndexingService {
|
||||
{
|
||||
try {
|
||||
log.debug("Solr URL: " + solrService);
|
||||
solr = new HttpSolrServer(solrService);
|
||||
HttpSolrServer solrServer = new HttpSolrServer(solrService);
|
||||
|
||||
solr.setBaseURL(solrService);
|
||||
solr.setUseMultiPartPost(true);
|
||||
solrServer.setBaseURL(solrService);
|
||||
solrServer.setUseMultiPartPost(true);
|
||||
// Dummy/test query to search for Item (type=2) of ID=1
|
||||
SolrQuery solrQuery = new SolrQuery()
|
||||
.setQuery(RESOURCE_TYPE_FIELD + ":2 AND " + RESOURCE_ID_FIELD + ":1");
|
||||
@@ -157,6 +192,8 @@ public class SolrServiceImpl implements SearchService, IndexingService {
|
||||
// As long as Solr initialized, check with DatabaseUtils to see
|
||||
// if a reindex is in order. If so, reindex everything
|
||||
DatabaseUtils.checkReindexDiscovery(this);
|
||||
|
||||
solr = solrServer;
|
||||
} catch (SolrServerException e) {
|
||||
log.error("Error while initializing solr server", e);
|
||||
}
|
||||
@@ -1797,7 +1834,7 @@ public class SolrServiceImpl implements SearchService, IndexingService {
|
||||
|
||||
@Override
|
||||
public InputStream searchJSON(Context context, DiscoverQuery discoveryQuery, String jsonIdentifier) throws SearchServiceException {
|
||||
if (getSolr() == null)
|
||||
if (getSolr() == null || !(getSolr() instanceof HttpSolrServer))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -1809,7 +1846,7 @@ public class SolrServiceImpl implements SearchService, IndexingService {
|
||||
solrQuery.setParam(CommonParams.WT, "json");
|
||||
|
||||
StringBuilder urlBuilder = new StringBuilder();
|
||||
urlBuilder.append(getSolr().getBaseURL()).append("/select?");
|
||||
urlBuilder.append(((HttpSolrServer) getSolr()).getBaseURL()).append("/select?");
|
||||
urlBuilder.append(solrQuery.toString());
|
||||
|
||||
try {
|
||||
@@ -1988,38 +2025,6 @@ public class SolrServiceImpl implements SearchService, IndexingService {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Simple means to return the search result as an InputStream
|
||||
*
|
||||
* @param query discovery query
|
||||
* @return input stream
|
||||
* @throws IOException
|
||||
* A general class of exceptions produced by failed or interrupted I/O operations.
|
||||
* @throws SearchServiceException if something went wrong with querying the solr server
|
||||
*/
|
||||
public java.io.InputStream searchAsInputStream(DiscoverQuery query) throws SearchServiceException, java.io.IOException {
|
||||
if (getSolr() == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
HttpHost hostURL = (HttpHost)(getSolr().getHttpClient().getParams().getParameter(ClientPNames.DEFAULT_HOST));
|
||||
|
||||
HttpGet method = new HttpGet(hostURL.toHostString() + "");
|
||||
try
|
||||
{
|
||||
URI uri = new URIBuilder(method.getURI()).addParameter("q",query.toString()).build();
|
||||
}
|
||||
catch (URISyntaxException e)
|
||||
{
|
||||
throw new SearchServiceException(e);
|
||||
}
|
||||
|
||||
HttpResponse response = getSolr().getHttpClient().execute(method);
|
||||
|
||||
return response.getEntity().getContent();
|
||||
}
|
||||
|
||||
public List<DSpaceObject> search(Context context, String query, int offset, int max, String... filterquery)
|
||||
{
|
||||
return search(context, query, null, true, offset, max, filterquery);
|
||||
|
@@ -7,6 +7,32 @@
|
||||
*/
|
||||
package org.dspace.statistics;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.sql.SQLException;
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import au.com.bytecode.opencsv.CSVReader;
|
||||
import au.com.bytecode.opencsv.CSVWriter;
|
||||
import com.maxmind.geoip.Location;
|
||||
@@ -20,6 +46,7 @@ import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.impl.client.DefaultHttpClient;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.apache.solr.client.solrj.SolrQuery;
|
||||
import org.apache.solr.client.solrj.SolrServer;
|
||||
import org.apache.solr.client.solrj.SolrServerException;
|
||||
import org.apache.solr.client.solrj.impl.HttpSolrServer;
|
||||
import org.apache.solr.client.solrj.request.AbstractUpdateRequest;
|
||||
@@ -36,9 +63,18 @@ import org.apache.solr.common.SolrDocument;
|
||||
import org.apache.solr.common.SolrDocumentList;
|
||||
import org.apache.solr.common.SolrInputDocument;
|
||||
import org.apache.solr.common.luke.FieldFlag;
|
||||
import org.apache.solr.common.params.*;
|
||||
import org.dspace.content.*;
|
||||
import org.apache.solr.common.params.CommonParams;
|
||||
import org.apache.solr.common.params.FacetParams;
|
||||
import org.apache.solr.common.params.MapSolrParams;
|
||||
import org.apache.solr.common.params.ModifiableSolrParams;
|
||||
import org.apache.solr.common.params.ShardParams;
|
||||
import org.dspace.content.Bitstream;
|
||||
import org.dspace.content.Bundle;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.Community;
|
||||
import org.dspace.content.DCDate;
|
||||
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.DSpaceObjectLegacySupportService;
|
||||
@@ -55,15 +91,6 @@ import org.dspace.usage.UsageWorkflowEvent;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.*;
|
||||
import java.net.URLEncoder;
|
||||
import java.sql.SQLException;
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Static holder for a HttpSolrClient connection pool to issue
|
||||
* usage logging events to Solr from DSpace libraries, and some static query
|
||||
@@ -77,7 +104,7 @@ public class SolrLoggerServiceImpl implements SolrLoggerService, InitializingBea
|
||||
{
|
||||
private static final Logger log = Logger.getLogger(SolrLoggerServiceImpl.class);
|
||||
private static final String MULTIPLE_VALUES_SPLITTER = "|";
|
||||
protected HttpSolrServer solr;
|
||||
protected SolrServer solr;
|
||||
|
||||
public static final String DATE_FORMAT_8601 = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
|
||||
|
||||
@@ -1183,6 +1210,10 @@ public class SolrLoggerServiceImpl implements SolrLoggerService, InitializingBea
|
||||
|
||||
@Override
|
||||
public void shardSolrIndex() throws IOException, SolrServerException {
|
||||
if(!(solr instanceof HttpSolrServer)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
Start by faceting by year so we can include each year in a separate core !
|
||||
*/
|
||||
@@ -1243,14 +1274,14 @@ public class SolrLoggerServiceImpl implements SolrLoggerService, InitializingBea
|
||||
|
||||
//Start by creating a new core
|
||||
String coreName = "statistics-" + dcStart.getYearUTC();
|
||||
HttpSolrServer statisticsYearServer = createCore(solr, coreName);
|
||||
HttpSolrServer statisticsYearServer = createCore((HttpSolrServer) solr, coreName);
|
||||
|
||||
System.out.println("Moving: " + totalRecords + " into core " + coreName);
|
||||
log.info("Moving: " + totalRecords + " records into core " + coreName);
|
||||
|
||||
List<File> filesToUpload = new ArrayList<File>();
|
||||
for (int i = 0; i < totalRecords; i+=10000) {
|
||||
String solrRequestUrl = solr.getBaseURL() + "/select";
|
||||
String solrRequestUrl = ((HttpSolrServer) solr).getBaseURL() + "/select";
|
||||
solrRequestUrl = generateURL(solrRequestUrl, yearQueryParams);
|
||||
|
||||
HttpGet get = new HttpGet(solrRequestUrl);
|
||||
@@ -1356,6 +1387,10 @@ public class SolrLoggerServiceImpl implements SolrLoggerService, InitializingBea
|
||||
|
||||
@Override
|
||||
public void reindexBitstreamHits(boolean removeDeletedBitstreams) throws Exception {
|
||||
if(!(solr instanceof HttpSolrServer)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Context context = new Context();
|
||||
|
||||
try {
|
||||
@@ -1380,7 +1415,7 @@ public class SolrLoggerServiceImpl implements SolrLoggerService, InitializingBea
|
||||
params.put(CommonParams.ROWS, String.valueOf(10000));
|
||||
params.put(CommonParams.START, String.valueOf(i));
|
||||
|
||||
String solrRequestUrl = solr.getBaseURL() + "/select";
|
||||
String solrRequestUrl = ((HttpSolrServer) solr).getBaseURL() + "/select";
|
||||
solrRequestUrl = generateURL(solrRequestUrl, params);
|
||||
|
||||
HttpGet get = new HttpGet(solrRequestUrl);
|
||||
@@ -1587,7 +1622,7 @@ public class SolrLoggerServiceImpl implements SolrLoggerService, InitializingBea
|
||||
* This code is synchonized in the event that 2 threads trigger the initialization at the same time.
|
||||
*/
|
||||
protected synchronized void initSolrYearCores() {
|
||||
if (statisticYearCoresInit) {
|
||||
if (statisticYearCoresInit || !(solr instanceof HttpSolrServer)) {
|
||||
return;
|
||||
}
|
||||
try
|
||||
@@ -1603,16 +1638,16 @@ public class SolrLoggerServiceImpl implements SolrLoggerService, InitializingBea
|
||||
}
|
||||
});
|
||||
//Base url should like : http://localhost:{port.number}/solr
|
||||
String baseSolrUrl = solr.getBaseURL().replace("statistics", "");
|
||||
String baseSolrUrl = ((HttpSolrServer) solr).getBaseURL().replace("statistics", "");
|
||||
for (File solrCoreFile : solrCoreFiles) {
|
||||
log.info("Loading core with name: " + solrCoreFile.getName());
|
||||
|
||||
createCore(solr, solrCoreFile.getName());
|
||||
createCore((HttpSolrServer) solr, solrCoreFile.getName());
|
||||
//Add it to our cores list so we can query it !
|
||||
statisticYearCores.add(baseSolrUrl.replace("http://", "").replace("https://", "") + solrCoreFile.getName());
|
||||
}
|
||||
//Also add the core containing the current year !
|
||||
statisticYearCores.add(solr.getBaseURL().replace("http://", "").replace("https://", ""));
|
||||
statisticYearCores.add(((HttpSolrServer) solr).getBaseURL().replace("http://", "").replace("https://", ""));
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
|
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:util="http://www.springframework.org/schema/util"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
http://www.springframework.org/schema/context
|
||||
http://www.springframework.org/schema/context/spring-context-3.0.xsd
|
||||
http://www.springframework.org/schema/util
|
||||
http://www.springframework.org/schema/util/spring-util-3.0.xsd"
|
||||
default-autowire-candidates="*Service,*DAO,javax.sql.DataSource">
|
||||
|
||||
<context:annotation-config /> <!-- allows us to use spring annotations in beans -->
|
||||
|
||||
<!-- Run an internal SOLR server for the Discovery search service -->
|
||||
<bean class="org.dspace.discovery.MockSolrServiceImpl" id="org.dspace.discovery.SearchService"/>
|
||||
|
||||
<!-- Run an internal SOLR server for the statistics service -->
|
||||
<bean class="org.dspace.statistics.MockSolrLoggerServiceImpl" id="solrLoggerService" lazy-init="true"/>
|
||||
|
||||
</beans>
|
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* 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.discovery;
|
||||
|
||||
import org.dspace.solr.MockSolrServer;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
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 void afterPropertiesSet() throws Exception {
|
||||
mockSolrServer = new MockSolrServer("search");
|
||||
solr = mockSolrServer.getSolrServer();
|
||||
}
|
||||
|
||||
public void destroy() throws Exception {
|
||||
mockSolrServer.destroy();
|
||||
}
|
||||
}
|
57
dspace-api/src/test/java/org/dspace/solr/MockSolrServer.java
Normal file
57
dspace-api/src/test/java/org/dspace/solr/MockSolrServer.java
Normal file
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* 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.statistics;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import com.maxmind.geoip.Location;
|
||||
import com.maxmind.geoip.LookupService;
|
||||
|
||||
/**
|
||||
* Mock service to mock the location Lookup Service used by the SOLR statistics logger
|
||||
*/
|
||||
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");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getLocation(String str) {
|
||||
Location location = new Location();
|
||||
location.countryCode = "US";
|
||||
location.countryName = "United States";
|
||||
location.region = "NY";
|
||||
location.city = "New York";
|
||||
location.postalCode = "10036";
|
||||
location.latitude = 40.760498F;
|
||||
location.longitude = -73.9933F;
|
||||
location.dma_code = 501;
|
||||
location.area_code = 212;
|
||||
location.metro_code = 501;
|
||||
|
||||
return location;
|
||||
}
|
||||
}
|
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* 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.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;
|
||||
|
||||
@Autowired(required = true)
|
||||
private ConfigurationService configurationService;
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
mockSolrServer = new MockSolrServer("statistics");
|
||||
solr = mockSolrServer.getSolrServer();
|
||||
locationService = new MockLookupService();
|
||||
useProxies = configurationService.getBooleanProperty("useProxies");
|
||||
}
|
||||
|
||||
public void destroy() throws Exception {
|
||||
mockSolrServer.destroy();
|
||||
}
|
||||
|
||||
}
|
@@ -15,7 +15,7 @@ import org.dspace.services.ConfigurationService;
|
||||
*
|
||||
* @author Aaron Zeckoski (azeckoski @ gmail.com)
|
||||
*/
|
||||
public interface DSpaceKernel {
|
||||
public interface DSpaceKernel extends CommonLifecycle<DSpaceKernel> {
|
||||
|
||||
public static final String KERNEL_NAME = "Kernel";
|
||||
public static final String MBEAN_PREFIX = "org.dspace:name=";
|
||||
|
@@ -24,7 +24,6 @@ import javax.management.modelmbean.ModelMBeanAttributeInfo;
|
||||
import javax.management.modelmbean.ModelMBeanInfoSupport;
|
||||
import javax.management.modelmbean.ModelMBeanOperationInfo;
|
||||
|
||||
import org.dspace.kernel.CommonLifecycle;
|
||||
import org.dspace.kernel.DSpaceKernel;
|
||||
import org.dspace.kernel.DSpaceKernelManager;
|
||||
import org.dspace.kernel.ServiceManager;
|
||||
@@ -50,7 +49,7 @@ import org.slf4j.LoggerFactory;
|
||||
*
|
||||
* @author Aaron Zeckoski (azeckoski @ gmail.com)
|
||||
*/
|
||||
public final class DSpaceKernelImpl implements DSpaceKernel, DynamicMBean, CommonLifecycle<DSpaceKernel> {
|
||||
public final class DSpaceKernelImpl implements DSpaceKernel, DynamicMBean {
|
||||
|
||||
private static Logger log = LoggerFactory.getLogger(DSpaceKernelImpl.class);
|
||||
|
||||
@@ -197,6 +196,7 @@ public final class DSpaceKernelImpl implements DSpaceKernel, DynamicMBean, Commo
|
||||
/* (non-Javadoc)
|
||||
* @see org.dspace.kernel.CommonLifecycle#destroy()
|
||||
*/
|
||||
@Override
|
||||
public void destroy() {
|
||||
if (this.destroyed) {
|
||||
return;
|
||||
|
@@ -289,6 +289,30 @@
|
||||
<artifactId>json-path-assert</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>
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
@@ -19,6 +19,7 @@ import org.dspace.app.rest.filter.DSpaceRequestContextFilter;
|
||||
import org.dspace.app.rest.model.hateoas.DSpaceRelProvider;
|
||||
import org.dspace.app.rest.utils.ApplicationConfig;
|
||||
import org.dspace.app.util.DSpaceContextListener;
|
||||
import org.dspace.kernel.DSpaceKernel;
|
||||
import org.dspace.kernel.DSpaceKernelManager;
|
||||
import org.dspace.servicemanager.DSpaceKernelImpl;
|
||||
import org.dspace.servicemanager.DSpaceKernelInit;
|
||||
@@ -87,7 +88,7 @@ public class Application extends SpringBootServletInitializer {
|
||||
public ServletContextInitializer contextInitializer() {
|
||||
return new ServletContextInitializer() {
|
||||
|
||||
private transient DSpaceKernelImpl kernelImpl;
|
||||
private transient DSpaceKernel dspaceKernel;
|
||||
|
||||
@Override
|
||||
public void onStartup(ServletContext servletContext)
|
||||
@@ -95,22 +96,23 @@ public class Application extends SpringBootServletInitializer {
|
||||
servletContext.setInitParameter("dspace.dir", configuration.getDspaceHome());
|
||||
|
||||
// start the kernel when the webapp starts
|
||||
if (DSpaceKernelManager.getDefaultKernel() == null) {
|
||||
this.dspaceKernel = DSpaceKernelManager.getDefaultKernel();
|
||||
if (this.dspaceKernel == null) {
|
||||
DSpaceKernelImpl kernelImpl = null;
|
||||
try {
|
||||
this.kernelImpl = DSpaceKernelInit.getKernel(null);
|
||||
if (!this.kernelImpl.isRunning()) {
|
||||
this.kernelImpl.start(getProvidedHome(configuration.getDspaceHome())); // init the kernel
|
||||
kernelImpl = DSpaceKernelInit.getKernel(null);
|
||||
if (!kernelImpl.isRunning()) {
|
||||
kernelImpl.start(getProvidedHome(configuration.getDspaceHome())); // init the kernel
|
||||
}
|
||||
//Set the DSpace Kernel Application context as a parent of the Spring Boot context so that
|
||||
//we can auto-wire all DSpace Kernel services
|
||||
springBootApplicationContext.setParent(kernelImpl.getServiceManager().getApplicationContext());
|
||||
this.dspaceKernel = kernelImpl;
|
||||
|
||||
//Add a listener for Spring Boot application shutdown so that we can nicely cleanup the DSpace kernel.
|
||||
springBootApplicationContext.addApplicationListener(new DSpaceKernelDestroyer(kernelImpl));
|
||||
} catch (Exception e) {
|
||||
// failed to start so destroy it and log and throw an exception
|
||||
try {
|
||||
this.kernelImpl.destroy();
|
||||
if(kernelImpl != null) {
|
||||
kernelImpl.destroy();
|
||||
}
|
||||
this.dspaceKernel = null;
|
||||
} catch (Exception e1) {
|
||||
// nothing
|
||||
}
|
||||
@@ -119,6 +121,15 @@ public class Application extends SpringBootServletInitializer {
|
||||
throw new RuntimeException(message, e);
|
||||
}
|
||||
}
|
||||
|
||||
if(springBootApplicationContext.getParent() == null) {
|
||||
//Set the DSpace Kernel Application context as a parent of the Spring Boot context so that
|
||||
//we can auto-wire all DSpace Kernel services
|
||||
springBootApplicationContext.setParent(dspaceKernel.getServiceManager().getApplicationContext());
|
||||
|
||||
//Add a listener for Spring Boot application shutdown so that we can nicely cleanup the DSpace kernel.
|
||||
springBootApplicationContext.addApplicationListener(new DSpaceKernelDestroyer(dspaceKernel));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -208,16 +219,16 @@ public class Application extends SpringBootServletInitializer {
|
||||
|
||||
/** Utility class that will destory the DSpace Kernel on Spring Boot shutdown */
|
||||
private class DSpaceKernelDestroyer implements ApplicationListener<ContextClosedEvent> {
|
||||
private DSpaceKernelImpl kernelImpl;
|
||||
private DSpaceKernel dspaceKernel;
|
||||
|
||||
public DSpaceKernelDestroyer(DSpaceKernelImpl kernelImpl) {
|
||||
this.kernelImpl = kernelImpl;
|
||||
public DSpaceKernelDestroyer(DSpaceKernel kernelImpl) {
|
||||
this.dspaceKernel = kernelImpl;
|
||||
}
|
||||
|
||||
public void onApplicationEvent(final ContextClosedEvent event) {
|
||||
if (this.kernelImpl != null) {
|
||||
this.kernelImpl.destroy();
|
||||
this.kernelImpl = null;
|
||||
if (this.dspaceKernel != null) {
|
||||
this.dspaceKernel.destroy();
|
||||
this.dspaceKernel = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -7,14 +7,18 @@
|
||||
*/
|
||||
package org.dspace.app.rest;
|
||||
|
||||
import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasJsonPath;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.hamcrest.text.IsEqualIgnoringCase.equalToIgnoringCase;
|
||||
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.ItemBuilder;
|
||||
import org.dspace.app.rest.matcher.BrowseIndexMatchers;
|
||||
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
|
||||
import org.hamcrest.Matcher;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.Community;
|
||||
import org.dspace.content.Item;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
@@ -42,48 +46,117 @@ public class BrowsesResourceControllerTest extends AbstractControllerIntegration
|
||||
|
||||
//Check that all (and only) the default browse indexes are present
|
||||
.andExpect(jsonPath("$._embedded.browses", containsInAnyOrder(
|
||||
dateIssuedBrowseIndex("asc"),
|
||||
contributorBrowseIndex("asc"),
|
||||
titleBrowseIndex("asc"),
|
||||
subjectBrowseIndex("asc")
|
||||
BrowseIndexMatchers.dateIssuedBrowseIndex("asc"),
|
||||
BrowseIndexMatchers.contributorBrowseIndex("asc"),
|
||||
BrowseIndexMatchers.titleBrowseIndex("asc"),
|
||||
BrowseIndexMatchers.subjectBrowseIndex("asc")
|
||||
)))
|
||||
;
|
||||
}
|
||||
|
||||
private Matcher<? super Object> subjectBrowseIndex(final String order) {
|
||||
return allOf(
|
||||
hasJsonPath("$.metadata", contains("dc.subject.*")),
|
||||
hasJsonPath("$.metadataBrowse", is(true)),
|
||||
hasJsonPath("$.order", equalToIgnoringCase(order)),
|
||||
hasJsonPath("$.sortOptions[*].name", containsInAnyOrder("title", "dateissued", "dateaccessioned"))
|
||||
);
|
||||
@Test
|
||||
public void findBrowseByTitle() throws Exception {
|
||||
//When we call the root endpoint
|
||||
mockMvc.perform(get("/api/discover/browses/title"))
|
||||
//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))
|
||||
|
||||
//Check that the JSON root matches the expected browse index
|
||||
.andExpect(jsonPath("$", BrowseIndexMatchers.titleBrowseIndex("asc")))
|
||||
;
|
||||
}
|
||||
|
||||
private Matcher<? super Object> titleBrowseIndex(final String order) {
|
||||
return allOf(
|
||||
hasJsonPath("$.metadata", contains("dc.title")),
|
||||
hasJsonPath("$.metadataBrowse", is(false)),
|
||||
hasJsonPath("$.order", equalToIgnoringCase(order)),
|
||||
hasJsonPath("$.sortOptions[*].name", containsInAnyOrder("title", "dateissued", "dateaccessioned"))
|
||||
);
|
||||
@Test
|
||||
public void findBrowseByDateIssued() throws Exception {
|
||||
//When we call the root endpoint
|
||||
mockMvc.perform(get("/api/discover/browses/dateissued"))
|
||||
//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))
|
||||
|
||||
//Check that the JSON root matches the expected browse index
|
||||
.andExpect(jsonPath("$", BrowseIndexMatchers.dateIssuedBrowseIndex("asc")))
|
||||
;
|
||||
}
|
||||
|
||||
private Matcher<? super Object> contributorBrowseIndex(final String order) {
|
||||
return allOf(
|
||||
hasJsonPath("$.metadata", contains("dc.contributor.*", "dc.creator")),
|
||||
hasJsonPath("$.metadataBrowse", is(true)),
|
||||
hasJsonPath("$.order", equalToIgnoringCase(order)),
|
||||
hasJsonPath("$.sortOptions[*].name", containsInAnyOrder("title", "dateissued", "dateaccessioned"))
|
||||
);
|
||||
@Test
|
||||
public void findBrowseByContributor() throws Exception {
|
||||
//When we call the root endpoint
|
||||
mockMvc.perform(get("/api/discover/browses/author"))
|
||||
//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))
|
||||
|
||||
//Check that the JSON root matches the expected browse index
|
||||
.andExpect(jsonPath("$", BrowseIndexMatchers.contributorBrowseIndex("asc")))
|
||||
;
|
||||
}
|
||||
|
||||
private Matcher<? super Object> dateIssuedBrowseIndex(final String order) {
|
||||
return allOf(
|
||||
hasJsonPath("$.metadata", contains("dc.date.issued")),
|
||||
hasJsonPath("$.metadataBrowse", is(false)),
|
||||
hasJsonPath("$.order", equalToIgnoringCase(order)),
|
||||
hasJsonPath("$.sortOptions[*].name", containsInAnyOrder("title", "dateissued", "dateaccessioned"))
|
||||
);
|
||||
@Test
|
||||
public void findBrowseBySubject() throws Exception {
|
||||
//When we call the root endpoint
|
||||
mockMvc.perform(get("/api/discover/browses/subject"))
|
||||
//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))
|
||||
|
||||
//Check that the JSON root matches the expected browse index
|
||||
.andExpect(jsonPath("$", BrowseIndexMatchers.subjectBrowseIndex("asc")))
|
||||
;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findBrowseByTitleItems() throws Exception {
|
||||
|
||||
context.turnOffAuthorisationSystem();
|
||||
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")
|
||||
.withIssueDate("2017-10-17")
|
||||
.withAuthor("Smith, Donald")
|
||||
.withAuthor("Doe, John")
|
||||
.withSubject("Java")
|
||||
.withSubject("Unit Testing")
|
||||
.build();
|
||||
|
||||
Item item2 = new ItemBuilder().createItem(context, col2)
|
||||
.withTitle("My second test item")
|
||||
.withIssueDate("2016-02-13")
|
||||
.withAuthor("Smith, Maria")
|
||||
.withAuthor("Doe, Jane")
|
||||
.withSubject("Angular")
|
||||
.withSubject("Unit Testing")
|
||||
.build();
|
||||
|
||||
context.restoreAuthSystemState();
|
||||
|
||||
//When we browse the items in the Browse by item endpoint
|
||||
mockMvc.perform(get("/api/discover/browses/title/items"))
|
||||
//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
|
||||
.andExpect(jsonPath("$.page.size", is(20)))
|
||||
.andExpect(jsonPath("$.page.totalElements", is(2)))
|
||||
.andExpect(jsonPath("$.page.totalPages", is(1)))
|
||||
.andExpect(jsonPath("$.page.number", is(0)))
|
||||
;
|
||||
}
|
||||
}
|
@@ -30,17 +30,17 @@ public class RootRestResourceControllerTest extends AbstractControllerIntegratio
|
||||
//We expect the content type to be "application/hal+json;charset=UTF-8"
|
||||
.andExpect(content().contentType(contentType))
|
||||
//Check that all required root links are present and that they are absolute
|
||||
.andExpect(jsonPath("$._links.bitstreamformats.href", startsWith("http://localhost/api")))
|
||||
.andExpect(jsonPath("$._links.bitstreams.href", startsWith("http://localhost/api")))
|
||||
.andExpect(jsonPath("$._links.browses.href", startsWith("http://localhost/api")))
|
||||
.andExpect(jsonPath("$._links.collections.href", startsWith("http://localhost/api")))
|
||||
.andExpect(jsonPath("$._links.communities.href", startsWith("http://localhost/api")))
|
||||
.andExpect(jsonPath("$._links.epersons.href", startsWith("http://localhost/api")))
|
||||
.andExpect(jsonPath("$._links.groups.href", startsWith("http://localhost/api")))
|
||||
.andExpect(jsonPath("$._links.items.href", startsWith("http://localhost/api")))
|
||||
.andExpect(jsonPath("$._links.metadatafields.href", startsWith("http://localhost/api")))
|
||||
.andExpect(jsonPath("$._links.metadataschemas.href", startsWith("http://localhost/api")))
|
||||
.andExpect(jsonPath("$._links.sites.href", startsWith("http://localhost/api")))
|
||||
.andExpect(jsonPath("$._links.bitstreamformats.href", startsWith(REST_SERVER_URL)))
|
||||
.andExpect(jsonPath("$._links.bitstreams.href", startsWith(REST_SERVER_URL)))
|
||||
.andExpect(jsonPath("$._links.browses.href", startsWith(REST_SERVER_URL)))
|
||||
.andExpect(jsonPath("$._links.collections.href", startsWith(REST_SERVER_URL)))
|
||||
.andExpect(jsonPath("$._links.communities.href", startsWith(REST_SERVER_URL)))
|
||||
.andExpect(jsonPath("$._links.epersons.href", startsWith(REST_SERVER_URL)))
|
||||
.andExpect(jsonPath("$._links.groups.href", startsWith(REST_SERVER_URL)))
|
||||
.andExpect(jsonPath("$._links.items.href", startsWith(REST_SERVER_URL)))
|
||||
.andExpect(jsonPath("$._links.metadatafields.href", startsWith(REST_SERVER_URL)))
|
||||
.andExpect(jsonPath("$._links.metadataschemas.href", startsWith(REST_SERVER_URL)))
|
||||
.andExpect(jsonPath("$._links.sites.href", startsWith(REST_SERVER_URL)))
|
||||
;
|
||||
}
|
||||
|
||||
|
@@ -0,0 +1,46 @@
|
||||
package org.dspace.app.rest.builder;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
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.core.Context;
|
||||
import org.dspace.discovery.IndexingService;
|
||||
import org.dspace.eperson.factory.EPersonServiceFactory;
|
||||
import org.dspace.eperson.service.EPersonService;
|
||||
import org.dspace.eperson.service.GroupService;
|
||||
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||
|
||||
/**
|
||||
* TODO TOM UNIT TEST
|
||||
*/
|
||||
public class AbstractBuilder {
|
||||
|
||||
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);
|
||||
|
||||
protected Context context;
|
||||
|
||||
/** log4j category */
|
||||
private static final Logger log = Logger.getLogger(AbstractBuilder.class);
|
||||
|
||||
protected <T> T handleException(final Exception e) {
|
||||
log.error(e);
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,50 @@
|
||||
package org.dspace.app.rest.builder;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.Community;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.content.MetadataSchema;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.discovery.SearchServiceException;
|
||||
|
||||
/**
|
||||
* TODO TOM UNIT TEST
|
||||
*/
|
||||
public class CollectionBuilder extends AbstractBuilder {
|
||||
|
||||
private Collection collection;
|
||||
private Context context;
|
||||
|
||||
public CollectionBuilder createCollection(final Context context, final Community parent) {
|
||||
this.context = context;
|
||||
try {
|
||||
this.collection = collectionService.create(context, parent);
|
||||
} catch (Exception e) {
|
||||
return handleException(e);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public Collection build() {
|
||||
context.dispatchEvents();
|
||||
try {
|
||||
indexingService.commit();
|
||||
} catch (SearchServiceException e) {
|
||||
return handleException(e);
|
||||
}
|
||||
return collection;
|
||||
}
|
||||
}
|
@@ -0,0 +1,63 @@
|
||||
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.core.Context;
|
||||
import org.dspace.discovery.IndexingService;
|
||||
import org.dspace.discovery.SearchServiceException;
|
||||
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||
|
||||
/**
|
||||
* TODO TOM UNIT TEST
|
||||
*/
|
||||
public class CommunityBuilder {
|
||||
|
||||
protected CommunityService communityService = ContentServiceFactory.getInstance().getCommunityService();
|
||||
protected IndexingService indexingService = DSpaceServicesFactory.getInstance().getServiceManager().getServiceByName(IndexingService.class.getName(),IndexingService.class);
|
||||
|
||||
private Community community;
|
||||
private Context context;
|
||||
|
||||
public CommunityBuilder createCommunity(final Context context) {
|
||||
return createSubCommunity(context, null);
|
||||
}
|
||||
|
||||
public CommunityBuilder createSubCommunity(final Context context, final Community parent) {
|
||||
this.context = context;
|
||||
try {
|
||||
community = communityService.create(parent, context);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public Community build() {
|
||||
context.dispatchEvents();
|
||||
try {
|
||||
indexingService.commit();
|
||||
} catch (SearchServiceException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
return community;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,74 @@
|
||||
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.core.Context;
|
||||
|
||||
/**
|
||||
* TODO TOM UNIT TEST
|
||||
*/
|
||||
public class ItemBuilder extends AbstractBuilder {
|
||||
|
||||
private WorkspaceItem workspaceItem;
|
||||
|
||||
public ItemBuilder createItem(final Context context, final Collection col1) {
|
||||
this.context = context;
|
||||
|
||||
try {
|
||||
workspaceItem = workspaceItemService.create(context, col1, false);
|
||||
} catch (Exception e) {
|
||||
return handleException(e);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public ItemBuilder withIssueDate(final String issueDate) {
|
||||
return addMetadataValueToItem(MetadataSchema.DC_SCHEMA, "date", "issued", new DCDate(issueDate).toString());
|
||||
}
|
||||
|
||||
public ItemBuilder withAuthor(final String authorName) {
|
||||
return addMetadataValueToItem(MetadataSchema.DC_SCHEMA, "date", "issued", authorName);
|
||||
}
|
||||
|
||||
public ItemBuilder withSubject(final String subject) {
|
||||
return addMetadataValueToItem(MetadataSchema.DC_SCHEMA, "subject", null, subject);
|
||||
}
|
||||
|
||||
public Item build() {
|
||||
try {
|
||||
Item item = installItemService.installItem(context, workspaceItem);
|
||||
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);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
@@ -0,0 +1,60 @@
|
||||
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.*;
|
||||
import static org.hamcrest.text.IsEqualIgnoringCase.equalToIgnoringCase;
|
||||
|
||||
import org.hamcrest.Matcher;
|
||||
import org.hamcrest.Matchers;
|
||||
|
||||
public class BrowseIndexMatchers {
|
||||
public BrowseIndexMatchers() {
|
||||
}
|
||||
|
||||
public static Matcher<? super Object> subjectBrowseIndex(final String order) {
|
||||
return allOf(
|
||||
hasJsonPath("$.metadata", contains("dc.subject.*")),
|
||||
hasJsonPath("$.metadataBrowse", Matchers.is(true)),
|
||||
hasJsonPath("$.order", equalToIgnoringCase(order)),
|
||||
hasJsonPath("$.sortOptions[*].name", containsInAnyOrder("title", "dateissued", "dateaccessioned")),
|
||||
hasJsonPath("$._links.self.href", is(REST_SERVER_URL + "discover/browses/subject")),
|
||||
hasJsonPath("$._links.entries.href", is(REST_SERVER_URL + "discover/browses/subject/entries")),
|
||||
hasJsonPath("$._links.items.href", is(REST_SERVER_URL + "discover/browses/subject/items"))
|
||||
);
|
||||
}
|
||||
|
||||
public static Matcher<? super Object> titleBrowseIndex(final String order) {
|
||||
return allOf(
|
||||
hasJsonPath("$.metadata", contains("dc.title")),
|
||||
hasJsonPath("$.metadataBrowse", Matchers.is(false)),
|
||||
hasJsonPath("$.order", equalToIgnoringCase(order)),
|
||||
hasJsonPath("$.sortOptions[*].name", containsInAnyOrder("title", "dateissued", "dateaccessioned")),
|
||||
hasJsonPath("$._links.self.href", is(REST_SERVER_URL + "discover/browses/title")),
|
||||
hasJsonPath("$._links.items.href", is(REST_SERVER_URL + "discover/browses/title/items"))
|
||||
);
|
||||
}
|
||||
|
||||
public static Matcher<? super Object> contributorBrowseIndex(final String order) {
|
||||
return allOf(
|
||||
hasJsonPath("$.metadata", contains("dc.contributor.*", "dc.creator")),
|
||||
hasJsonPath("$.metadataBrowse", Matchers.is(true)),
|
||||
hasJsonPath("$.order", equalToIgnoringCase(order)),
|
||||
hasJsonPath("$.sortOptions[*].name", containsInAnyOrder("title", "dateissued", "dateaccessioned")),
|
||||
hasJsonPath("$._links.self.href", is(REST_SERVER_URL + "discover/browses/author")),
|
||||
hasJsonPath("$._links.entries.href", is(REST_SERVER_URL + "discover/browses/author/entries")),
|
||||
hasJsonPath("$._links.items.href", is(REST_SERVER_URL + "discover/browses/author/items"))
|
||||
);
|
||||
}
|
||||
|
||||
public static Matcher<? super Object> dateIssuedBrowseIndex(final String order) {
|
||||
return allOf(
|
||||
hasJsonPath("$.metadata", contains("dc.date.issued")),
|
||||
hasJsonPath("$.metadataBrowse", Matchers.is(false)),
|
||||
hasJsonPath("$.order", equalToIgnoringCase(order)),
|
||||
hasJsonPath("$.sortOptions[*].name", containsInAnyOrder("title", "dateissued", "dateaccessioned")),
|
||||
hasJsonPath("$._links.self.href", is(REST_SERVER_URL + "discover/browses/dateissued")),
|
||||
hasJsonPath("$._links.items.href", is(REST_SERVER_URL + "discover/browses/dateissued/items"))
|
||||
);
|
||||
}
|
||||
}
|
@@ -17,6 +17,7 @@ import javax.servlet.Filter;
|
||||
import org.apache.commons.io.Charsets;
|
||||
import org.dspace.app.rest.Application;
|
||||
import org.dspace.app.rest.utils.ApplicationConfig;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -48,10 +49,12 @@ import org.springframework.web.context.WebApplicationContext;
|
||||
@WebAppConfiguration
|
||||
public class AbstractControllerIntegrationTest extends AbstractUnitTestWithDatabase {
|
||||
|
||||
public static final String REST_SERVER_URL = "http://localhost/api/";
|
||||
|
||||
protected MediaType contentType = new MediaType(MediaTypes.HAL_JSON.getType(),
|
||||
MediaTypes.HAL_JSON.getSubtype(), Charsets.UTF_8);
|
||||
|
||||
protected MockMvc mockMvc;
|
||||
protected MockMvc mockMvc = null;
|
||||
|
||||
protected HttpMessageConverter mappingJackson2HttpMessageConverter;
|
||||
|
||||
@@ -74,10 +77,18 @@ public class AbstractControllerIntegrationTest extends AbstractUnitTestWithDatab
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
this.mockMvc = webAppContextSetup(webApplicationContext)
|
||||
//Add all filter implementations
|
||||
.addFilters(requestFilters.toArray(new Filter[requestFilters.size()]))
|
||||
.build();
|
||||
if(mockMvc == null) {
|
||||
mockMvc = webAppContextSetup(webApplicationContext)
|
||||
//Add all filter implementations
|
||||
.addFilters(requestFilters.toArray(new Filter[requestFilters.size()]))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@After
|
||||
public void destroy() {
|
||||
super.destroy();
|
||||
mockMvc = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -13,6 +13,8 @@ import java.sql.SQLException;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.content.Community;
|
||||
import org.dspace.content.factory.ContentServiceFactory;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.core.I18nUtil;
|
||||
import org.dspace.eperson.EPerson;
|
||||
@@ -40,6 +42,11 @@ public class AbstractUnitTestWithDatabase extends AbstractDSpaceTest {
|
||||
*/
|
||||
protected EPerson eperson;
|
||||
|
||||
/**
|
||||
* The test Parent Community
|
||||
*/
|
||||
protected Community parentCommunity = null;
|
||||
|
||||
/**
|
||||
* This method will be run before the first test as per @BeforeClass. It will
|
||||
* initialize shared resources required for all tests of this class.
|
||||
@@ -134,8 +141,21 @@ public class AbstractUnitTestWithDatabase extends AbstractDSpaceTest {
|
||||
{
|
||||
// Cleanup our global context object
|
||||
try {
|
||||
context.commit();
|
||||
parentCommunity = context.reloadEntity(parentCommunity);
|
||||
eperson = context.reloadEntity(eperson);
|
||||
|
||||
context.turnOffAuthorisationSystem();
|
||||
if(parentCommunity != null) {
|
||||
ContentServiceFactory.getInstance().getCommunityService().delete(context, parentCommunity);
|
||||
}
|
||||
if(eperson != null) {
|
||||
EPersonServiceFactory.getInstance().getEPersonService().delete(context, eperson);
|
||||
}
|
||||
|
||||
parentCommunity = null;
|
||||
cleanupContext(context);
|
||||
} catch (SQLException e) {
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,23 @@
|
||||
package org.dspace.app.rest.test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.dspace.kernel.DSpaceKernelManager;
|
||||
import org.springframework.test.context.ContextConfigurationAttributes;
|
||||
import org.springframework.test.context.ContextCustomizer;
|
||||
import org.springframework.test.context.ContextCustomizerFactory;
|
||||
|
||||
/**
|
||||
* Context customizer factory to set the parent context of our Spring Boot application in TEST mode
|
||||
*/
|
||||
public class DSpaceKernelContextCustomizerFactory implements ContextCustomizerFactory {
|
||||
|
||||
@Override
|
||||
public ContextCustomizer createContextCustomizer(Class<?> testClass,
|
||||
List<ContextConfigurationAttributes> configAttributes) {
|
||||
return (context, mergedConfig) -> {
|
||||
context.setParent(DSpaceKernelManager.getDefaultKernel().getServiceManager().getApplicationContext());
|
||||
};
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* 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.discovery;
|
||||
|
||||
import org.dspace.solr.MockSolrServer;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
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 void afterPropertiesSet() throws Exception {
|
||||
mockSolrServer = new MockSolrServer("search");
|
||||
solr = mockSolrServer.getSolrServer();
|
||||
}
|
||||
|
||||
public void destroy() throws Exception {
|
||||
mockSolrServer.destroy();
|
||||
}
|
||||
}
|
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* 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.statistics;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import com.maxmind.geoip.Location;
|
||||
import com.maxmind.geoip.LookupService;
|
||||
|
||||
/**
|
||||
* Mock service to mock the location Lookup Service used by the SOLR statistics logger
|
||||
*/
|
||||
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");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getLocation(String str) {
|
||||
Location location = new Location();
|
||||
location.countryCode = "US";
|
||||
location.countryName = "United States";
|
||||
location.region = "NY";
|
||||
location.city = "New York";
|
||||
location.postalCode = "10036";
|
||||
location.latitude = 40.760498F;
|
||||
location.longitude = -73.9933F;
|
||||
location.dma_code = 501;
|
||||
location.area_code = 212;
|
||||
location.metro_code = 501;
|
||||
|
||||
return location;
|
||||
}
|
||||
}
|
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* 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.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;
|
||||
|
||||
@Autowired(required = true)
|
||||
private ConfigurationService configurationService;
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
mockSolrServer = new MockSolrServer("statistics");
|
||||
solr = mockSolrServer.getSolrServer();
|
||||
locationService = new MockLookupService();
|
||||
useProxies = configurationService.getBooleanProperty("useProxies");
|
||||
}
|
||||
|
||||
public void destroy() throws Exception {
|
||||
mockSolrServer.destroy();
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user