Search in sources :

Example 1 with DBSource

use of org.exist.source.DBSource in project exist by eXist-db.

the class RESTServer method executeXQuery.

/**
 * Directly execute an XQuery stored as a binary document in the database.
 *
 * @throws PermissionDeniedException
 */
private void executeXQuery(final DBBroker broker, final Txn transaction, final DocumentImpl resource, final HttpServletRequest request, final HttpServletResponse response, final Properties outputProperties, final String servletPath, final String pathInfo) throws XPathException, BadRequestException, PermissionDeniedException {
    final Source source = new DBSource(broker, (BinaryDocument) resource, true);
    final XQueryPool pool = broker.getBrokerPool().getXQueryPool();
    CompiledXQuery compiled = null;
    try {
        final XQuery xquery = broker.getBrokerPool().getXQueryService();
        compiled = pool.borrowCompiledXQuery(broker, source);
        XQueryContext context;
        if (compiled == null) {
            // special header to indicate that the query is not returned from
            // cache
            response.setHeader("X-XQuery-Cached", "false");
            context = new XQueryContext(broker.getBrokerPool());
        } else {
            response.setHeader("X-XQuery-Cached", "true");
            context = compiled.getContext();
            context.prepareForReuse();
        }
        // TODO: don't hardcode this?
        context.setModuleLoadPath(XmldbURI.EMBEDDED_SERVER_URI.append(resource.getCollection().getURI()).toString());
        context.setStaticallyKnownDocuments(new XmldbURI[] { resource.getCollection().getURI() });
        final HttpRequestWrapper reqw = declareVariables(context, null, request, response);
        reqw.setServletPath(servletPath);
        reqw.setPathInfo(pathInfo);
        final long compilationTime;
        if (compiled == null) {
            try {
                final long compilationStart = System.currentTimeMillis();
                compiled = xquery.compile(context, source);
                compilationTime = System.currentTimeMillis() - compilationStart;
            } catch (final IOException e) {
                throw new BadRequestException("Failed to read query from " + resource.getURI(), e);
            }
        } else {
            compilationTime = 0;
        }
        DebuggeeFactory.checkForDebugRequest(request, context);
        boolean wrap = outputProperties.getProperty("_wrap") != null && "yes".equals(outputProperties.getProperty("_wrap"));
        try {
            final long executeStart = System.currentTimeMillis();
            final Sequence result = xquery.execute(broker, compiled, null, outputProperties);
            writeResults(response, broker, transaction, result, -1, 1, false, outputProperties, wrap, compilationTime, System.currentTimeMillis() - executeStart);
        } finally {
            context.runCleanupTasks();
        }
    } finally {
        if (compiled != null) {
            pool.returnCompiledXQuery(source, compiled);
        }
    }
}
Also used : XQueryPool(org.exist.storage.XQueryPool) HttpRequestWrapper(org.exist.http.servlets.HttpRequestWrapper) DBSource(org.exist.source.DBSource) StringSource(org.exist.source.StringSource) Source(org.exist.source.Source) DBSource(org.exist.source.DBSource) InputSource(org.xml.sax.InputSource) URLSource(org.exist.source.URLSource)

Example 2 with DBSource

use of org.exist.source.DBSource in project exist by eXist-db.

the class XQueryURLRewrite method getSource.

private SourceInfo getSource(final DBBroker broker, final String moduleLoadPath) throws ServletException {
    final SourceInfo sourceInfo;
    if (query.startsWith(XmldbURI.XMLDB_URI_PREFIX)) {
        // Is the module source stored in the database?
        try {
            final XmldbURI locationUri = XmldbURI.xmldbUriFor(query);
            try (final LockedDocument lockedSourceDoc = broker.getXMLResource(locationUri.toCollectionPathURI(), LockMode.READ_LOCK)) {
                if (lockedSourceDoc == null) {
                    throw new ServletException("XQuery resource: " + query + " not found in database");
                }
                final DocumentImpl sourceDoc = lockedSourceDoc.getDocument();
                if (sourceDoc.getResourceType() != DocumentImpl.BINARY_FILE || !"application/xquery".equals(sourceDoc.getMimeType())) {
                    throw new ServletException("XQuery resource: " + query + " is not an XQuery or " + "declares a wrong mime-type");
                }
                sourceInfo = new SourceInfo(new DBSource(broker, (BinaryDocument) sourceDoc, true), locationUri.toString());
            } catch (final PermissionDeniedException e) {
                throw new ServletException("permission denied to read module source from " + query);
            }
        } catch (final URISyntaxException e) {
            throw new ServletException(e.getMessage(), e);
        }
    } else {
        try {
            sourceInfo = new SourceInfo(SourceFactory.getSource(broker, moduleLoadPath, query, true), moduleLoadPath);
        } catch (final IOException e) {
            throw new ServletException("IO error while reading XQuery source: " + query);
        } catch (final PermissionDeniedException e) {
            throw new ServletException("Permission denied while reading XQuery source: " + query);
        }
    }
    return sourceInfo;
}
Also used : LockedDocument(org.exist.dom.persistent.LockedDocument) DBSource(org.exist.source.DBSource) PermissionDeniedException(org.exist.security.PermissionDeniedException) URISyntaxException(java.net.URISyntaxException) DocumentImpl(org.exist.dom.persistent.DocumentImpl) XmldbURI(org.exist.xmldb.XmldbURI)

