Skip to content

Commit 91ab58f

Browse files
committed
[feature] New implementation of Java Binding from XQuery
Closes eXist-db/exist#5090
1 parent 7100883 commit 91ab58f

File tree

16 files changed

+3759
-285
lines changed

16 files changed

+3759
-285
lines changed

exist-core/pom.xml

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -753,17 +753,21 @@
753753
<include>src/main/java/org/exist/util/JREUtil.java</include>
754754
<include>src/main/java/org/exist/util/OSUtil.java</include>
755755
<include>src/main/java/org/exist/util/StringUtil.java</include>
756+
<include>src/main/java/org/exist/xquery/JavaBinding.java</include>
756757
<include>src/main/java/org/exist/xquery/functions/fn/FunDocAvailable.java</include>
757758
<include>src/test/java/org/exist/xquery/ImportFromPkgTest.java</include>
759+
<include>src/test/java/org/exist/xquery/JavaBindingTest.java</include>
758760
<include>src/test/java/org/exist/xquery/WatchdogTest.java</include>
759761
<include>src/test/java/org/exist/xquery/value/DateTimeTypesTest.java</include>
760762
<include>src/test/java/org/exist/xquery/functions/fn/FunXmlToJsonTest.java</include>
761763
<include>src/test/java/org/exist/xquery/functions/fn/ParsingFunctionsTest.java</include>
762764
<include>src/test/java/org/exist/xquery/functions/fn/transform/ConvertTest.java</include>
763765
<include>src/test/java/org/exist/xquery/functions/fn/transform/FunTransformITTest.java</include>
766+
<include>src/main/java/org/exist/xquery/functions/system/FunctionAvailable.java</include>
764767
<include>src/test/java/org/exist/xquery/functions/xmldb/XMLDBStoreTest.java</include>
765768
<include>src/test/java/org/exist/xquery/functions/xquery3/SerializeTest.java</include>
766769
<include>src/test/resources-filtered/org/exist/xquery/import-from-pkg-test.conf.xml</include>
770+
<include>src/test/resources-filtered/org/exist/xquery/JavaBindingTest.conf.xml</include>
767771
<include>src/test/xquery/securitymanager/acl.xqm</include>
768772
</includes>
769773
</licenseSet>
@@ -903,16 +907,19 @@
903907
<include>src/main/java/org/exist/xmldb/RemoteRestoreService.java</include>
904908
<include>src/main/java/org/exist/xmlrpc/ExistRpcTypeFactory.java</include>
905909
<include>src/main/java/org/exist/xqj/Marshaller.java</include>
910+
<include>src/main/java/org/exist/xquery/DynamicTypeCheck.java</include>
911+
<include>src/main/java/org/exist/xquery/ErrorCodes.java</include>
906912
<include>src/main/java/org/exist/xquery/UserDefinedFunction.java</include>
907913
<include>src/main/java/org/exist/xquery/FunctionFactory.java</include>
908914
<include>src/main/java/org/exist/xquery/Optimizer.java</include>
915+
<include>src/main/java/org/exist/xquery/XPathUtil.java</include>
909916
<include>src/main/java/org/exist/xquery/XQueryContext.java</include>
910917
<include>src/main/java/org/exist/xquery/functions/fn/FunDeepEqual.java</include>
911918
<include>src/main/java/org/exist/xquery/functions/fn/FunUriCollection.java</include>
912919
<include>src/main/java/org/exist/xquery/functions/fn/ParsingFunctions.java</include>
913920
<include>src/main/java/org/exist/xquery/functions/integer/WordPicture.java</include>
914-
<include>src/main/java/org/exist/xquery/functions/system/FunctionAvailable.java</include>
915921
<include>src/main/java/org/exist/xquery/functions/system/GetUptime.java</include>
922+
<include>src/main/java/org/exist/xquery/functions/system/SystemModule.java</include>
916923
<include>src/main/java/org/exist/xquery/functions/system/Shutdown.java</include>
917924
<include>src/main/java/org/exist/xquery/functions/system/TriggerSystemTask.java</include>
918925
<include>src/main/java/org/exist/xquery/functions/util/BuiltinFunctions.java</include>
@@ -924,6 +931,7 @@
924931
<include>src/test/java/org/exist/xquery/update/UpdateReplaceTest.java</include>
925932
<include>src/main/java/org/exist/xquery/util/SerializerUtils.java</include>
926933
<include>src/main/java/org/exist/xquery/value/AbstractDateTimeValue.java</include>
934+
<include>src/main/java/org/exist/xquery/value/SequenceType.java</include>
927935
<include>src/main/java/org/exist/xquery/value/Type.java</include>
928936
<include>src/main/java/org/exist/xslt/EXistURIResolver.java</include>
929937
<include>src/main/resources-filtered/org/exist/system.properties</include>
@@ -946,6 +954,7 @@
946954
<include>src/main/java/org/exist/management/impl/JMXAgent.java</include>
947955
<include>src/test/java/org/exist/xmldb/CreateCollectionsTest.java</include>
948956
<include>src/test/java/org/exist/xquery/XQueryFunctionsTest.java</include>
957+
<include>src/main/java/org/exist/xquery/functions/array/ArrayType.java</include>
949958
<include>src/test/java/org/exist/xquery/functions/fn/DocTest.java</include>
950959
<include>src/main/java/org/exist/xquery/functions/fn/FnModule.java</include>
951960
<include>src/main/java/org/exist/xquery/functions/fn/FunBaseURI.java</include>
@@ -997,6 +1006,7 @@
9971006
<exclude>src/test/resources-filtered/conf.xml</exclude>
9981007
<exclude>src/test/resources-filtered/org/exist/storage/statistics/conf.xml</exclude>
9991008
<exclude>src/test/resources-filtered/org/exist/xquery/import-from-pkg-test.conf.xml</exclude>
1009+
<exclude>src/test/resources-filtered/org/exist/xquery/JavaBindingTest.conf.xml</exclude>
10001010
<exclude>src/test/resources-filtered/org/exist/xquery/functions/transform/transform-from-pkg-test.conf.xml</exclude>
10011011
<exclude>src/main/antlr/org/exist/xquery/parser/XQueryTree.g</exclude>
10021012
<exclude>src/main/java/org/exist/Indexer.java</exclude>
@@ -1126,13 +1136,19 @@
11261136
<exclude>src/main/java/org/exist/xmldb/RemoteRestoreService.java</exclude>
11271137
<exclude>src/main/java/org/exist/xmlrpc/ExistRpcTypeFactory.java</exclude>
11281138
<exclude>src/main/java/org/exist/xqj/Marshaller.java</exclude>
1139+
<exclude>src/main/java/org/exist/xquery/DynamicTypeCheck.java</exclude>
1140+
<exclude>src/main/java/org/exist/xquery/ErrorCodes.java</exclude>
11291141
<exclude>src/main/java/org/exist/xquery/FunctionFactory.java</exclude>
11301142
<exclude>src/test/java/org/exist/xquery/ImportFromPkgTest.java</exclude>
1143+
<exclude>src/main/java/org/exist/xquery/JavaBinding.java</exclude>
1144+
<exclude>src/test/java/org/exist/xquery/JavaBindingTest.java</exclude>
11311145
<exclude>src/main/java/org/exist/xquery/NameTest.java</exclude>
11321146
<exclude>src/main/java/org/exist/xquery/Optimizer.java</exclude>
11331147
<exclude>src/main/java/org/exist/xquery/UserDefinedFunction.java</exclude>
11341148
<exclude>src/test/java/org/exist/xquery/WatchdogTest.java</exclude>
1149+
<exclude>src/main/java/org/exist/xquery/XPathUtil.java</exclude>
11351150
<exclude>src/main/java/org/exist/xquery/XQueryContext.java</exclude>
1151+
<exclude>src/main/java/org/exist/xquery/functions/array/ArrayType.java</exclude>
11361152
<exclude>src/main/java/org/exist/xquery/functions/fn/FnModule.java</exclude>
11371153
<exclude>src/main/java/org/exist/xquery/functions/fn/FunDeepEqual.java</exclude>
11381154
<exclude>src/main/java/org/exist/xquery/functions/fn/FunDocAvailable.java</exclude>
@@ -1152,6 +1168,7 @@
11521168
<exclude>src/main/java/org/exist/xquery/functions/system/FunctionAvailable.java</exclude>
11531169
<exclude>src/main/java/org/exist/xquery/functions/system/GetUptime.java</exclude>
11541170
<exclude>src/main/java/org/exist/xquery/functions/system/Shutdown.java</exclude>
1171+
<exclude>src/main/java/org/exist/xquery/functions/system/SystemModule.java</exclude>
11551172
<exclude>src/main/java/org/exist/xquery/functions/system/TriggerSystemTask.java</exclude>
11561173
<exclude>src/main/java/org/exist/xquery/functions/xmldb/XMLDBStore.java</exclude>
11571174
<exclude>src/test/java/org/exist/xquery/functions/xmldb/XMLDBStoreTest.java</exclude>
@@ -1278,6 +1295,7 @@
12781295
<exclude>src/main/java/org/exist/xquery/value/AtomicValueComparator.java</exclude>
12791296
<exclude>src/main/java/org/exist/xquery/value/ItemComparator.java</exclude>
12801297
<exclude>src/main/java/org/exist/xquery/value/SequenceComparator.java</exclude>
1298+
<exclude>src/main/java/org/exist/xquery/value/SequenceType.java</exclude>
12811299
<exclude>src/main/java/org/exist/xquery/value/SubSequence.java</exclude>
12821300
<exclude>src/test/java/org/exist/xquery/value/SubSequenceRangeTest.java</exclude>
12831301
<exclude>src/test/java/org/exist/xquery/value/SubSequenceTest.java</exclude>

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@
229229
import static org.exist.xquery.FunctionFactory.DISABLE_DEPRECATED_FUNCTIONS_ATTRIBUTE;
230230
import static org.exist.xquery.FunctionFactory.DISABLE_DEPRECATED_FUNCTIONS_BY_DEFAULT;
231231
import static org.exist.xquery.FunctionFactory.ENABLE_JAVA_BINDING_ATTRIBUTE;
232+
import static org.exist.xquery.FunctionFactory.ENABLE_JAVA_BINDING_BY_DEFAULT;
232233
import static org.exist.xquery.FunctionFactory.PROPERTY_DISABLE_DEPRECATED_FUNCTIONS;
233234
import static org.exist.xquery.FunctionFactory.PROPERTY_ENABLE_JAVA_BINDING;
234235
import static org.exist.xquery.XQueryContext.BUILT_IN_MODULE_CLASS_ATTRIBUTE;
@@ -544,7 +545,7 @@ private void configureBinaryManager(final Element binaryManager) throws Database
544545

