From 40f663ad6845e3ca13d2b017ea217938c3c8a048 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Gr=C3=BCn?= Date: Mon, 3 Mar 2025 10:48:17 +0100 Subject: [PATCH] [MOD] Databases: refactorings --- .../src/main/java/org/basex/core/Context.java | 22 ---- .../main/java/org/basex/core/Databases.java | 100 ++++++++++-------- .../java/org/basex/core/cmd/CreateBackup.java | 3 +- .../java/org/basex/core/cmd/DropBackup.java | 8 +- .../main/java/org/basex/core/cmd/DropDB.java | 2 +- .../main/java/org/basex/core/cmd/List.java | 5 +- .../main/java/org/basex/core/users/User.java | 4 +- .../main/java/org/basex/core/users/Users.java | 2 +- .../org/basex/gui/dialog/DialogInput.java | 3 +- .../org/basex/gui/dialog/DialogManage.java | 4 +- .../java/org/basex/gui/dialog/DialogNew.java | 2 +- .../java/org/basex/query/func/db/DbList.java | 9 +- .../basex/query/func/db/DbListDetails.java | 2 +- .../basex/query/func/xquery/XQueryEval.java | 2 +- .../org/basex/query/up/DatabaseModifier.java | 5 +- 15 files changed, 84 insertions(+), 89 deletions(-) diff --git a/basex-core/src/main/java/org/basex/core/Context.java b/basex-core/src/main/java/org/basex/core/Context.java index af60ae9882..f539e172a1 100644 --- a/basex-core/src/main/java/org/basex/core/Context.java +++ b/basex-core/src/main/java/org/basex/core/Context.java @@ -10,7 +10,6 @@ import org.basex.query.util.pkg.*; import org.basex.query.value.seq.*; import org.basex.server.*; -import org.basex.util.list.*; import org.basex.util.log.*; import org.basex.util.options.*; @@ -270,27 +269,6 @@ public String clientName() { return client != null ? client.clientName() : user != null ? user.name() : null; } - /** - * Returns all databases for which the current user has read access. - * @return resulting list - */ - public StringList listDBs() { - return listDBs(null); - } - - /** - * Returns all databases for which the current user has read access. - * @param pattern database pattern (can be {@code null}) - * @return resulting list - */ - public StringList listDBs(final String pattern) { - final StringList dbs = databases.listDBs(pattern), sl = new StringList(dbs.size()); - for(final String db : dbs) { - if(user.has(Perm.READ, db)) sl.add(db); - } - return sl; - } - /** * Assigns an external object. * @param object external object diff --git a/basex-core/src/main/java/org/basex/core/Databases.java b/basex-core/src/main/java/org/basex/core/Databases.java index 8fcd544d36..a3154b0191 100644 --- a/basex-core/src/main/java/org/basex/core/Databases.java +++ b/basex-core/src/main/java/org/basex/core/Databases.java @@ -3,6 +3,7 @@ import java.util.*; import java.util.regex.*; +import org.basex.core.users.*; import org.basex.io.*; import org.basex.util.*; import org.basex.util.list.*; @@ -45,73 +46,60 @@ public final class Databases { } /** - * Lists all available databases and backups. - * @return database and backup list + * Returns the sorted names of all databases and backups. + * @return databases and backups + */ + public StringList all() { + return list(null, null, true); + } + + /** + * Returns the sorted names of all databases. + * @return databases and backups */ public StringList list() { - return list(true, null); + return list(null, null, false); } /** - * Lists all available databases matching the given name. Supports glob patterns. + * Returns the sorted names of all databases. + * @param user accessing user * @param pattern database pattern (can be {@code null}) - * @return database list + * @return databases */ - StringList listDBs(final String pattern) { - return list(false, pattern); + public StringList list(final User user, final String pattern) { + return list(user, pattern, false); } /** - * Returns the sorted names of all available databases and, optionally, backups. - * Filters for {@code name} if not {@code null} with glob support. - * @param backup return backups? + * Returns the sorted names of all databases and, optionally, backups. + * @param user accessing user (can be {@code null}) * @param pattern database pattern (can be {@code null}) - * @return database and backups list + * @param all include names of backed up databases + * @return databases and, optionally, backups */ - private StringList list(final boolean backup, final String pattern) { + private StringList list(final User user, final String pattern, final boolean all) { final Pattern pt = pattern == null ? null : regex(pattern); - final IOFile[] files = soptions.dbPath().children(); - final StringList list = new StringList(files.length); - final HashSet map = new HashSet<>(files.length); - for(final IOFile file : files) { + final StringList list = new StringList(); + final HashSet map = new HashSet<>(); + for(final IOFile file : soptions.dbPath().children()) { final String name = file.name(); - String add = null; - if(backup && name.endsWith(IO.ZIPSUFFIX)) { + String entry = null; + if(all && name.endsWith(IO.ZIPSUFFIX)) { final String[] split = ZIPPATTERN.split(name); - if(split.length > 0 && !split[0].equals(name)) add = split[0]; + if(split.length > 0 && !split[0].equals(name)) entry = split[0]; } else if(file.isDir() && !Strings.startsWith(name, '.')) { - add = name; + entry = name; } - // add entry if it matches the pattern, and has not already been added - if(add != null && (pt == null || pt.matcher(add).matches()) && map.add(add)) { - list.add(add); + // add entry if it has not already been added, matches the pattern, and is accessible + if(entry != null && map.add(entry) && (pt == null || pt.matcher(entry).matches()) && + (user == null || user.has(Perm.READ, entry))) { + list.add(entry); } } return list.sort(false); } - /** - * Returns a regular expression for the specified name pattern. - * @param pattern pattern - * @return regular expression - */ - public static Pattern regex(final String pattern) { - return regex(pattern, ""); - } - - /** - * Returns a regular expression for the specified name pattern. - * @param pattern pattern (can be {@code null}) - * @param suffix regular expression suffix - * @return regular expression or {@code null} - */ - private static Pattern regex(final String pattern, final String suffix) { - if(pattern == null) return null; - final String nm = REGEX.matcher(pattern).matches() ? IOFile.regex(pattern) : - pattern.replaceAll("([" + REGEXCHARS + "])", "\\\\$1") + suffix; - return Pattern.compile(nm, Prop.CASE ? 0 : Pattern.CASE_INSENSITIVE); - } - /** * Returns the names of all backups. * @return backups @@ -146,6 +134,15 @@ public StringList backups(final String name) { return backups.sort(Prop.CASE, false); } + /** + * Returns a regular expression for the specified name pattern. + * @param pattern pattern + * @return regular expression + */ + public static Pattern regex(final String pattern) { + return regex(pattern, ""); + } + /** * Extracts the name of a database from the name of a backup. * @param backup name of the backup (empty string for general data), optionally followed by date @@ -193,6 +190,19 @@ public static boolean validPattern(final String pattern) { return valid(pattern, true); } + /** + * Returns a regular expression for the specified name pattern. + * @param pattern pattern (can be {@code null}) + * @param suffix regular expression suffix + * @return regular expression or {@code null} + */ + private static Pattern regex(final String pattern, final String suffix) { + if(pattern == null) return null; + final String nm = REGEX.matcher(pattern).matches() ? IOFile.regex(pattern) : + pattern.replaceAll("([" + REGEXCHARS + "])", "\\\\$1") + suffix; + return Pattern.compile(nm, Prop.CASE ? 0 : Pattern.CASE_INSENSITIVE); + } + /** * Checks if the specified string is a valid database name. * @param name name to be checked (can be {@code null}) diff --git a/basex-core/src/main/java/org/basex/core/cmd/CreateBackup.java b/basex-core/src/main/java/org/basex/core/cmd/CreateBackup.java index 1a62baefe2..7039131041 100644 --- a/basex-core/src/main/java/org/basex/core/cmd/CreateBackup.java +++ b/basex-core/src/main/java/org/basex/core/cmd/CreateBackup.java @@ -52,7 +52,8 @@ protected boolean run() { return error(NAME_INVALID_X, pattern); // retrieve all databases - final StringList names = pattern.isEmpty() ? new StringList("") : context.listDBs(pattern); + final StringList names = pattern.isEmpty() ? new StringList("") : + context.databases.list(context.user(), pattern); if(names.isEmpty()) return error(DB_NOT_FOUND_X, pattern); // loop through all databases diff --git a/basex-core/src/main/java/org/basex/core/cmd/DropBackup.java b/basex-core/src/main/java/org/basex/core/cmd/DropBackup.java index 837b3a38d6..1c6fa50baf 100644 --- a/basex-core/src/main/java/org/basex/core/cmd/DropBackup.java +++ b/basex-core/src/main/java/org/basex/core/cmd/DropBackup.java @@ -31,13 +31,15 @@ protected boolean run() { if(!(general || Databases.validPattern(pattern))) return error(NAME_INVALID_X, pattern); // loop through all databases and collect databases to be dropped - final StringList names = general ? new StringList("") : context.listDBs(pattern); + final Databases db = context.databases; + final User user = context.user(); + final StringList names = general ? new StringList("") : db.list(user, pattern); // if the given argument is not a database name, it could be the name of a backup file - if(names.isEmpty() && context.user().has(Perm.READ, pattern)) names.add(pattern); + if(names.isEmpty() && user.has(Perm.READ, pattern)) names.add(pattern); // drop all backups for(final String name : names) { - for(final String backup : context.databases.backups(name)) { + for(final String backup : db.backups(name)) { drop(backup, soptions); } } diff --git a/basex-core/src/main/java/org/basex/core/cmd/DropDB.java b/basex-core/src/main/java/org/basex/core/cmd/DropDB.java index cfd9e5ebd1..6936e83c53 100644 --- a/basex-core/src/main/java/org/basex/core/cmd/DropDB.java +++ b/basex-core/src/main/java/org/basex/core/cmd/DropDB.java @@ -30,7 +30,7 @@ protected boolean run() { if(!Databases.validPattern(pattern)) return error(NAME_INVALID_X, pattern); // retrieve all databases; return true if no database is found (no error) - final StringList dbs = context.listDBs(pattern); + final StringList dbs = context.databases.list(context.user(), pattern); if(dbs.isEmpty()) return info(NO_DB_DROPPED); // loop through all databases diff --git a/basex-core/src/main/java/org/basex/core/cmd/List.java b/basex-core/src/main/java/org/basex/core/cmd/List.java index e73582653e..d0cfa84464 100644 --- a/basex-core/src/main/java/org/basex/core/cmd/List.java +++ b/basex-core/src/main/java/org/basex/core/cmd/List.java @@ -65,11 +65,12 @@ private boolean list() throws IOException { final Table table = new Table(); table.description = DATABASES_X; - final boolean create = context.user().has(Perm.CREATE); + final User user = context.user(); + final boolean create = user.has(Perm.CREATE); table.header.add(NAME).add(RESOURCES).add(SIZE); if(create) table.header.add(INPUT_PATH); - for(final String name : context.listDBs()) { + for(final String name : context.databases.list(user, null)) { String file; long dbsize = 0; int count = 0; diff --git a/basex-core/src/main/java/org/basex/core/users/User.java b/basex-core/src/main/java/org/basex/core/users/User.java index 873affa177..32a65e54d8 100644 --- a/basex-core/src/main/java/org/basex/core/users/User.java +++ b/basex-core/src/main/java/org/basex/core/users/User.java @@ -204,7 +204,7 @@ public synchronized String code(final Algorithm algorithm, final Code code) { * @param db database pattern (can be {@code null}) * @return permission */ - public synchronized Perm perm(final String db) { + public synchronized Perm permission(final String db) { if(db != null) { final Entry entry = find(db); if(entry != null) return entry.getValue(); @@ -265,7 +265,7 @@ public synchronized boolean has(final Perm perm) { * @return result of check */ public synchronized boolean has(final Perm perm, final String db) { - return perm(db).ordinal() >= perm.ordinal(); + return permission(db).ordinal() >= perm.ordinal(); } /** diff --git a/basex-core/src/main/java/org/basex/core/users/Users.java b/basex-core/src/main/java/org/basex/core/users/Users.java index beefb87232..554ab38ccc 100644 --- a/basex-core/src/main/java/org/basex/core/users/Users.java +++ b/basex-core/src/main/java/org/basex/core/users/Users.java @@ -168,7 +168,7 @@ public synchronized Table info(final String db, final Context ctx) { for(final String user : S_USERINFO) table.header.add(user); for(final User user : users(db, ctx)) { - table.contents.add(new TokenList().add(user.name()).add(user.perm(db).toString())); + table.contents.add(new TokenList().add(user.name()).add(user.permission(db).toString())); } return table.sort().toTop(token(ADMIN)); } diff --git a/basex-core/src/main/java/org/basex/gui/dialog/DialogInput.java b/basex-core/src/main/java/org/basex/gui/dialog/DialogInput.java index 117d80a3f2..3cca3dd026 100644 --- a/basex-core/src/main/java/org/basex/gui/dialog/DialogInput.java +++ b/basex-core/src/main/java/org/basex/gui/dialog/DialogInput.java @@ -61,7 +61,8 @@ enum Action { DialogInput(final String old, final BaseXDialog dialog, final Action action) { super(dialog, action.title); this.action = action; - databases = dialog.gui().context.listDBs(); + final Context ctx = dialog.gui().context; + databases = ctx.databases.list(); set(new BaseXLabel(action.label + COL, false, true).border(0, 0, 6, 0), BorderLayout.NORTH); diff --git a/basex-core/src/main/java/org/basex/gui/dialog/DialogManage.java b/basex-core/src/main/java/org/basex/gui/dialog/DialogManage.java index 913c9c064c..ce02f8a1dc 100644 --- a/basex-core/src/main/java/org/basex/gui/dialog/DialogManage.java +++ b/basex-core/src/main/java/org/basex/gui/dialog/DialogManage.java @@ -64,7 +64,7 @@ public DialogManage(final GUI gui) { panel.setLayout(new BorderLayout(4, 0)); // create database chooser - final String[] dbs = gui.context.databases.list().finish(); + final String[] dbs = gui.context.databases.all().finish(); choice = new BaseXList(this, false, dbs); choice.setSize(240, 600); final Data data = gui.context.data(); @@ -139,7 +139,7 @@ public void action(final Object cmp) { final Context ctx = gui.context; if(refresh) { // rebuild databases and focus list chooser - choice.setData(ctx.databases.list().finish()); + choice.setData(ctx.databases.all().finish()); choice.requestFocusInWindow(); refresh = false; } diff --git a/basex-core/src/main/java/org/basex/gui/dialog/DialogNew.java b/basex-core/src/main/java/org/basex/gui/dialog/DialogNew.java index 3db99a12de..d91c9f7865 100644 --- a/basex-core/src/main/java/org/basex/gui/dialog/DialogNew.java +++ b/basex-core/src/main/java/org/basex/gui/dialog/DialogNew.java @@ -137,7 +137,7 @@ public void action(final Object comp) { // database will be empty inf = EMPTY_DB; icon = Msg.WARN; - } else if(gui.context.listDBs().contains(nm)) { + } else if(gui.context.databases.list().contains(nm)) { // old database will be overwritten inf = OVERWRITE_DB; icon = Msg.WARN; diff --git a/basex-core/src/main/java/org/basex/query/func/db/DbList.java b/basex-core/src/main/java/org/basex/query/func/db/DbList.java index 9a4e71bd32..ceffeb8457 100644 --- a/basex-core/src/main/java/org/basex/query/func/db/DbList.java +++ b/basex-core/src/main/java/org/basex/query/func/db/DbList.java @@ -43,7 +43,7 @@ public Value value(final QueryContext qc) throws QueryException { */ private static Value list(final QueryContext qc) { final Context ctx = qc.context; - final StringList dbs = ctx.listDBs(); + final StringList dbs = ctx.databases.list(ctx.user(), null); final TokenList list = new TokenList(dbs.size()); for(final String name : dbs) list.add(name); return StrSeq.get(list); @@ -59,9 +59,10 @@ private Iter resources(final QueryContext qc) throws QueryException { final Data data = toData(qc); final String path = defined(1) ? toString(arg(1), qc) : ""; - final IntList docs = data.resources.docs(path); - final StringList binaries = data.resources.paths(path, ResourceType.BINARY); - final StringList values = data.resources.paths(path, ResourceType.VALUE); + final Resources resources = data.resources; + final IntList docs = resources.docs(path); + final StringList binaries = resources.paths(path, ResourceType.BINARY); + final StringList values = resources.paths(path, ResourceType.VALUE); final int ds = docs.size(), bs = ds + binaries.size(), size = bs + values.size(); return new BasicIter(size) { diff --git a/basex-core/src/main/java/org/basex/query/func/db/DbListDetails.java b/basex-core/src/main/java/org/basex/query/func/db/DbListDetails.java index 857b202fd9..30257854fa 100644 --- a/basex-core/src/main/java/org/basex/query/func/db/DbListDetails.java +++ b/basex-core/src/main/java/org/basex/query/func/db/DbListDetails.java @@ -44,7 +44,7 @@ public Value value(final QueryContext qc) throws QueryException { */ private static Iter list(final QueryContext qc) { final Context ctx = qc.context; - final StringList dbs = ctx.listDBs(); + final StringList dbs = ctx.databases.list(ctx.user(), null); return new BasicIter(dbs.size()) { @Override public FNode get(final long i) { diff --git a/basex-core/src/main/java/org/basex/query/func/xquery/XQueryEval.java b/basex-core/src/main/java/org/basex/query/func/xquery/XQueryEval.java index 7304c9b5a1..d7c183af63 100644 --- a/basex-core/src/main/java/org/basex/query/func/xquery/XQueryEval.java +++ b/basex-core/src/main/java/org/basex/query/func/xquery/XQueryEval.java @@ -64,7 +64,7 @@ final Value eval(final IOContent query, final boolean updating, final QueryConte final HashMap bindings = toBindings(arg(1), qc); final XQueryOptions options = new XQueryOptions(); final User user = qc.context.user(); - options.put(XQueryOptions.PERMISSION, user.perm("")); + options.put(XQueryOptions.PERMISSION, user.permission("")); toOptions(arg(2), options, qc); final Perm perm = Perm.get(options.get(XQueryOptions.PERMISSION).toString()); diff --git a/basex-core/src/main/java/org/basex/query/up/DatabaseModifier.java b/basex-core/src/main/java/org/basex/query/up/DatabaseModifier.java index 2f89072720..b3cce70a88 100644 --- a/basex-core/src/main/java/org/basex/query/up/DatabaseModifier.java +++ b/basex-core/src/main/java/org/basex/query/up/DatabaseModifier.java @@ -24,11 +24,12 @@ public void addData(final Data data) { @Override synchronized void add(final Update update, final QueryContext qc) throws QueryException { // check permissions + final User user = qc.context.user(); if(update instanceof NameUpdate) { - if(!qc.context.user().has(Perm.CREATE, ((NameUpdate) update).name())) + if(!user.has(Perm.CREATE, ((NameUpdate) update).name())) throw BASEX_PERMISSION_X.get(update.info(), Perm.CREATE); } else if(update instanceof DataUpdate) { - if(!qc.context.user().has(Perm.WRITE, ((DataUpdate) update).data().meta.name)) + if(!user.has(Perm.WRITE, ((DataUpdate) update).data().meta.name)) throw BASEX_PERMISSION_X.get(update.info(), Perm.WRITE); } super.add(update, qc);