use of org.exist.http.servlets.ResponseWrapper in project exist by eXist-db.
the class RetrieveBackup method eval.
public Sequence eval(final Sequence[] args, final Sequence contextSequence) throws XPathException {
if (!context.getEffectiveUser().hasDbaRole()) {
throw new XPathException("You must be a DBA to retrieve a backup");
}
final String exportDir = args[0].getStringValue();
Path dir = Paths.get(exportDir);
if (!dir.isAbsolute()) {
dir = ((Path) context.getBroker().getConfiguration().getProperty(BrokerPool.PROPERTY_DATA_DIR)).resolve(exportDir);
}
final String name = args[1].getStringValue();
final Path backupFile = dir.resolve(name);
if (!Files.isReadable(backupFile)) {
return (Sequence.EMPTY_SEQUENCE);
}
if (!name.endsWith(".zip")) {
throw (new XPathException(this, "for security reasons, the function only allows " + "reading zipped backup archives"));
}
try {
final ZipArchiveBackupDescriptor descriptor = new ZipArchiveBackupDescriptor(backupFile);
final Properties properties = descriptor.getProperties();
if ((properties == null) || (properties.isEmpty())) {
throw (new XPathException(this, "the file does not see to be a valid backup archive"));
}
} catch (final IOException e) {
throw (new XPathException(this, "the file does not see to be a valid backup archive"));
}
// directly stream the backup contents to the HTTP response
final Optional<ResponseWrapper> maybeResponse = Optional.ofNullable(context.getHttpContext()).map(XQueryContext.HttpContext::getResponse);
if (!maybeResponse.isPresent()) {
throw (new XPathException(this, "No response object found in the current XQuery context."));
}
final ResponseWrapper response = maybeResponse.get();
if (!"org.exist.http.servlets.HttpResponseWrapper".equals(response.getClass().getName())) {
throw new XPathException(this, signature.toString() + " can only be used within the EXistServlet or XQueryServlet");
}
response.setContentType("application/zip");
response.setHeader("Content-Length", String.valueOf(FileUtils.sizeQuietly(backupFile)));
try {
try (final OutputStream os = response.getOutputStream()) {
Files.copy(backupFile, os);
}
response.flushBuffer();
} catch (final IOException e) {
throw (new XPathException(this, "An IO error occurred while reading the backup archive"));
}
return (Sequence.EMPTY_SEQUENCE);
}
use of org.exist.http.servlets.ResponseWrapper in project exist by eXist-db.
the class RESTServer method declareVariables.
/**
* Pass the request, response and session objects to the XQuery context.
*
* @param context
* @param request
* @param response
* @throws XPathException
*/
private HttpRequestWrapper declareVariables(final XQueryContext context, final ElementImpl variables, final HttpServletRequest request, final HttpServletResponse response) throws XPathException {
final HttpRequestWrapper reqw = new HttpRequestWrapper(request, formEncoding, containerEncoding);
final ResponseWrapper respw = new HttpResponseWrapper(response);
context.setHttpContext(new XQueryContext.HttpContext(reqw, respw));
// enable EXQuery Request Module (if present)
try {
if (xqueryContextExqueryRequestAttribute != null && cstrHttpServletRequestAdapter != null) {
final HttpRequest exqueryRequestAdapter = cstrHttpServletRequestAdapter.apply(request, () -> (String) context.getBroker().getConfiguration().getProperty(Configuration.BINARY_CACHE_CLASS_PROPERTY));
if (exqueryRequestAdapter != null) {
context.setAttribute(xqueryContextExqueryRequestAttribute, exqueryRequestAdapter);
}
}
} catch (final Exception e) {
if (LOG.isDebugEnabled()) {
LOG.debug("EXQuery Request Module is not present: {}", e.getMessage(), e);
}
}
if (variables != null) {
declareExternalAndXQJVariables(context, variables);
}
return reqw;
}
use of org.exist.http.servlets.ResponseWrapper in project exist by eXist-db.
the class Transform method eval.
/* (non-Javadoc)
* @see org.exist.xquery.BasicFunction#eval(org.exist.xquery.value.Sequence[], org.exist.xquery.value.Sequence)
*/
public Sequence eval(Sequence[] args, Sequence contextSequence) throws XPathException {
final Properties attributes = new Properties();
final Properties serializationProps = new Properties();
final Properties stylesheetParams = new Properties();
// Parameter 1 & 2
final Sequence inputNode = args[0];
final Item stylesheetItem = args[1].itemAt(0);
// Parse 3rd parameter
final Node options = args[2].isEmpty() ? null : ((NodeValue) args[2].itemAt(0)).getNode();
if (options != null) {
stylesheetParams.putAll(parseParameters(options));
}
// Parameter 4 when present
if (getArgumentCount() >= 4) {
final Sequence attrs = args[3];
attributes.putAll(extractAttributes(attrs));
}
// Parameter 5 when present
if (getArgumentCount() >= 5) {
// extract serialization options
final Sequence serOpts = args[4];
serializationProps.putAll(extractSerializationProperties(serOpts));
} else {
context.checkOptions(serializationProps);
}
boolean expandXIncludes = "yes".equals(serializationProps.getProperty(EXistOutputKeys.EXPAND_XINCLUDES, "yes"));
final XSLTErrorsListener<XPathException> errorListener = new XSLTErrorsListener<XPathException>(stopOnError, stopOnWarn) {
@Override
protected void raiseError(String error, Exception ex) throws XPathException {
throw new XPathException(Transform.this, error, ex);
}
};
// Setup handler and error listener
final TransformerHandler handler = createHandler(stylesheetItem, stylesheetParams, attributes, errorListener);
if (isCalledAs("transform")) {
// transform:transform()
final ValueSequence seq = new ValueSequence();
context.pushDocumentContext();
try {
final MemTreeBuilder builder = context.getDocumentBuilder();
final DocumentBuilderReceiver builderReceiver = new DocumentBuilderReceiver(builder, true);
final SAXResult result = new SAXResult(builderReceiver);
// preserve comments etc... from xslt output
result.setLexicalHandler(builderReceiver);
handler.setResult(result);
final Receiver receiver = new ReceiverToSAX(handler);
final Serializer serializer = context.getBroker().borrowSerializer();
try {
serializer.setProperties(serializationProps);
serializer.setReceiver(receiver, true);
if (expandXIncludes) {
String xiPath = serializationProps.getProperty(EXistOutputKeys.XINCLUDE_PATH);
if (xiPath != null && !xiPath.startsWith(XmldbURI.XMLDB_URI_PREFIX)) {
final Path f = Paths.get(xiPath).normalize();
if (!f.isAbsolute()) {
xiPath = Paths.get(context.getModuleLoadPath(), xiPath).normalize().toAbsolutePath().toString();
}
} else {
xiPath = context.getModuleLoadPath();
}
serializer.getXIncludeFilter().setModuleLoadPath(xiPath);
}
serializer.toSAX(inputNode, 1, inputNode.getItemCount(), false, false, 0, 0);
} catch (final Exception e) {
throw new XPathException(this, "Exception while transforming node: " + e.getMessage(), e);
} finally {
context.getBroker().returnSerializer(serializer);
}
errorListener.checkForErrors();
Node next = builder.getDocument().getFirstChild();
while (next != null) {
seq.add((NodeValue) next);
next = next.getNextSibling();
}
return seq;
} finally {
context.popDocumentContext();
}
} else {
// transform:stream-transform()
final Optional<ResponseWrapper> maybeResponse = Optional.ofNullable(context.getHttpContext()).map(XQueryContext.HttpContext::getResponse);
if (!maybeResponse.isPresent()) {
throw new XPathException(this, ErrorCodes.XPDY0002, "No response object found in the current XQuery context.");
}
final ResponseWrapper response = maybeResponse.get();
if (!"org.exist.http.servlets.HttpResponseWrapper".equals(response.getClass().getName())) {
throw new XPathException(this, ErrorCodes.XPDY0002, signatures[1] + " can only be used within the EXistServlet or XQueryServlet");
}
// setup the response correctly
final String mediaType = handler.getTransformer().getOutputProperty("media-type");
final String encoding = handler.getTransformer().getOutputProperty("encoding");
if (mediaType != null) {
if (encoding == null) {
response.setContentType(mediaType);
} else {
response.setContentType(mediaType + "; charset=" + encoding);
}
}
// do the transformation
try {
final OutputStream os = new BufferedOutputStream(response.getOutputStream());
final StreamResult result = new StreamResult(os);
handler.setResult(result);
final Serializer serializer = context.getBroker().borrowSerializer();
Receiver receiver = new ReceiverToSAX(handler);
try {
serializer.setProperties(serializationProps);
if (expandXIncludes) {
XIncludeFilter xinclude = new XIncludeFilter(serializer, receiver);
String xiPath = serializationProps.getProperty(EXistOutputKeys.XINCLUDE_PATH);
if (xiPath != null) {
final Path f = Paths.get(xiPath).normalize();
if (!f.isAbsolute()) {
xiPath = Paths.get(context.getModuleLoadPath(), xiPath).normalize().toAbsolutePath().toString();
}
} else {
xiPath = context.getModuleLoadPath();
}
xinclude.setModuleLoadPath(xiPath);
receiver = xinclude;
}
serializer.setReceiver(receiver);
serializer.toSAX(inputNode);
} catch (final Exception e) {
throw new XPathException(this, "Exception while transforming node: " + e.getMessage(), e);
} finally {
context.getBroker().returnSerializer(serializer);
}
errorListener.checkForErrors();
os.close();
// commit the response
response.flushBuffer();
} catch (final IOException e) {
throw new XPathException(this, "IO exception while transforming node: " + e.getMessage(), e);
}
return Sequence.EMPTY_SEQUENCE;
}
}
use of org.exist.http.servlets.ResponseWrapper in project exist by eXist-db.
the class HTTPUtils method addLastModifiedHeader.
/**
* Feature "Guess last modification time for an XQuery result";
* the HTTP header Last-Modified is filled with most recent time stamp among all
* XQuery documents appearing in the actual response.
* Note however, that the actual response can be influenced, through tests in the query,
* by documents more recent.
*
* @param result the XQuery result to inspect
* @param context current context
*/
public static void addLastModifiedHeader(Sequence result, XQueryContext context) {
try {
final DocumentSet documentSet = result.getDocumentSet();
long mostRecentDocumentTime = 0;
for (final Iterator<DocumentImpl> i = documentSet.getDocumentIterator(); i.hasNext(); ) {
final DocumentImpl doc = i.next();
if (doc != null) {
mostRecentDocumentTime = Math.max(doc.getLastModified(), mostRecentDocumentTime);
// LOG.debug("getFileName: " + doc.getFileName() + ", "
// + doc.getLastModified());
}
}
LOG.debug("mostRecentDocumentTime: {}", mostRecentDocumentTime);
if (mostRecentDocumentTime > 0) {
final Optional<ResponseWrapper> maybeResponse = Optional.ofNullable(context.getHttpContext()).map(XQueryContext.HttpContext::getResponse);
if (maybeResponse.isPresent()) {
// have to take in account that if the header has allready been explicitely set
// by the XQuery script, we should not modify it .
final ResponseWrapper responseWrapper = maybeResponse.get();
if (responseWrapper.getDateHeader("Last-Modified") == 0) {
responseWrapper.setDateHeader("Last-Modified", mostRecentDocumentTime);
}
}
}
} catch (final Exception e) {
LOG.debug(e.getMessage(), e);
}
}
Aggregations