Skip to content

Commit 4b2b99d

Browse files
committed
[feature] New implementation of Java Binding from XQuery
Closes eXist-db/exist#5090
1 parent 710c231 commit 4b2b99d

File tree

17 files changed

+3763
-297
lines changed

17 files changed

+3763
-297
lines changed

exist-core/pom.xml

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -704,17 +704,21 @@
704704
<include>src/main/java/org/exist/util/JREUtil.java</include>
705705
<include>src/main/java/org/exist/util/OSUtil.java</include>
706706
<include>src/main/java/org/exist/util/StringUtil.java</include>
707+
<include>src/main/java/org/exist/xquery/JavaBinding.java</include>
707708
<include>src/main/java/org/exist/xquery/functions/fn/FunDocAvailable.java</include>
708709
<include>src/test/java/org/exist/xquery/ImportFromPkgTest.java</include>
710+
<include>src/test/java/org/exist/xquery/JavaBindingTest.java</include>
709711
<include>src/test/java/org/exist/xquery/WatchdogTest.java</include>
710712
<include>src/test/java/org/exist/xquery/value/DateTimeTypesTest.java</include>
711713
<include>src/test/java/org/exist/xquery/functions/fn/FunXmlToJsonTest.java</include>
712714
<include>src/test/java/org/exist/xquery/functions/fn/ParsingFunctionsTest.java</include>
713715
<include>src/test/java/org/exist/xquery/functions/fn/transform/ConvertTest.java</include>
714716
<include>src/test/java/org/exist/xquery/functions/fn/transform/FunTransformITTest.java</include>
717+
<include>src/main/java/org/exist/xquery/functions/system/FunctionAvailable.java</include>
715718
<include>src/test/java/org/exist/xquery/functions/xmldb/XMLDBStoreTest.java</include>
716719
<include>src/test/java/org/exist/xquery/functions/xquery3/SerializeTest.java</include>
717720
<include>src/test/resources-filtered/org/exist/xquery/import-from-pkg-test.conf.xml</include>
721+
<include>src/test/resources-filtered/org/exist/xquery/JavaBindingTest.conf.xml</include>
718722
<include>src/test/xquery/securitymanager/acl.xqm</include>
719723
</includes>
720724
</licenseSet>
@@ -849,16 +853,19 @@
849853
<include>src/main/java/org/exist/xmldb/RemoteRestoreService.java</include>
850854
<include>src/main/java/org/exist/xmlrpc/ExistRpcTypeFactory.java</include>
851855
<include>src/main/java/org/exist/xqj/Marshaller.java</include>
856+
<include>src/main/java/org/exist/xquery/DynamicTypeCheck.java</include>
857+
<include>src/main/java/org/exist/xquery/ErrorCodes.java</include>
852858
<include>src/main/java/org/exist/xquery/UserDefinedFunction.java</include>
853859
<include>src/main/java/org/exist/xquery/FunctionFactory.java</include>
854860
<include>src/main/java/org/exist/xquery/Optimizer.java</include>
861+
<include>src/main/java/org/exist/xquery/XPathUtil.java</include>
855862
<include>src/main/java/org/exist/xquery/XQueryContext.java</include>
856863
<include>src/main/java/org/exist/xquery/functions/fn/FunDeepEqual.java</include>
857864
<include>src/main/java/org/exist/xquery/functions/fn/FunUriCollection.java</include>
858865
<include>src/main/java/org/exist/xquery/functions/fn/ParsingFunctions.java</include>
859866
<include>src/main/java/org/exist/xquery/functions/integer/WordPicture.java</include>
860-
<include>src/main/java/org/exist/xquery/functions/system/FunctionAvailable.java</include>
861867
<include>src/main/java/org/exist/xquery/functions/system/GetUptime.java</include>
868+
<include>src/main/java/org/exist/xquery/functions/system/SystemModule.java</include>
862869
<include>src/main/java/org/exist/xquery/functions/system/Shutdown.java</include>
863870
<include>src/main/java/org/exist/xquery/functions/system/TriggerSystemTask.java</include>
864871
<include>src/main/java/org/exist/xquery/functions/util/BuiltinFunctions.java</include>
@@ -870,6 +877,7 @@
870877
<include>src/test/java/org/exist/xquery/update/UpdateReplaceTest.java</include>
871878
<include>src/main/java/org/exist/xquery/util/SerializerUtils.java</include>
872879
<include>src/main/java/org/exist/xquery/value/AbstractDateTimeValue.java</include>
880+
<include>src/main/java/org/exist/xquery/value/SequenceType.java</include>
873881
<include>src/main/java/org/exist/xquery/value/Type.java</include>
874882
<include>src/main/java/org/exist/xslt/EXistURIResolver.java</include>
875883
<include>src/main/resources-filtered/org/exist/system.properties</include>
@@ -892,6 +900,7 @@
892900
<include>src/main/java/org/exist/management/impl/JMXAgent.java</include>
893901
<include>src/test/java/org/exist/xmldb/CreateCollectionsTest.java</include>
894902
<include>src/test/java/org/exist/xquery/XQueryFunctionsTest.java</include>
903+
<include>src/main/java/org/exist/xquery/functions/array/ArrayType.java</include>
895904
<include>src/test/java/org/exist/xquery/functions/fn/DocTest.java</include>
896905
<include>src/main/java/org/exist/xquery/functions/fn/FnModule.java</include>
897906
<include>src/main/java/org/exist/xquery/functions/fn/FunBaseURI.java</include>
@@ -943,6 +952,7 @@
943952
<exclude>src/test/resources-filtered/conf.xml</exclude>
944953
<exclude>src/test/resources-filtered/org/exist/storage/statistics/conf.xml</exclude>
945954
<exclude>src/test/resources-filtered/org/exist/xquery/import-from-pkg-test.conf.xml</exclude>
955+
<exclude>src/test/resources-filtered/org/exist/xquery/JavaBindingTest.conf.xml</exclude>
946956
<exclude>src/test/resources-filtered/org/exist/xquery/functions/transform/transform-from-pkg-test.conf.xml</exclude>
947957
<exclude>src/main/antlr/org/exist/xquery/parser/XQueryTree.g</exclude>
948958
<exclude>src/main/java/org/exist/Indexer.java</exclude>
@@ -1066,13 +1076,19 @@
10661076
<exclude>src/main/java/org/exist/xmldb/RemoteRestoreService.java</exclude>
10671077
<exclude>src/main/java/org/exist/xmlrpc/ExistRpcTypeFactory.java</exclude>
10681078
<exclude>src/main/java/org/exist/xqj/Marshaller.java</exclude>
1079+
<exclude>src/main/java/org/exist/xquery/DynamicTypeCheck.java</exclude>
1080+
<exclude>src/main/java/org/exist/xquery/ErrorCodes.java</exclude>
10691081
<exclude>src/main/java/org/exist/xquery/FunctionFactory.java</exclude>
10701082
<exclude>src/test/java/org/exist/xquery/ImportFromPkgTest.java</exclude>
1083+
<exclude>src/main/java/org/exist/xquery/JavaBinding.java</exclude>
1084+
<exclude>src/test/java/org/exist/xquery/JavaBindingTest.java</exclude>
10711085
<exclude>src/main/java/org/exist/xquery/NameTest.java</exclude>
10721086
<exclude>src/main/java/org/exist/xquery/Optimizer.java</exclude>
10731087
<exclude>src/main/java/org/exist/xquery/UserDefinedFunction.java</exclude>
10741088
<exclude>src/test/java/org/exist/xquery/WatchdogTest.java</exclude>
1089+
<exclude>src/main/java/org/exist/xquery/XPathUtil.java</exclude>
10751090
<exclude>src/main/java/org/exist/xquery/XQueryContext.java</exclude>
1091+
<exclude>src/main/java/org/exist/xquery/functions/array/ArrayType.java</exclude>
10761092
<exclude>src/main/java/org/exist/xquery/functions/fn/FnModule.java</exclude>
10771093
<exclude>src/main/java/org/exist/xquery/functions/fn/FunDeepEqual.java</exclude>
10781094
<exclude>src/main/java/org/exist/xquery/functions/fn/FunDocAvailable.java</exclude>
@@ -1092,6 +1108,7 @@
10921108
<exclude>src/main/java/org/exist/xquery/functions/system/FunctionAvailable.java</exclude>
10931109
<exclude>src/main/java/org/exist/xquery/functions/system/GetUptime.java</exclude>
10941110
<exclude>src/main/java/org/exist/xquery/functions/system/Shutdown.java</exclude>
1111+
<exclude>src/main/java/org/exist/xquery/functions/system/SystemModule.java</exclude>
10951112
<exclude>src/main/java/org/exist/xquery/functions/system/TriggerSystemTask.java</exclude>
10961113
<exclude>src/main/java/org/exist/xquery/functions/xmldb/XMLDBStore.java</exclude>
10971114
<exclude>src/test/java/org/exist/xquery/functions/xmldb/XMLDBStoreTest.java</exclude>
@@ -1213,6 +1230,7 @@
12131230
<exclude>src/main/java/org/exist/xquery/value/AtomicValueComparator.java</exclude>
12141231
<exclude>src/main/java/org/exist/xquery/value/ItemComparator.java</exclude>
12151232
<exclude>src/main/java/org/exist/xquery/value/SequenceComparator.java</exclude>
1233+
<exclude>src/main/java/org/exist/xquery/value/SequenceType.java</exclude>
12161234
<exclude>src/main/java/org/exist/xquery/value/SubSequence.java</exclude>
12171235
<exclude>src/test/java/org/exist/xquery/value/SubSequenceRangeTest.java</exclude>
12181236
<exclude>src/test/java/org/exist/xquery/value/SubSequenceTest.java</exclude>

