Search in sources :

Example 16 with ElementImpl

use of org.exist.dom.memtree.ElementImpl in project exist by eXist-db.

the class RESTServer method doGet.

/**
 * Handle GET request. In the simplest case just returns the document or
 * binary resource specified in the path. If the path leads to a collection,
 * a listing of the collection contents is returned. If it resolves to a
 * binary resource with mime-type "application/xquery", this resource will
 * be loaded and executed by the XQuery engine.
 *
 * The method also recognizes a number of predefined parameters:
 *
 * <ul> <li>_xpath or _query: if specified, the given query is executed on
 * the current resource or collection.</li>
 *
 * <li>_howmany: defines how many items from the query result will be
 * returned.</li>
 *
 * <li>_start: a start offset into the result set.</li>
 *
 * <li>_wrap: if set to "yes", the query results will be wrapped into a
 * exist:result element.</li>
 *
 * <li>_indent: if set to "yes", the returned XML will be pretty-printed.
 * </li>
 *
 * <li>_source: if set to "yes" and a resource with mime-type
 * "application/xquery" is requested then the xquery will not be executed,
 * instead the source of the document will be returned. Must be enabled in
 * descriptor.xml with the following syntax
 * <pre>{@code
 *     <xquery-app>
 *         <allow-source>
 *             <xquery path="/db/mycollection/myquery.xql"/>
 *         </allow-source>
 *     </xquery-app>
 * }</pre>
 * </li>
 *
 * <li>_xsl: an URI pointing to an XSL stylesheet that will be applied to
 * the returned XML.</li>
 * </ul>
 *
 * @param broker the database broker
 * @param transaction the database transaction
 * @param request the request
 * @param response the response
 * @param path the path of the request
 *
 * @throws BadRequestException if a bad request is made
 * @throws PermissionDeniedException if the request has insufficient permissions
 * @throws NotFoundException if the request resource cannot be found
 * @throws IOException if an I/O error occurs
 */
