in the XQuery module repository, and how new packages are built and deployed.
==Motivation=Introduction=
One of the reasons why things that makes languages such as Java or Perl have been so successful is the vast amount availability of external libraries that are available to developers.As XQuery is a Turing complete language, but it just provides around 100 comes with only 150 pre-defined functions, which cannot meet all requirements. This is why , additional libraries arise library modules exist – such as [http://www.xqueryfunctionsfunctx.com/ FunctX] – that which extend the language with new features.
BaseX offers two the following mechanisms to make new packages external modules accessible to the XQuery processor:
# With {{Version|7.2.1}}, we offer a simple The internal [[#Packaging|packagingPackaging]] mechanism to directly will install single XQuery and Java JAR modules to in the repository.# The [[#EXPath Packaging|EXPath Packaging]] system provides a generic mechanism for adding XQuery modules to query processors. A package is defined as a {{MonoCode|.xar}} archive, which encapsulates one or more extension libraries.
==UsageAccessing Modules==
All packages are stored in Library modules can be imported with the package repository. The repository is a directory named {{MonoCode|BaseXRepoimport module}} statement, followed by a freely choosable prefix and the namespace of the target module. The specified location may be absolute or {{Mono|repo}}, which resides relative; in your [[Configuration#Home Directory|home directory]]. BaseX provides three commands for interaction with the package repository: <code>[[Commands#REPO_INSTALL|REPO INSTALL]]</code>latter case, <code>[[Commands#REPO_DELETE|REPO DELETE]]</code>it is resolved against the location (i.e., and <code>[[Commands#REPO_LIST|REPO LIST]]</code>''static base URI'') of the calling module. Packages can also Import module statements must be managed from within XQuery, using placed at the [[Repository Module]].beginning of a module:
===Installation==='''Main Module''' <code>hello-universe.xq</code>:
A <pre lang='xquery'>import module or package can be installed with the {{Mono|REPO INSTALL}} commandnamespace m = 'http://basex.org/modules/hello' at 'hello-world. The path to the file has to be given as a parameter, as the following two examples demonstratexqm';m:hello("Universe")</pre>
REPO INSTALL '''Library Module''' <code>hello-world.xqm</code> (in the same directory): <pre lang='xquery'>module namespace m = 'http://files.basex.org/modules/functx-1.0.xarHello'; REPO INSTALL declare function m:hello-($world) { 'Hello ' || $world.xqm};</pre>
The installation will only succeed if the specified file conforms to the constraints described below. If you know that your input no location is validsupplied, you may as well copy modules will be looked up in the files directly to repository. Repository modules are stored in the repository {{Code|repo}} directory, or edit its contents which resides in your [[Configuration#Home Directory|home directory]]. XQuery modules can be manually copied to the repository without deleting directory or installed and reinstalling themdeleted via [[#Commands|commands]].
Since {{Version|7.2.1}}, existing packages are simply replaced (before, an error was raised).The following example calls a function from the FunctX module in the repository:
<pre lang='xquery'>import module namespace functx ==Querying==='http://www.functx.com';functx:capitalize-first('test')</pre>
Installed packages can be addressed by importing them as ''modules''. Since we have the package repository in which all packages are located, it is sufficient to just specify the namespace URI of a module:=Commands=
<pre class="brushThere are various ways to organize your packages:xquery">import module namespace functx = "http://www.functx.com";</pre>
When this statement is parsed, the query processor will check if the namespace "http://www.functx.com" is used in any * Execute BaseX REPO commands (listed below)* Call XQuery functions of the installed packages and, if yes, will load and parse the modules. In the remaining query, you can call the parsed module functions in [[Repository Module]]* Use the standard way, e.g.:GUI (''Options'' → ''Packages'')
<pre class="brush:xquery">functx:capitalize-first("test")</pre>You can even manually add and remove packages in the repository directory; all changes will automatically be detected by BaseX.
Package encapsulating Java archives can be imported in the same way as pure XQuery modules (see below).==Installation==
===Listing===A module or package can be installed with {{Command|REPO INSTALL}}. The path to the file has to be given as a parameter:
All currently installed packages can be listed with the <code> REPO LIST<INSTALL https:/code> command/files.basex. It will return the names of all packages, their version, and the directory in which they are installed:org/modules/expath/functx-1.0.xar REPO INSTALL hello-world.xqm
URI Version Directory ------------------------------------------------------- <nowiki>http://wwwThe installation will only succeed if the specified file conforms to the constraints described below.functx.com</nowiki> 1.0 http-www.functx.com-1.0 1 package(s)If you know that your input is valid, you may as well copy the files directly to the repository directory, or edit its contents in the repository without deleting and reinstalling them.
===Removal=Listing==
A package All currently installed packages can be deleted listed with the command REPO DELETE and by specifying its name or (since {{VersionCommand|7.2.1REPO LIST}}) the name. The names of all packages are listed, suffixed along with a hyphen their version, their package type, and the package versionrepository path:
REPO DELETE Name Version Type Path ----------------------------------------------------------------- <nowiki>http://www.functx.com</nowiki> 1...or... REPO DELETE <nowiki>0 EXPath http://-www.functx.com-1.0</nowiki>
==PackagingRemoval==
With A package can be deleted with {{VersionCommand|7.2.1REPO DELETE}}and an additional argument, XQuery modules containing its name or the name suffixed with a hyphen and JAR archives can directly be added to the repository without further packaging effortspackage version:
===XQuery=== REPO DELETE <nowiki>http://www.functx.com</nowiki> REPO DELETE <nowiki>http://www.functx.com-1.0</nowiki>
If an XQuery file is specified as input for the install command, it will be parsed as XQuery module. If parsing was successful, the module URI will be [[#URI Rewriting|rewritten]] to a file path and attached with the {{Mono|.xqm}} file suffix, and the original file will be renamed and copied to that path into the repository.=Packaging=
'''Example:'''==XQuery==
Contents of If an XQuery file is specified as input for the install command, it will be parsed as XQuery library module. If the file <code>can successfully be parsed, the module URI will be [http://files.basex.org/modules/hello/HelloWorld[Java Bindings#URI Rewriting|rewritten]] to a file path and attached with the {{Code|.xqm HelloWorld}} file suffix, and the original file will possibly be renamed and copied to that path into the repository.xqm]</code> (comments removed):
<pre class="brush:xquery">module namespace m = 'http''Example://basex.org/modules/Hello';declare function m:hello($world) { 'Hello ' || $world};</pre>
Installation (the original file will be copied to the {{MonoCode|org/basex/modules/Hello.xqm}}subdirectory of the repository):
REPO INSTALL https://files.basex.org/modules/org/basex/modules/Hello/HelloWorld.xqm
XQuery file <code>[http://files.basex.org/modules/hello/HelloWorld.xqm HelloUniverse.xq]</code> (comments removed)Importing the repository module:
<pre classlang="brush:'xquery"'>
import module namespace m = 'http://basex.org/modules/Hello';
m:hello("Universe")
</pre>
===Java=== For general notes on importing Java classes, please read the Java Bindings article on [[Java Bindings#Module_Imports|Module Imports]].
Suitable JAR Java archives (JARs) may contain one or more class files. One of them will be chosen as main class, which must be specified in a {{MonoCode|Main-Class}} entry in the manifest file ({{MonoCode|META-INF/MANIFEST.MF}}). This fully qualified Java class name will be rewritten to a file path by replacing the dots with slashes and attaching with the {{MonoCode|.jar}} file suffix, and the original file will be renamed and copied to that path into the repository.
The If the class will be imported in the prolog of the XQuery module, an instance of it will be created, and its public functions of this class can then be addressed from XQuery, using the class or file path as namespace URI, or an alternative writing that can be [[#URI Rewriting|rewritten]] to the module file path. Moreover, a A class may extend the {{MonoCode|QueryModule}} class to get access to the current query context and to be enriched by some helpful annotations (please consult see [[Java_Bindings#Context-AwarenessAnnotations|Context Awareness of Java BindingsAnnotations]] for more information).
'''Example:'''
Structure of the <code>[httphttps://files.basex.org/modules/helloorg/basex/modules/Hello/HelloWorld.jar HelloWorld.jar]</code> archive:
META-INF/
Hello.class
Contents of the file {{MonoCode|MANIFEST.mf}} (the whitespaces are obligatory):
Manifest-Version: 1.0
Main-Class: org.basex.modules.Hello
Contents of the file {{Mono|Code|Hello.java}} (comments removed):
<pre classlang="brush:java">
package org.basex.modules;
public class Hello {
</pre>
Installation (the file will be copied to {{MonoCode|org/basex/modules/Hello.jar}}):
REPO INSTALL HelloWorld.jar
XQuery file <code>[httphttps://files.basex.org/modules/helloorg/basex/modules/Hello/HelloWorldHelloUniverse.xqm xq HelloUniverse.xq]</code> (same as above):
<pre classlang="brush:'xquery"'>
import module namespace m = 'http://basex.org/modules/Hello';
m:hello("Universe")
</pre>
After installing having installed the module, all of the following URIs can be used in XQuery to import this module or call its functions(see [[Java Bindings#URI Rewriting|URI Rewriting]] for more information):
<nowiki>http://basex.org/modules/hello/WorldHello</nowiki> org/basex/modules/hello/WorldHello org.basex.modules.hello.WorldHello
Please be aware that the execution of Java code can cause side effects that conflict with the functional nature of XQuery, or may introduce new security risks. The article on [[Java Bindings]] gives more insight on how Java code is handled from the XQuery processor.===Additional Libraries===
==EXPath Packaging==A Java class may depend on additional libraries. The dependencies can be resolved by creating a fat JAR file, i.e., extracting all files of the library archives and producing a single, flat JAR package.
The [http://expath.org/spec/pkg EXPath specification] defines how Another solution is to copy the structure libraries into a {{Code|lib}} directory of a the JAR package.xar archive shall look like. The When the package contains at its root is installed, the additional library archives will be extracted and copied to a package descriptor named <code>expath-pkghidden subdirectory in the repository.xml</code>. This descriptor presents some meta data about If the package is deleted, the hidden subdirectory will be removed as well as the libraries which it contains and their dependencies on other libraries or processors.
===XQuery===; Examplary contents of {{Code|Image.jar}}
lib/ Images.jar META-INF/ MANIFEST.MF org/basex/modules/ Image.class ; Directory structure of the repository directory after installing the package org/basex/modules/ Image.class .Images/ Images.jar ==Combined== It makes sense to combine the advantages of XQuery and Java packages: * Instead of directly calling Java code, a wrapper module can be provided. This module contains functions that invoke the Java functions.* These functions can be strictly typed. This reduces the danger of erroneous or unexpected conversions between XQuery and Java code.* In addition, the entry functions can have properly maintained XQuery comments. XQuery and Java can be combined as follows: * First, a JAR package is created (as described above).* A new XQuery wrapper module is created, which is named identically to the Java main class.* The URL of the {{Code|import module}} statement in the wrapper module must start with the {{Code|java:}} prefix.* The finalized XQuery module must be copied into the JAR file, and placed in the same directory as the Java main class. If the resulting JAR file is installed, the embedded XQuery module will be extracted, and will be called first if the module will be imported. ; Main Module {{Code|hello-universe.xq}}: <pre lang='xquery'>import module namespace m = 'http://basex.org/modules/Hello';m:hello("Universe")</pre> ; Wrapper Module {{Code|Hello.xqm}}: <pre lang='xquery'>module namespace hello = 'http://basex.org/modules/Hello'; (: Import JAR file :)import module namespace java = 'java:org.basex.modules.Hello'; (:~ : Say hello to someone. : @param $world the one to be greeted : @return welcome string :)declare function hello:hello( $world as xs:string) as xs:string { java:hello($world)};</pre> ; Java class {{Code|Hello.java}}: <pre lang="java">package org.basex.modules; public class Hello { public String hello(final String world) { return "Hello " + world; }}</pre> If the JAR file is installed, {{Code|Combined}} will be displayed as type: REPO INSTALL https://files.basex.org/modules/org/basex/modules/Hello.jar REPO LIST Name Version Type Path ----------------------------------------------------------------------- org.basex.modules.Hello - Combined org/basex/modules/Hello.xqm =EXPath Packaging= The [http://expath.org/spec/pkg EXPath specification] defines the structure of a .xar archive. The package contains at its root a package descriptor named <code>expath-pkg.xml</code>. This descriptor presents some metadata about the package as well as the libraries which it contains and their dependencies on other libraries or processors. ==XQuery== Apart from the package descriptor, a {{MonoCode|.xar}} archive contains a directory which includes the actual XQuery modules. For example, the [httphttps://wwwfiles.basex.org/modules/expath/functx-1.com/ 0.xar FunctX XQuery LibraryXAR archive] is packaged as follows:
<pre>
</pre>
===Java===
In case If you want to extend BaseX package an EXPath archive with a Java archivecode, some additional requirements have to be fulfilled:
* Apart from the package descriptor <code>expath-pkg.xml</code>, the package has to contain a descriptor file at its root, defining the included jars and the binary names of their public classes. It must be named <code>basex.xml</code> and must conform to the following structure:
<pre classlang="brush:xml">
<package xmlns="http://expath.org/ns/pkg">
<jar>...</jar>
* The jar file itself along with an XQuery file defining wrapper functions around the java methods has to reside in the module directory. The following example illustrates how java methods are wrapped with XQuery functions:
'''Example:'''<br> Suppose we have a simple class <code>Printer</code> having just one public method <code>print()</code>:
<pre classlang="brush:java">
package test;
We want to extend BaseX with this class and use its method. In order to make this possible we have to define an XQuery function which wraps the <code>print</code> method of our class. This can be done in the following way:
<pre classlang="brush:'xquery"'>
import module namespace j="http://basex.org/lib/testJar";
</pre>
As it can be seen, the class {{MonoCode|Printer}} is declared with its binary name as a namespace prefixed with "java" and the XQuery function is implemented using the [http://docs.basex.org/wiki/Java_Bindings Java Bindings] offered by BaseX.
On our [httphttps://files.basex.org/modules/ file server], you can find some example libraries packaged as XML archives (xar files). You can use them to try our packaging API or just as a reference for creating your own packages.
==URI Rewriting=Performance=
If Importing XQuery modules that are looked up located in the repository, their URIs is just as fast as importing any other modules. Modules that are rewritten to imported several times in a local file path. The URI transformation has been inspired by [http://www.zorba-xqueryproject will only be compiled once.com/html/documentation/latest/zorba/uriresolvers Zorba]:
1Imported Java archives will be dynamically added to the classpath and unregistered after query execution. This requires some constant overhead and may lead to unexpected effects in scenarios with highly concurrent read operations. If a URI authority existsyou want to get optimal performance, it is reversed, and its dots are replaced by slashes.<brrecommendable to move your JAR files into the {{Code|lib/>2custom}} directory of BaseX. The URI path This way, the archive will be added to the classpath if BaseX is appendedstarted. If no path existsyou have installed a [[#Combined|Combined Package]], a single slash is appended instead.<br/>3. If you can simply keep your XQuery module in the resulting string ends with a slashrepository, and the {{Mono|index}} string is appendedJava classes will be automatically detected.
If the resulting path has no file suffix, it may point to either an XQuery module or a Java archive.The following examples show some rewritings:=Changelog=
* {{Mono|<nowiki>http://basex;Version 9.org/modules/hello/World</nowiki> → org/basex/modules/hello/World}}* {{Mono|<nowiki>http://www.example.com</nowiki> → com/example/www/index}}* {{Mono|a/little/example.xq → a/little/example.xq}}0
==Changelog==* Added: [[#Combined|Combined]] XQuery and Java packages* Added: [[#Additional Libraries|Additional Libraries]]
===;Version 7.2.1===
* Updated: [[#Installation|Installation]]: existing packages will be replacedwithout raising an error
* Updated: [[#Removal|Removal]]: remove specific version of a package
* Added: [[#Packaging|Packaging]], [[#URI Rewriting|URI Rewriting]]
===;Version 7.1===
* Added: [[Repository Module]]
===;Version 7.0===
* Added: [[#EXPath Packaging|EXPath Packaging]]
[[Category:XQuery]]