Example 3 with DBSource

use of org.exist.source.DBSource in project exist by eXist-db.

the class Eval method doEval.

private Sequence doEval(final XQueryContext evalContext, final Sequence contextSequence, final Sequence[] args) throws XPathException {
    if (evalContext.getProfiler().isEnabled()) {
        evalContext.getProfiler().start(this);
        evalContext.getProfiler().message(this, Profiler.DEPENDENCIES, "DEPENDENCIES", Dependency.getDependenciesName(this.getDependencies()));
        if (contextSequence != null) {
            evalContext.getProfiler().message(this, Profiler.START_SEQUENCES, "CONTEXT SEQUENCE", contextSequence);
        }
    }
    int argCount = 0;
    Sequence exprContext = null;
    if (isCalledAs(FS_EVAL_INLINE_NAME)) {
        // the current expression context
        exprContext = args[argCount++];
    }
    // get the query expression
    final Item expr = args[argCount++].itemAt(0);
    final Source querySource;
    if (Type.subTypeOf(expr.getType(), Type.ANY_URI)) {
        querySource = loadQueryFromURI(expr);
    } else {
        final String queryStr = expr.getStringValue();
        if (queryStr.trim().isEmpty()) {
            return new EmptySequence();
        }
        querySource = new StringSource(queryStr);
    }
    final NodeValue contextInit;
    if (isCalledAs(FS_EVAL_WITH_CONTEXT_NAME)) {
        // set the context initialization param for later use
        contextInit = (NodeValue) args[argCount++].itemAt(0);
    } else {
        contextInit = null;
    }
    // should the compiled query be cached?
    final boolean cache;
    if (isCalledAs(FS_EVAL_AND_SERIALIZE_NAME)) {
        cache = true;
    } else if (argCount < getArgumentCount()) {
        cache = ((BooleanValue) args[argCount++].itemAt(0)).effectiveBooleanValue();
    } else {
        cache = false;
    }
    // save some context properties
    evalContext.pushNamespaceContext();
    final LocalVariable mark = evalContext.markLocalVariables(false);
    // save the static document set of the current context, so it can be restored later
    final DocumentSet oldDocs = evalContext.getStaticDocs();
    if (exprContext != null) {
        evalContext.setStaticallyKnownDocuments(exprContext.getDocumentSet());
    }
    if (evalContext.isProfilingEnabled(2)) {
        evalContext.getProfiler().start(this, "eval: " + expr);
    }
    // fixme! - hook for debugger here /ljo
    final XQuery xqueryService = evalContext.getBroker().getBrokerPool().getXQueryService();
    final XQueryContext innerContext;
    final Sequence initContextSequence;
    if (contextInit != null) {
        // eval-with-context: initialize a new context
        innerContext = new XQueryContext(context.getBroker().getBrokerPool());
        initContextSequence = initContext(contextInit.getNode(), innerContext);
    } else {
        // use the existing outer context
        // TODO: check if copying the static context would be sufficient???
        innerContext = evalContext.copyContext();
        innerContext.setShared(true);
        // innerContext = context;
        initContextSequence = null;
    }
    // set module load path
    if (Type.subTypeOf(expr.getType(), Type.ANY_URI)) {
        String uri = null;
        if (querySource instanceof DBSource) {
            final XmldbURI documentPath = ((DBSource) querySource).getDocumentPath();
            uri = XmldbURI.EMBEDDED_SERVER_URI.append(documentPath).removeLastSegment().toString();
        } else if (querySource instanceof FileSource) {
            uri = ((FileSource) querySource).getPath().getParent().toString();
        }
        if (uri != null) {
            innerContext.setModuleLoadPath(uri);
        }
    }
    // bind external vars?
    if (isCalledAs(FS_EVAL_NAME) && getArgumentCount() >= 3) {
        final Sequence externalVars = args[argCount++];
        for (int i = 0; i < externalVars.getItemCount(); i++) {
            final Item varName = externalVars.itemAt(i);
            if (varName.getType() == Type.QNAME) {
                final Item varValue = externalVars.itemAt(++i);
                innerContext.declareVariable(((QNameValue) varName).getQName(), varValue);
            }
        }
    }
    // determine if original line/column number are passed on
    final boolean pass;
    if (isCalledAs(FS_EVAL_NAME) && getArgumentCount() == 4) {
        pass = args[3].itemAt(0).toJavaObject(Boolean.class);
    } else if (isCalledAs(FS_EVAL_WITH_CONTEXT_NAME) && getArgumentCount() == 5) {
        pass = args[4].itemAt(0).toJavaObject(Boolean.class);
    } else if (isCalledAs(FS_EVAL_INLINE_NAME) && getArgumentCount() == 4) {
        pass = args[3].itemAt(0).toJavaObject(Boolean.class);
    } else if (isCalledAs(FS_EVAL_AND_SERIALIZE_NAME) && getArgumentCount() == 5) {
        pass = args[4].itemAt(0).toJavaObject(Boolean.class);
    } else {
        // default
        pass = false;
    }
    // fixme! - hook for debugger here /ljo
    try {
        if (isCalledAs(FS_EVAL_WITH_CONTEXT_NAME) && getArgumentCount() >= 4) {
            final Item contextItem = args[argCount++].itemAt(0);
            if (contextItem != null) {
                // TODO : sort this out
                if (exprContext != null) {
                    LOG.warn("exprContext and contextItem are not null");
                }
                exprContext = contextItem.toSequence();
            }
        }
        if (initContextSequence != null) {
            exprContext = initContextSequence;
        }
        Sequence result = null;
        try {
            if (!isCalledAs(FS_EVAL_AND_SERIALIZE_NAME)) {
                result = execute(evalContext.getBroker(), xqueryService, querySource, innerContext, exprContext, cache, null);
                return result;
            } else {
                // get the default serialization options
                final Properties defaultOutputOptions;
                if (getArgumentCount() >= 2 && !args[1].isEmpty()) {
                    defaultOutputOptions = FunSerialize.getSerializationProperties(this, args[1].itemAt(0));
                } else {
                    defaultOutputOptions = new Properties();
                }
                // execute the query, XQuery prolog serialization options are collected into `xqueryOutputProperties`
                final Properties xqueryOutputProperties = new Properties();
                result = execute(evalContext.getBroker(), xqueryService, querySource, innerContext, exprContext, cache, xqueryOutputProperties);
                // do we need to subsequence the results?
                if (getArgumentCount() > 2) {
                    result = FunSubSequence.subsequence(result, ((DoubleValue) getArgument(2).eval(contextSequence, null).convertTo(Type.DOUBLE)), getArgumentCount() == 3 ? null : ((DoubleValue) getArgument(3).eval(contextSequence, null).convertTo(Type.DOUBLE)));
                }
                // override the default options with the ones from the xquery prolog
                final Properties serializationProperties = new Properties();
                serializationProperties.putAll(defaultOutputOptions);
                serializationProperties.putAll(xqueryOutputProperties);
                // serialize the results
                try (final StringWriter writer = new StringWriter()) {
                    final XQuerySerializer xqSerializer = new XQuerySerializer(context.getBroker(), serializationProperties, writer);
                    final Sequence seq;
                    if (xqSerializer.normalize()) {
                        seq = FunSerialize.normalize(this, context, result);
                    } else {
                        seq = result;
                    }
                    xqSerializer.serialize(seq);
                    return new StringValue(writer.toString());
                } catch (final IOException | SAXException e) {
                    throw new XPathException(this, FnModule.SENR0001, e.getMessage());
                }
            }
        } finally {
            cleanup(evalContext, innerContext, oldDocs, mark, expr, result);
        }
    } catch (final XPathException e) {
        try {
            e.prependMessage("Error while evaluating expression: " + querySource.getContent() + ". ");
        } catch (final IOException e1) {
        }
        if (!pass) {
            e.setLocation(line, column);
        }
        throw e;
    }
}
Also used : XQuerySerializer(org.exist.util.serializer.XQuerySerializer) Properties(java.util.Properties) StringSource(org.exist.source.StringSource) Source(org.exist.source.Source) DBSource(org.exist.source.DBSource) InputSource(org.xml.sax.InputSource) FileSource(org.exist.source.FileSource) SAXException(org.xml.sax.SAXException) StringWriter(java.io.StringWriter) DBSource(org.exist.source.DBSource) XmldbURI(org.exist.xmldb.XmldbURI) FileSource(org.exist.source.FileSource) FunSubSequence(org.exist.xquery.functions.fn.FunSubSequence) IOException(java.io.IOException) StringSource(org.exist.source.StringSource) DocumentSet(org.exist.dom.persistent.DocumentSet)

