Search in sources :

Example 1 with XIncludeFilter

use of org.exist.storage.serializers.XIncludeFilter 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 2 with XIncludeFilter

use of org.exist.storage.serializers.XIncludeFilter in project exist by eXist-db.

the class XSLTServlet method doPost.

@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    final String uri = (String) request.getAttribute(REQ_ATTRIBUTE_STYLESHEET);
    if (uri == null) {
        throw new ServletException("No stylesheet source specified!");
    }
    Item inputNode = null;
    final String sourceAttrib = (String) request.getAttribute(REQ_ATTRIBUTE_INPUT);
    if (sourceAttrib != null) {
        Object sourceObj = request.getAttribute(sourceAttrib);
        if (sourceObj != null) {
            if (sourceObj instanceof ValueSequence) {
                final ValueSequence seq = (ValueSequence) sourceObj;
                if (seq.size() == 1) {
                    sourceObj = seq.itemAt(0);
                }
            }
            if (sourceObj instanceof Item) {
                inputNode = (Item) sourceObj;
                if (!Type.subTypeOf(inputNode.getType(), Type.NODE)) {
                    throw new ServletException("Input for XSLT servlet is not a node. Read from attribute " + sourceAttrib);
                }
                if (LOG.isDebugEnabled()) {
                    LOG.debug("Taking XSLT input from request attribute {}", sourceAttrib);
                }
            } else {
                throw new ServletException("Input for XSLT servlet is not a node. Read from attribute " + sourceAttrib);
            }
        }
    }
    try {
        pool = BrokerPool.getInstance();
    } catch (final EXistException e) {
        throw new ServletException(e.getMessage(), e);
    }
    Subject user = pool.getSecurityManager().getGuestSubject();
    Subject requestUser = HttpAccount.getUserFromServletRequest(request);
    if (requestUser != null) {
        user = requestUser;
    }
    // Retrieve username / password from HTTP request attributes
    final String userParam = (String) request.getAttribute("xslt.user");
    final String passwd = (String) request.getAttribute("xslt.password");
    if (userParam != null) {
        try {
            user = pool.getSecurityManager().authenticate(userParam, passwd);
        } catch (final AuthenticationException e1) {
            response.sendError(HttpServletResponse.SC_FORBIDDEN, "Wrong password or user");
            return;
        }
    }
    final Stylesheet stylesheet = stylesheet(uri, request, response);
    if (stylesheet == null) {
        return;
    }
    // do the transformation
    try (final DBBroker broker = pool.get(Optional.of(user))) {
        final TransformerHandler handler = stylesheet.newTransformerHandler(broker, errorListener);
        setTransformerParameters(request, handler.getTransformer());
        final Properties properties = handler.getTransformer().getOutputProperties();
        setOutputProperties(request, properties);
        String encoding = properties.getProperty("encoding");
        if (encoding == null) {
            encoding = "UTF-8";
        }
        response.setCharacterEncoding(encoding);
        final String mediaType = properties.getProperty("media-type");
        if (mediaType != null) {
            // check, do mediaType have "charset"
            if (!mediaType.contains("charset")) {
                response.setContentType(mediaType + "; charset=" + encoding);
            } else {
                response.setContentType(mediaType);
            }
        }
        final SAXSerializer sax = (SAXSerializer) SerializerPool.getInstance().borrowObject(SAXSerializer.class);
        final Writer writer = new BufferedWriter(response.getWriter());
        sax.setOutput(writer, properties);
        final SAXResult result = new SAXResult(sax);
        handler.setResult(result);
        final Serializer serializer = broker.borrowSerializer();
        Receiver receiver = new ReceiverToSAX(handler);
        try {
            XIncludeFilter xinclude = new XIncludeFilter(serializer, receiver);
            receiver = xinclude;
            String baseUri;
            final String base = (String) request.getAttribute(REQ_ATTRIBUTE_BASE);
            if (base != null) {
                baseUri = getServletContext().getRealPath(base);
            } else if (uri.startsWith("xmldb:exist://")) {
                baseUri = XmldbURI.xmldbUriFor(uri).getCollectionPath();
            } else {
                baseUri = getCurrentDir(request).toAbsolutePath().toString();
            }
            xinclude.setModuleLoadPath(baseUri);
            serializer.setReceiver(receiver);
            if (inputNode != null) {
                serializer.toSAX((NodeValue) inputNode);
            } else {
                final SAXToReceiver saxreceiver = new SAXToReceiver(receiver);
                final XMLReader reader = pool.getParserPool().borrowXMLReader();
                try {
                    reader.setContentHandler(saxreceiver);
                    // Handle gziped input stream
                    InputStream stream;
                    InputStream inStream = new BufferedInputStream(request.getInputStream());
                    inStream.mark(10);
                    try {
                        stream = new GZIPInputStream(inStream);
                    } catch (final IOException e) {
                        inStream.reset();
                        stream = inStream;
                    }
                    reader.parse(new InputSource(stream));
                } finally {
                    pool.getParserPool().returnXMLReader(reader);
                }
            }
        } catch (final SAXParseException e) {
            LOG.error(e.getMessage());
            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
        } catch (final SAXException e) {
            throw new ServletException("SAX exception while transforming node: " + e.getMessage(), e);
        } finally {
            SerializerPool.getInstance().returnObject(sax);
            broker.returnSerializer(serializer);
        }
        writer.flush();
        response.flushBuffer();
    } catch (final IOException e) {
        throw new ServletException("IO exception while transforming node: " + e.getMessage(), e);
    } catch (final TransformerException e) {
        throw new ServletException("Exception while transforming node: " + e.getMessage(), e);
    } catch (final Throwable e) {
        LOG.error(e);
        throw new ServletException("An error occurred: " + e.getMessage(), e);
    }
}
Also used : TransformerHandler(javax.xml.transform.sax.TransformerHandler) InputSource(org.xml.sax.InputSource) AuthenticationException(org.exist.security.AuthenticationException) Properties(java.util.Properties) SAXException(org.xml.sax.SAXException) ServletException(javax.servlet.ServletException) GZIPInputStream(java.util.zip.GZIPInputStream) Item(org.exist.xquery.value.Item) XIncludeFilter(org.exist.storage.serializers.XIncludeFilter) SAXParseException(org.xml.sax.SAXParseException) ValueSequence(org.exist.xquery.value.ValueSequence) XMLReader(org.xml.sax.XMLReader) TransformerException(javax.xml.transform.TransformerException) Serializer(org.exist.storage.serializers.Serializer) GZIPInputStream(java.util.zip.GZIPInputStream) EXistException(org.exist.EXistException) Subject(org.exist.security.Subject) Stylesheet(org.exist.xslt.Stylesheet) DBBroker(org.exist.storage.DBBroker) SAXResult(javax.xml.transform.sax.SAXResult)

Aggregations

Properties (java.util.Properties)2 SAXResult (javax.xml.transform.sax.SAXResult)2 TransformerHandler (javax.xml.transform.sax.TransformerHandler)2 Serializer (org.exist.storage.serializers.Serializer)2 XIncludeFilter (org.exist.storage.serializers.XIncludeFilter)2 BufferedOutputStream (java.io.BufferedOutputStream)1 IOException (java.io.IOException)1 OutputStream (java.io.OutputStream)1 Path (java.nio.file.Path)1 GZIPInputStream (java.util.zip.GZIPInputStream)1 ServletException (javax.servlet.ServletException)1 TransformerException (javax.xml.transform.TransformerException)1 StreamResult (javax.xml.transform.stream.StreamResult)1 EXistException (org.exist.EXistException)1 DocumentBuilderReceiver (org.exist.dom.memtree.DocumentBuilderReceiver)1 MemTreeBuilder (org.exist.dom.memtree.MemTreeBuilder)1 ResponseWrapper (org.exist.http.servlets.ResponseWrapper)1 AuthenticationException (org.exist.security.AuthenticationException)1 Subject (org.exist.security.Subject)1 DBBroker (org.exist.storage.DBBroker)1