From 7ee7a8d1d14a7ddac29c26e6ede87e0e8630c50b Mon Sep 17 00:00:00 2001 From: Amine REBATI Date: Sun, 17 Sep 2023 16:36:53 +0300 Subject: [PATCH 01/20] Added create collection from a path, and the one parameter signature. --- .../xmldb/XMLDBCreateCollection.java | 179 ++++++++++++++---- 1 file changed, 138 insertions(+), 41 deletions(-) diff --git a/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java b/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java index 9c8842c6057..17d2585af2a 100644 --- a/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java +++ b/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java @@ -25,18 +25,15 @@ import org.apache.logging.log4j.Logger; import org.exist.dom.QName; -import org.exist.xquery.Cardinality; -import org.exist.xquery.FunctionSignature; -import org.exist.xquery.XPathException; -import org.exist.xquery.XQueryContext; -import org.exist.xquery.value.FunctionReturnSequenceType; -import org.exist.xquery.value.FunctionParameterSequenceType; -import org.exist.xquery.value.Sequence; -import org.exist.xquery.value.SequenceType; -import org.exist.xquery.value.StringValue; -import org.exist.xquery.value.Type; +import org.exist.dom.persistent.NodeProxy; +import org.exist.xmldb.LocalCollection; +import org.exist.xmldb.XmldbURI; +import org.exist.xquery.*; +import org.exist.xquery.value.*; import org.xmldb.api.base.Collection; import org.xmldb.api.base.XMLDBException; +import java.net.URISyntaxException; +import java.util.Optional; /** * Implements eXist's xmldb:create-collection() function. @@ -44,45 +41,145 @@ * @author wolf */ public class XMLDBCreateCollection extends XMLDBAbstractCollectionManipulator { - private static final Logger logger = LogManager.getLogger(XMLDBCreateCollection.class); - public final static FunctionSignature signature = new FunctionSignature( + private static final Logger logger = LogManager.getLogger(XMLDBCreateCollection.class); + public final static FunctionSignature SIGNATURE_WITH_PARENT = new FunctionSignature( new QName("create-collection", XMLDBModule.NAMESPACE_URI, XMLDBModule.PREFIX), - "Create a new collection with name $new-collection as a child of " + - "$target-collection-uri. " + XMLDBModule.COLLECTION_URI + - "Returns the path to the new collection if successfully created, " + - "otherwise the empty sequence.", + "Create a new collection with name $new-collection as a child of " + + "$target-collection-uri. " + XMLDBModule.COLLECTION_URI + + "Returns the path to the new collection if successfully created, " + + "otherwise the empty sequence.", new SequenceType[]{ - new FunctionParameterSequenceType("target-collection-uri", Type.STRING, Cardinality.EXACTLY_ONE, "The target collection URI"), - new FunctionParameterSequenceType("new-collection", Type.STRING, Cardinality.EXACTLY_ONE, "The name of the new collection to create")}, + new FunctionParameterSequenceType("target-collection-uri", Type.STRING, Cardinality.EXACTLY_ONE, "The target collection URI"), + new FunctionParameterSequenceType("new-collection", Type.STRING, Cardinality.EXACTLY_ONE, "The name of the new collection to create")}, new FunctionReturnSequenceType(Type.STRING, Cardinality.ZERO_OR_ONE, "the path to the new collection if successfully created, otherwise the empty sequence")); - public XMLDBCreateCollection(XQueryContext context) { - super(context, signature); - } + public final static FunctionSignature SIGNATURE_WITH_URI = new FunctionSignature( + new QName("create-collection", XMLDBModule.NAMESPACE_URI, + XMLDBModule.PREFIX), + "Create a new collection by specifying the full uri $new-collection-uri. " + XMLDBModule.COLLECTION_URI + + "Returns the path to the new collection if successfully created, " + + "otherwise the empty sequence.", + new SequenceType[]{ + new FunctionParameterSequenceType("new-collection-uri", Type.STRING, Cardinality.EXACTLY_ONE, "The new collection URI")}, + new FunctionReturnSequenceType(Type.STRING, Cardinality.ZERO_OR_ONE, "the path to the new collection if successfully created, otherwise the empty sequence")); + + public XMLDBCreateCollection(XQueryContext context, FunctionSignature signature) { + super(context, signature); + } + + /* + * (non-Javadoc) + * + * @see org.exist.xquery.Expression#eval(org.exist.dom.persistent.DocumentSet, + * org.exist.xquery.value.Sequence, org.exist.xquery.value.Item) + */ + public Sequence evalWithCollection(Collection collection, Sequence[] args, Sequence contextSequence) + throws XPathException { + String collectionName = null; + if(2 == args.length) { + collectionName = args[1].getStringValue(); + } else if(1 == args.length) { + collectionName = args[0].getStringValue(); + } - /* - * (non-Javadoc) - * - * @see org.exist.xquery.Expression#eval(org.exist.dom.persistent.DocumentSet, - * org.exist.xquery.value.Sequence, org.exist.xquery.value.Item) - */ - public Sequence evalWithCollection(Collection collection, Sequence[] args, Sequence contextSequence) - throws XPathException { + try { + final Collection newCollection = createCollectionPath(collection, collectionName); - final String collectionName = args[1].getStringValue(); - - try { - final Collection newCollection = createCollectionPath(collection, collectionName); + if (newCollection == null) + {return Sequence.EMPTY_SEQUENCE;} + else + {return new StringValue(this, newCollection.getName());} - if (newCollection == null) - {return Sequence.EMPTY_SEQUENCE;} - else - {return new StringValue(this, newCollection.getName());} + } catch (final XMLDBException e) { + logger.error("Unable to create new collection {}", collectionName, e); + throw new XPathException(this, "failed to create new collection " + collectionName + ": " + e.getMessage(), e); + } + } + + /** + * Override of the eval method so we can create + * a collection using just its path. + * */ + @Override + public Sequence eval(final Sequence[] args, final Sequence contextSequence) + throws XPathException { + int paramNumber = 0; + + if (0 == args.length) { + throw new XPathException(this, "Expected a collection as the argument " + (paramNumber + 1) + "."); + } else if (2 == args.length) { + return super.eval(args, contextSequence); + } + + final boolean collectionNeedsClose = false; + Collection collection = null; + final Item item = args[paramNumber].itemAt(0); + if (Type.subTypeOf(item.getType(), Type.NODE)) { + final NodeValue node = (NodeValue) item; + if (logger.isDebugEnabled()) { + logger.debug("Found node"); + } + if (node.getImplementationType() == NodeValue.PERSISTENT_NODE) { + final org.exist.collections.Collection internalCol = ((NodeProxy) node).getOwnerDocument().getCollection(); + if (logger.isDebugEnabled()) { + logger.debug("Found node"); + } + try { + //TODO: use xmldbURI + collection = getLocalCollection(this, context, internalCol.getURI().toString()); + return new StringValue(this, collection.getName()); + } catch (final XMLDBException e) { + if (logger.isDebugEnabled()) { + logger.debug("Couldn't find parent collection, creating a new one."); + } + } + } else { + return Sequence.EMPTY_SEQUENCE; + } + } + + final String collectionURI = args[paramNumber].getStringValue(); + if (collection == null && collectionURI != null) { + try { + collection = getCollection(this, context, collectionURI, Optional.empty(), Optional.empty()); + return new StringValue(this, collection.getName()); + } catch (final XMLDBException xe) { + if (logger.isDebugEnabled()) { + logger.debug("Couldn't find parent collection, creating a new one."); + } + } + } else { + try { + return new StringValue(this, collection.getName()); + } catch (XMLDBException e) { + throw new RuntimeException(e); + } + } + + Sequence s = Sequence.EMPTY_SEQUENCE; + try { + collection = getRootCollection(context, collectionURI); + s = evalWithCollection(collection, args, contextSequence); + } finally { + if (collectionNeedsClose && collection != null) { + try { + collection.close(); + } catch (final Exception e) { + throw new XPathException(this, "Unable to close collection", e); + } + } + } + return s; + } - } catch (final XMLDBException e) { - logger.error("Unable to create new collection {}", collectionName, e); - throw new XPathException(this, "failed to create new collection " + collectionName + ": " + e.getMessage(), e); + public Collection getRootCollection(final XQueryContext context, final String collectionUri) throws XPathException { + Collection rootCollection = null; + try { + rootCollection = new LocalCollection(context.getSubject(), context.getBroker().getBrokerPool(), XmldbURI.xmldbUriFor("/db", false)); + } catch (final XMLDBException | URISyntaxException e) { + throw new XPathException(this, "Failed to access the root collection", e); + } + return rootCollection; } - } } From 206772ad57b29c684f0b5175db4b85129c3ade10 Mon Sep 17 00:00:00 2001 From: Amine REBATI Date: Sun, 17 Sep 2023 16:37:20 +0300 Subject: [PATCH 02/20] Added create collection with path signature. --- .../java/org/exist/xquery/functions/xmldb/XMLDBModule.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBModule.java b/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBModule.java index eef6edcbc1c..b96fe7b421e 100644 --- a/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBModule.java +++ b/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBModule.java @@ -55,7 +55,8 @@ public class XMLDBModule extends AbstractInternalModule { public final static String ANY_URI = "Resource URIs can be specified either as a simple collection path, an XMLDB URI or any URI."; public final static FunctionDef[] functions = { - new FunctionDef(XMLDBCreateCollection.signature, XMLDBCreateCollection.class), + new FunctionDef(XMLDBCreateCollection.SIGNATURE_WITH_URI, XMLDBCreateCollection.class), + new FunctionDef(XMLDBCreateCollection.SIGNATURE_WITH_PARENT, XMLDBCreateCollection.class), new FunctionDef(XMLDBRegisterDatabase.signature, XMLDBRegisterDatabase.class), new FunctionDef(XMLDBStore.FS_STORE[0], XMLDBStore.class), new FunctionDef(XMLDBStore.FS_STORE[1], XMLDBStore.class), From 66a060e79b43bc0428ba37fda326431dca2b50b7 Mon Sep 17 00:00:00 2001 From: Amine REBATI Date: Sun, 17 Sep 2023 17:28:49 +0300 Subject: [PATCH 03/20] Added test file for create-collection with path. --- .../xquery/xmldb/collection-create-tests.xql | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 exist-core/src/test/xquery/xmldb/collection-create-tests.xql diff --git a/exist-core/src/test/xquery/xmldb/collection-create-tests.xql b/exist-core/src/test/xquery/xmldb/collection-create-tests.xql new file mode 100644 index 00000000000..9d6728599ea --- /dev/null +++ b/exist-core/src/test/xquery/xmldb/collection-create-tests.xql @@ -0,0 +1,51 @@ +(: + : eXist-db Open Source Native XML Database + : Copyright (C) 2001 The eXist-db Authors + : + : info@exist-db.org + : http://www.exist-db.org + : + : This library is free software; you can redistribute it and/or + : modify it under the terms of the GNU Lesser General Public + : License as published by the Free Software Foundation; either + : version 2.1 of the License, or (at your option) any later version. + : + : This library is distributed in the hope that it will be useful, + : but WITHOUT ANY WARRANTY; without even the implied warranty of + : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + : Lesser General Public License for more details. + : + : You should have received a copy of the GNU Lesser General Public + : License along with this library; if not, write to the Free Software + : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + :) +xquery version "3.0"; + +module namespace t="http://exist-db.org/testsuite/collection-create"; + +import module namespace test="http://exist-db.org/xquery/xqsuite" at "resource:org/exist/xquery/lib/xqsuite/xqsuite.xql"; + +declare variable $t:parent-collection-name := "parent-collection"; +declare variable $t:parent-collection := "/db/" || $t:parent-collection-name; +declare variable $t:path-collection := "path/to/new-collection"; + +declare + %test:setUp +function t:setup() { + xmldb:create-collection("/db", $t:parent-collection-name) +}; + +declare + %test:tearDown +function t:cleanup() { + xmldb:remove($t:parent-collection) +}; + +declare + %test:assertEquals("/db/path/to/new-collection") +function t:fnDocAvailableOnHiddenResource() { + let $collection := xmldb:create-collection($t:path-collection) + return ( + $collection + ) +}; From f907b10ea58fd876fab1cdc99085f04b115d4d7f Mon Sep 17 00:00:00 2001 From: Amine REBATI Date: Tue, 26 Sep 2023 12:26:23 +0300 Subject: [PATCH 04/20] Removed wildcard imports. --- .../xmldb/XMLDBCreateCollection.java | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java b/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java index 17d2585af2a..1cb9c3757ea 100644 --- a/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java +++ b/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java @@ -24,14 +24,25 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.exist.dom.QName; import org.exist.dom.persistent.NodeProxy; +import org.exist.dom.QName; import org.exist.xmldb.LocalCollection; import org.exist.xmldb.XmldbURI; -import org.exist.xquery.*; -import org.exist.xquery.value.*; +import org.exist.xquery.FunctionSignature; +import org.exist.xquery.XPathException; +import org.exist.xquery.XQueryContext; +import org.exist.xquery.Cardinality; +import org.exist.xquery.value.FunctionParameterSequenceType; +import org.exist.xquery.value.FunctionReturnSequenceType; +import org.exist.xquery.value.SequenceType; +import org.exist.xquery.value.StringValue; +import org.exist.xquery.value.NodeValue; +import org.exist.xquery.value.Sequence; +import org.exist.xquery.value.Type; +import org.exist.xquery.value.Item; import org.xmldb.api.base.Collection; import org.xmldb.api.base.XMLDBException; + import java.net.URISyntaxException; import java.util.Optional; @@ -42,6 +53,7 @@ */ public class XMLDBCreateCollection extends XMLDBAbstractCollectionManipulator { private static final Logger logger = LogManager.getLogger(XMLDBCreateCollection.class); + public final static FunctionSignature SIGNATURE_WITH_PARENT = new FunctionSignature( new QName("create-collection", XMLDBModule.NAMESPACE_URI, XMLDBModule.PREFIX), @@ -64,7 +76,7 @@ public class XMLDBCreateCollection extends XMLDBAbstractCollectionManipulator { new FunctionParameterSequenceType("new-collection-uri", Type.STRING, Cardinality.EXACTLY_ONE, "The new collection URI")}, new FunctionReturnSequenceType(Type.STRING, Cardinality.ZERO_OR_ONE, "the path to the new collection if successfully created, otherwise the empty sequence")); - public XMLDBCreateCollection(XQueryContext context, FunctionSignature signature) { + public XMLDBCreateCollection(XQueryContext context, FunctionSignature signature) { super(context, signature); } @@ -97,6 +109,7 @@ public Sequence evalWithCollection(Collection collection, Sequence[] args, Seque } } + /** * Override of the eval method so we can create * a collection using just its path. From 5135da73dac03e4fb5aa2a80059a851c39253821 Mon Sep 17 00:00:00 2001 From: Amine REBATI Date: Tue, 26 Sep 2023 12:29:45 +0300 Subject: [PATCH 05/20] Changed new-collection-uri to collection-uri. --- .../exist/xquery/functions/xmldb/XMLDBCreateCollection.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java b/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java index 1cb9c3757ea..099a449a62c 100644 --- a/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java +++ b/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java @@ -69,11 +69,11 @@ public class XMLDBCreateCollection extends XMLDBAbstractCollectionManipulator { public final static FunctionSignature SIGNATURE_WITH_URI = new FunctionSignature( new QName("create-collection", XMLDBModule.NAMESPACE_URI, XMLDBModule.PREFIX), - "Create a new collection by specifying the full uri $new-collection-uri. " + XMLDBModule.COLLECTION_URI + + "Create a new collection by specifying the full uri $collection-uri. " + XMLDBModule.COLLECTION_URI + "Returns the path to the new collection if successfully created, " + "otherwise the empty sequence.", new SequenceType[]{ - new FunctionParameterSequenceType("new-collection-uri", Type.STRING, Cardinality.EXACTLY_ONE, "The new collection URI")}, + new FunctionParameterSequenceType("collection-uri", Type.STRING, Cardinality.EXACTLY_ONE, "The new collection URI")}, new FunctionReturnSequenceType(Type.STRING, Cardinality.ZERO_OR_ONE, "the path to the new collection if successfully created, otherwise the empty sequence")); public XMLDBCreateCollection(XQueryContext context, FunctionSignature signature) { From 78bf82ed6ccd158e82d7416d4e60b29c062c8606 Mon Sep 17 00:00:00 2001 From: Amine REBATI Date: Tue, 26 Sep 2023 12:38:09 +0300 Subject: [PATCH 06/20] Fixed order to public final static as per the JLS. --- .../exist/xquery/functions/xmldb/XMLDBCreateCollection.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java b/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java index 099a449a62c..e0b9f826560 100644 --- a/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java +++ b/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java @@ -54,7 +54,7 @@ public class XMLDBCreateCollection extends XMLDBAbstractCollectionManipulator { private static final Logger logger = LogManager.getLogger(XMLDBCreateCollection.class); - public final static FunctionSignature SIGNATURE_WITH_PARENT = new FunctionSignature( + public static final FunctionSignature SIGNATURE_WITH_PARENT = new FunctionSignature( new QName("create-collection", XMLDBModule.NAMESPACE_URI, XMLDBModule.PREFIX), "Create a new collection with name $new-collection as a child of " + @@ -66,7 +66,7 @@ public class XMLDBCreateCollection extends XMLDBAbstractCollectionManipulator { new FunctionParameterSequenceType("new-collection", Type.STRING, Cardinality.EXACTLY_ONE, "The name of the new collection to create")}, new FunctionReturnSequenceType(Type.STRING, Cardinality.ZERO_OR_ONE, "the path to the new collection if successfully created, otherwise the empty sequence")); - public final static FunctionSignature SIGNATURE_WITH_URI = new FunctionSignature( + public static final FunctionSignature SIGNATURE_WITH_URI = new FunctionSignature( new QName("create-collection", XMLDBModule.NAMESPACE_URI, XMLDBModule.PREFIX), "Create a new collection by specifying the full uri $collection-uri. " + XMLDBModule.COLLECTION_URI + From e898899edc044278ac84518c25553d8c0ef1740b Mon Sep 17 00:00:00 2001 From: Amine REBATI Date: Tue, 26 Sep 2023 12:44:23 +0300 Subject: [PATCH 07/20] Fixed catch blocs and thrown exception. --- .../exist/xquery/functions/xmldb/XMLDBCreateCollection.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java b/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java index e0b9f826560..0de4ca16362 100644 --- a/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java +++ b/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java @@ -165,8 +165,8 @@ public Sequence eval(final Sequence[] args, final Sequence contextSequence) } else { try { return new StringValue(this, collection.getName()); - } catch (XMLDBException e) { - throw new RuntimeException(e); + } catch (final XMLDBException e) { + throw new XPathException(this, "Unable to get collection name.", e); } } @@ -178,7 +178,7 @@ public Sequence eval(final Sequence[] args, final Sequence contextSequence) if (collectionNeedsClose && collection != null) { try { collection.close(); - } catch (final Exception e) { + } catch (final XMLDBException e) { throw new XPathException(this, "Unable to close collection", e); } } From 31abe51d71eaa68e7bd6de8bc382d17d5e9e72bf Mon Sep 17 00:00:00 2001 From: Amine REBATI Date: Tue, 26 Sep 2023 13:04:46 +0300 Subject: [PATCH 08/20] Fixed current test-case collection names. --- .../src/test/xquery/xmldb/collection-create-tests.xql | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/exist-core/src/test/xquery/xmldb/collection-create-tests.xql b/exist-core/src/test/xquery/xmldb/collection-create-tests.xql index 9d6728599ea..21d30ce7104 100644 --- a/exist-core/src/test/xquery/xmldb/collection-create-tests.xql +++ b/exist-core/src/test/xquery/xmldb/collection-create-tests.xql @@ -25,9 +25,9 @@ module namespace t="http://exist-db.org/testsuite/collection-create"; import module namespace test="http://exist-db.org/xquery/xqsuite" at "resource:org/exist/xquery/lib/xqsuite/xqsuite.xql"; -declare variable $t:parent-collection-name := "parent-collection"; -declare variable $t:parent-collection := "/db/" || $t:parent-collection-name; -declare variable $t:path-collection := "path/to/new-collection"; +declare variable $t:parent-collection-name := "/parent-collection"; +declare variable $t:parent-collection := "/db" || $t:parent-collection-name; +declare variable $t:path-collection := "/path/to/new-collection"; declare %test:setUp From e7118ed370f1ec9d3f5ad7afdf99b751e069de19 Mon Sep 17 00:00:00 2001 From: Amine REBATI Date: Tue, 26 Sep 2023 14:50:18 +0300 Subject: [PATCH 09/20] Added cleanCollectionUri function. --- .../xmldb/XMLDBCreateCollection.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java b/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java index 0de4ca16362..d3787f5566c 100644 --- a/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java +++ b/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java @@ -195,4 +195,28 @@ public Collection getRootCollection(final XQueryContext context, final String c } return rootCollection; } + + public String cleanCollectionUri(final String collectionUri) throws XPathException{ + final String newCollectionUri; + if (!collectionUri.startsWith("xmldb:")) { + newCollectionUri = collectionUri; + } else if (collectionUri.startsWith("xmldb:exist:///")) { + newCollectionUri = collectionUri.replaceFirst("xmldb:exist://", ""); + } else if (collectionUri.startsWith("xmldb:exist://embedded-eXist-server")) { + newCollectionUri = collectionUri.replaceFirst("xmldb:exist://embedded-eXist-server", ""); + } else if (collectionUri.startsWith("xmldb:exist://localhost")) { + newCollectionUri = collectionUri.replaceFirst("xmldb:exist://localhost", ""); + } else if (collectionUri.startsWith("xmldb:exist://127.0.0.1")) { + newCollectionUri = collectionUri.replaceFirst("xmldb:exist://127.0.0.1", ""); + } else { + // Maybe it's better to check for the existence of /db/ and remove the preceding part. @@TODO + throw new XPathException(this, "The collection name provided is incorrect."); + } + + if (newCollectionUri.startsWith("/db/")) { + return newCollectionUri.replaceFirst("/db", ""); + } + + return newCollectionUri; + } } From ac5f200ddfbd4b1e7a5926b001827603bc6966f6 Mon Sep 17 00:00:00 2001 From: Amine REBATI Date: Tue, 26 Sep 2023 14:55:19 +0300 Subject: [PATCH 10/20] Remove unused parameter collectionURI. --- .../exist/xquery/functions/xmldb/XMLDBCreateCollection.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java b/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java index d3787f5566c..30f893be87b 100644 --- a/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java +++ b/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java @@ -172,7 +172,7 @@ public Sequence eval(final Sequence[] args, final Sequence contextSequence) Sequence s = Sequence.EMPTY_SEQUENCE; try { - collection = getRootCollection(context, collectionURI); + collection = getRootCollection(context); s = evalWithCollection(collection, args, contextSequence); } finally { if (collectionNeedsClose && collection != null) { @@ -186,7 +186,7 @@ public Sequence eval(final Sequence[] args, final Sequence contextSequence) return s; } - public Collection getRootCollection(final XQueryContext context, final String collectionUri) throws XPathException { + public Collection getRootCollection(final XQueryContext context) throws XPathException { Collection rootCollection = null; try { rootCollection = new LocalCollection(context.getSubject(), context.getBroker().getBrokerPool(), XmldbURI.xmldbUriFor("/db", false)); From 7cbd6dd423e9d927b18c7865499672fe31ace30f Mon Sep 17 00:00:00 2001 From: Amine REBATI Date: Tue, 26 Sep 2023 18:33:46 +0300 Subject: [PATCH 11/20] Fixed duplicating root collection. --- .../functions/xmldb/XMLDBCreateCollection.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java b/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java index 30f893be87b..da40e1fb8c2 100644 --- a/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java +++ b/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java @@ -86,13 +86,12 @@ public XMLDBCreateCollection(XQueryContext context, FunctionSignature signature) * @see org.exist.xquery.Expression#eval(org.exist.dom.persistent.DocumentSet, * org.exist.xquery.value.Sequence, org.exist.xquery.value.Item) */ - public Sequence evalWithCollection(Collection collection, Sequence[] args, Sequence contextSequence) - throws XPathException { - String collectionName = null; - if(2 == args.length) { + public Sequence evalWithCollection(Collection collection, Sequence[] args, Sequence contextSequence) throws XPathException { + final String collectionName; + if (args.length > 1) { collectionName = args[1].getStringValue(); - } else if(1 == args.length) { - collectionName = args[0].getStringValue(); + } else { + collectionName = cleanCollectionUri(args[0].getStringValue()); } try { @@ -105,7 +104,7 @@ public Sequence evalWithCollection(Collection collection, Sequence[] args, Seque } catch (final XMLDBException e) { logger.error("Unable to create new collection {}", collectionName, e); - throw new XPathException(this, "failed to create new collection " + collectionName + ": " + e.getMessage(), e); + throw new XPathException(this, "Failed to create new collection " + collectionName + ": " + e.getMessage(), e); } } From 43f331f35939b2916231f20847544f4e7beb290f Mon Sep 17 00:00:00 2001 From: Amine REBATI Date: Tue, 26 Sep 2023 18:47:08 +0300 Subject: [PATCH 12/20] Fixed indentation. --- .../xquery/functions/xmldb/XMLDBCreateCollection.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java b/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java index da40e1fb8c2..b621d3db8be 100644 --- a/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java +++ b/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java @@ -97,10 +97,11 @@ public Sequence evalWithCollection(Collection collection, Sequence[] args, Seque try { final Collection newCollection = createCollectionPath(collection, collectionName); - if (newCollection == null) - {return Sequence.EMPTY_SEQUENCE;} - else - {return new StringValue(this, newCollection.getName());} + if (newCollection == null) { + return Sequence.EMPTY_SEQUENCE; + } else { + return new StringValue(this, newCollection.getName()); + } } catch (final XMLDBException e) { logger.error("Unable to create new collection {}", collectionName, e); From cf1a8de07624fb3e68e1d3bfabda440a26bf59fc Mon Sep 17 00:00:00 2001 From: Amine REBATI Date: Tue, 26 Sep 2023 18:47:36 +0300 Subject: [PATCH 13/20] Fixed function doc. --- .../xmldb/XMLDBCreateCollection.java | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java b/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java index b621d3db8be..c1ca35f66c0 100644 --- a/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java +++ b/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java @@ -80,11 +80,13 @@ public XMLDBCreateCollection(XQueryContext context, FunctionSignature signature) super(context, signature); } - /* - * (non-Javadoc) - * - * @see org.exist.xquery.Expression#eval(org.exist.dom.persistent.DocumentSet, - * org.exist.xquery.value.Sequence, org.exist.xquery.value.Item) + /** + * Creates a new collection using the provided arguments. + * @param collection The parent collection. + * @param args The arguments given to the function. + * @param contextSequence The context sequence for the function or null. + * @return Sequence The collection uri. + * @throws XPathException */ public Sequence evalWithCollection(Collection collection, Sequence[] args, Sequence contextSequence) throws XPathException { final String collectionName; @@ -110,10 +112,14 @@ public Sequence evalWithCollection(Collection collection, Sequence[] args, Seque } + /** - * Override of the eval method so we can create - * a collection using just its path. - * */ + * Override of the eval method, so we can create a collection using just its path. + * @param args The arguments given to the function. + * @param contextSequence The context sequence for the function or null. + * @return Sequence The collection uri. + * @throws XPathException + */ @Override public Sequence eval(final Sequence[] args, final Sequence contextSequence) throws XPathException { From 1915cfae17e724b7fded08b975ed19091c3278af Mon Sep 17 00:00:00 2001 From: Amine REBATI Date: Tue, 26 Sep 2023 18:50:53 +0300 Subject: [PATCH 14/20] Fixed log level and removed unecessary logs. --- .../xquery/functions/xmldb/XMLDBCreateCollection.java | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java b/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java index c1ca35f66c0..5524cd7b3a9 100644 --- a/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java +++ b/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java @@ -136,20 +136,14 @@ public Sequence eval(final Sequence[] args, final Sequence contextSequence) final Item item = args[paramNumber].itemAt(0); if (Type.subTypeOf(item.getType(), Type.NODE)) { final NodeValue node = (NodeValue) item; - if (logger.isDebugEnabled()) { - logger.debug("Found node"); - } if (node.getImplementationType() == NodeValue.PERSISTENT_NODE) { final org.exist.collections.Collection internalCol = ((NodeProxy) node).getOwnerDocument().getCollection(); - if (logger.isDebugEnabled()) { - logger.debug("Found node"); - } try { //TODO: use xmldbURI collection = getLocalCollection(this, context, internalCol.getURI().toString()); return new StringValue(this, collection.getName()); } catch (final XMLDBException e) { - if (logger.isDebugEnabled()) { + if (logger.isTraceEnabled()) { logger.debug("Couldn't find parent collection, creating a new one."); } } @@ -164,7 +158,7 @@ public Sequence eval(final Sequence[] args, final Sequence contextSequence) collection = getCollection(this, context, collectionURI, Optional.empty(), Optional.empty()); return new StringValue(this, collection.getName()); } catch (final XMLDBException xe) { - if (logger.isDebugEnabled()) { + if (logger.isTraceEnabled()) { logger.debug("Couldn't find parent collection, creating a new one."); } } From 3ed9193c2f639352987b4428fb9a5ab87ec27504 Mon Sep 17 00:00:00 2001 From: Amine REBATI Date: Tue, 26 Sep 2023 18:58:13 +0300 Subject: [PATCH 15/20] Removed sequenced constructor and added a new test case. --- .../xquery/xmldb/collection-create-tests.xql | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/exist-core/src/test/xquery/xmldb/collection-create-tests.xql b/exist-core/src/test/xquery/xmldb/collection-create-tests.xql index 21d30ce7104..d5e5f83a586 100644 --- a/exist-core/src/test/xquery/xmldb/collection-create-tests.xql +++ b/exist-core/src/test/xquery/xmldb/collection-create-tests.xql @@ -27,7 +27,8 @@ import module namespace test="http://exist-db.org/xquery/xqsuite" at "resource:o declare variable $t:parent-collection-name := "/parent-collection"; declare variable $t:parent-collection := "/db" || $t:parent-collection-name; -declare variable $t:path-collection := "/path/to/new-collection"; +declare variable $t:path-collection := $t:parent-collection-name || "/path/to/new-collection"; +declare variable $t:path-collection-from-root := "/db/path/to/new-collection-from-root"; declare %test:setUp @@ -38,14 +39,20 @@ function t:setup() { declare %test:tearDown function t:cleanup() { - xmldb:remove($t:parent-collection) + xmldb:remove($t:parent-collection), + xmldb:remove($t:path-collection-from-root) }; declare - %test:assertEquals("/db/path/to/new-collection") -function t:fnDocAvailableOnHiddenResource() { + %test:assertEquals("/db/parent-collection/path/to/new-collection") +function t:fnCreateNewRecursiveCollection() { let $collection := xmldb:create-collection($t:path-collection) - return ( - $collection - ) + return $collection +}; + +declare + %test:assertEquals("/db/path/to/new-collection-from-root") +function t:fnCreateNewRecursiveCollectionFromRoot() { + let $collection := xmldb:create-collection($t:path-collection-from-root) + return $collection }; From 11b270b0c537c26490f60a81b4f5a6794a310923 Mon Sep 17 00:00:00 2001 From: Amine REBATI Date: Wed, 27 Sep 2023 10:16:08 +0300 Subject: [PATCH 16/20] Use ROOT_COLLECTION constant instead of /db string --- .../org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java b/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java index 5524cd7b3a9..ea5277343a6 100644 --- a/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java +++ b/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java @@ -189,7 +189,7 @@ public Sequence eval(final Sequence[] args, final Sequence contextSequence) public Collection getRootCollection(final XQueryContext context) throws XPathException { Collection rootCollection = null; try { - rootCollection = new LocalCollection(context.getSubject(), context.getBroker().getBrokerPool(), XmldbURI.xmldbUriFor("/db", false)); + rootCollection = new LocalCollection(context.getSubject(), context.getBroker().getBrokerPool(), XmldbURI.xmldbUriFor(XmldbURI.ROOT_COLLECTION, false)); } catch (final XMLDBException | URISyntaxException e) { throw new XPathException(this, "Failed to access the root collection", e); } From 72bc0ee412833f800bfbaf6197238fced068da91 Mon Sep 17 00:00:00 2001 From: Amine Rebati Date: Thu, 12 Oct 2023 16:08:18 +0100 Subject: [PATCH 17/20] [feature] used Automatic Resource Management to close collection. --- .../xmldb/XMLDBCreateCollection.java | 53 +++++++------------ 1 file changed, 18 insertions(+), 35 deletions(-) diff --git a/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java b/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java index ea5277343a6..99b3edf0c19 100644 --- a/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java +++ b/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java @@ -131,62 +131,45 @@ public Sequence eval(final Sequence[] args, final Sequence contextSequence) return super.eval(args, contextSequence); } - final boolean collectionNeedsClose = false; - Collection collection = null; final Item item = args[paramNumber].itemAt(0); if (Type.subTypeOf(item.getType(), Type.NODE)) { final NodeValue node = (NodeValue) item; if (node.getImplementationType() == NodeValue.PERSISTENT_NODE) { final org.exist.collections.Collection internalCol = ((NodeProxy) node).getOwnerDocument().getCollection(); - try { - //TODO: use xmldbURI - collection = getLocalCollection(this, context, internalCol.getURI().toString()); + //TODO: use xmldbURI + try (Collection collection = getLocalCollection(this, context, internalCol.getURI().toString())) { return new StringValue(this, collection.getName()); } catch (final XMLDBException e) { if (logger.isTraceEnabled()) { logger.debug("Couldn't find parent collection, creating a new one."); } + + final String collectionURI = args[paramNumber].getStringValue(); + if (collectionURI != null) { + try (Collection collection = getCollection(this, context, collectionURI, Optional.empty(), Optional.empty())) { + return new StringValue(this, collection.getName()); + } catch (final XMLDBException xe) { + if (logger.isTraceEnabled()) { + logger.debug("Couldn't find parent collection, creating a new one."); + } + } + } } } else { return Sequence.EMPTY_SEQUENCE; } } - final String collectionURI = args[paramNumber].getStringValue(); - if (collection == null && collectionURI != null) { - try { - collection = getCollection(this, context, collectionURI, Optional.empty(), Optional.empty()); - return new StringValue(this, collection.getName()); - } catch (final XMLDBException xe) { - if (logger.isTraceEnabled()) { - logger.debug("Couldn't find parent collection, creating a new one."); - } - } - } else { - try { - return new StringValue(this, collection.getName()); - } catch (final XMLDBException e) { - throw new XPathException(this, "Unable to get collection name.", e); - } - } - Sequence s = Sequence.EMPTY_SEQUENCE; - try { - collection = getRootCollection(context); - s = evalWithCollection(collection, args, contextSequence); - } finally { - if (collectionNeedsClose && collection != null) { - try { - collection.close(); - } catch (final XMLDBException e) { - throw new XPathException(this, "Unable to close collection", e); - } - } + try (Collection rootCollection = getRootCollection(context)) { + s = evalWithCollection(rootCollection, args, contextSequence); + } catch (final XMLDBException e) { + throw new XPathException(this, "Unable to close collection", e); } return s; } - public Collection getRootCollection(final XQueryContext context) throws XPathException { + public Collection getRootCollection(final XQueryContext context) throws XPathException { Collection rootCollection = null; try { rootCollection = new LocalCollection(context.getSubject(), context.getBroker().getBrokerPool(), XmldbURI.xmldbUriFor(XmldbURI.ROOT_COLLECTION, false)); From bd4d1d253bcd5bbdfa929fc1532c9e2e9ca40d0e Mon Sep 17 00:00:00 2001 From: Amine REBATI Date: Mon, 16 Oct 2023 08:05:22 +0100 Subject: [PATCH 18/20] [feature] Add final keyword to automatic resource management try catch blocks. --- .../exist/xquery/functions/xmldb/XMLDBCreateCollection.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java b/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java index 99b3edf0c19..97287c06b23 100644 --- a/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java +++ b/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java @@ -137,7 +137,7 @@ public Sequence eval(final Sequence[] args, final Sequence contextSequence) if (node.getImplementationType() == NodeValue.PERSISTENT_NODE) { final org.exist.collections.Collection internalCol = ((NodeProxy) node).getOwnerDocument().getCollection(); //TODO: use xmldbURI - try (Collection collection = getLocalCollection(this, context, internalCol.getURI().toString())) { + try (final Collection collection = getLocalCollection(this, context, internalCol.getURI().toString())) { return new StringValue(this, collection.getName()); } catch (final XMLDBException e) { if (logger.isTraceEnabled()) { @@ -146,7 +146,7 @@ public Sequence eval(final Sequence[] args, final Sequence contextSequence) final String collectionURI = args[paramNumber].getStringValue(); if (collectionURI != null) { - try (Collection collection = getCollection(this, context, collectionURI, Optional.empty(), Optional.empty())) { + try (final Collection collection = getCollection(this, context, collectionURI, Optional.empty(), Optional.empty())) { return new StringValue(this, collection.getName()); } catch (final XMLDBException xe) { if (logger.isTraceEnabled()) { @@ -161,7 +161,7 @@ public Sequence eval(final Sequence[] args, final Sequence contextSequence) } Sequence s = Sequence.EMPTY_SEQUENCE; - try (Collection rootCollection = getRootCollection(context)) { + try (final Collection rootCollection = getRootCollection(context)) { s = evalWithCollection(rootCollection, args, contextSequence); } catch (final XMLDBException e) { throw new XPathException(this, "Unable to close collection", e); From b963c004e72c56c144d572324337ad2f071fdaf1 Mon Sep 17 00:00:00 2001 From: Amine REBATI Date: Mon, 16 Oct 2023 08:07:53 +0100 Subject: [PATCH 19/20] [feature] Fix creating a collection with a path not starting by /db. --- .../exist/xquery/functions/xmldb/XMLDBCreateCollection.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java b/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java index 97287c06b23..06a360b91ee 100644 --- a/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java +++ b/exist-core/src/main/java/org/exist/xquery/functions/xmldb/XMLDBCreateCollection.java @@ -196,10 +196,10 @@ public String cleanCollectionUri(final String collectionUri) throws XPathExcept throw new XPathException(this, "The collection name provided is incorrect."); } - if (newCollectionUri.startsWith("/db/")) { - return newCollectionUri.replaceFirst("/db", ""); + if (!newCollectionUri.startsWith("/db/")) { + throw new XPathException(this, "Wrong collection path provided."); } - return newCollectionUri; + return newCollectionUri.replaceFirst("/db", ""); } } From 4f71bdc99d396b1a3b56965b84783bad277a5211 Mon Sep 17 00:00:00 2001 From: Amine REBATI Date: Mon, 16 Oct 2023 08:22:56 +0100 Subject: [PATCH 20/20] [feature] Fixed test case and added a new assert error test. --- .../test/xquery/xmldb/collection-create-tests.xql | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/exist-core/src/test/xquery/xmldb/collection-create-tests.xql b/exist-core/src/test/xquery/xmldb/collection-create-tests.xql index d5e5f83a586..00626106340 100644 --- a/exist-core/src/test/xquery/xmldb/collection-create-tests.xql +++ b/exist-core/src/test/xquery/xmldb/collection-create-tests.xql @@ -27,8 +27,9 @@ import module namespace test="http://exist-db.org/xquery/xqsuite" at "resource:o declare variable $t:parent-collection-name := "/parent-collection"; declare variable $t:parent-collection := "/db" || $t:parent-collection-name; -declare variable $t:path-collection := $t:parent-collection-name || "/path/to/new-collection"; +declare variable $t:path-collection := $t:parent-collection || "/path/to/new-collection"; declare variable $t:path-collection-from-root := "/db/path/to/new-collection-from-root"; +declare variable $t:wrong-path-collection := "/wrong/path-to-collection"; declare %test:setUp @@ -45,14 +46,21 @@ function t:cleanup() { declare %test:assertEquals("/db/parent-collection/path/to/new-collection") -function t:fnCreateNewRecursiveCollection() { +function t:fn-create-new-recursive-collection() { let $collection := xmldb:create-collection($t:path-collection) return $collection }; declare %test:assertEquals("/db/path/to/new-collection-from-root") -function t:fnCreateNewRecursiveCollectionFromRoot() { +function t:fn-create-new-recursive-collection-from-root() { let $collection := xmldb:create-collection($t:path-collection-from-root) return $collection }; + +declare + %test:assertError +function t:fn-create-new-recursive-collection-with-wrong-path() { + xmldb:create-collection($t:wrong-path-collection) +}; +