Example 4 with DBSource

use of org.exist.source.DBSource in project exist by eXist-db.

the class ResourceFunctionExecutorImpl method getEffectiveSubject.

/**
 * If the compiled xquery is setUid and/or setGid
 * we return the EffectiveSubject that should be used
 * for execution
 *
 * @param xquery The XQuery to determine the effective subject for
 * @return Maybe an effective subject or empty if there is no setUid or setGid bits
 */
private Optional<EffectiveSubject> getEffectiveSubject(final CompiledXQuery xquery) {
    final Optional<EffectiveSubject> effectiveSubject;
    final Source src = xquery.getContext().getSource();
    if (src instanceof DBSource) {
        final DBSource dbSrc = (DBSource) src;
        final Permission perm = dbSrc.getPermissions();
        if (perm.isSetUid()) {
            if (perm.isSetGid()) {
                // setUid and SetGid
                effectiveSubject = Optional.of(new EffectiveSubject(perm.getOwner(), perm.getGroup()));
            } else {
                // just setUid
                effectiveSubject = Optional.of(new EffectiveSubject(perm.getOwner()));
            }
        } else if (perm.isSetGid()) {
            // just setGid, so we use the current user as the effective user
            effectiveSubject = Optional.of(new EffectiveSubject(xquery.getContext().getBroker().getCurrentSubject(), perm.getGroup()));
        } else {
            effectiveSubject = Optional.empty();
        }
    } else {
        effectiveSubject = Optional.empty();
    }
    return effectiveSubject;
}
Also used : EffectiveSubject(org.exist.security.EffectiveSubject) Permission(org.exist.security.Permission) DBSource(org.exist.source.DBSource) Source(org.exist.source.Source) DBSource(org.exist.source.DBSource)