545546
private void configureXQuery(final Element xquery) throws DatabaseConfigurationException {
546547
//java binding
547-
configureProperty(xquery, ENABLE_JAVA_BINDING_ATTRIBUTE, PROPERTY_ENABLE_JAVA_BINDING);
548+
configureProperty(xquery, ENABLE_JAVA_BINDING_ATTRIBUTE, PROPERTY_ENABLE_JAVA_BINDING, Configuration::asBoolean, ENABLE_JAVA_BINDING_BY_DEFAULT);
548549
configureProperty(xquery, DISABLE_DEPRECATED_FUNCTIONS_ATTRIBUTE, PROPERTY_DISABLE_DEPRECATED_FUNCTIONS, Configuration::asBoolean, DISABLE_DEPRECATED_FUNCTIONS_BY_DEFAULT);
549550
configureProperty(xquery, ENABLE_QUERY_REWRITING_ATTRIBUTE, PROPERTY_ENABLE_QUERY_REWRITING);
550551
configureProperty(xquery, ENFORCE_INDEX_USE_ATTRIBUTE, PROPERTY_ENFORCE_INDEX_USE);

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

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

191+
/**
192+
* Compare this Cardinality to another Cardinality.
193+
*
194+
* NOTE we can't implement (override) {@link Comparable#compareTo(Object)}
195+
* here as it is final in {@link java.lang.Enum}.
196+
*
197+
* @param other the other Cardinality to be compared.
198+
*
199+
* @return a negative integer, zero, or a positive integer as this Cardinality is less than, equal to, or greater than the other Cardinality.
200+
*/
201+
public int compare(final Cardinality other) {
202+
return Byte.compare(val, other.val);
203+
}
204+
191205
static class InternalValue {
192206
static final byte ZERO = 1;
193207
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
*
@@ -262,6 +286,10 @@ public class ErrorCodes {
262286
public static final ErrorCode EXXQDY0005 = new EXistErrorCode("EXXQDY0005", "No function call details were provided when trying to execute a Library Module.");
263287
public static final ErrorCode EXXQDY0006 = new EXistErrorCode("EXXQDY0006", "Unable to find named function when trying to execute a Library Module.");
264288

289+
public static final ErrorCode EXXQST0001 = new EXistErrorCode("EXXQST0001", "Java binding is disabled in the current configuration.");
290+
public static final ErrorCode EXXQST0002 = new EXistErrorCode("EXXQST0002", "No Java binding possible for the indicated Java class.");
291+
public static final ErrorCode EXXQST0003 = new EXistErrorCode("EXXQST0003", "No Java binding possible for the indicated Java field/method.");
292+
265293
public static final ErrorCode ERROR = new EXistErrorCode("ERROR", "Error.");
266294

267295
public static class ErrorCode {
@@ -309,12 +337,12 @@ private EXistErrorCode(String code, String description) {
309337

310338
public static class JavaErrorCode extends ErrorCode {
311339

312-
public JavaErrorCode(Throwable throwable) {
340+
public JavaErrorCode(final Throwable throwable) {
313341
super(new QName(
314342
throwable.getClass().getName(),
315343
Namespaces.EXIST_JAVA_BINDING_NS,
316344
Namespaces.EXIST_JAVA_BINDING_NS_PREFIX),
317-
throwable.getMessage());
345+
throwable.getMessage() != null ? throwable.getMessage() : throwable.getCause().getMessage());
318346
}
319347
}
320348
}

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

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ public class FunctionFactory {
6565

6666
public static final String ENABLE_JAVA_BINDING_ATTRIBUTE = "enable-java-binding";
6767
public static final String PROPERTY_ENABLE_JAVA_BINDING = "xquery.enable-java-binding";
68+
public static final boolean ENABLE_JAVA_BINDING_BY_DEFAULT = false;
6869
public static final String DISABLE_DEPRECATED_FUNCTIONS_ATTRIBUTE = "disable-deprecated-functions";
6970
public static final String PROPERTY_DISABLE_DEPRECATED_FUNCTIONS = "xquery.disable-deprecated-functions";
7071
public static final boolean DISABLE_DEPRECATED_FUNCTIONS_BY_DEFAULT = false;
@@ -125,7 +126,7 @@ public static Expression createFunction(XQueryContext context, QName qname, XQue
125126
//Check if the namespace URI starts with "java:". If yes, treat
126127
//the function call as a call to an arbitrary Java function.
127128
} else if (uri.startsWith("java:")) {
128-
step = javaFunctionBinding(context, ast, params, qname);
129+
step = javaBinding(context, ast, qname, params);
129130
}
130131
//None of the above matched: function is either a built-in function or
131132
//a user-defined function
@@ -273,20 +274,14 @@ private static CastExpression castExpression(XQueryContext context,
273274
return castExpr;
274275
}
275276

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.");
277+
private static JavaBinding javaBinding(final XQueryContext context, final XQueryAST ast, final QName qname, final List<Expression> params) throws XPathException {
278+
// NOTE(AR) Only allow java binding if specified in config file <xquery enable-java-binding="yes">
279+
final boolean enableJavaBinding = context.getBroker().getConfiguration().getProperty(PROPERTY_ENABLE_JAVA_BINDING, false);
280+
if (!enableJavaBinding) {
281+
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.");
285282
}
286-
final JavaCall call = new JavaCall(context, qname);
287-
call.setLocation(ast.getLine(), ast.getColumn());
288-
call.setArguments(params);
289-
return call;
283+
284+
return JavaBinding.createFunction(ast.getLine(), ast.getColumn(), context, qname, params);
290285
}
291286

292287
private static Function functionCall(final XQueryContext context,

0 commit comments

Comments
 (0)