Search in sources :

Example 6 with Module

use of org.exist.xquery.Module in project exist by eXist-db.

the class FunctionFunction method lookupFunction.

private FunctionCall lookupFunction(String funcName, int arity) throws XPathException {
    // try to parse the qname
    QName qname;
    try {
        qname = QName.parse(context, funcName, context.getDefaultFunctionNamespace());
    } catch (final QName.IllegalQNameException e) {
        throw new XPathException(this, ErrorCodes.XPST0081, "No namespace defined for prefix " + funcName);
    }
    // check if the function is from a module
    final Module[] modules = context.getModules(qname.getNamespaceURI());
    UserDefinedFunction func = null;
    if (isEmpty(modules)) {
        func = context.resolveFunction(qname, arity);
    } else {
        for (final Module module : modules) {
            func = ((ExternalModule) module).getFunction(qname, arity, context);
            if (func != null) {
                if (module.isInternalModule()) {
                    logger.error("Cannot create a reference to an internal Java function");
                    throw new XPathException(this, "Cannot create a reference to an internal Java function");
                }
                break;
            }
        }
    }
    if (func == null) {
        throw new XPathException(this, Messages.getMessage(Error.FUNC_NOT_FOUND, qname, Integer.toString(arity)));
    }
    final FunctionCall funcCall = new FunctionCall(context, func);
    funcCall.setLocation(line, column);
    return funcCall;
}
Also used : QName(org.exist.dom.QName) Module(org.exist.xquery.Module)

Example 7 with Module

use of org.exist.xquery.Module in project exist by eXist-db.

the class LoadXQueryModule method eval.

