Search in sources :

Example 1 with ResponseWrapper

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);
}
Also used : Path(java.nio.file.Path) ZipArchiveBackupDescriptor(org.exist.backup.ZipArchiveBackupDescriptor) OutputStream(java.io.OutputStream) ResponseWrapper(org.exist.http.servlets.ResponseWrapper) IOException(java.io.IOException) Properties(java.util.Properties)

Example 2 with ResponseWrapper

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;
}
Also used : HttpRequest(org.exquery.http.HttpRequest) HttpResponseWrapper(org.exist.http.servlets.HttpResponseWrapper) HttpRequestWrapper(org.exist.http.servlets.HttpRequestWrapper) ResponseWrapper(org.exist.http.servlets.ResponseWrapper) HttpResponseWrapper(org.exist.http.servlets.HttpResponseWrapper) PermissionDeniedException(org.exist.security.PermissionDeniedException) XMLStreamException(javax.xml.stream.XMLStreamException) SAXException(org.xml.sax.SAXException) TriggerException(org.exist.collections.triggers.TriggerException) EXistException(org.exist.EXistException) TransformerConfigurationException(javax.xml.transform.TransformerConfigurationException) SAXParseException(org.xml.sax.SAXParseException) ParserConfigurationException(javax.xml.parsers.ParserConfigurationException)

Example 3 with ResponseWrapper

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;
    }
}
Also used : TransformerHandler(javax.xml.transform.sax.TransformerHandler) Node(org.w3c.dom.Node) BufferedOutputStream(java.io.BufferedOutputStream) OutputStream(java.io.OutputStream) ResponseWrapper(org.exist.http.servlets.ResponseWrapper) Properties(java.util.Properties) XIncludeFilter(org.exist.storage.serializers.XIncludeFilter) XSLTErrorsListener(org.exist.xslt.XSLTErrorsListener) BufferedOutputStream(java.io.BufferedOutputStream) Serializer(org.exist.storage.serializers.Serializer) Path(java.nio.file.Path) StreamResult(javax.xml.transform.stream.StreamResult) ReceiverToSAX(org.exist.util.serializer.ReceiverToSAX) DocumentBuilderReceiver(org.exist.dom.memtree.DocumentBuilderReceiver) Receiver(org.exist.util.serializer.Receiver) IOException(java.io.IOException) DocumentBuilderReceiver(org.exist.dom.memtree.DocumentBuilderReceiver) IOException(java.io.IOException) MemTreeBuilder(org.exist.dom.memtree.MemTreeBuilder) SAXResult(javax.xml.transform.sax.SAXResult)

Example 4 with ResponseWrapper

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);
    }
}
Also used : ResponseWrapper(org.exist.http.servlets.ResponseWrapper) DocumentSet(org.exist.dom.persistent.DocumentSet) DocumentImpl(org.exist.dom.persistent.DocumentImpl)

Aggregations

ResponseWrapper (org.exist.http.servlets.ResponseWrapper)4 IOException (java.io.IOException)2 OutputStream (java.io.OutputStream)2 Path (java.nio.file.Path)2 Properties (java.util.Properties)2 BufferedOutputStream (java.io.BufferedOutputStream)1 ParserConfigurationException (javax.xml.parsers.ParserConfigurationException)1 XMLStreamException (javax.xml.stream.XMLStreamException)1 TransformerConfigurationException (javax.xml.transform.TransformerConfigurationException)1 SAXResult (javax.xml.transform.sax.SAXResult)1 TransformerHandler (javax.xml.transform.sax.TransformerHandler)1 StreamResult (javax.xml.transform.stream.StreamResult)1 EXistException (org.exist.EXistException)1 ZipArchiveBackupDescriptor (org.exist.backup.ZipArchiveBackupDescriptor)1 TriggerException (org.exist.collections.triggers.TriggerException)1 DocumentBuilderReceiver (org.exist.dom.memtree.DocumentBuilderReceiver)1 MemTreeBuilder (org.exist.dom.memtree.MemTreeBuilder)1 DocumentImpl (org.exist.dom.persistent.DocumentImpl)1 DocumentSet (org.exist.dom.persistent.DocumentSet)1 HttpRequestWrapper (org.exist.http.servlets.HttpRequestWrapper)1