Changes

Jump to navigation Jump to search
2,362 bytes added ,  18:52, 18 November 2020
no edit summary
A Java class is identified by a namespace URI. The original URI is rewritten as follows:
# The [[Repository#URI_RewritingURI Rewriting|URI Rewriting]] steps are applied to the URI.
# Slashes in the resulting URI are replaced with dots.
# The last path segment of the URI is capitalized and rewritten to [https://en.wikipedia.org/wiki/CamelCase camel caseCamelCase].
The normalization steps are skipped if the URI is prefixed with {{Code|java:}}. See the following examples:
* <code><nowiki>http://basex.org/modules/meta-data</nowiki></code> → <code>org.basex.modules.MetaData</code>
* The namespace of the function name identifies the Java class.
* The local part of the name, which is rewritten to camel case, identifies a variable or function of that class.
* The middle dot character (<code>[httphttps://www.fileformat.info/info/unicode/char/b7/index.htm ·]</code> (&amp;#xB7;]</code>) is , a valid character in XQuery names, but not in Java. It ) can be used to append exact Java parameter types to the function name. Class types must be referenced by their full path.
{| class="wikitable"
|- valign="top"
| Variable
| <code>Q{java.lang.Integer}MIN_VALUE()</code>
| <code>[https://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html#MAX_VALUE Integer.MIN_VALUE]</code>
|- valign="top"
| Function
| <code>Q{java.lang.Object}hash-code($object)</code>
| <code>[https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#hashCode() object.hashCode()]</code>
|- valign="top"
| Function with types
| <code>Q{java.lang.String}split·java.lang.String·int($string, ';', xs:int(3))</code>
| <code>[https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#split-java.lang.String-int- string.split(";", 3)]</code>
|}
In the following example, Java’s {{Code|Math}} class is referenced. When executed, the query returns the cosine of an angle by calling the static method {{Code|cos()}}, and the value of π by addressing the static variable via {{Code|PI()}}:
<pre classsyntaxhighlight lang="brush:xquery">
declare namespace math = "java:java.lang.Math";
math:cos(xs:double(0)), math:PI()
</presyntaxhighlight>
With the [[XQuery 3.0#Expanded QNames|Expanded QName]] notation of XQuery 3.0,
the namespace can directly be embedded in the function call:
<pre classsyntaxhighlight lang="brush:xquery">
Q{java:java.lang.Math}cos(xs:double(0))
</presyntaxhighlight>
The constructor of a class can be invoked by calling the virtual function {{Code|new()}}. Instance methods can then called by passing on the resulting Java object as first argument. In the following example, 256 bytes are written to the file {{Code|output.txt}}. First, a new {{Code|FileWriter}} instance is created, and its {{Code|write()}} function is called in the next step:
<pre classsyntaxhighlight lang="brush:xquery">declare namespace fw = "java.io.FileWriter";
let $file := fw:new('output.txt')
return (
fw:close($file)
)
</presyntaxhighlight>
If the result of a Java call contains invalid XML characters, it will be rejected. The validity check can be disabled by setting the [[Options#CHECKSTRINGS{{Option|CHECKSTRINGS]] option }} to false. The following query writes In the example below, a file with a single {{Code|00-}} byteis written, which and this file will then be successfully read accessed by via Java functions:
<pre classsyntaxhighlight lang="brush:xquery">
declare namespace br = 'java.io.BufferedReader';
declare namespace fr = 'java.io.FileReader';
file:write-binary('00.bin', xs:hexBinary('00')),
br:new(fr:new('00.bin')) ! (br:readLine(.), br:close(.))
</presyntaxhighlight>
Note that Java code cannot be pre-compiled, and will as such be evaluated slower than optimized XQuery code.
=Module Imports=
An alternative solution is to access Java code can also be integrated by ''importing'' classes as modules. A new instance of the addressed class is will be created, which can then be accessed referenced in the query body.
The following, In the (side-effecting ) example returns below, the number size of distinct values added to a Java hash set (the is returned. The boolean values that are returned by {{Code|set:add()}} will be are swallowed):
<pre classsyntaxhighlight lang="brush:xquery">import module namespace set = "java:java.util.HashSet";
prof:void(
for $s in ("one", "two", "one")
),
set:size()
</presyntaxhighlight>
The advantages execution of this approach is that imported code classes is executed faster more efficient than the execution of instances that are created at runtime via {{Code|new()}}. A drawback is that no arguments can be passed on to the class constructor. As a consequence, the import will fail fails if the addressed class has no default constructor, but at least one constructor with arguments and no default constructor.
=Context-AwarenessIntegration=
Java classes can be coupled even more closely to the BaseX core library.If a class inherits the abstract [https://github.com/BaseXdb/basex/blob/master/basex-core/src/main/java/org/basex/query/QueryModule.java QueryModule] class, the two variables [https://github.com/BaseXdb/basex/blob/master/basex-core/src/main/java/org/basex/query/QueryContext.java queryContext] and [https://github.com/BaseXdb/basex/blob/master/basex-core/src/main/java/org/basex/query/StaticContext.java staticContext] get available, which provide access to the global and static context of a query. Additionally The [https://github.com/BaseXdb/basex/blob/master/basex-core/src/main/java/org/basex/query/QueryResource.java QueryResource] interface can be implemented to enforce finalizing operations, such as the closing of opened connections or resources in a module. Its {{Code|close()}} method will be called after the default XQuery expression has been fully evaluated. ==Annotations== The internal properties of functions can be changed assigned via annotations:
* Java functions can only be executed by users with [[User_Management|Admin permissions]]. You may annotate a function with {{Code|@Requires(<Permission>)}} to also make it accessible to users with less privileges.
* Java code is treated as ''focus-independent''. If a function accesses the current context item, position or size, it should be annotated as {{Code|@FocusDependent}}
The [https://github.com/BaseXdb/basex/blob/master/basex-core/src/main/java/org/basex/query/QueryResource.java QueryResource] interface can be implemented to enforce finalizing operations, such as In the closing of opened connections or resources in a module. Its {{Code|close()}} method will be called after a query has been fully evaluated. The following XQuery code invokes two Java methods. The first Java function retrieves , information from the static query contextis returned by the first function, and the second one throws a query exceptionis raised by the second function:
<pre classsyntaxhighlight lang="brush:xquery">
import module namespace context = 'org.basex.examples.query.ContextModule';
context:user()
},
try { element to-int { try { context:to-int('abc') }} catch basex:error { catch * element error { 'Error in line', $err:line-number description }
}
</presyntaxhighlight>
The imported Java class is shown below:
<pre classsyntaxhighlight lang="brush:java">
package org.basex.examples.query;
/**
* Returns the name of the logged in user.
* @return userstring
*/
@Requires(Permission.NONE)
/**
* Converts the specified string to an integer.
* @param value string representationto be converted * @return resulting integer
* @throws QueryException query exception
*/
return Integer.parseInt(value);
} catch(NumberFormatException ex) {
throw new QueryException(ex.getMessage()"Integer conversion failed: " + value);
}
}
@Override
public void close() {
// see description abovedefined in QueryResource interface, will be called after query evaluation
}
}
</presyntaxhighlight>
The result will look as follows:
<pre classsyntaxhighlight lang="brush:xml">
<user>admin</admin>
<to-interror>Error in line 6Integer conversion failed: abc</to-interror></presyntaxhighlight>
Please visit the XQuery 3.0 specification if you want to get more insight into
[httphttps://www.w3.org/TR/xpath-functions-3031/#properties-of-functions function properties].
=Locking=Updates==
By default, a Java function will The {{Code|@Updating}} annotation can be executed in parallel with other code. However, if a applied to mark Java function performs sensitive functions that perform write or update operations, it is advisable to explicitly lock the code. This can be realized via locking annotations:
<pre classsyntaxhighlight lang="brush:java"> @Lock(write = { "HEAVYIO" })Updating public void writebackup() {
// ...
}
</syntaxhighlight>
 
An XQuery expression will be handled as an [[XQuery Update#Updating Expressions|updating expression]] if it calls an updating Java function. In contrast to XQuery update operations, the Java code will immediately be executed, but the result will be cached as if {{Function|Update|update:output}} was called.
 
The annotation is particularly helpful if combined with a lock annotation.
==Locking== By default, a Java function will be executed in parallel with other code. If a Java function performs sensitive operations, it is advisable to explicitly lock the code. ===Java Locks=== Java provides a handful of mechanism to control the execution of code. The concurrent execution of functions can be avoided with the {{Code|synchronized}} keyword. For more complex scenarios, Lock and Semaphor and Atomic classes exist. ===XQuery Locks=== If you want to synchronize the execution of your code with BaseX locks, you can take advantage of the {{Code|@Lock}} annotation: <syntaxhighlight lang="java"> @Lock(read = { "HEAVYIO" })
public void read() {
// ...
}
</pre>
@Updating @Lock("HEAVYIO") public void write() { // ... }</syntaxhighlight> If an XQuery expression is run which calls the Java invokes {{Code|write()}} function, every any other query that calls call {{Code|write()}} or {{Code|read()}} needs to wait for the query to be finished. If a query calls the The {{Code|read()}} function, can be run in parallel; only those queries are queued that call {{Code|write()}}, because this function is only annotated with a {{Code|read}} lock.  More details on parallel query execution concurrent querying can be found in the article on [[Transaction Management]].
==Data Types==
The following table lists the mappings of XQuery and Java typesare mapped as follows:
{| class="wikitable"
| <code>null</code>
|}
 
==URI Rewriting==
 
Before a Java class or module is accessed, its namespace URI will be normalized:
 
# If the URI is a URL:
## colons will be replaced with slashes,
## in the URI authority, the order of all substrings separated by dots is reversed, and
## dots in the authority and the path are replaced by slashes. If no path exists, a single slash is appended.
# Otherwise, if the URI is a URN, colons will be replaced with slashes.
# Characters other than letters, dots and slashes will be replaced with dashes.
# If the resulting string ends with a slash, the {{Code|index}} string is appended.
 
If the resulting path has no file suffix, it may point to either an XQuery module or a Java archive:
 
* {{Code|<nowiki>http://basex.org/modules/hello/World</nowiki>}} → {{Code|org/basex/modules/hello/World}}
* {{Code|<nowiki>http://www.example.com</nowiki>}} → {{Code|com/example/www/index}}
* {{Code|a/little/example}} → {{Code|a/little/example}}
* {{Code|a:b:c}} → {{Code|a/b/c}}
=Changelog=
 
; Version 9.4
* Added: Annotation for [[#Updates|updating functions]].
* Updated: Single annotation for read and write locks.
; Version 8.4
* Updated: Rewriting rules
;Version 8.2* UpdatedAdded: [[#URI Rewriting rules|URI Rewriting]]: support for URNs
; Version 8.0
 
* Added: {{Code|QueryResource}} interface, called after a query has been fully evaluated.
; Version 7.8
 
* Added: Java locking annotations
* Updated: {{Code|context}} variable has been split into {{Code|queryContext}} and {{Code|staticContext}}.
; Version 7.2.1
 
* Added: import of Java modules, context awareness
* Added: [[#Packaging|Packaging]], [[#URI Rewriting|URI Rewriting]]
Bureaucrats, editor, reviewer, Administrators
13,550

edits

Navigation menu