com.sap.cloud.sdk.odatav2.connectivity.internal.ErpErrorResultHandler Maven / Gradle / Ivy
/*******************************************************************************
* (c) 201X SAP SE or an SAP affiliate company. All rights reserved.
******************************************************************************/
package com.sap.cloud.sdk.odatav2.connectivity.internal;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import com.sap.cloud.sdk.cloudplatform.logging.CloudLoggerFactory;
import com.sap.cloud.sdk.odatav2.connectivity.ODataException;
import com.sap.cloud.sdk.odatav2.connectivity.ODataQuery;
@NoArgsConstructor
public class ErpErrorResultHandler extends DefaultErrorResultHandler
{
private static final Logger logger = CloudLoggerFactory.getLogger(ErpErrorResultHandler.class);
public static final String MISSING_JSON_XML = "Not an XML";
private static final String FEATURE_EXTERNAL_GENERAL_ENTITIES =
"http://xml.org/sax/features/external-general-entities";
private static final String FEATURE_EXTERNAL_PARAMETER_ENTITIES =
"http://xml.org/sax/features/external-parameter-entities";
@NoArgsConstructor
public static class ErpODataException extends ODataException
{
private static final long serialVersionUID = 6880772175494689747L;
@Setter
private boolean parsedXml = false;
@Getter
@Setter
transient private ODataQuery query;
@Getter
@Setter
private String code;
public String getMessageClass()
{
final String[] parts = StringUtils.split(code, "/", 2);
if( parts != null && parts.length == 2 ) {
return parts[0];
}
return null;
}
public String getMessageNumber()
{
final String[] parts = StringUtils.split(code, "/", 2);
if( parts != null && parts.length == 2 ) {
return parts[1];
}
return null;
}
}
@Override
protected Class getExceptionType()
{
return ErpODataException.class;
}
private Document getXmlDocument( final String message )
throws ParserConfigurationException,
IOException,
SAXException
{
final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setFeature(FEATURE_EXTERNAL_GENERAL_ENTITIES, false);
factory.setFeature(FEATURE_EXTERNAL_PARAMETER_ENTITIES, false);
factory.setExpandEntityReferences(false);
return factory.newDocumentBuilder().parse(new ByteArrayInputStream(message.getBytes(StandardCharsets.UTF_8)));
}
@Override
public ErpODataException createError( final String message, final Object origin, final int httpStatusCode )
{
final boolean isXml = StringUtils.startsWith(message, "<");
final boolean isJson = StringUtils.startsWith(message, "{");
final ErpODataException exception;
if( StringUtils.isEmpty(message) ) {
exception = new ErpODataException();
} else if( isXml ) {
exception = new ErpODataException();
try {
final Document doc = getXmlDocument(message);
exception.setMessage(doc.getDocumentElement().getTextContent());
final Node elementCode = doc.getElementsByTagName("code").item(0);
if( elementCode == null ) {
exception.setMessage(message);
} else {
exception.setCode(elementCode.getTextContent());
}
exception.setParsedXml(true);
}
catch( final Exception e ) {
logger.warn("Could not deserialize XML document.", e);
}
} else if( isJson ) {
exception = super.createError(message, origin, httpStatusCode);
} else {
exception = new ErpODataException();
exception.setMessage(MISSING_JSON_XML);
}
if( origin instanceof ODataQuery ) {
exception.setQuery((ODataQuery) origin);
}
return exception;
}
}