public void doGet(final DBBroker broker, final Txn transaction, final HttpServletRequest request, final HttpServletResponse response, final String path) throws BadRequestException, PermissionDeniedException, NotFoundException, IOException {
    // if required, set character encoding
    if (request.getCharacterEncoding() == null) {
        request.setCharacterEncoding(formEncoding);
    }
    String option;
    if ((option = getParameter(request, Release)) != null) {
        final int sessionId = Integer.parseInt(option);
        sessionManager.release(sessionId);
        if (LOG.isDebugEnabled()) {
            LOG.debug("Released session {}", sessionId);
        }
        response.setStatus(HttpServletResponse.SC_OK);
        return;
    }
    // Process special parameters
    int howmany = 10;
    int start = 1;
    boolean typed = false;
    boolean wrap = true;
    boolean source = false;
    boolean cache = false;
    final Properties outputProperties = new Properties(defaultOutputKeysProperties);
    String query = null;
    if (!safeMode) {
        query = getParameter(request, XPath);
        if (query == null) {
            query = getParameter(request, Query);
        }
    }
    final String _var = getParameter(request, Variables);
    List /*<Namespace>*/
    namespaces = null;
    ElementImpl variables = null;
    try {
        if (_var != null) {
            final NamespaceExtractor nsExtractor = new NamespaceExtractor();
            variables = parseXML(broker.getBrokerPool(), _var, nsExtractor);
            namespaces = nsExtractor.getNamespaces();
        }
    } catch (final SAXException e) {
        final XPathException x = new XPathException(e.toString());
        writeXPathException(response, HttpServletResponse.SC_BAD_REQUEST, "UTF-8", query, path, x);
    }
    if ((option = getParameter(request, HowMany)) != null) {
        try {
            howmany = Integer.parseInt(option);
        } catch (final NumberFormatException nfe) {
            throw new BadRequestException("Parameter _howmany should be an int");
        }
    }
    if ((option = getParameter(request, Start)) != null) {
        try {
            start = Integer.parseInt(option);
        } catch (final NumberFormatException nfe) {
            throw new BadRequestException("Parameter _start should be an int");
        }
    }
    if ((option = getParameter(request, Typed)) != null) {
        if ("yes".equals(option.toLowerCase())) {
            typed = true;
        }
    }
    if ((option = getParameter(request, Wrap)) != null) {
        wrap = "yes".equals(option);
        outputProperties.setProperty("_wrap", option);
    }
    if ((option = getParameter(request, Cache)) != null) {
        cache = "yes".equals(option);
    }
    if ((option = getParameter(request, Indent)) != null) {
        outputProperties.setProperty(OutputKeys.INDENT, option);
    }
    if ((option = getParameter(request, Source)) != null && !safeMode) {
        source = "yes".equals(option);
    }
    if ((option = getParameter(request, Session)) != null) {
        outputProperties.setProperty(Serializer.PROPERTY_SESSION_ID, option);
    }
    String stylesheet;
    if ((stylesheet = getParameter(request, XSL)) != null) {
        if ("no".equals(stylesheet)) {
            outputProperties.setProperty(EXistOutputKeys.PROCESS_XSL_PI, "no");
            outputProperties.remove(EXistOutputKeys.STYLESHEET);
            stylesheet = null;
        } else {
            outputProperties.setProperty(EXistOutputKeys.STYLESHEET, stylesheet);
        }
    } else {
        outputProperties.setProperty(EXistOutputKeys.PROCESS_XSL_PI, "yes");
    }
    LOG.debug("stylesheet = {}", stylesheet);
    LOG.debug("query = {}", query);
    String encoding;
    if ((encoding = getParameter(request, Encoding)) != null) {
        outputProperties.setProperty(OutputKeys.ENCODING, encoding);
    } else {
        encoding = "UTF-8";
    }
    final String mimeType = outputProperties.getProperty(OutputKeys.MEDIA_TYPE);
    if (query != null) {
        // query parameter specified, search method does all the rest of the work
        try {
            search(broker, transaction, query, path, namespaces, variables, howmany, start, typed, outputProperties, wrap, cache, request, response);
        } catch (final XPathException e) {
            if (MimeType.XML_TYPE.getName().equals(mimeType)) {
                writeXPathException(response, HttpServletResponse.SC_BAD_REQUEST, encoding, query, path, e);
            } else {
                writeXPathExceptionHtml(response, HttpServletResponse.SC_BAD_REQUEST, encoding, query, path, e);
            }
        }
        return;
    }
    // Process the request
    LockedDocument lockedDocument = null;
    DocumentImpl resource = null;
    final XmldbURI pathUri = XmldbURI.createInternal(path);
    try {
        // check if path leads to an XQuery resource
        final String xquery_mime_type = MimeType.XQUERY_TYPE.getName();
        final String xproc_mime_type = MimeType.XPROC_TYPE.getName();
        lockedDocument = broker.getXMLResource(pathUri, LockMode.READ_LOCK);
        resource = lockedDocument == null ? null : lockedDocument.getDocument();
        if (null != resource && !isExecutableType(resource)) {
            // return regular resource that is not an xquery and not is xproc
            writeResourceAs(resource, broker, transaction, stylesheet, encoding, null, outputProperties, request, response);
            return;
        }
        if (resource == null) {
            // no document: check if path points to a collection
            try (final Collection collection = broker.openCollection(pathUri, LockMode.READ_LOCK)) {
                if (collection != null) {
                    if (safeMode || !collection.getPermissionsNoLock().validate(broker.getCurrentSubject(), Permission.READ)) {
                        throw new PermissionDeniedException("Not allowed to read collection");
                    }
                    // return a listing of the collection contents
                    try {
                        writeCollection(response, encoding, broker, collection);
                        return;
                    } catch (final LockException le) {
                        if (MimeType.XML_TYPE.getName().equals(mimeType)) {
                            writeXPathException(response, HttpServletResponse.SC_BAD_REQUEST, encoding, query, path, new XPathException(le.getMessage(), le));
                        } else {
                            writeXPathExceptionHtml(response, HttpServletResponse.SC_BAD_REQUEST, encoding, query, path, new XPathException(le.getMessage(), le));
                        }
                    }
                } else if (source) {
                    // on a possible xquery resource that was not found
                    throw new NotFoundException("Document " + path + " not found");
                }
            }
        }
        XmldbURI servletPath = pathUri;
        // xquery or xproc resource
        while (null == resource) {
            // traverse up the path looking for xquery objects
            servletPath = servletPath.removeLastSegment();
            if (servletPath == XmldbURI.EMPTY_URI) {
                break;
            }
            lockedDocument = broker.getXMLResource(servletPath, LockMode.READ_LOCK);
            resource = lockedDocument == null ? null : lockedDocument.getDocument();
            if (null != resource && isExecutableType(resource)) {
                break;
            } else if (null != resource) {
                // moving up the path, so bail out now
                throw new NotFoundException("Document " + path + " not found");
            }
        }
        if (null == resource) {
            // path search failed
            throw new NotFoundException("Document " + path + " not found");
        }
        // found an XQuery or XProc resource, fixup request values
        final String pathInfo = pathUri.trimFromBeginning(servletPath).toString();
        // Should we display the source of the XQuery or XProc or execute it
        final Descriptor descriptor = Descriptor.getDescriptorSingleton();
        if (source) {
            // descriptor.xml
            if ((null != descriptor) && descriptor.allowSource(path) && resource.getPermissions().validate(broker.getCurrentSubject(), Permission.READ)) {
                if (xquery_mime_type.equals(resource.getMimeType())) {
                    // Show the source of the XQuery
                    writeResourceAs(resource, broker, transaction, stylesheet, encoding, MimeType.TEXT_TYPE.getName(), outputProperties, request, response);
                } else if (xproc_mime_type.equals(resource.getMimeType())) {
                    // Show the source of the XProc
                    writeResourceAs(resource, broker, transaction, stylesheet, encoding, MimeType.XML_TYPE.getName(), outputProperties, request, response);
                }
            } else {
                // we are not allowed to show the source - query not
                // allowed in descriptor.xml
                // or descriptor not found, so assume source view not
                // allowed
                response.sendError(HttpServletResponse.SC_FORBIDDEN, "Permission to view XQuery source for: " + path + " denied. Must be explicitly defined in descriptor.xml");
                return;
            }
        } else {
            try {
                if (xquery_mime_type.equals(resource.getMimeType())) {
                    // Execute the XQuery
                    executeXQuery(broker, transaction, resource, request, response, outputProperties, servletPath.toString(), pathInfo);
                } else if (xproc_mime_type.equals(resource.getMimeType())) {
                    // Execute the XProc
                    executeXProc(broker, transaction, resource, request, response, outputProperties, servletPath.toString(), pathInfo);
                }
            } catch (final XPathException e) {
                if (LOG.isDebugEnabled()) {
                    LOG.debug(e.getMessage(), e);
                }
                if (MimeType.XML_TYPE.getName().equals(mimeType)) {
                    writeXPathException(response, HttpServletResponse.SC_BAD_REQUEST, encoding, query, path, e);
                } else {
                    writeXPathExceptionHtml(response, HttpServletResponse.SC_BAD_REQUEST, encoding, query, path, e);
                }
            }
        }
    } finally {
        if (lockedDocument != null) {
            lockedDocument.close();
        }
    }
}
Also used : Properties(java.util.Properties) SAXException(org.xml.sax.SAXException) ElementImpl(org.exist.dom.memtree.ElementImpl) Collection(org.exist.collections.Collection) NodeList(org.w3c.dom.NodeList) PermissionDeniedException(org.exist.security.PermissionDeniedException) XmldbURI(org.exist.xmldb.XmldbURI)

Aggregations

ElementImpl (org.exist.dom.memtree.ElementImpl)16 BrokerPool (org.exist.storage.BrokerPool)7 DBBroker (org.exist.storage.DBBroker)7 Sequence (org.exist.xquery.value.Sequence)7 QName (org.exist.dom.QName)6 XQuery (org.exist.xquery.XQuery)6 NodeList (org.w3c.dom.NodeList)6 MemTreeBuilder (org.exist.dom.memtree.MemTreeBuilder)5 Item (org.exist.xquery.value.Item)5 Test (org.junit.Test)5 Element (org.w3c.dom.Element)5 Txn (org.exist.storage.txn.Txn)4 XQueryContext (org.exist.xquery.XQueryContext)3 Properties (java.util.Properties)2 XMLStreamException (javax.xml.stream.XMLStreamException)2 Collection (org.exist.collections.Collection)2 PermissionDeniedException (org.exist.security.PermissionDeniedException)2 XmldbURI (org.exist.xmldb.XmldbURI)2 Node (org.w3c.dom.Node)2 InputSource (org.xml.sax.InputSource)2