@Override
public Sequence eval(Sequence[] args, Sequence contextSequence) throws XPathException {
    final String targetNamespace = args[0].getStringValue();
    if (targetNamespace.isEmpty()) {
        throw new XPathException(this, ErrorCodes.FOQM0001, "Target namespace must be a string with length > 0");
    }
    AnyURIValue[] locationHints = null;
    String xqVersion = getXQueryVersion(context.getXQueryVersion());
    AbstractMapType externalVars = new MapType(context);
    Sequence contextItem = Sequence.EMPTY_SEQUENCE;
    // evaluate options
    if (getArgumentCount() == 2) {
        final AbstractMapType map = (AbstractMapType) args[1].itemAt(0);
        final Sequence locationHintsOption = map.get(OPTIONS_LOCATION_HINTS);
        locationHints = new AnyURIValue[locationHintsOption.getItemCount()];
        for (int i = 0; i < locationHints.length; i++) {
            locationHints[i] = (AnyURIValue) locationHintsOption.itemAt(i).convertTo(Type.ANY_URI);
        }
        final Sequence versions = map.get(OPTIONS_XQUERY_VERSION);
        if (!versions.isEmpty()) {
            xqVersion = versions.itemAt(0).getStringValue();
        }
        final Sequence vars = map.get(OPTIONS_VARIABLES);
        if (!vars.isEmpty()) {
            if (vars.hasOne() && vars.itemAt(0).getType() == Type.MAP) {
                externalVars = (AbstractMapType) vars.itemAt(0);
            } else {
                throw new XPathException(this, ErrorCodes.XPTY0004, "Option 'variables' must be a map");
            }
        }
        contextItem = map.get(OPTIONS_CONTEXT_ITEM);
        if (contextItem.getItemCount() > 1) {
            throw new XPathException(this, ErrorCodes.XPTY0004, "Option 'context-item' must contain zero or one " + "items");
        }
    }
    // create temporary context so main context is not polluted
    final XQueryContext tempContext = new XQueryContext(context.getBroker().getBrokerPool(), context.getProfiler());
    tempContext.setModuleLoadPath(context.getModuleLoadPath());
    setExternalVars(externalVars, tempContext::declareGlobalVariable);
    tempContext.prepareForExecution();
    Module[] loadedModules = null;
    try {
        loadedModules = tempContext.importModule(targetNamespace, null, locationHints);
    } catch (final XPathException e) {
        if (e.getErrorCode() == ErrorCodes.XQST0059) {
            // importModule may throw exception if no location is given and module cannot be resolved
            throw new XPathException(this, ErrorCodes.FOQM0002, "Module with URI " + targetNamespace + " not found");
        }
        throw new XPathException(this, ErrorCodes.FOQM0003, "Error found when importing module: " + e.getMessage());
    }
    // not found, raise error
    if (loadedModules == null || loadedModules.length == 0) {
        throw new XPathException(this, ErrorCodes.FOQM0002, "Module with URI " + targetNamespace + " not found");
    }
    if (!xqVersion.equals(getXQueryVersion(tempContext.getXQueryVersion()))) {
        throw new XPathException(ErrorCodes.FOQM0003, "Imported module has wrong XQuery version: " + getXQueryVersion(tempContext.getXQueryVersion()));
    }
    final IMap<AtomicValue, Sequence> variables = newLinearMap(null);
    final IMap<AtomicValue, IMap<AtomicValue, Sequence>> functions = newLinearMap(null);
    for (final Module loadedModule : loadedModules) {
        loadedModule.setContextItem(contextItem);
        setExternalVars(externalVars, loadedModule::declareVariable);
        if (!loadedModule.isInternalModule()) {
            // ensure variable declarations in the imported module are analyzed.
            // unlike when using a normal import statement, this is not done automatically
            ((ExternalModule) loadedModule).analyzeGlobalVars();
        }
        getModuleVariables(loadedModule, variables);
        getModuleFunctions(loadedModule, tempContext, functions);
    }
    final IMap<AtomicValue, Sequence> result = Map.from(io.lacuna.bifurcan.List.of(new Maps.Entry<>(RESULT_FUNCTIONS, new MapType(context, functions.mapValues((k, v) -> (Sequence) new MapType(context, v.forked(), Type.INTEGER)).forked(), Type.QNAME)), new Maps.Entry<>(RESULT_VARIABLES, new MapType(context, variables.forked(), Type.QNAME))));
    return new MapType(context, result, Type.STRING);
}
Also used : IEntry(io.lacuna.bifurcan.IEntry) AbstractMapType(org.exist.xquery.functions.map.AbstractMapType) java.util(java.util) Module(org.exist.xquery.Module) MapType.newLinearMap(org.exist.xquery.functions.map.MapType.newLinearMap) QName(org.exist.dom.QName) MapType(org.exist.xquery.functions.map.MapType) org.exist.xquery.value(org.exist.xquery.value) XQueryAST(org.exist.xquery.parser.XQueryAST) org.exist.xquery(org.exist.xquery) Maps(io.lacuna.bifurcan.Maps) ConsumerE(com.evolvedbinary.j8fu.function.ConsumerE) IMap(io.lacuna.bifurcan.IMap) Map(io.lacuna.bifurcan.Map) AbstractMapType(org.exist.xquery.functions.map.AbstractMapType) AbstractMapType(org.exist.xquery.functions.map.AbstractMapType) MapType(org.exist.xquery.functions.map.MapType) IMap(io.lacuna.bifurcan.IMap) IEntry(io.lacuna.bifurcan.IEntry) Module(org.exist.xquery.Module)

Example 8 with Module

use of org.exist.xquery.Module in project exist by eXist-db.

the class InspectModule method eval.

