Skip to content
Snippets Groups Projects
Commit eb85c5bd authored by Hugues.Cazeaux's avatar Hugues.Cazeaux
Browse files

fix(OAI-PMH): specifiy schema locations for XML validation

parent 2e7df300
No related branches found
No related tags found
1 merge request!316fix(OAI-PMH): specifiy schema locations for XML validation
......@@ -69,6 +69,7 @@ public class OAIConstants {
public static final String OAI_DC_NAMESPACE = "http://www.openarchives.org/OAI/2.0/oai_dc/";
// OAI Identifier
public static final String OAI_ID = "oai-identifier";
public static final String OAI_ID_SCHEMA = "http://www.openarchives.org/OAI/2.0/oai-identifier.xsd";
public static final String OAI_ID_NAMESPACE = "http://www.openarchives.org/OAI/2.0/oai-identifier";
// Dublin Core
public static final String DC = "dc";
......
......@@ -47,4 +47,7 @@ public interface OAIRepositoryInfo {
JAXBElement<?> getRepositoryDefinition();
String getRepositoryNamepsace();
String getRepositorySchema();
}
......@@ -29,6 +29,8 @@ import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn;
import java.io.IOException;
import java.time.Instant;
import java.time.ZoneOffset;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.xml.bind.JAXBException;
......@@ -61,6 +63,7 @@ import ch.unige.solidify.controller.OAIController;
import ch.unige.solidify.exception.OAIException;
import ch.unige.solidify.exception.SolidifyResourceNotFoundException;
import ch.unige.solidify.exception.SolidifyRuntimeException;
import ch.unige.solidify.model.oai.OAIMetadataPrefix;
import ch.unige.solidify.model.oai.OAIPMH;
import ch.unige.solidify.model.xml.oai.v2.OAIPMHerrorcodeType;
import ch.unige.solidify.model.xml.oai.v2.OAIPMHtype;
......@@ -92,6 +95,7 @@ public class OAIProviderController implements ControllerWithHateoasHome {
@RequestParam(value = OAIConstants.OAI_VIEW, required = false) String smartView) {
final OAIPMHtype oai = new OAIPMHtype();
final String oaiUrl = this.getBaseUrl(request) + this.getRequestUri(request); // OAI provider base URL
final Map<String, String> schemaLocations = new HashMap<>();
try {
switch (this.oaiService.getVerb(verb)) {
case GET_RECORD:
......@@ -99,12 +103,20 @@ public class OAIProviderController implements ControllerWithHateoasHome {
// ------------
// https://www.openarchives.org/OAI/openarchivesprotocol.html#GetRecord
oai.setGetRecord(this.oaiService.getRecord(this.getRootUrl(request), identifier, metadataPrefix));
final OAIMetadataPrefix oaiMetadataPrefixForRecord = this.oaiService.getOAIMetadataPrefix(metadataPrefix);
schemaLocations.put(oaiMetadataPrefixForRecord.getSchemaNamespace(), oaiMetadataPrefixForRecord.getSchemaUrl().toString());
break;
case IDENTIFY:
// Specification
// ------------
// https://www.openarchives.org/OAI/openarchivesprotocol.html#Identify
oai.setIdentify(this.oaiService.getIdentify(oaiUrl));
// OAI Identifier
schemaLocations.put(OAIConstants.OAI_ID_NAMESPACE, OAIConstants.OAI_ID_SCHEMA);
// OAI Repository
schemaLocations.put(
this.oaiService.getOaiRepositoryInfo().getRepositoryNamepsace(),
oaiUrl + SolidifyConstants.URL_SEP + SolidifyConstants.SCHEMA);
break;
case LIST_IDENTIFIERS:
// Specification
......@@ -123,6 +135,8 @@ public class OAIProviderController implements ControllerWithHateoasHome {
// ------------
// https://www.openarchives.org/OAI/openarchivesprotocol.html#ListRecords
oai.setListRecords(this.oaiService.listRecords(this.getBaseUrl(request), metadataPrefix, from, until, set, token));
final OAIMetadataPrefix oaiMetadataPrefixForList = this.oaiService.getOAIMetadataPrefix(metadataPrefix);
schemaLocations.put(oaiMetadataPrefixForList.getSchemaNamespace(), oaiMetadataPrefixForList.getSchemaUrl().toString());
break;
case LIST_SETS:
// Specification
......@@ -159,7 +173,7 @@ public class OAIProviderController implements ControllerWithHateoasHome {
if (!StringTool.isNullOrEmpty(smartView)) {
xslUrl = oaiUrl + SolidifyConstants.URL_SEP + SolidifyConstants.XSL + "?" + OAIConstants.OAI_VIEW + "=" + smartView;
}
result = this.oaiService.printOAIPMH(oai, xslUrl);
result = this.oaiService.printOAIPMH(oai, xslUrl, schemaLocations);
log.trace(result);
} catch (final JAXBException e) {
log.error("In converting OAI in xml", e);
......@@ -180,14 +194,14 @@ public class OAIProviderController implements ControllerWithHateoasHome {
}
@GetMapping
public HttpEntity<?> status() {
public HttpEntity<OAIPMH> status() {
final OAIPMH oaiPmh = new OAIPMH();
final OAIPMHtype oai = new OAIPMHtype();
final WebMvcLinkBuilder linkBuilder = linkTo(methodOn(this.getClass()).process(null, null, null, null, null, null, null, null, null));
oai.setIdentify(this.oaiService.getIdentify(linkBuilder.toUri().toASCIIString()));
oaiPmh.setOai(oai);
oaiPmh.add(linkTo(this.getClass()).withSelfRel());
oaiPmh.add(Tool.link(linkTo(methodOn(this.getClass()).xsl(null, null)).toUriComponentsBuilder()).withRel(SolidifyConstants.XSL));
oaiPmh.add(Tool.link(linkTo(methodOn(this.getClass()).xsl(null)).toUriComponentsBuilder()).withRel(SolidifyConstants.XSL));
oaiPmh.add(OAITool.oaiLink(linkBuilder.toUriComponentsBuilder(), OAIConstants.OAI_IDENTIFY).withRel(OAIConstants.OAI_IDENTIFY));
oaiPmh.add(OAITool.oaiLink(linkBuilder.toUriComponentsBuilder(), OAIConstants.OAI_LIST_METADATA_FORMATS)
.withRel(OAIConstants.OAI_LIST_METADATA_FORMATS));
......@@ -201,19 +215,19 @@ public class OAIProviderController implements ControllerWithHateoasHome {
}
@GetMapping(SolidifyConstants.URL_SEP + OAIConstants.OAI_RESOURCE + SolidifyConstants.URL_SEP + SolidifyConstants.XSL)
public HttpEntity<String> xsl(HttpServletRequest request, @RequestParam(value = OAIConstants.OAI_VIEW, required = false) String smartView) {
public HttpEntity<String> xsl(@RequestParam(value = OAIConstants.OAI_VIEW, required = false) String smartView) {
try {
String result = null;
String result;
if (StringTool.isNullOrEmpty(smartView)) {
result = "";
result += "<xmlTransformation>";
StringBuilder xslt = new StringBuilder();
xslt.append("<xmlTransformation>");
for (final Resource f : FileTool.scanClassPath("classpath:" + SolidifyConstants.XSL_HOME + "/*.xsl")) {
result += "<xslFile>" + f.getFilename() + "</xslFile>";
xslt.append("<xslFile>").append(f.getFilename()).append("</xslFile>");
}
result += "</xmlTransformation>";
xslt.append("</xmlTransformation>");
result = xslt.toString();
} else {
final ClassPathResource xsl = new ClassPathResource(SolidifyConstants.XSL_HOME + SolidifyConstants.URL_SEP + smartView);
result = FileTool.toString(xsl.getInputStream());
}
final HttpHeaders headers = new HttpHeaders();
......@@ -223,7 +237,22 @@ public class OAIProviderController implements ControllerWithHateoasHome {
log.error("XML Transformation error", e);
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}
@GetMapping(SolidifyConstants.URL_SEP + OAIConstants.OAI_RESOURCE + SolidifyConstants.URL_SEP + SolidifyConstants.SCHEMA)
public HttpEntity<String> xsd() {
try {
final ClassPathResource xsl = new ClassPathResource(
SolidifyConstants.SCHEMA_HOME + SolidifyConstants.URL_SEP + this.oaiService.getOaiRepositoryInfo().getRepositorySchema());
String result = FileTool.toString(xsl.getInputStream());
final HttpHeaders headers = new HttpHeaders();
headers.add(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_XML_VALUE);
return new ResponseEntity<>(result, headers, HttpStatus.OK);
} catch (final Exception e) {
log.error("XML Schema error", e);
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}
/**
......
......@@ -30,6 +30,7 @@ import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
......@@ -99,6 +100,7 @@ public class OAIService {
private final ObjectFactory oaiDcFactory = new ObjectFactory();
// OAI Objects
private final OAIRepositoryInfo oaiRepositoryInfo;
private final OAIMetadataPrefixService oaiMetadataPrefixService;
private final OAISetService oaiSetService;
// OAI Service
......@@ -138,6 +140,10 @@ public class OAIService {
return oaiError;
}
public OAIRepositoryInfo getOaiRepositoryInfo() {
return this.oaiRepositoryInfo;
}
public IdentifyType getIdentify(String oaiUrl) {
final IdentifyType oaiIdentify = new IdentifyType();
oaiIdentify.setRepositoryName(this.oaiRepositoryInfo.getLongName());
......@@ -170,6 +176,10 @@ public class OAIService {
return oaiIdentify;
}
public OAIMetadataPrefix getOAIMetadataPrefix(String metadataPrefix) {
return this.oaiMetadataPrefixService.findByPrefix(metadataPrefix);
}
public GetRecordType getRecord(String baseUrl, String identifier, String metadataPrefix) throws JAXBException {
// Check Parameters
this.checkParameters(identifier, metadataPrefix);
......@@ -268,10 +278,6 @@ public class OAIService {
PageRequest.of(0, RestCollectionPage.MAX_SIZE_PAGE, Sort.by("prefix")));
}
private OAIMetadataPrefix getMetadataPrefix(String metadataPrefix) {
return this.oaiMetadataPrefixService.findByPrefix(metadataPrefix);
}
public ListRecordsType listRecords(String baseUrl, String metadataPrefix, String from, String until, String set, String token)
throws JAXBException {
// Check Parameters
......@@ -329,13 +335,28 @@ public class OAIService {
return setTypes;
}
public String printOAIPMH(OAIPMHtype oai, String rootUrl) throws JAXBException {
public String printOAIPMH(OAIPMHtype oai, String rootUrl, Map<String, String> schemaLocationList) throws JAXBException {
final Marshaller marshaller = this.metadataService.getMarshaller(this.jaxbContext);
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
if (!StringTool.isNullOrEmpty(rootUrl)) {
marshaller.setProperty("com.sun.xml.bind.xmlHeaders", "<?xml-stylesheet type='text/xsl' href='" + rootUrl + "'?>");
}
marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, OAIConstants.OAI_PMH_NAMESPACE + " " + OAIConstants.OAI_PMH_SCHEMA);
// Build schema location string
StringBuilder schemaLocations = new StringBuilder();
schemaLocations
.append(OAIConstants.OAI_PMH_NAMESPACE)
.append(" ")
.append(OAIConstants.OAI_PMH_SCHEMA);
if (schemaLocationList != null && !schemaLocationList.isEmpty()) {
for (Map.Entry<String, String> schemaLocation : schemaLocationList.entrySet()) {
schemaLocations
.append(" ")
.append(schemaLocation.getKey())
.append(" ")
.append(schemaLocation.getValue());
}
}
marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, schemaLocations.toString());
final JAXBElement<OAIPMHtype> root = this.getXML(oai);
final ByteArrayOutputStream bos = new ByteArrayOutputStream();
marshaller.marshal(root, bos);
......@@ -446,7 +467,7 @@ public class OAIService {
@SuppressWarnings("squid:S128")
private Object getMetadata(String baseUrl, String metadataPrefix, OAIRecord oaiRecord) throws JAXBException {
final String archiveUrl = this.getArchiveUrl();
final OAIMetadataPrefix oaiMetadataPrefix = this.getMetadataPrefix(metadataPrefix);
final OAIMetadataPrefix oaiMetadataPrefix = this.getOAIMetadataPrefix(metadataPrefix);
if (oaiMetadataPrefix == null) {
throw new OAIException(OAIPMHerrorcodeType.NO_METADATA_FORMATS, "Undefined metadata prefix " + metadataPrefix + " this record");
}
......
......@@ -148,7 +148,7 @@ public abstract class OAIServiceTest {
void identityTest() throws JAXBException, IOException {
final OAIPMHtype oai = new OAIPMHtype();
oai.setIdentify(this.oaiService.getIdentify(HOST_URL));
String result = this.oaiService.printOAIPMH(oai, null);
String result = this.oaiService.printOAIPMH(oai, null, null);
this.checkResult(result, "oaiIdentity.xml");
}
......@@ -156,7 +156,7 @@ public abstract class OAIServiceTest {
void listMetadataFormatsTest() throws JAXBException, IOException {
final OAIPMHtype oai = new OAIPMHtype();
oai.setListMetadataFormats(this.oaiService.listMetadataFormats(null));
String result = this.oaiService.printOAIPMH(oai, null);
String result = this.oaiService.printOAIPMH(oai, null, null);
this.checkResult(result, "oaiListMetadataFormats.xml");
}
......@@ -166,7 +166,7 @@ public abstract class OAIServiceTest {
try {
final OAIPMHtype oai = new OAIPMHtype();
oai.setListIdentifiers(this.oaiService.listIdentifiers(metadata, null, null, null, null));
String result = this.oaiService.printOAIPMH(oai, null);
String result = this.oaiService.printOAIPMH(oai, null, null);
this.checkResult(result, "oaiIdentity-" + metadata + ".xml");
} catch (final Exception e) {
this.returnException(e);
......@@ -185,7 +185,7 @@ public abstract class OAIServiceTest {
try {
oai.setGetRecord(this.oaiService.getRecord(HOST_URL, "xxx", OAIConstants.OAI_DC));
} catch (OAIException e) {
String result = this.oaiService.printOAIPMH(oai, null);
String result = this.oaiService.printOAIPMH(oai, null, null);
this.checkResult(result, "oaiGetRecordNotFound.xml");
}
}
......@@ -197,7 +197,7 @@ public abstract class OAIServiceTest {
try {
final OAIPMHtype oai = new OAIPMHtype();
oai.setGetRecord(this.oaiService.getRecord(HOST_URL, id, metadataPrefix));
String result = this.oaiService.printOAIPMH(oai, null);
String result = this.oaiService.printOAIPMH(oai, null, null);
this.checkResult(result, "oaiGetRecord-" + metadataPrefix + "-" + id + ".xml");
} catch (final Exception e) {
this.returnException(e);
......@@ -212,7 +212,7 @@ public abstract class OAIServiceTest {
try {
final OAIPMHtype oai = new OAIPMHtype();
oai.setListRecords(this.oaiService.listRecords(HOST_URL, metadataPrefix, null, null, null, null));
String result = this.oaiService.printOAIPMH(oai, null);
String result = this.oaiService.printOAIPMH(oai, null, null);
this.checkResult(result, "oaiListRecords-" + metadataPrefix + ".xml");
} catch (final Exception e) {
this.returnException(e);
......@@ -224,7 +224,7 @@ public abstract class OAIServiceTest {
void listSetsTest() throws JAXBException, IOException {
final OAIPMHtype oai = new OAIPMHtype();
oai.setListSets(this.oaiService.listSets(null));
String result = this.oaiService.printOAIPMH(oai, null);
String result = this.oaiService.printOAIPMH(oai, null, null);
this.checkResult(result, "oaiListSets.xml");
}
......
......@@ -92,6 +92,7 @@ public class SolidifyConstants {
// XML
public static final String SCHEMA_HOME = "schemas";
public static final String SCHEMA = "schema";
public static final String XSL_HOME = "xslt";
public static final String XSL = "xsl";
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment