Skip to content

Commit 93bc641

Browse files
committed
[optimize] Optimize retrieving permissions of Collections and Documents in the XQuery Security Manager Module.
1 parent 11eefe8 commit 93bc641

2 files changed

Lines changed: 70 additions & 13 deletions

File tree

exist-core/pom.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1371,6 +1371,7 @@
13711371
<include>src/test/java/org/exist/xquery/functions/securitymanager/GroupManagementFunctionRemoveGroupTest.java</include>
13721372
<include>src/test/java/org/exist/xquery/functions/securitymanager/GroupMembershipFunctionRemoveGroupMemberTest.java</include>
13731373
<include>src/test/java/org/exist/xquery/functions/securitymanager/IdFunctionTest.java</include>
1374+
<include>src/main/java/org/exist/xquery/functions/securitymanager/PermissionsFunction.java</include>
13741375
<include>src/test/java/org/exist/xquery/functions/securitymanager/PermissionsFunctionChmodTest.java</include>
13751376
<include>src/test/java/org/exist/xquery/functions/securitymanager/PermissionsFunctionChownTest.java</include>
13761377
<include>src/test/java/org/exist/xquery/functions/system/GetRunningXQueriesTest.java</include>
@@ -2184,6 +2185,7 @@
21842185
<exclude>src/test/java/org/exist/xquery/functions/securitymanager/GroupManagementFunctionRemoveGroupTest.java</exclude>
21852186
<exclude>src/test/java/org/exist/xquery/functions/securitymanager/GroupMembershipFunctionRemoveGroupMemberTest.java</exclude>
21862187
<exclude>src/test/java/org/exist/xquery/functions/securitymanager/IdFunctionTest.java</exclude>
2188+
<exclude>src/main/java/org/exist/xquery/functions/securitymanager/PermissionsFunction.java</exclude>
21872189
<exclude>src/test/java/org/exist/xquery/functions/securitymanager/PermissionsFunctionChmodTest.java</exclude>
21882190
<exclude>src/test/java/org/exist/xquery/functions/securitymanager/PermissionsFunctionChownTest.java</exclude>
21892191
<exclude>src/test/java/org/exist/xquery/functions/securitymanager/SecurityManagerTestUtil.java</exclude>

exist-core/src/main/java/org/exist/xquery/functions/securitymanager/PermissionsFunction.java

Lines changed: 68 additions & 13 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+
* admin@evolvedbinary.com
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
*
@@ -22,15 +46,17 @@
2246
package org.exist.xquery.functions.securitymanager;
2347

2448
import org.exist.collections.Collection;
25-
import org.exist.dom.persistent.DocumentImpl;
2649
import org.exist.dom.QName;
2750
import org.exist.dom.memtree.MemTreeBuilder;
51+
import org.exist.dom.persistent.LockedDocument;
2852
import org.exist.security.*;
2953
import org.exist.security.ACLPermission.ACE_ACCESS_TYPE;
3054
import org.exist.security.ACLPermission.ACE_TARGET;
3155
import org.exist.storage.DBBroker;
56+
import org.exist.storage.lock.Lock;
3257
import org.exist.storage.txn.TransactionException;
3358
import org.exist.storage.txn.Txn;
59+
import org.exist.util.LockException;
3460
import org.exist.util.SyntaxException;
3561
import org.exist.xmldb.XmldbURI;
3662
import org.exist.xquery.BasicFunction;
@@ -52,7 +78,7 @@
5278

5379
/**
5480
*
55-
* @author <a href="mailto:adam@existsolutions.com">Adam Retter</a>
81+
* @author <a href="mailto:adam@evolvedbinary.com">Adam Retter</a>
5682
*/
5783
public class PermissionsFunction extends BasicFunction {
5884

@@ -409,20 +435,49 @@ private Sequence functionOctalToMode(final String octal) {
409435
}
410436

411437
private Permission getPermissions(final XmldbURI pathUri) throws XPathException, PermissionDeniedException {
412-
final Permission permissions;
413-
final Collection col = context.getBroker().getCollection(pathUri);
414-
if(col != null) {
415-
permissions = col.getPermissionsNoLock();
438+
final DBBroker broker = context.getBroker();
439+
if (pathUri.equals(XmldbURI.DB)) {
440+
// Can only be a Collection (i.e. `/db`)
441+
try (final Collection rootCollection = broker.openCollection(pathUri, Lock.LockMode.READ_LOCK)) {
442+
return rootCollection.getPermissions();
443+
}
444+
416445
} else {
417-
final DocumentImpl doc = context.getBroker().getResource(pathUri, Permission.READ);
418-
if(doc != null) {
419-
permissions = doc.getPermissions();
420-
} else {
421-
throw new XPathException(this, "Resource or collection '" + pathUri.toString() + "' does not exist.");
446+
// Interrogate the parent Collection so that we can efficiently work out if this URI indicates a Collection or Document
447+
final XmldbURI parentCollectionUri = pathUri.removeLastSegment();
448+
final XmldbURI resourceName = pathUri.lastSegment();
449+
450+
try (final Collection parentCollection = broker.openCollection(parentCollectionUri, Lock.LockMode.READ_LOCK)) {
451+
452+
if (parentCollection.hasChildCollectionNoLock(broker, resourceName)) {
453+
// URI indicates a Collection
454+
455+
try (final Collection collection = broker.openCollection(pathUri, Lock.LockMode.READ_LOCK)) {
456+
457+
// asymmetrical locking - unlock parent
458+
parentCollection.close();
459+
460+
return collection.getPermissions();
461+
}
462+
} else {
463+
// URI indicates a Document
464+
465+
try (final LockedDocument lockedDocument = parentCollection.getDocumentWithLock(broker, resourceName, Lock.LockMode.READ_LOCK)) {
466+
467+
// asymmetrical locking - unlock parent
468+
parentCollection.close();
469+
470+
if (lockedDocument != null) {
471+
return lockedDocument.getDocument().getPermissions();
472+
}
473+
} catch (final LockException e) {
474+
throw new PermissionDeniedException(e.getMessage(), e);
475+
}
476+
}
422477
}
423-
}
424478

425-
return permissions;
479+
throw new XPathException(this, "Resource or collection '" + pathUri + "' does not exist.");
480+
}
426481
}
427482

428483
private org.exist.dom.memtree.DocumentImpl permissionsToXml(final Permission permission) {

0 commit comments

Comments
 (0)