Difference between revisions of "Repository"

From BaseX Documentation
Jump to navigation Jump to search
(The listed URIs to import module HelloWorld.jar were wrong. Replaced {modules/hello/World, modules.hello.World} with {modules/Hello, modules.Hello}. Better to name the file Hello.jar anyway :))
Line 131: Line 131:
 
After installing the module, all of the following URIs can be used in XQuery to import this module or call its functions:
 
After installing the module, all of the following URIs can be used in XQuery to import this module or call its functions:
  
  <nowiki>http://basex.org/modules/hello/World</nowiki>
+
  <nowiki>http://basex.org/modules/Hello</nowiki>
  org/basex/modules/hello/World
+
  org/basex/modules/Hello
  org.basex.modules.hello.World
+
  org.basex.modules.Hello
  
 
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.
 
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.

Revision as of 14:20, 3 May 2012

This article is part of the XQuery Portal. It describes how external XQuery modules and Java code can be installed in the XQuery module repository, and how new packages are built and deployed.

Motivation

One of the reasons why languages such as Java or Perl have been so successful is the vast amount of libraries that are available to developers. XQuery is a Turing complete language, but it just provides around 100 pre-defined functions, which cannot meet all requirements. This is why additional libraries arise – such as FunctX – that extend the language with new features.

BaseX offers two mechanisms to make new packages accessible to the XQuery processor:

  1. With Version 7.2.1, we offer a simple packaging mechanism to directly install single XQuery and Java modules to the repository.
  2. The EXPath Packaging system provides a generic mechanism for adding XQuery modules to query processors. A package is defined as a .xar archive, which encapsulates one or more extension libraries.

Usage

All packages are stored in the repository. The repository is a directory named BaseXRepo or repo, which resides in your home directory. BaseX provides three commands for interaction with the package repository: REPO INSTALL, REPO DELETE, and REPO LIST. Packages can also be managed from within XQuery, using the Repository Module.

Installation

A module or package can be installed with the REPO INSTALL command. The path to the file has to be given as a parameter, as the following two examples demonstrate:

REPO INSTALL http://files.basex.org/modules/functx-1.0.xar
REPO INSTALL hello-world.xqm

The installation will only succeed if the specified file conforms to the constraints described below. 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.

Since Version 7.2.1, existing packages are simply replaced (before, an error was raised).

Querying

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:

import module namespace functx = "http://www.functx.com";

When this statement is parsed, the query processor will check if the namespace "http://www.functx.com" is used in any 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 the standard way, e.g.:

functx:capitalize-first("test")

Package encapsulating Java archives can be imported in the same way as pure XQuery modules (see below).

Listing

All currently installed packages can be listed with the REPO LIST command. It will return the names of all packages, their version, and the directory in which they are installed:

URI                    Version  Directory
-------------------------------------------------------
http://www.functx.com  1.0      http-www.functx.com-1.0

1 package(s).

Removal

A package can be deleted with the command REPO DELETE and by specifying its name or (since Version 7.2.1) the name, suffixed with a hyphen and the package version:

REPO DELETE http://www.functx.com  ...or...
REPO DELETE http://www.functx.com-1.0

Packaging

With Version 7.2.1, XQuery modules and JAR archives can directly be added to the repository without further packaging efforts:

XQuery

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 rewritten to a file path and attached with the .xqm file suffix, and the original file will be renamed and copied to that path into the repository.

Example:

Contents of the file HelloWorld.xqm (comments removed):

module namespace m = 'http://basex.org/modules/Hello';
declare function m:hello($world) {
  'Hello ' || $world
};

Installation (the original file will be copied to org/basex/modules/Hello.xqm):

REPO INSTALL HelloWorld.xqm

XQuery file HelloUniverse.xq (comments removed):

import module namespace m = 'http://basex.org/modules/Hello';
m:hello("Universe")

Java

Suitable JAR archives may contain one or more class files. One of them will be chosen as main class, which must be specified in a Main-Class entry in the manifest file (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 .jar file suffix, and the original file will be renamed and copied to that path into the repository.

The 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 rewritten to the module file path. Moreover, a class may extend the QueryModule class to get access to the current query context and to be enriched by some helpful annotations (please consult Context Awareness of Java Bindings for more information).

Example:

Structure of the HelloWorld.jar archive:

META-INF/
  MANIFEST.MF
org/basex/modules/
  Hello.class

Contents of the file MANIFEST.mf (the whitespaces are obligatory):

Manifest-Version: 1.0
Main-Class: org.basex.modules.Hello

Contents of the file (comments removed):

package org.basex.modules;
public class Hello {
  public String hello(final String world) {
    return "Hello " + world;
  }
}

Installation (the file will be copied to org/basex/modules/Hello.jar):

REPO INSTALL HelloWorld.jar

XQuery file HelloUniverse.xq (same as above):

import module namespace m = 'http://basex.org/modules/Hello';
m:hello("Universe")

After installing the module, all of the following URIs can be used in XQuery to import this module or call its functions:

http://basex.org/modules/Hello
org/basex/modules/Hello
org.basex.modules.Hello

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.

EXPath Packaging

The EXPath specification defines how the structure of a .xar archive shall look like. The package contains at its root a package descriptor named expath-pkg.xml. This descriptor presents some meta data 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 .xar archive contains a directory which includes the actual XQuery modules. For example, the FunctX XQuery Library is packaged as follows:

expath-pkg.xml
functx/
  functx.xql
  functx.xsl

Java

In case you want to extend BaseX with a Java archive, some additional requirements have to be fulfilled:

  • Apart from the package descriptor expath-pkg.xml, 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 basex.xml and must conform to the following structure:
<package xmlns="http://expath.org/ns/pkg">
  <jar>...</jar>
    ....
    <class>...</class>
    <class>...</class>
    ....
</package>
  • 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:
Suppose we have a simple class Printer having just one public method print():

package test;

public final class Printer {
  public String print(final String s) {
    return new Writer(s).write();
  }
}

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 print method of our class. This can be done in the following way:

import module namespace j="http://basex.org/lib/testJar";

declare namespace p="java:test.Printer";

declare function j:print($str as xs:string) as xs:string {
  let $printer := p:new()
  return p:print($printer, $str)
};

As it can be seen, the class Printer is declared with its binary name as a namespace prefixed with "java" and the XQuery function is implemented using the Java Bindings offered by BaseX.

On our 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

If modules are looked up in the repository, their URIs are rewritten to a local file path. The URI transformation has been inspired by Zorba:

1. If a URI authority exists, it is reversed, and its dots are replaced by slashes.
2. The URI path is appended. If no path exists, a single slash is appended instead.
3. If the resulting string ends with a slash, the index string is appended.

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:

  • http://basex.org/modules/hello/World → org/basex/modules/hello/World
  • http://www.example.com → com/example/www/index
  • a/little/example.xq → a/little/example.xq

Changelog

Version 7.2.1

Version 7.1

Version 7.0