@Override
public Sequence eval(final Sequence[] args, final Sequence contextSequence) throws XPathException {
    final XQueryContext tempContext = new XQueryContext(context.getBroker().getBrokerPool());
    tempContext.setModuleLoadPath(context.getModuleLoadPath());
    final Module[] modules;
    if (isCalledAs(FN_INSPECT_MODULE_NAME)) {
        modules = tempContext.importModule(null, null, new AnyURIValue[] { (AnyURIValue) args[0].itemAt(0) });
    } else {
        modules = tempContext.importModule(args[0].getStringValue(), null, null);
    }
    if (modules == null || modules.length == 0) {
        return Sequence.EMPTY_SEQUENCE;
    }
    // this function only supports working with a singular module for a namespace!
    final Module module = modules[0];
    try {
        context.pushDocumentContext();
        final MemTreeBuilder builder = context.getDocumentBuilder();
        final AttributesImpl attribs = new AttributesImpl();
        attribs.addAttribute("", "uri", "uri", "CDATA", module.getNamespaceURI());
        attribs.addAttribute("", "prefix", "prefix", "CDATA", module.getDefaultPrefix());
        if (module.isInternalModule()) {
            attribs.addAttribute("", "location", "location", "CDATA", "java:" + module.getClass().getName());
        } else if (isCalledAs("inspect-module")) {
            attribs.addAttribute("", "location", "location", "CDATA", args[0].getStringValue());
        }
        final int nodeNr = builder.startElement(MODULE_QNAME, attribs);
        if (!module.isInternalModule()) {
            XQDocHelper.parse((ExternalModule) module);
        }
        if (module.getDescription() != null) {
            builder.startElement(InspectFunctionHelper.DESCRIPTION_QNAME, null);
            builder.characters(module.getDescription());
            builder.endElement();
        }
        if (!module.isInternalModule()) {
            final ExternalModule externalModule = (ExternalModule) module;
            if (externalModule.getMetadata() != null) {
                for (final Map.Entry<String, String> entry : externalModule.getMetadata().entrySet()) {
                    builder.startElement(new QName(entry.getKey(), XMLConstants.NULL_NS_URI), null);
                    builder.characters(entry.getValue());
                    builder.endElement();
                }
            }
            // variables
            for (final VariableDeclaration var : externalModule.getVariableDeclarations()) {
                attribs.clear();
                attribs.addAttribute("", "name", "name", "CDATA", var.getName().toString());
                final SequenceType type = var.getSequenceType();
                if (type != null) {
                    attribs.addAttribute("", "type", "type", "CDATA", Type.getTypeName(type.getPrimaryType()));
                    attribs.addAttribute("", "cardinality", "cardinality", "CDATA", type.getCardinality().getHumanDescription());
                }
                builder.startElement(VARIABLE_QNAME, attribs);
                builder.endElement();
            }
        }
        // functions
        for (final FunctionSignature sig : module.listFunctions()) {
            if (!sig.isPrivate()) {
                UserDefinedFunction func = null;
                if (!module.isInternalModule()) {
                    func = ((ExternalModule) module).getFunction(sig.getName(), sig.getArgumentCount(), null);
                }
                InspectFunctionHelper.generateDocs(sig, func, builder);
            }
        }
        builder.endElement();
        return builder.getDocument().getNode(nodeNr);
    } finally {
        context.popDocumentContext();
    }
}
Also used : QName(org.exist.dom.QName) AttributesImpl(org.xml.sax.helpers.AttributesImpl) MemTreeBuilder(org.exist.dom.memtree.MemTreeBuilder) Module(org.exist.xquery.Module) Map(java.util.Map)

Example 9 with Module

use of org.exist.xquery.Module in project exist by eXist-db.

the class ModuleFunctions method eval.

