mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-07 01:54:22 +00:00
Merge branch 'master' into DS-4317_bundles-in-REST
# Conflicts: # dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BitstreamRestRepository.java
This commit is contained in:
@@ -27,8 +27,6 @@
|
||||
<resource.delimiter>@</resource.delimiter>
|
||||
<!-- Define our starting class for our Spring Boot Application -->
|
||||
<start-class>org.dspace.app.rest.Application</start-class>
|
||||
<!-- Library for reading JSON documents: https://github.com/json-path/JsonPath -->
|
||||
<json-path.version>2.4.0</json-path.version>
|
||||
<!-- Library for managing JSON Web Tokens (JWT): https://bitbucket.org/connect2id/nimbus-jose-jwt/wiki/Home -->
|
||||
<nimbus-jose-jwt.version>6.2</nimbus-jose-jwt.version>
|
||||
</properties>
|
||||
@@ -150,6 +148,37 @@
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<configuration>
|
||||
<attachClasses>true</attachClasses>
|
||||
<!-- Filter the web.xml (needed for IDE compatibility/debugging) -->
|
||||
<filteringDeploymentDescriptors>true</filteringDeploymentDescriptors>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>prepare-package</phase>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<!-- Builds a *-tests.jar of all test classes -->
|
||||
<goal>test-jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
@@ -299,7 +328,6 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<version>${spring-boot.version}</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<!-- Temporary exclusion to avoid dependency conflict with version of org.json:json used by dspace-api.
|
||||
@@ -325,7 +353,6 @@
|
||||
<dependency>
|
||||
<groupId>com.jayway.jsonpath</groupId>
|
||||
<artifactId>json-path-assert</artifactId>
|
||||
<version>${json-path.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency> <!-- Keep jmockit before junit -->
|
||||
@@ -418,7 +445,6 @@
|
||||
<dependency>
|
||||
<groupId>org.apache.solr</groupId>
|
||||
<artifactId>solr-cell</artifactId>
|
||||
<version>${solr.client.version}</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
@@ -480,7 +506,6 @@
|
||||
<dependency>
|
||||
<groupId>org.apache.lucene</groupId>
|
||||
<artifactId>lucene-analyzers-icu</artifactId>
|
||||
<version>${solr.client.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
@@ -0,0 +1,112 @@
|
||||
/**
|
||||
* 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;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.UUID;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.dspace.app.rest.exception.UnprocessableEntityException;
|
||||
import org.dspace.app.rest.model.BitstreamRest;
|
||||
import org.dspace.app.rest.model.CollectionRest;
|
||||
import org.dspace.app.rest.model.hateoas.BitstreamResource;
|
||||
import org.dspace.app.rest.repository.CollectionRestRepository;
|
||||
import org.dspace.app.rest.utils.ContextUtil;
|
||||
import org.dspace.app.rest.utils.Utils;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.service.CollectionService;
|
||||
import org.dspace.core.Context;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.rest.webmvc.ControllerUtils;
|
||||
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
|
||||
import org.springframework.hateoas.ResourceSupport;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
/**
|
||||
* This RestController takes care of the creation and deletion of Collection's nested objects
|
||||
* This class will typically receive the UUID of a Collection and it'll perform logic on its nested objects
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/" + CollectionRest.CATEGORY + "/" + CollectionRest.PLURAL_NAME
|
||||
+ CollectionLogoController.REGEX_REQUESTMAPPING_IDENTIFIER_AS_UUID + "/logo")
|
||||
public class CollectionLogoController {
|
||||
|
||||
/**
|
||||
* Regular expression in the request mapping to accept UUID as identifier
|
||||
*/
|
||||
protected static final String REGEX_REQUESTMAPPING_IDENTIFIER_AS_UUID =
|
||||
"/{uuid:[0-9a-fxA-FX]{8}-[0-9a-fxA-FX]{4}-[0-9a-fxA-FX]{4}-[0-9a-fxA-FX]{4}-[0-9a-fxA-FX]{12}}";
|
||||
|
||||
@Autowired
|
||||
protected Utils utils;
|
||||
|
||||
@Autowired
|
||||
private CollectionRestRepository collectionRestRepository;
|
||||
|
||||
@Autowired
|
||||
private CollectionService collectionService;
|
||||
|
||||
/**
|
||||
* This method will add a logo to the collection.
|
||||
*
|
||||
* curl -X POST http://<dspace.restUrl>/api/core/collections/1c11f3f1-ba1f-4f36-908a-3f1ea9a557eb/logo' \
|
||||
* -XPOST -H 'Content-Type: multipart/form-data' \
|
||||
* -H 'Authorization: Bearer eyJhbGciOiJI...' \
|
||||
* -F "file=@Downloads/test.png"
|
||||
*
|
||||
* Example:
|
||||
* <pre>
|
||||
* {@code
|
||||
* curl -X POST http://<dspace.restUrl>/api/core/collections/1c11f3f1-ba1f-4f36-908a-3f1ea9a557eb/logo' \
|
||||
* -XPOST -H 'Content-Type: multipart/form-data' \
|
||||
* -H 'Authorization: Bearer eyJhbGciOiJI...' \
|
||||
* -F "file=@Downloads/test.png"
|
||||
* }
|
||||
* </pre>
|
||||
* @param request The StandardMultipartHttpServletRequest that will contain the logo in its body
|
||||
* @param uuid The UUID of the collection
|
||||
* @return The created bitstream
|
||||
* @throws SQLException If something goes wrong
|
||||
* @throws IOException If something goes wrong
|
||||
* @throws AuthorizeException If the user doesn't have the correct rights
|
||||
*/
|
||||
@PreAuthorize("hasPermission(#uuid, 'COLLECTION', 'WRITE')")
|
||||
@RequestMapping(method = RequestMethod.POST,
|
||||
headers = "content-type=multipart/form-data")
|
||||
public ResponseEntity<ResourceSupport> createLogo(HttpServletRequest request, @PathVariable UUID uuid,
|
||||
@RequestParam(value = "file", required = false) MultipartFile uploadfile)
|
||||
throws SQLException, IOException, AuthorizeException {
|
||||
|
||||
if (uploadfile == null) {
|
||||
throw new UnprocessableEntityException("No file was given");
|
||||
}
|
||||
Context context = ContextUtil.obtainContext(request);
|
||||
|
||||
Collection collection = collectionService.find(context, uuid);
|
||||
if (collection == null) {
|
||||
throw new ResourceNotFoundException(
|
||||
"The given uuid did not resolve to a collection on the server: " + uuid);
|
||||
}
|
||||
BitstreamRest bitstream = collectionRestRepository.setLogo(context, collection, uploadfile);
|
||||
|
||||
BitstreamResource bitstreamResource = new BitstreamResource(bitstream, utils);
|
||||
context.complete();
|
||||
return ControllerUtils.toResponseEntity(HttpStatus.CREATED, null, bitstreamResource);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,114 @@
|
||||
/**
|
||||
* 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;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.dspace.app.rest.exception.UnprocessableEntityException;
|
||||
import org.dspace.app.rest.model.BitstreamRest;
|
||||
import org.dspace.app.rest.model.CommunityRest;
|
||||
import org.dspace.app.rest.model.hateoas.BitstreamResource;
|
||||
import org.dspace.app.rest.repository.CommunityRestRepository;
|
||||
import org.dspace.app.rest.utils.ContextUtil;
|
||||
import org.dspace.app.rest.utils.Utils;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.content.Community;
|
||||
import org.dspace.content.service.CommunityService;
|
||||
import org.dspace.core.Context;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.rest.webmvc.ControllerUtils;
|
||||
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
|
||||
import org.springframework.hateoas.ResourceSupport;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
/**
|
||||
* This RestController takes care of the creation and deletion of Communities' nested objects
|
||||
* This class will typically receive the UUID of a Community and it'll perform logic on its nested objects
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/" + CommunityRest.CATEGORY + "/" + CommunityRest.PLURAL_NAME
|
||||
+ CommunityLogoController.REGEX_REQUESTMAPPING_IDENTIFIER_AS_UUID + "/logo")
|
||||
public class CommunityLogoController {
|
||||
|
||||
/**
|
||||
* Regular expression in the request mapping to accept UUID as identifier
|
||||
*/
|
||||
protected static final String REGEX_REQUESTMAPPING_IDENTIFIER_AS_UUID =
|
||||
"/{uuid:[0-9a-fxA-FX]{8}-[0-9a-fxA-FX]{4}-[0-9a-fxA-FX]{4}-[0-9a-fxA-FX]{4}-[0-9a-fxA-FX]{12}}";
|
||||
|
||||
@Autowired
|
||||
protected Utils utils;
|
||||
|
||||
@Autowired
|
||||
private CommunityRestRepository communityRestRepository;
|
||||
|
||||
@Autowired
|
||||
private CommunityService communityService;
|
||||
|
||||
/**
|
||||
* This method will add a logo to the community.
|
||||
*
|
||||
* curl -X POST http://<dspace.restUrl>/api/core/communities/1c11f3f1-ba1f-4f36-908a-3f1ea9a557eb/logo' \
|
||||
* -XPOST -H 'Content-Type: multipart/form-data' \
|
||||
* -H 'Authorization: Bearer eyJhbGciOiJI...' \
|
||||
* -F "file=@Downloads/test.png"
|
||||
*
|
||||
* Example:
|
||||
* <pre>
|
||||
* {@code
|
||||
* curl -X POST http://<dspace.restUrl>/api/core/communities/1c11f3f1-ba1f-4f36-908a-3f1ea9a557eb/logo' \
|
||||
* -XPOST -H 'Content-Type: multipart/form-data' \
|
||||
* -H 'Authorization: Bearer eyJhbGciOiJI...' \
|
||||
* -F "file=@Downloads/test.png"
|
||||
* }
|
||||
* </pre>
|
||||
* @param request The StandardMultipartHttpServletRequest that will contain the logo in its body
|
||||
* @param uuid The UUID of the community
|
||||
* @return The created bitstream
|
||||
* @throws SQLException If something goes wrong
|
||||
* @throws IOException If something goes wrong
|
||||
* @throws AuthorizeException If the user doesn't have the correct rights
|
||||
*/
|
||||
@PreAuthorize("hasPermission(#uuid, 'COMMUNITY', 'WRITE')")
|
||||
@RequestMapping(method = RequestMethod.POST,
|
||||
headers = "content-type=multipart/form-data")
|
||||
public ResponseEntity<ResourceSupport> createLogo(HttpServletRequest request, @PathVariable UUID uuid,
|
||||
@RequestParam(value = "file", required = false) MultipartFile uploadfile)
|
||||
throws SQLException, IOException, AuthorizeException {
|
||||
|
||||
if (uploadfile == null) {
|
||||
throw new UnprocessableEntityException("No file was given");
|
||||
}
|
||||
|
||||
Context context = ContextUtil.obtainContext(request);
|
||||
|
||||
Community community = communityService.find(context, uuid);
|
||||
if (community == null) {
|
||||
throw new ResourceNotFoundException(
|
||||
"The given uuid did not resolve to a community on the server: " + uuid);
|
||||
}
|
||||
BitstreamRest bitstream = communityRestRepository.setLogo(context, community, uploadfile);
|
||||
|
||||
BitstreamResource bitstreamResource = new BitstreamResource(bitstream, utils);
|
||||
context.complete();
|
||||
return ControllerUtils.toResponseEntity(HttpStatus.CREATED, null, bitstreamResource);
|
||||
}
|
||||
|
||||
}
|
@@ -23,6 +23,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
})
|
||||
public class CollectionRest extends DSpaceObjectRest {
|
||||
public static final String NAME = "collection";
|
||||
public static final String PLURAL_NAME = "collections";
|
||||
public static final String CATEGORY = RestAddressableModel.CORE;
|
||||
public static final String LICENSE = "license";
|
||||
public static final String HARVEST = "harvester";
|
||||
|
@@ -19,6 +19,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
*/
|
||||
public class CommunityRest extends DSpaceObjectRest {
|
||||
public static final String NAME = "community";
|
||||
public static final String PLURAL_NAME = "communities";
|
||||
public static final String CATEGORY = RestAddressableModel.CORE;
|
||||
|
||||
@JsonIgnore
|
||||
|
@@ -18,7 +18,6 @@ import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.dspace.app.rest.converter.BitstreamConverter;
|
||||
import org.dspace.app.rest.exception.DSpaceBadRequestException;
|
||||
import org.dspace.app.rest.exception.UnprocessableEntityException;
|
||||
import org.dspace.app.rest.model.BitstreamRest;
|
||||
import org.dspace.app.rest.model.hateoas.BitstreamResource;
|
||||
import org.dspace.app.rest.model.patch.Patch;
|
||||
@@ -27,8 +26,12 @@ import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.authorize.service.AuthorizeService;
|
||||
import org.dspace.content.Bitstream;
|
||||
import org.dspace.content.Bundle;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.Community;
|
||||
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.core.Context;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
@@ -56,6 +59,12 @@ public class BitstreamRestRepository extends DSpaceObjectRestRepository<Bitstrea
|
||||
@Autowired
|
||||
AuthorizeService authorizeService;
|
||||
|
||||
@Autowired
|
||||
private CollectionService collectionService;
|
||||
|
||||
@Autowired
|
||||
private CommunityService communityService;
|
||||
|
||||
@Autowired
|
||||
public BitstreamRestRepository(BitstreamService dsoService,
|
||||
BitstreamConverter dsoConverter) {
|
||||
@@ -126,10 +135,21 @@ public class BitstreamRestRepository extends DSpaceObjectRestRepository<Bitstrea
|
||||
Bitstream bit = null;
|
||||
try {
|
||||
bit = bs.find(context, id);
|
||||
if (bit.getCommunity() != null | bit.getCollection() != null) {
|
||||
throw new UnprocessableEntityException("The bitstream cannot be deleted it is a logo");
|
||||
if (bit == null) {
|
||||
throw new ResourceNotFoundException("The bitstream with uuid " + id + " could not be found");
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
if (bit.isDeleted()) {
|
||||
throw new ResourceNotFoundException("The bitstream with uuid " + id + " was already deleted");
|
||||
}
|
||||
Community community = bit.getCommunity();
|
||||
if (community != null) {
|
||||
communityService.setLogo(context, community, null);
|
||||
}
|
||||
Collection collection = bit.getCollection();
|
||||
if (collection != null) {
|
||||
collectionService.setLogo(context, collection, null);
|
||||
}
|
||||
} catch (SQLException | IOException e) {
|
||||
throw new RuntimeException(e.getMessage(), e);
|
||||
}
|
||||
try {
|
||||
|
@@ -17,13 +17,16 @@ import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dspace.app.rest.Parameter;
|
||||
import org.dspace.app.rest.SearchRestMethod;
|
||||
import org.dspace.app.rest.converter.BitstreamConverter;
|
||||
import org.dspace.app.rest.converter.CollectionConverter;
|
||||
import org.dspace.app.rest.converter.MetadataConverter;
|
||||
import org.dspace.app.rest.exception.DSpaceBadRequestException;
|
||||
import org.dspace.app.rest.exception.RepositoryMethodNotImplementedException;
|
||||
import org.dspace.app.rest.exception.UnprocessableEntityException;
|
||||
import org.dspace.app.rest.model.BitstreamRest;
|
||||
import org.dspace.app.rest.model.CollectionRest;
|
||||
import org.dspace.app.rest.model.CommunityRest;
|
||||
import org.dspace.app.rest.model.hateoas.CollectionResource;
|
||||
@@ -31,8 +34,10 @@ import org.dspace.app.rest.model.patch.Patch;
|
||||
import org.dspace.app.rest.repository.patch.DSpaceObjectPatch;
|
||||
import org.dspace.app.rest.utils.CollectionRestEqualityUtils;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.content.Bitstream;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.Community;
|
||||
import org.dspace.content.service.BitstreamService;
|
||||
import org.dspace.content.service.CollectionService;
|
||||
import org.dspace.content.service.CommunityService;
|
||||
import org.dspace.core.Constants;
|
||||
@@ -44,6 +49,7 @@ import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
/**
|
||||
* This is the repository responsible to manage Item Rest object
|
||||
@@ -54,7 +60,8 @@ import org.springframework.stereotype.Component;
|
||||
@Component(CollectionRest.CATEGORY + "." + CollectionRest.NAME)
|
||||
public class CollectionRestRepository extends DSpaceObjectRestRepository<Collection, CollectionRest> {
|
||||
|
||||
private final CollectionService cs;
|
||||
private static final Logger log = org.apache.logging.log4j.LogManager
|
||||
.getLogger(CollectionRestRepository.class);
|
||||
|
||||
@Autowired
|
||||
CommunityService communityService;
|
||||
@@ -62,17 +69,24 @@ public class CollectionRestRepository extends DSpaceObjectRestRepository<Collect
|
||||
@Autowired
|
||||
CollectionConverter converter;
|
||||
|
||||
@Autowired
|
||||
BitstreamConverter bitstreamConverter;
|
||||
|
||||
@Autowired
|
||||
MetadataConverter metadataConverter;
|
||||
|
||||
@Autowired
|
||||
CollectionRestEqualityUtils collectionRestEqualityUtils;
|
||||
|
||||
@Autowired
|
||||
private CollectionService cs;
|
||||
|
||||
@Autowired
|
||||
private BitstreamService bitstreamService;
|
||||
|
||||
public CollectionRestRepository(CollectionService dsoService,
|
||||
CollectionConverter dsoConverter) {
|
||||
super(dsoService, dsoConverter, new DSpaceObjectPatch<CollectionRest>() {});
|
||||
this.cs = dsoService;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -253,4 +267,28 @@ public class CollectionRestRepository extends DSpaceObjectRestRepository<Collect
|
||||
throw new RuntimeException("Unable to delete collection because the logo couldn't be deleted", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to install a logo on a Collection which doesn't have a logo
|
||||
* Called by request mappings in CollectionLogoController
|
||||
* @param context
|
||||
* @param collection The collection on which to install the logo
|
||||
* @param uploadfile The new logo
|
||||
* @return The created bitstream containing the new logo
|
||||
* @throws IOException
|
||||
* @throws AuthorizeException
|
||||
* @throws SQLException
|
||||
*/
|
||||
public BitstreamRest setLogo(Context context, Collection collection, MultipartFile uploadfile)
|
||||
throws IOException, AuthorizeException, SQLException {
|
||||
|
||||
if (collection.getLogo() != null) {
|
||||
throw new UnprocessableEntityException(
|
||||
"The collection with the given uuid already has a logo: " + collection.getID());
|
||||
}
|
||||
Bitstream bitstream = cs.setLogo(context, collection, uploadfile.getInputStream());
|
||||
cs.update(context, collection);
|
||||
bitstreamService.update(context, bitstream);
|
||||
return bitstreamConverter.fromModel(context.reloadEntity(bitstream));
|
||||
}
|
||||
}
|
||||
|
@@ -17,20 +17,25 @@ import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dspace.app.rest.Parameter;
|
||||
import org.dspace.app.rest.SearchRestMethod;
|
||||
import org.dspace.app.rest.converter.BitstreamConverter;
|
||||
import org.dspace.app.rest.converter.CommunityConverter;
|
||||
import org.dspace.app.rest.converter.MetadataConverter;
|
||||
import org.dspace.app.rest.exception.DSpaceBadRequestException;
|
||||
import org.dspace.app.rest.exception.RepositoryMethodNotImplementedException;
|
||||
import org.dspace.app.rest.exception.UnprocessableEntityException;
|
||||
import org.dspace.app.rest.model.BitstreamRest;
|
||||
import org.dspace.app.rest.model.CommunityRest;
|
||||
import org.dspace.app.rest.model.hateoas.CommunityResource;
|
||||
import org.dspace.app.rest.model.patch.Patch;
|
||||
import org.dspace.app.rest.repository.patch.DSpaceObjectPatch;
|
||||
import org.dspace.app.rest.utils.CommunityRestEqualityUtils;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.content.Bitstream;
|
||||
import org.dspace.content.Community;
|
||||
import org.dspace.content.service.BitstreamService;
|
||||
import org.dspace.content.service.CommunityService;
|
||||
import org.dspace.core.Context;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -40,6 +45,7 @@ import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
/**
|
||||
* This is the repository responsible to manage Community Rest object
|
||||
@@ -50,21 +56,30 @@ import org.springframework.stereotype.Component;
|
||||
@Component(CommunityRest.CATEGORY + "." + CommunityRest.NAME)
|
||||
public class CommunityRestRepository extends DSpaceObjectRestRepository<Community, CommunityRest> {
|
||||
|
||||
private final CommunityService cs;
|
||||
private static final Logger log = org.apache.logging.log4j.LogManager
|
||||
.getLogger(CommunityRestRepository.class);
|
||||
|
||||
@Autowired
|
||||
CommunityConverter converter;
|
||||
|
||||
@Autowired
|
||||
BitstreamConverter bitstreamConverter;
|
||||
|
||||
@Autowired
|
||||
MetadataConverter metadataConverter;
|
||||
|
||||
@Autowired
|
||||
CommunityRestEqualityUtils communityRestEqualityUtils;
|
||||
|
||||
@Autowired
|
||||
private CommunityService cs;
|
||||
|
||||
@Autowired
|
||||
private BitstreamService bitstreamService;
|
||||
|
||||
public CommunityRestRepository(CommunityService dsoService,
|
||||
CommunityConverter dsoConverter) {
|
||||
super(dsoService, dsoConverter, new DSpaceObjectPatch<CommunityRest>() {});
|
||||
this.cs = dsoService;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -260,4 +275,28 @@ public class CommunityRestRepository extends DSpaceObjectRestRepository<Communit
|
||||
throw new RuntimeException("Unable to delete community because the logo couldn't be deleted", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to install a logo on a Community which doesn't have a logo
|
||||
* Called by request mappings in CommunityLogoController
|
||||
* @param context
|
||||
* @param community The community on which to install the logo
|
||||
* @param uploadfile The new logo
|
||||
* @return The created bitstream containing the new logo
|
||||
* @throws IOException
|
||||
* @throws AuthorizeException
|
||||
* @throws SQLException
|
||||
*/
|
||||
public BitstreamRest setLogo(Context context, Community community, MultipartFile uploadfile)
|
||||
throws IOException, AuthorizeException, SQLException {
|
||||
|
||||
if (community.getLogo() != null) {
|
||||
throw new UnprocessableEntityException(
|
||||
"The community with the given uuid already has a logo: " + community.getID());
|
||||
}
|
||||
Bitstream bitstream = cs.setLogo(context, community, uploadfile.getInputStream());
|
||||
cs.update(context, community);
|
||||
bitstreamService.update(context, bitstream);
|
||||
return bitstreamConverter.fromModel(context.reloadEntity(bitstream));
|
||||
}
|
||||
}
|
||||
|
@@ -474,7 +474,7 @@ public class BitstreamRestRepositoryIT extends AbstractControllerIntegrationTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteUnauthorized() throws Exception {
|
||||
public void deleteForbidden() throws Exception {
|
||||
|
||||
//We turn off the authorization system in order to create the structure as defined below
|
||||
context.turnOffAuthorisationSystem();
|
||||
@@ -521,7 +521,7 @@ public class BitstreamRestRepositoryIT extends AbstractControllerIntegrationTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteForbidden() throws Exception {
|
||||
public void deleteUnauthorized() throws Exception {
|
||||
|
||||
//We turn off the authorization system in order to create the structure as defined below
|
||||
context.turnOffAuthorisationSystem();
|
||||
@@ -581,13 +581,72 @@ public class BitstreamRestRepositoryIT extends AbstractControllerIntegrationTest
|
||||
|
||||
String token = getAuthToken(admin.getEmail(), password);
|
||||
|
||||
// 422 error when trying to DELETE parentCommunity logo
|
||||
// trying to DELETE parentCommunity logo should work
|
||||
getClient(token).perform(delete("/api/core/bitstreams/" + parentCommunity.getLogo().getID()))
|
||||
.andExpect(status().is(422));
|
||||
.andExpect(status().is(204));
|
||||
|
||||
// 422 error when trying to DELETE collection logo
|
||||
// trying to DELETE collection logo should work
|
||||
getClient(token).perform(delete("/api/core/bitstreams/" + col.getLogo().getID()))
|
||||
.andExpect(status().is(422));
|
||||
.andExpect(status().is(204));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteMissing() throws Exception {
|
||||
String token = getAuthToken(admin.getEmail(), password);
|
||||
|
||||
// Delete
|
||||
getClient(token).perform(delete("/api/core/bitstreams/1c11f3f1-ba1f-4f36-908a-3f1ea9a557eb"))
|
||||
.andExpect(status().isNotFound());
|
||||
|
||||
// Verify 404 after failed delete
|
||||
getClient(token).perform(delete("/api/core/bitstreams/1c11f3f1-ba1f-4f36-908a-3f1ea9a557eb"))
|
||||
.andExpect(status().isNotFound());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteDeleted() throws Exception {
|
||||
//We turn off the authorization system in order to create the structure as defined below
|
||||
context.turnOffAuthorisationSystem();
|
||||
|
||||
//** GIVEN **
|
||||
//1. A community-collection structure with one parent community with sub-community and one collection.
|
||||
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||
.withName("Parent Community")
|
||||
.build();
|
||||
Community child1 = CommunityBuilder.createSubCommunity(context, parentCommunity)
|
||||
.withName("Sub Community")
|
||||
.build();
|
||||
Collection col1 = CollectionBuilder.createCollection(context, child1).withName("Collection 1").build();
|
||||
|
||||
//2. One public items that is readable by Anonymous
|
||||
Item publicItem1 = ItemBuilder.createItem(context, col1)
|
||||
.withTitle("Test")
|
||||
.withIssueDate("2010-10-17")
|
||||
.withAuthor("Smith, Donald")
|
||||
.withSubject("ExtraEntry")
|
||||
.build();
|
||||
|
||||
String bitstreamContent = "ThisIsSomeDummyText";
|
||||
//Add a bitstream to an item
|
||||
Bitstream bitstream = null;
|
||||
try (InputStream is = IOUtils.toInputStream(bitstreamContent, CharEncoding.UTF_8)) {
|
||||
bitstream = BitstreamBuilder.
|
||||
createBitstream(context, publicItem1, is)
|
||||
.withName("Bitstream")
|
||||
.withDescription("Description")
|
||||
.withMimeType("text/plain")
|
||||
.build();
|
||||
}
|
||||
|
||||
String token = getAuthToken(admin.getEmail(), password);
|
||||
|
||||
// Delete
|
||||
getClient(token).perform(delete("/api/core/bitstreams/" + bitstream.getID()))
|
||||
.andExpect(status().is(204));
|
||||
|
||||
// Verify 404 when trying to delete a non-existing bitstream
|
||||
getClient(token).perform(delete("/api/core/bitstreams/" + bitstream.getID()))
|
||||
.andExpect(status().isNotFound());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@@ -0,0 +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;
|
||||
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.dspace.app.rest.builder.CollectionBuilder;
|
||||
import org.dspace.app.rest.builder.CommunityBuilder;
|
||||
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
|
||||
import org.dspace.content.Collection;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||
|
||||
public class CollectionLogoControllerIT extends AbstractControllerIntegrationTest {
|
||||
|
||||
private ObjectMapper mapper;
|
||||
private String adminAuthToken;
|
||||
private String bitstreamContent;
|
||||
private MockMultipartFile bitstreamFile;
|
||||
private Collection childCollection;
|
||||
|
||||
@Before
|
||||
public void createStructure() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||
.withName("Parent Community")
|
||||
.build();
|
||||
childCollection = CollectionBuilder.createCollection(context, parentCommunity)
|
||||
.withName("Collection 1").build();
|
||||
adminAuthToken = getAuthToken(admin.getEmail(), password);
|
||||
bitstreamContent = "Hello, World!";
|
||||
bitstreamFile = new MockMultipartFile("file",
|
||||
"hello.txt", MediaType.TEXT_PLAIN_VALUE,
|
||||
bitstreamContent.getBytes());
|
||||
mapper = new ObjectMapper();
|
||||
}
|
||||
|
||||
private String createLogoInternal() throws Exception {
|
||||
MvcResult mvcPostResult = getClient(adminAuthToken).perform(
|
||||
MockMvcRequestBuilders.fileUpload(getLogoUrlTemplate(childCollection.getID().toString()))
|
||||
.file(bitstreamFile))
|
||||
.andExpect(status().isCreated())
|
||||
.andReturn();
|
||||
|
||||
String postContent = mvcPostResult.getResponse().getContentAsString();
|
||||
Map<String, Object> mapPostResult = mapper.readValue(postContent, Map.class);
|
||||
return String.valueOf(mapPostResult.get("uuid"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createLogoNotLoggedIn() throws Exception {
|
||||
getClient().perform(
|
||||
MockMvcRequestBuilders.fileUpload(getLogoUrlTemplate(childCollection.getID().toString()))
|
||||
.file(bitstreamFile))
|
||||
.andExpect(status().isUnauthorized());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createLogo() throws Exception {
|
||||
String postUuid = createLogoInternal();
|
||||
assert (postUuid != null);
|
||||
|
||||
MvcResult mvcGetResult = getClient().perform(get(getLogoUrlTemplate(childCollection.getID().toString())))
|
||||
.andExpect(status().is2xxSuccessful())
|
||||
.andReturn();
|
||||
|
||||
String getContent = mvcGetResult.getResponse().getContentAsString();
|
||||
Map<String, Object> mapGetResult = mapper.readValue(getContent, Map.class);
|
||||
String getUuid = String.valueOf(mapGetResult.get("uuid"));
|
||||
assert (postUuid.equals(getUuid));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createLogoNoRights() throws Exception {
|
||||
String userToken = getAuthToken(eperson.getEmail(), password);
|
||||
getClient(userToken).perform(
|
||||
MockMvcRequestBuilders.fileUpload(getLogoUrlTemplate(childCollection.getID().toString()))
|
||||
.file(bitstreamFile))
|
||||
.andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createDuplicateLogo() throws Exception {
|
||||
getClient(adminAuthToken).perform(
|
||||
MockMvcRequestBuilders.fileUpload(getLogoUrlTemplate(childCollection.getID().toString()))
|
||||
.file(bitstreamFile))
|
||||
.andExpect(status().isCreated());
|
||||
|
||||
getClient(adminAuthToken).perform(
|
||||
MockMvcRequestBuilders.fileUpload(getLogoUrlTemplate(childCollection.getID().toString()))
|
||||
.file(bitstreamFile))
|
||||
.andExpect(status().isUnprocessableEntity());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createLogoForNonexisting() throws Exception {
|
||||
getClient(adminAuthToken).perform(
|
||||
MockMvcRequestBuilders.fileUpload(getLogoUrlTemplate("16a4b65b-3b3f-4ef5-8058-ef6f5a653ef9"))
|
||||
.file(bitstreamFile))
|
||||
.andExpect(status().isNotFound());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteLogoNotLoggedIn() throws Exception {
|
||||
String postUuid = createLogoInternal();
|
||||
|
||||
getClient().perform(delete(getBitstreamUrlTemplate(postUuid)))
|
||||
.andExpect(status().isUnauthorized());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteLogo() throws Exception {
|
||||
String postUuid = createLogoInternal();
|
||||
|
||||
getClient(adminAuthToken).perform(delete(getBitstreamUrlTemplate(postUuid)))
|
||||
.andExpect(status().isNoContent());
|
||||
|
||||
getClient(adminAuthToken).perform(get(getLogoUrlTemplate(childCollection.getID().toString())))
|
||||
.andExpect(status().isNoContent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteLogoNoRights() throws Exception {
|
||||
String postUuid = createLogoInternal();
|
||||
|
||||
String userToken = getAuthToken(eperson.getEmail(), password);
|
||||
getClient(userToken).perform(delete(getBitstreamUrlTemplate(postUuid)))
|
||||
.andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
private String getLogoUrlTemplate(String uuid) {
|
||||
return "/api/core/collections/" + uuid + "/logo";
|
||||
}
|
||||
|
||||
private String getBitstreamUrlTemplate(String uuid) {
|
||||
return "/api/core/bitstreams/" + uuid;
|
||||
}
|
||||
}
|
@@ -0,0 +1,147 @@
|
||||
/**
|
||||
* 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;
|
||||
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.dspace.app.rest.builder.CommunityBuilder;
|
||||
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||
|
||||
public class CommunityLogoControllerIT extends AbstractControllerIntegrationTest {
|
||||
|
||||
private ObjectMapper mapper;
|
||||
private String adminAuthToken;
|
||||
private String bitstreamContent;
|
||||
private MockMultipartFile bitstreamFile;
|
||||
|
||||
@Before
|
||||
public void createStructure() throws Exception {
|
||||
context.turnOffAuthorisationSystem();
|
||||
parentCommunity = CommunityBuilder.createCommunity(context)
|
||||
.withName("Parent Community")
|
||||
.build();
|
||||
adminAuthToken = getAuthToken(admin.getEmail(), password);
|
||||
bitstreamContent = "Hello, World!";
|
||||
bitstreamFile = new MockMultipartFile("file",
|
||||
"hello.txt", MediaType.TEXT_PLAIN_VALUE,
|
||||
bitstreamContent.getBytes());
|
||||
mapper = new ObjectMapper();
|
||||
}
|
||||
|
||||
private String createLogoInternal() throws Exception {
|
||||
MvcResult mvcPostResult = getClient(adminAuthToken).perform(
|
||||
MockMvcRequestBuilders.fileUpload(getLogoUrlTemplate(parentCommunity.getID().toString()))
|
||||
.file(bitstreamFile))
|
||||
.andExpect(status().isCreated())
|
||||
.andReturn();
|
||||
|
||||
String postContent = mvcPostResult.getResponse().getContentAsString();
|
||||
Map<String, Object> mapPostResult = mapper.readValue(postContent, Map.class);
|
||||
return String.valueOf(mapPostResult.get("uuid"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createLogoNotLoggedIn() throws Exception {
|
||||
getClient().perform(
|
||||
MockMvcRequestBuilders.fileUpload(getLogoUrlTemplate(parentCommunity.getID().toString()))
|
||||
.file(bitstreamFile))
|
||||
.andExpect(status().isUnauthorized());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createLogo() throws Exception {
|
||||
String postUuid = createLogoInternal();
|
||||
assert (postUuid != null);
|
||||
|
||||
MvcResult mvcGetResult = getClient().perform(get(getLogoUrlTemplate(parentCommunity.getID().toString())))
|
||||
.andExpect(status().is2xxSuccessful())
|
||||
.andReturn();
|
||||
|
||||
String getContent = mvcGetResult.getResponse().getContentAsString();
|
||||
Map<String, Object> mapGetResult = mapper.readValue(getContent, Map.class);
|
||||
String getUuid = String.valueOf(mapGetResult.get("uuid"));
|
||||
assert (postUuid.equals(getUuid));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createLogoNoRights() throws Exception {
|
||||
String userToken = getAuthToken(eperson.getEmail(), password);
|
||||
getClient(userToken).perform(
|
||||
MockMvcRequestBuilders.fileUpload(getLogoUrlTemplate(parentCommunity.getID().toString()))
|
||||
.file(bitstreamFile))
|
||||
.andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createDuplicateLogo() throws Exception {
|
||||
getClient(adminAuthToken).perform(
|
||||
MockMvcRequestBuilders.fileUpload(getLogoUrlTemplate(parentCommunity.getID().toString()))
|
||||
.file(bitstreamFile))
|
||||
.andExpect(status().isCreated());
|
||||
|
||||
getClient(adminAuthToken).perform(
|
||||
MockMvcRequestBuilders.fileUpload(getLogoUrlTemplate(parentCommunity.getID().toString()))
|
||||
.file(bitstreamFile))
|
||||
.andExpect(status().isUnprocessableEntity());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createLogoForNonexisting() throws Exception {
|
||||
getClient(adminAuthToken).perform(
|
||||
MockMvcRequestBuilders.fileUpload(getLogoUrlTemplate("16a4b65b-3b3f-4ef5-8058-ef6f5a653ef9"))
|
||||
.file(bitstreamFile))
|
||||
.andExpect(status().isNotFound());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteLogoNotLoggedIn() throws Exception {
|
||||
String postUuid = createLogoInternal();
|
||||
|
||||
getClient().perform(delete(getBitstreamUrlTemplate(postUuid)))
|
||||
.andExpect(status().isUnauthorized());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteLogo() throws Exception {
|
||||
String postUuid = createLogoInternal();
|
||||
|
||||
getClient(adminAuthToken).perform(delete(getBitstreamUrlTemplate(postUuid)))
|
||||
.andExpect(status().isNoContent());
|
||||
|
||||
getClient(adminAuthToken).perform(get(getLogoUrlTemplate(parentCommunity.getID().toString())))
|
||||
.andExpect(status().isNoContent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteLogoNoRights() throws Exception {
|
||||
String postUuid = createLogoInternal();
|
||||
|
||||
String userToken = getAuthToken(eperson.getEmail(), password);
|
||||
getClient(userToken).perform(delete(getBitstreamUrlTemplate(postUuid)))
|
||||
.andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
private String getLogoUrlTemplate(String uuid) {
|
||||
return "/api/core/communities/" + uuid + "/logo";
|
||||
}
|
||||
|
||||
private String getBitstreamUrlTemplate(String uuid) {
|
||||
return "/api/core/bitstreams/" + uuid;
|
||||
}
|
||||
}
|
@@ -42,6 +42,130 @@
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</profile>
|
||||
<!-- If Unit Testing is enabled, then setup the Unit Test Environment.
|
||||
See also the 'skiptests' profile in Parent POM. -->
|
||||
<profile>
|
||||
<id>test-environment</id>
|
||||
<activation>
|
||||
<activeByDefault>false</activeByDefault>
|
||||
<property>
|
||||
<name>maven.test.skip</name>
|
||||
<value>false</value>
|
||||
</property>
|
||||
</activation>
|
||||
<build>
|
||||
<plugins>
|
||||
<!-- Unit/Integration Testing setup: This plugin unzips the
|
||||
'testEnvironment.zip' file (created by dspace-parent POM), into
|
||||
the 'target/testing/' folder, to essentially create a test
|
||||
install of DSpace, against which Tests can be run. -->
|
||||
<plugin>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<version>2.8</version>
|
||||
<configuration>
|
||||
<outputDirectory>${project.build.directory}/testing</outputDirectory>
|
||||
<artifactItems>
|
||||
<artifactItem>
|
||||
<groupId>org.dspace</groupId>
|
||||
<artifactId>dspace-parent</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>zip</type>
|
||||
<classifier>testEnvironment</classifier>
|
||||
</artifactItem>
|
||||
</artifactItems>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>setupTestEnvironment</id>
|
||||
<phase>generate-test-resources</phase>
|
||||
<goals>
|
||||
<goal>unpack</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>setupIntegrationTestEnvironment</id>
|
||||
<phase>pre-integration-test</phase>
|
||||
<goals>
|
||||
<goal>unpack</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<!-- This plugin allows us to run a Groovy script in our Maven POM
|
||||
(see: http://gmaven.codehaus.org/Executing+Groovy+Code )
|
||||
We are generating a OS-agnostic version (agnostic.build.dir) of
|
||||
the ${project.build.directory} property (full path of target dir).
|
||||
This is needed by the FileWeaver & Surefire plugins (see below)
|
||||
to initialize the Unit Test environment's dspace.cfg file.
|
||||
Otherwise, the Unit Test Framework will not work on Windows OS.
|
||||
This Groovy code was mostly borrowed from:
|
||||
http://stackoverflow.com/questions/3872355/how-to-convert-file-separator-in-maven
|
||||
-->
|
||||
<plugin>
|
||||
<groupId>org.codehaus.gmaven</groupId>
|
||||
<artifactId>groovy-maven-plugin</artifactId>
|
||||
<version>2.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>setproperty</id>
|
||||
<phase>generate-test-resources
|
||||
</phase> <!-- XXX I think this should be 'initialize' - MHW -->
|
||||
<goals>
|
||||
<goal>execute</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<source>
|
||||
project.properties['agnostic.build.dir'] = project.build.directory.replace(File.separator, '/');
|
||||
println("Initializing Maven property 'agnostic.build.dir' to: " + project.properties['agnostic.build.dir']);
|
||||
</source>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<!-- Run Unit Testing! This plugin just kicks off the tests (when enabled). -->
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<systemPropertyVariables>
|
||||
<!-- Specify the dspace.dir to use for test environment -->
|
||||
<!-- This system property is loaded by AbstractDSpaceTest to initialize the test environment -->
|
||||
<dspace.dir>${agnostic.build.dir}/testing/dspace/</dspace.dir>
|
||||
<!-- Turn off any DSpace logging -->
|
||||
<dspace.log.init.disable>true</dspace.log.init.disable>
|
||||
<solr.install.dir>${agnostic.build.dir}/testing/dspace/solr/</solr.install.dir>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!-- Run Integration Testing! This plugin just kicks off the tests (when enabled). -->
|
||||
<plugin>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<configuration>
|
||||
<systemPropertyVariables>
|
||||
<!-- Specify the dspace.dir to use for test environment -->
|
||||
<dspace.dir>${agnostic.build.dir}/testing/dspace/</dspace.dir>
|
||||
<!-- Turn off any DSpace logging -->
|
||||
<dspace.log.init.disable>true</dspace.log.init.disable>
|
||||
<solr.install.dir>${agnostic.build.dir}/testing/dspace/solr/</solr.install.dir>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<dependencies>
|
||||
<!-- When running tests, also include test classes from dspace-api
|
||||
(this test-jar is only built when tests are enabled). -->
|
||||
<dependency>
|
||||
<groupId>org.dspace</groupId>
|
||||
<artifactId>dspace-api</artifactId>
|
||||
<version>7.0-SNAPSHOT</version>
|
||||
<type>test-jar</type>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
<!--
|
||||
@@ -73,6 +197,33 @@
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- Keep jmockit before junit -->
|
||||
<dependency>
|
||||
<groupId>org.jmockit</groupId>
|
||||
<artifactId>jmockit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
<artifactId>hamcrest-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
@@ -8,9 +8,7 @@
|
||||
package org.dspace.example;
|
||||
|
||||
/**
|
||||
* TODO: Add Description
|
||||
*
|
||||
* @author mdiggory @ atmire.com
|
||||
* This interface serves as an example of how & where to add local customizations to the DSpace REST API.
|
||||
*/
|
||||
public interface Example {
|
||||
}
|
||||
|
@@ -10,9 +10,7 @@ package org.dspace.example.impl;
|
||||
import org.dspace.example.Example;
|
||||
|
||||
/**
|
||||
* TODO: Add Description
|
||||
*
|
||||
* @author mdiggory @ atmire.com
|
||||
* This class serves as an example of how & where to add local customizations to the DSpace REST API.
|
||||
*/
|
||||
public class ExampleImpl implements Example {
|
||||
}
|
||||
|
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* 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.example;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.dspace.AbstractIntegrationTest;
|
||||
import org.dspace.example.impl.ExampleImpl;
|
||||
import org.dspace.utils.DSpace;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* This IT serves as an an example of how & where to add integration tests for local customizations to the DSpace API.
|
||||
* See {@link Example} and {@link ExampleImpl} for the class of which the functionality is tested.
|
||||
*/
|
||||
public class ExampleIT extends AbstractIntegrationTest {
|
||||
|
||||
@Test
|
||||
public void testExampleImpl() {
|
||||
assertTrue(new DSpace().getSingletonService(Example.class) instanceof ExampleImpl);
|
||||
}
|
||||
}
|
@@ -77,6 +77,128 @@ just adding new jar in the classloader</description>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<!-- If Unit Testing is enabled, then setup the Unit Test Environment.
|
||||
See also the 'skiptests' profile in Parent POM. -->
|
||||
<profile>
|
||||
<id>test-environment</id>
|
||||
<activation>
|
||||
<activeByDefault>false</activeByDefault>
|
||||
<property>
|
||||
<name>maven.test.skip</name>
|
||||
<value>false</value>
|
||||
</property>
|
||||
</activation>
|
||||
<build>
|
||||
<plugins>
|
||||
<!-- Unit/Integration Testing setup: This plugin unzips the
|
||||
'testEnvironment.zip' file (created by dspace-parent POM), into
|
||||
the 'target/testing/' folder, to essentially create a test
|
||||
install of DSpace, against which Tests can be run. -->
|
||||
<plugin>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<configuration>
|
||||
<outputDirectory>${project.build.directory}/testing</outputDirectory>
|
||||
<artifactItems>
|
||||
<artifactItem>
|
||||
<groupId>org.dspace</groupId>
|
||||
<artifactId>dspace-parent</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>zip</type>
|
||||
<classifier>testEnvironment</classifier>
|
||||
</artifactItem>
|
||||
</artifactItems>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>setupTestEnvironment</id>
|
||||
<phase>generate-test-resources</phase>
|
||||
<goals>
|
||||
<goal>unpack</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>setupIntegrationTestEnvironment</id>
|
||||
<phase>pre-integration-test</phase>
|
||||
<goals>
|
||||
<goal>unpack</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<!-- This plugin allows us to run a Groovy script in our Maven POM
|
||||
(see: http://gmaven.codehaus.org/Executing+Groovy+Code )
|
||||
We are generating a OS-agnostic version (agnostic.build.dir) of
|
||||
the ${project.build.directory} property (full path of target dir).
|
||||
This is needed by the FileWeaver & Surefire plugins (see below)
|
||||
to initialize the Unit Test environment's dspace.cfg file.
|
||||
Otherwise, the Unit Test Framework will not work on Windows OS.
|
||||
This Groovy code was mostly borrowed from:
|
||||
http://stackoverflow.com/questions/3872355/how-to-convert-file-separator-in-maven
|
||||
-->
|
||||
<plugin>
|
||||
<groupId>org.codehaus.gmaven</groupId>
|
||||
<artifactId>groovy-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>setproperty</id>
|
||||
<phase>generate-test-resources
|
||||
</phase> <!-- XXX I think this should be 'initialize' - MHW -->
|
||||
<goals>
|
||||
<goal>execute</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<source>
|
||||
project.properties['agnostic.build.dir'] = project.build.directory.replace(File.separator, '/');
|
||||
println("Initializing Maven property 'agnostic.build.dir' to: " + project.properties['agnostic.build.dir']);
|
||||
</source>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<!-- Run Unit Testing! This plugin just kicks off the tests (when enabled). -->
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<systemPropertyVariables>
|
||||
<!-- Specify the dspace.dir to use for test environment -->
|
||||
<!-- This system property is loaded by AbstractDSpaceTest to initialize the test environment -->
|
||||
<dspace.dir>${agnostic.build.dir}/testing/dspace/</dspace.dir>
|
||||
<!-- Turn off any DSpace logging -->
|
||||
<dspace.log.init.disable>true</dspace.log.init.disable>
|
||||
<solr.install.dir>${agnostic.build.dir}/testing/dspace/solr/</solr.install.dir>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!-- Run Integration Testing! This plugin just kicks off the tests (when enabled). -->
|
||||
<plugin>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<configuration>
|
||||
<systemPropertyVariables>
|
||||
<!-- Specify the dspace.dir to use for test environment -->
|
||||
<dspace.dir>${agnostic.build.dir}/testing/dspace/</dspace.dir>
|
||||
<!-- Turn off any DSpace logging -->
|
||||
<dspace.log.init.disable>true</dspace.log.init.disable>
|
||||
<solr.install.dir>${agnostic.build.dir}/testing/dspace/solr/</solr.install.dir>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<dependencies>
|
||||
<!-- When running tests, also include test classes from dspace-server-webapp
|
||||
(this test-jar is only built when tests are enabled). -->
|
||||
<dependency>
|
||||
<groupId>org.dspace</groupId>
|
||||
<artifactId>dspace-server-webapp</artifactId>
|
||||
<version>7.0-SNAPSHOT</version>
|
||||
<type>test-jar</type>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>oracle-support</id>
|
||||
<activation>
|
||||
@@ -95,15 +217,85 @@ just adding new jar in the classloader</description>
|
||||
</profiles>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.dspace.modules</groupId>
|
||||
<artifactId>additions</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.dspace</groupId>
|
||||
<artifactId>dspace-server-webapp</artifactId>
|
||||
<classifier>classes</classifier>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.dspace</groupId>
|
||||
<artifactId>dspace-server-webapp</artifactId>
|
||||
<type>war</type>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-tomcat</artifactId>
|
||||
<scope>provided</scope>
|
||||
<version>${spring-boot.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<exclusions>
|
||||
<!-- Temporary exclusion to avoid dependency conflict with version of org.json:json used by dspace-api.
|
||||
NOTE: THIS CAN BE REMOVED ONCE WE UPGRADE TO SPRING-BOOT v1.5 (or above), see DS-3802
|
||||
As of Spring-Boot 1.5, org.json:json is no longer used by spring-boot-starter-test -->
|
||||
<exclusion>
|
||||
<groupId>org.json</groupId>
|
||||
<artifactId>json</artifactId>
|
||||
</exclusion>
|
||||
<!-- More recent version used for testing below -->
|
||||
<exclusion>
|
||||
<groupId>com.jayway.jsonpath</groupId>
|
||||
<artifactId>json-path</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.jayway.jsonpath</groupId>
|
||||
<artifactId>json-path-assert</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jmockit</groupId>
|
||||
<artifactId>jmockit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.solr</groupId>
|
||||
<artifactId>solr-cell</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!-- Reminder: Keep icu4j (in Parent POM) synced with version used by lucene-analyzers-icu below,
|
||||
otherwise ICUFoldingFilterFactory may throw errors in tests. -->
|
||||
<dependency>
|
||||
<groupId>org.apache.lucene</groupId>
|
||||
<artifactId>lucene-analyzers-icu</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* 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.example;
|
||||
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* This Controller serves as an example of how & where to add local customizations to the DSpace REST API.
|
||||
* See {@link ExampleControllerIT} for the integration tests for this controller.
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("example")
|
||||
public class ExampleController {
|
||||
|
||||
@RequestMapping("")
|
||||
public String test() {
|
||||
return "Hello world";
|
||||
}
|
||||
}
|
@@ -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.app.rest.example;
|
||||
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* This IT serves as an example of how & where to add integration tests for local customizations to the DSpace REST API.
|
||||
* See {@link ExampleController} for the Controller of which the functionality is tested.
|
||||
*/
|
||||
public class ExampleControllerIT extends AbstractControllerIntegrationTest {
|
||||
|
||||
@Test
|
||||
public void testTest() throws Exception {
|
||||
|
||||
getClient()
|
||||
.perform(get("/example"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("Hello world"));
|
||||
}
|
||||
}
|
79
pom.xml
79
pom.xml
@@ -42,6 +42,9 @@
|
||||
<solr.client.version>7.3.1</solr.client.version>
|
||||
<spring.version>4.3.24.RELEASE</spring.version>
|
||||
<spring-boot.version>1.4.4.RELEASE</spring-boot.version>
|
||||
<!-- Library for reading JSON documents: https://github.com/json-path/JsonPath -->
|
||||
<json-path.version>2.4.0</json-path.version>
|
||||
|
||||
<!-- 'root.basedir' is the path to the root [dspace-src] dir. It must be redefined by each child POM,
|
||||
as it is used to reference the LICENSE_HEADER and *.properties file(s) in that directory. -->
|
||||
<root.basedir>${basedir}</root.basedir>
|
||||
@@ -978,24 +981,25 @@
|
||||
<version>7.0-SNAPSHOT</version>
|
||||
<type>war</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.dspace</groupId>
|
||||
<artifactId>dspace-server-webapp</artifactId>
|
||||
<version>7.0-SNAPSHOT</version>
|
||||
<type>jar</type>
|
||||
<classifier>classes</classifier>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.dspace</groupId>
|
||||
<artifactId>dspace-server-webapp</artifactId>
|
||||
<version>7.0-SNAPSHOT</version>
|
||||
<type>war</type>
|
||||
</dependency>
|
||||
<!-- DSpace Localization Packages -->
|
||||
<!-- DSpace API Localization Packages -->
|
||||
<dependency>
|
||||
<groupId>org.dspace</groupId>
|
||||
<artifactId>dspace-api-lang</artifactId>
|
||||
<version>[6.0.0,7.0.0)</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.dspace</groupId>
|
||||
<artifactId>dspace-xmlui-lang</artifactId>
|
||||
<version>[6.0.0,7.0.0)</version>
|
||||
<type>war</type>
|
||||
</dependency>
|
||||
|
||||
<!-- DSpace third Party Dependencies -->
|
||||
|
||||
@@ -1105,6 +1109,67 @@
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-expression</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<version>${spring-boot.version}</version>
|
||||
<exclusions>
|
||||
<!-- Temporary exclusion to avoid dependency conflict with version of org.json:json used by dspace-api.
|
||||
NOTE: THIS CAN BE REMOVED ONCE WE UPGRADE TO SPRING-BOOT v1.5 (or above), see DS-3802
|
||||
As of Spring-Boot 1.5, org.json:json is no longer used by spring-boot-starter-test -->
|
||||
<exclusion>
|
||||
<groupId>org.json</groupId>
|
||||
<artifactId>json</artifactId>
|
||||
</exclusion>
|
||||
<!-- More recent version used for testing below -->
|
||||
<exclusion>
|
||||
<groupId>com.jayway.jsonpath</groupId>
|
||||
<artifactId>json-path</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.solr</groupId>
|
||||
<artifactId>solr-cell</artifactId>
|
||||
<version>${solr.client.version}</version>
|
||||
</dependency>
|
||||
<!-- Reminder: Keep icu4j (in Parent POM) synced with version used by lucene-analyzers-icu below,
|
||||
otherwise ICUFoldingFilterFactory may throw errors in tests. -->
|
||||
<dependency>
|
||||
<groupId>org.apache.lucene</groupId>
|
||||
<artifactId>lucene-analyzers-icu</artifactId>
|
||||
<version>${solr.client.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.jayway.jsonpath</groupId>
|
||||
<artifactId>json-path-assert</artifactId>
|
||||
<version>${json-path.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.jayway.jsonpath</groupId>
|
||||
<artifactId>json-path</artifactId>
|
||||
<version>${json-path.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.ant</groupId>
|
||||
<artifactId>ant</artifactId>
|
||||
|
Reference in New Issue
Block a user