package be.error.wsproxy.interceptors.logging;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.soap.SoapMessage;
import org.w3c.dom.Node;
import be.error.wsproxy.core.MessageSupport;
import be.error.wsproxy.interceptors.logging.WebServiceMessageXPathExpressionMetaData.XPathExpressionResultCardinality;
import be.error.wsproxy.interceptors.logging.WebServiceMessageXPathExpressionMetaData.XPathExpressionScope;
/**
* Helper class for executing XPath expressions (via {@link WebServiceMessageXPathExpressionMetaData} on a
* {@link WebServiceMessage}. The result is a map which has as key the XPath identifier contained by
* {@link WebServiceMessageXPathExpressionMetaData#getXPathKey()}. The value is the actual value as selected by the
* XPath expression: {@link WebServiceMessageXPathExpressionMetaData#getXPathExpression()} (can be null or empty string
* if no value was found or the path does not refer to an existing node).
*
* @see LoggingXPathInterceptor
*
* @author Koen Serneels
*/
public class WebServiceMessageXPathExtractor {
private static final Logger LOG = Logger.getLogger(WebServiceMessageXPathExtractor.class);
public Map<WebServiceMessageXPathExpressionMetaData, String> extractXPath(
WebServiceMessageXPathExpressionMetaData webServiceMessageIdentifiableXPathExpression,
WebServiceMessage webServiceMessage) throws TransformerConfigurationException, TransformerException,
UnsupportedEncodingException {
List<WebServiceMessageXPathExpressionMetaData> list = new ArrayList<>();
list.add(webServiceMessageIdentifiableXPathExpression);
return extractXPaths(list, webServiceMessage);
}
public Map<WebServiceMessageXPathExpressionMetaData, String> extractXPaths(
List<WebServiceMessageXPathExpressionMetaData> webServiceMessageIdentifiableXPathExpressions,
WebServiceMessage webServiceMessage) throws TransformerConfigurationException, TransformerException,
UnsupportedEncodingException {
Map<WebServiceMessageXPathExpressionMetaData, String> xpathResults = new HashMap<>();
for (WebServiceMessageXPathExpressionMetaData webServiceMessageIdentifiableXPathExpression : webServiceMessageIdentifiableXPathExpressions) {
Node messageNode;
if (webServiceMessageIdentifiableXPathExpression.getXPathExpressionScope() == XPathExpressionScope.SOAP_BODY) {
messageNode = MessageSupport.transformSourceToNode(webServiceMessage.getPayloadSource());
} else {
messageNode = MessageSupport.transformSourceToNode(((SoapMessage) webServiceMessage).getEnvelope()
.getSource());
}
switch (webServiceMessageIdentifiableXPathExpression.getXPathExpressionType()) {
case NODE:
xpathResults.put(webServiceMessageIdentifiableXPathExpression, MessageSupport
.transformNodeToString(webServiceMessageIdentifiableXPathExpression.getXPathExpression()
.evaluateAsNode(messageNode)));
break;
case VALUE:
xpathResults
.put(webServiceMessageIdentifiableXPathExpression, webServiceMessageIdentifiableXPathExpression
.getXPathExpression().evaluateAsString(messageNode));
break;
}
}
return validate(xpathResults);
}
private Map<WebServiceMessageXPathExpressionMetaData, String> validate(
Map<WebServiceMessageXPathExpressionMetaData, String> extractedFragments) {
List<String> mandatoryButMissingFragments = new ArrayList<>();
for (Entry<WebServiceMessageXPathExpressionMetaData, String> entry : extractedFragments.entrySet()) {
if (StringUtils.isEmpty(entry.getValue())) {
if (entry.getKey().getXPathExpressionResultCardinality() == XPathExpressionResultCardinality.MANDATORY) {
mandatoryButMissingFragments.add(entry.getKey().getXPathKey());
} else if (entry.getKey().getXPathExpressionResultCardinality() == XPathExpressionResultCardinality.MANDATORY_BLOCKING) {
MandatoryXPathValueAbsentException mandatoryXpathValueAbsentException = new MandatoryXPathValueAbsentException(
"XPath value identified by expression: " + entry.getKey().getUnparsedXpathExpression()
+ " returned no value but was indicated as mandatory and blocking.");
LOG.error(mandatoryXpathValueAbsentException);
throw mandatoryXpathValueAbsentException;
}
}
}
if (mandatoryButMissingFragments.size() > 0) {
LOG.warn("One or more mandatory parameters could not be obtained from the message:"
+ StringUtils.join(mandatoryButMissingFragments, ","));
}
return extractedFragments;
}
}