@Override
public Sequence eval(final Sequence[] args, final Sequence contextSequence) throws XPathException {
    final ValueSequence list = new ValueSequence();
    if (getArgumentCount() == 1) {
        final XQueryContext tempContext = new XQueryContext(context.getBroker().getBrokerPool(), context.getProfiler());
        tempContext.setModuleLoadPath(context.getModuleLoadPath());
        tempContext.prepareForExecution();
        final AnyURIValue uri = ((AnyURIValue) args[0].itemAt(0));
        if (isCalledAs(FS_MODULE_FUNCTIONS_NAME)) {
            try {
                final URI locationUri = uri.toURI();
                final Source source = SourceFactory.getSource(context.getBroker(), tempContext.getModuleLoadPath(), locationUri.toString(), false);
                if (source != null) {
                    tempContext.setSource(source);
                }
            } catch (final IOException | PermissionDeniedException e) {
                throw new XPathException(this, ErrorCodes.XQST0059, e.getMessage());
            }
        }
        // attempt to import the module
        Module[] modules = null;
        try {
            modules = tempContext.importModule(null, null, new AnyURIValue[] { uri });
        } catch (final XPathException e) {
            if (e.getErrorCode().equals(ErrorCodes.XQST0059)) {
                if (LOG.isDebugEnabled()) {
                    LOG.debug("Failed to import module: {}: {}", args[0].getStringValue(), e.getMessage(), e);
                }
                modules = null;
            } else {
                if (e.getLine() < 1) {
                    e.setLocation(this.getLine(), this.getColumn(), this.getSource());
                }
                throw e;
            }
        }
        if (modules == null || modules.length == 0) {
            return Sequence.EMPTY_SEQUENCE;
        }
        // there can be only one!
        final Module module = modules[0];
        if (!module.isInternalModule()) {
            // ensure variable declarations in the imported module are analyzed.
            // unlike when using a normal import statement, this is not done automatically
            ((ExternalModule) module).analyzeGlobalVars();
        }
        LoadXQueryModule.addFunctionRefsFromModule(this, tempContext, list, module);
    } else {
        addFunctionRefsFromContext(list);
    }
    return list;
}
Also used : PermissionDeniedException(org.exist.security.PermissionDeniedException) IOException(java.io.IOException) Module(org.exist.xquery.Module) LoadXQueryModule(org.exist.xquery.functions.fn.LoadXQueryModule) URI(java.net.URI) Source(org.exist.source.Source)

Example 10 with Module

use of org.exist.xquery.Module in project exist by eXist-db.

the class ExistRepository method getModule.

/**
 * Load a module instance from its class name.  Check the namespace is consistent.
 */
private Module getModule(final String name, final String namespace, final XQueryContext ctxt) throws XPathException {
    try {
        final ClassLoader existClassLoader = ctxt.getBroker().getBrokerPool().getClassLoader();
        final Class<Module> clazz = (Class<Module>) Class.forName(name, false, existClassLoader);
        final Module module = instantiateModule(clazz);
        final String ns = module.getNamespaceURI();
        if (!ns.equals(namespace)) {
            throw new XPathException("The namespace in the Java module " + "does not match the namespace in the package descriptor: " + namespace + " - " + ns);
        }
        return ctxt.loadBuiltInModule(namespace, name);
    } catch (final ClassNotFoundException ex) {
        throw new XPathException("Cannot find module class from EXPath repository: " + name, ex);
    } catch (final ClassCastException ex) {
        throw new XPathException("The class configured in EXPath repository is not a Module: " + name, ex);
    } catch (final IllegalArgumentException ex) {
        throw new XPathException("Illegal argument passed to the module ctor", ex);
    }
}
Also used : XPathException(org.exist.xquery.XPathException) Module(org.exist.xquery.Module)

Aggregations

Module (org.exist.xquery.Module)12 QName (org.exist.dom.QName)5 MemTreeBuilder (org.exist.dom.memtree.MemTreeBuilder)3 URI (java.net.URI)2 Map (java.util.Map)2 Source (org.exist.source.Source)2 ExternalModule (org.exist.xquery.ExternalModule)2 XPathException (org.exist.xquery.XPathException)2 AttributesImpl (org.xml.sax.helpers.AttributesImpl)2 ConsumerE (com.evolvedbinary.j8fu.function.ConsumerE)1 IEntry (io.lacuna.bifurcan.IEntry)1 IMap (io.lacuna.bifurcan.IMap)1 Map (io.lacuna.bifurcan.Map)1 Maps (io.lacuna.bifurcan.Maps)1 IOException (java.io.IOException)1 java.util (java.util)1 TreeSet (java.util.TreeSet)1 DocumentImpl (org.exist.dom.memtree.DocumentImpl)1 RequestWrapper (org.exist.http.servlets.RequestWrapper)1 PermissionDeniedException (org.exist.security.PermissionDeniedException)1