Example 5 with DBSource

use of org.exist.source.DBSource in project exist by eXist-db.

the class XQueryInspector method getDependencies.

private static void getDependencies(final XQueryContext xqyCtx, final Map<String, Set<String>> dependencies) {
    final String xqueryUri = getDbUri(xqyCtx.getSource());
    Set<String> depSet = dependencies.get(xqueryUri);
    if (depSet == null) {
        final Iterator<Module> itModule = xqyCtx.getModules();
        while (itModule.hasNext()) {
            final Module module = itModule.next();
            if (module instanceof ExternalModule) {
                final ExternalModule extModule = (ExternalModule) module;
                final Source source = extModule.getSource();
                if (source instanceof DBSource) {
                    final String moduleUri = getDbUri(source);
                    if (depSet == null) {
                        depSet = new HashSet<>();
                    }
                    depSet.add(moduleUri);
                    /*
                         * must merge map here as recursive function
                         * can cause problems with recursive
                         * module imports m1 -> m2 -> m2 -> m1
                         */
                    dependencies.put(xqueryUri, depSet);
                }
                getDependencies(extModule.getContext(), dependencies);
            }
        }
    }
}
Also used : DBSource(org.exist.source.DBSource) Module(org.exist.xquery.Module) ExternalModule(org.exist.xquery.ExternalModule) ExternalModule(org.exist.xquery.ExternalModule) Source(org.exist.source.Source) DBSource(org.exist.source.DBSource)

Aggregations

DBSource (org.exist.source.DBSource)20 Source (org.exist.source.Source)12 XmldbURI (org.exist.xmldb.XmldbURI)10 PermissionDeniedException (org.exist.security.PermissionDeniedException)8 StringSource (org.exist.source.StringSource)8 InputSource (org.xml.sax.InputSource)8 IOException (java.io.IOException)7 BinaryDocument (org.exist.dom.persistent.BinaryDocument)6 LockedDocument (org.exist.dom.persistent.LockedDocument)5 Sequence (org.exist.xquery.value.Sequence)5 URISyntaxException (java.net.URISyntaxException)4 DocumentImpl (org.exist.dom.persistent.DocumentImpl)4 BrokerPool (org.exist.storage.BrokerPool)4 DBBroker (org.exist.storage.DBBroker)4 XQueryPool (org.exist.storage.XQueryPool)4 XQueryContext (org.exist.xquery.XQueryContext)4 Properties (java.util.Properties)3 EXistException (org.exist.EXistException)3 Subject (org.exist.security.Subject)3 FileSource (org.exist.source.FileSource)3