exist-core/src/main/java/org/exist/util/Configuration.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -390,12 +390,10 @@ private void configureBinaryManager(Element binaryManager) throws DatabaseConfig
390390
private void configureXQuery( Element xquery ) throws DatabaseConfigurationException
391391
{
392392
//java binding
393-
final String javabinding = getConfigAttributeValue( xquery, FunctionFactory.ENABLE_JAVA_BINDING_ATTRIBUTE );
393+
final boolean enableJavaBinding = parseBoolean(getConfigAttributeValue(xquery, FunctionFactory.ENABLE_JAVA_BINDING_ATTRIBUTE), false);
394394

395-
if( javabinding != null ) {
396-
config.put( FunctionFactory.PROPERTY_ENABLE_JAVA_BINDING, javabinding );
397-
LOG.debug(FunctionFactory.PROPERTY_ENABLE_JAVA_BINDING + ": {}", config.get(FunctionFactory.PROPERTY_ENABLE_JAVA_BINDING));
398-
}
395+
config.put(FunctionFactory.PROPERTY_ENABLE_JAVA_BINDING, enableJavaBinding);
396+
LOG.debug(FunctionFactory.PROPERTY_ENABLE_JAVA_BINDING + ": {}", enableJavaBinding);
399397

400398
final String disableDeprecated = getConfigAttributeValue( xquery, FunctionFactory.DISABLE_DEPRECATED_FUNCTIONS_ATTRIBUTE );
401399
config.put( FunctionFactory.PROPERTY_DISABLE_DEPRECATED_FUNCTIONS, Configuration.parseBoolean( disableDeprecated, FunctionFactory.DISABLE_DEPRECATED_FUNCTIONS_BY_DEFAULT ) );

exist-core/src/main/java/org/exist/xquery/Cardinality.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,20 @@ public static Cardinality fromInt(final int intValue) {
209209
throw new IllegalArgumentException("No know cardinality for intValue: " + intValue);
210210
}
211211

212+
/**
213+
* Compare this Cardinality to another Cardinality.
214+
*
215+
* NOTE we can't implement (override) {@link Comparable#compareTo(Object)}
216+
* here as it is final in {@link java.lang.Enum}.
217+
*
218+
* @param other the other Cardinality to be compared.
219+
*
220+
* @return a negative integer, zero, or a positive integer as this Cardinality is less than, equal to, or greater than the other Cardinality.
221+
*/
222+
public int compare(final Cardinality other) {
223+
return Byte.compare(val, other.val);
224+
}
225+
212226
static class InternalValue {
213227
static final byte ZERO = 1;
214228
static final byte ONE = 2;

exist-core/src/main/java/org/exist/xquery/DynamicTypeCheck.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,28 @@
11
/*
2+
* Elemental
3+
* Copyright (C) 2024, Evolved Binary Ltd
4+
*
5+
6+
* https://www.evolvedbinary.com | https://www.elemental.xyz
7+
*
8+
* This library is free software; you can redistribute it and/or
9+
* modify it under the terms of the GNU Lesser General Public
10+
* License as published by the Free Software Foundation; version 2.1.
11+
*
12+
* This library is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15+
* Lesser General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU Lesser General Public
18+
* License along with this library; if not, write to the Free Software
19+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20+
*
21+
* NOTE: Parts of this file contain code from 'The eXist-db Authors'.
22+
* The original license header is included below.
23+
*
24+
* =====================================================================
25+
*
226
* eXist-db Open Source Native XML Database
327
* Copyright (C) 2001 The eXist-db Authors
428
*
@@ -82,6 +106,9 @@ private void check(Sequence result, Item item) throws XPathException {
82106
//Retrieve the actual node
83107
{type= ((NodeProxy) item).getNode().getNodeType();}
84108
}
109+
if (requiredType == Type.JAVA_OBJECT) {
110+
type = Type.JAVA_OBJECT;
111+
}
85112
if(type != requiredType && !Type.subTypeOf(type, requiredType)) {
86113
//TODO : how to make this block more generic ? -pb
87114
if (type == Type.UNTYPED_ATOMIC) {

exist-core/src/main/java/org/exist/xquery/ErrorCodes.java

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,28 @@
11
/*
2+
* Elemental
3+
* Copyright (C) 2024, Evolved Binary Ltd
4+
*
5+
6+
* https://www.evolvedbinary.com | https://www.elemental.xyz
7+
*
8+
* This library is free software; you can redistribute it and/or
9+
* modify it under the terms of the GNU Lesser General Public
10+
* License as published by the Free Software Foundation; version 2.1.
11+
*
12+
* This library is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15+
* Lesser General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU Lesser General Public
18+
* License along with this library; if not, write to the Free Software
19+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20+
*
21+
* NOTE: Parts of this file contain code from 'The eXist-db Authors'.
22+
* The original license header is included below.
23+
*
24+
* =====================================================================
25+
*
226
* eXist-db Open Source Native XML Database
327
* Copyright (C) 2001 The eXist-db Authors
428
*
@@ -258,6 +282,10 @@ public class ErrorCodes {
258282
public static final ErrorCode EXXQDY0005 = new EXistErrorCode("EXXQDY0005", "No function call details were provided when trying to execute a Library Module.");
259283
public static final ErrorCode EXXQDY0006 = new EXistErrorCode("EXXQDY0006", "Unable to find named function when trying to execute a Library Module.");
260284

285+
public static final ErrorCode EXXQST0001 = new EXistErrorCode("EXXQST0001", "Java binding is disabled in the current configuration.");
286+
public static final ErrorCode EXXQST0002 = new EXistErrorCode("EXXQST0002", "No Java binding possible for the indicated Java class.");
287+
public static final ErrorCode EXXQST0003 = new EXistErrorCode("EXXQST0003", "No Java binding possible for the indicated Java field/method.");
288+
261289
public static final ErrorCode ERROR = new EXistErrorCode("ERROR", "Error.");
262290

263291
public static class ErrorCode {
@@ -305,12 +333,12 @@ private EXistErrorCode(String code, String description) {
305333

306334
public static class JavaErrorCode extends ErrorCode {
307335

308-
public JavaErrorCode(Throwable throwable) {
336+
public JavaErrorCode(final Throwable throwable) {
309337
super(new QName(
310338
throwable.getClass().getName(),
311339
Namespaces.EXIST_JAVA_BINDING_NS,
312340
Namespaces.EXIST_JAVA_BINDING_NS_PREFIX),
313-
throwable.getMessage());
341+
throwable.getMessage() != null ? throwable.getMessage() : throwable.getCause().getMessage());
314342
}
315343
}
316344
}

exist-core/src/main/java/org/exist/xquery/FunctionFactory.java

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ public static Expression createFunction(XQueryContext context, QName qname, XQue
125125
//Check if the namespace URI starts with "java:". If yes, treat
126126
//the function call as a call to an arbitrary Java function.
127127
} else if (uri.startsWith("java:")) {
128-
step = javaFunctionBinding(context, ast, params, qname);
128+
step = javaBinding(context, ast, qname, params);
129129
}
130130
//None of the above matched: function is either a built-in function or
131131
//a user-defined function
@@ -273,20 +273,14 @@ private static CastExpression castExpression(XQueryContext context,
273273
return castExpr;
274274
}
275275

276-
private static JavaCall javaFunctionBinding(XQueryContext context,
277-
XQueryAST ast, List<Expression> params, QName qname) throws XPathException {
278-
//Only allow java binding if specified in config file <xquery enable-java-binding="yes">
279-
final String javabinding = (String) context.getBroker().getConfiguration()
280-
.getProperty(PROPERTY_ENABLE_JAVA_BINDING);
281-
if(javabinding == null || !"yes".equals(javabinding)) {
282-
throw new XPathException(ast.getLine(), ast.getColumn(),
283-
"Java binding is disabled in the current configuration (see conf.xml)." +
284-
" Call to " + qname.getStringValue() + " denied.");
276+
private static JavaBinding javaBinding(final XQueryContext context, final XQueryAST ast, final QName qname, final List<Expression> params) throws XPathException {
277+
// NOTE(AR) Only allow java binding if specified in config file <xquery enable-java-binding="yes">
278+
final boolean enableJavaBinding = context.getBroker().getConfiguration().getProperty(PROPERTY_ENABLE_JAVA_BINDING, false);
279+
if (!enableJavaBinding) {
280+
throw new XPathException(ast.getLine(), ast.getColumn(), ErrorCodes.EXXQST0001, "Java binding is disabled in the current configuration (see conf.xml). Call to " + qname.getStringValue() + " denied.");
285281
}
286-
final JavaCall call = new JavaCall(context, qname);
287-
call.setLocation(ast.getLine(), ast.getColumn());
288-
call.setArguments(params);
289-
return call;
282+
283+
return JavaBinding.createFunction(ast.getLine(), ast.getColumn(), context, qname, params);
290284
}
291285

292286
private static Function functionCall(final XQueryContext context,

0 commit comments

Comments
 (0)