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;
}
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);
}
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();
}
}
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;
}
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);
}
}
Aggregations