// check if there is a response body
if(bodyAsStream != null) {
CachingFilterInputStream cfis = null;
FilterInputStreamCache cache = null;
try {
//we have to cache the input stream, so we can reread it, as we may use it twice (once for xml attempt and once for string attempt)
cache = FilterInputStreamCacheFactory.getCacheInstance(new FilterInputStreamCacheFactory.FilterInputStreamCacheConfiguration(){
@Override
public String getCacheClass() {
return (String) context.getBroker().getConfiguration().getProperty(Configuration.BINARY_CACHE_CLASS_PROPERTY);
}
});
cfis = new CachingFilterInputStream(cache, bodyAsStream);
//mark the start of the stream
cfis.mark(Integer.MAX_VALUE);
// determine the type of the response document
final Header responseContentType = method.getResponseHeader("Content-Type");
final MimeType responseMimeType = getResponseMimeType(responseContentType);
if(responseContentType != null) {
builder.addAttribute(new QName("mimetype", null, null), responseContentType.getValue());
}
//try and parse the response as XML
try {
//we have to use CloseShieldInputStream otherwise the parser closes the stream and we cant later reread
final InputStream shieldedInputStream = new CloseShieldInputStream(cfis);
responseNode = (NodeImpl)ModuleUtils.streamToXML(context, shieldedInputStream);
builder.addAttribute(new QName("type", null, null ), "xml");
responseNode.copyTo(null, new DocumentBuilderReceiver(builder));
} catch(final SAXException se) {
// could not parse to xml
// not an error in itself, it will be treated either as HTML,
// text or binary here below
final String msg = "Request for URI '"
+ method.getURI().toString()
+ "' Could not parse http response content as XML (will try html, text or fallback to binary): "
+ se.getMessage();
if(logger.isDebugEnabled()) {
logger.debug(msg, se);
} else {
logger.info(msg);
}
} catch(final IOException ioe) {
final String msg = "Request for URI '" + method.getURI().toString() + "' Could not read http response content: " + ioe.getMessage();
logger.error(msg, ioe);
throw new XPathException(msg, ioe);
}
if(responseNode == null) {
//response is NOT parseable as XML
//is it a html document?
if(responseMimeType.getName().equals(MimeType.HTML_TYPE.getName())) {
//html document
try {
//reset the stream to the start, as we need to reuse since attempting to parse to XML
cfis.reset();
//parse html to xml(html)
//we have to use CloseShieldInputStream otherwise the parser closes the stream and we cant later reread
final InputStream shieldedInputStream = new CloseShieldInputStream(cfis);
responseNode = (NodeImpl)ModuleUtils.htmlToXHtml(context, method.getURI().toString(), new InputSource(shieldedInputStream), parserFeatures, parserProperties).getDocumentElement();
builder.addAttribute(new QName("type", null, null), "xhtml" );
responseNode.copyTo(null, new DocumentBuilderReceiver(builder));
} catch(final URIException ue) {
throw new XPathException(this, ue.getMessage(), ue);
} catch(final SAXException se) {
//could not parse to xml(html)
logger.debug("Could not parse http response content from HTML to XML: " + se.getMessage(), se);
}
}
}
if(responseNode == null) {
//reset the stream to the start, as we need to reuse since attempting to parse to HTML->XML
cfis.reset();
if(responseMimeType.getName().startsWith("text/")) {
// Assume it's a text body and URL encode it
builder.addAttribute(new QName("type", null, null), "text");
builder.addAttribute(new QName("encoding", null, null), "URLEncoded");
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
final byte buf[] = new byte[4096];
int read = -1;
while((read = cfis.read(buf)) > -1) {
baos.write(buf);
}
builder.characters(URLEncoder.encode(EncodingUtil.getString(baos.toByteArray(), ((HttpMethodBase)method).getResponseCharSet()), "UTF-8"));
baos.close();
} else {
// Assume it's a binary body and Base64 encode it
builder.addAttribute( new QName( "type", null, null ), "binary" );
builder.addAttribute( new QName( "encoding", null, null ), "Base64Encoded" );
BinaryValue binary = null;
try {
binary = BinaryValueFromInputStream.getInstance(context, new Base64BinaryValueType(), cfis);
builder.characters(binary.getStringValue());
} finally {
// free resources
if (binary != null) {
binary.destroy(context, null);
}
}
}
}
} finally {
if(cache != null) {
try {
cache.invalidate();
} catch(final IOException ioe) {
LOG.error(ioe.getMessage(), ioe);
}
}