From a19e921c7da1656a24d8c7a80075faf3a1470efd Mon Sep 17 00:00:00 2001 From: duncdrum Date: Sun, 5 Jul 2026 15:08:31 +0200 Subject: [PATCH 1/4] [feature] Add enabled="no" to disable modules, triggers, jobs, and SAX parser features in conf.xml Co-Authored-By: Claude Sonnet 4.6 --- .../java/org/exist/util/Configuration.java | 31 +++++++++-- .../org/exist/util/ParametersExtractor.java | 4 ++ .../resources/org/exist/xmldb/allowAnyUri.xml | 1 - exist-distribution/src/main/config/conf.xml | 31 ++++------- .../resources-filtered/lazy-cache-conf.xml | 1 - .../non-lazy-cache-conf.xml | 1 - schema/conf.xsd | 51 ++++++++++++++++++- schema/generate-conf-fixture.xsl | 10 ++++ 8 files changed, 103 insertions(+), 27 deletions(-) diff --git a/exist-core/src/main/java/org/exist/util/Configuration.java b/exist-core/src/main/java/org/exist/util/Configuration.java index bbead109e73..519d23aff27 100644 --- a/exist-core/src/main/java/org/exist/util/Configuration.java +++ b/exist-core/src/main/java/org/exist/util/Configuration.java @@ -591,6 +591,12 @@ private void loadModuleClasses(final Element xquery, throw (new DatabaseConfigurationException("element 'module' requires an attribute 'uri'")); } + // enabled="no" disables the module without removing it from conf.xml + if ("no".equalsIgnoreCase(elem.getAttribute("enabled"))) { + LOG.debug("Module '{}' is disabled via enabled=\"no\", skipping", uri); + continue; + } + final String clazz = elem.getAttribute(BUILT_IN_MODULE_CLASS_ATTRIBUTE); final String source = elem.getAttribute(BUILT_IN_MODULE_SOURCE_ATTRIBUTE); // either class or source attribute must be present @@ -836,6 +842,12 @@ private void configureScheduler(final Element scheduler) { } private void addJobToList(final List jobList, final Element job) { + // enabled="no" disables the job without removing it from conf.xml + if ("no".equalsIgnoreCase(getConfigAttributeValue(job, "enabled"))) { + LOG.debug("Job '{}' is disabled via enabled=\"no\", skipping", getConfigAttributeValue(job, JOB_NAME_ATTRIBUTE)); + return; + } + //get the job type final String strJobType = getConfigAttributeValue(job, JOB_TYPE_ATTRIBUTE); @@ -1107,6 +1119,12 @@ private void configureStartup(final Element startup) throws DatabaseConfiguratio // Get element final Element trigger = (Element) nlTrigger.item(i); + // enabled="no" disables the trigger without removing it from conf.xml + if ("no".equalsIgnoreCase(trigger.getAttribute("enabled"))) { + LOG.debug("Startup trigger '{}' is disabled via enabled=\"no\", skipping", trigger.getAttribute("class")); + continue; + } + // Get @class final String startupTriggerClass = trigger.getAttribute("class"); @@ -1191,10 +1209,17 @@ private void configureIndexer(final Document doc, final Element indexer) throws return; } final NodeList module = ((Element) modules.item(0)).getElementsByTagName(IndexManager.CONFIGURATION_MODULE_ELEMENT_NAME); - final IndexModuleConfig[] modConfig = new IndexModuleConfig[module.getLength()]; + final List modConfigList = new ArrayList<>(); for (int i = 0; i < module.getLength(); i++) { final Element elem = (Element) module.item(i); + + // enabled="no" disables the index module without removing it from conf.xml + if ("no".equalsIgnoreCase(elem.getAttribute("enabled"))) { + LOG.debug("Index module '{}' is disabled via enabled=\"no\", skipping", elem.getAttribute(IndexManager.INDEXER_MODULES_ID_ATTRIBUTE)); + continue; + } + final String className = elem.getAttribute(IndexManager.INDEXER_MODULES_CLASS_ATTRIBUTE); final String id = elem.getAttribute(IndexManager.INDEXER_MODULES_ID_ATTRIBUTE); @@ -1206,9 +1231,9 @@ private void configureIndexer(final Document doc, final Element indexer) throws throw (new DatabaseConfigurationException("Required attribute id is missing for module")); } - modConfig[i] = new IndexModuleConfig(id, className, elem); + modConfigList.add(new IndexModuleConfig(id, className, elem)); } - setProperty(IndexManager.PROPERTY_INDEXER_MODULES, modConfig); + setProperty(IndexManager.PROPERTY_INDEXER_MODULES, modConfigList.toArray(new IndexModuleConfig[0])); } private void configureValidation(final Optional dbHome, final Element validation) { diff --git a/exist-core/src/main/java/org/exist/util/ParametersExtractor.java b/exist-core/src/main/java/org/exist/util/ParametersExtractor.java index 28f0cfa15e8..7fc78febab0 100644 --- a/exist-core/src/main/java/org/exist/util/ParametersExtractor.java +++ b/exist-core/src/main/java/org/exist/util/ParametersExtractor.java @@ -255,6 +255,10 @@ private static Properties parseProperties(final Node container, final String ele for (int i = 0; i < params.getLength(); i++) { final Element param = ((Element) params.item(i)); + if ("no".equals(param.getAttribute("enabled"))) { + continue; + } + final String name = param.getAttribute("name"); final String value = param.getAttribute("value"); diff --git a/exist-core/src/test/resources/org/exist/xmldb/allowAnyUri.xml b/exist-core/src/test/resources/org/exist/xmldb/allowAnyUri.xml index a938990b72a..ef6f4ded5fd 100644 --- a/exist-core/src/test/resources/org/exist/xmldb/allowAnyUri.xml +++ b/exist-core/src/test/resources/org/exist/xmldb/allowAnyUri.xml @@ -924,7 +924,6 @@ xmldb:xcollection() should return an empty sequence when an XML resource can not be retrieved. --> - - + - + @@ -547,9 +547,7 @@ - + @@ -571,9 +569,7 @@ distribution of elements in the database, which can be used by the query optimizer for additional optimizations. --> - + - - @@ -998,22 +993,18 @@ - - + + - + @@ -1053,13 +1044,13 @@ - + - + diff --git a/extensions/modules/cache/src/test/resources-filtered/lazy-cache-conf.xml b/extensions/modules/cache/src/test/resources-filtered/lazy-cache-conf.xml index af9663be608..0350bee319a 100644 --- a/extensions/modules/cache/src/test/resources-filtered/lazy-cache-conf.xml +++ b/extensions/modules/cache/src/test/resources-filtered/lazy-cache-conf.xml @@ -735,7 +735,6 @@ xmldb:xcollection() should return an empty sequence when an XML resource can not be retrieved. --> - - + version="2.3.0"> @@ -36,6 +36,13 @@ + + + + Optional human-readable description of the parameter's purpose. + + + @@ -64,6 +71,13 @@ + + + + Set to "no" to disable this trigger without removing it from the configuration. + + + @@ -637,6 +651,13 @@ + + + + Set to "no" to disable this index module without removing it from the configuration. + + + @@ -823,6 +844,13 @@ + + + + Set to "no" to disable this job without removing it from the configuration. + + + @@ -853,6 +881,13 @@ + + + + Set to "no" to disable this feature flag without removing it from the configuration. + + + @@ -907,6 +942,13 @@ + + + + Set to "no" to disable this feature flag without removing it from the configuration. + + + @@ -1214,6 +1256,13 @@ + + + + Set to "no" to disable this module without removing it from the configuration. + + + diff --git a/schema/generate-conf-fixture.xsl b/schema/generate-conf-fixture.xsl index 98b44a42248..f5e931d6a3d 100644 --- a/schema/generate-conf-fixture.xsl +++ b/schema/generate-conf-fixture.xsl @@ -125,6 +125,10 @@ + + + @@ -135,6 +139,9 @@ + + + @@ -146,9 +153,12 @@ Canonical's RestXq/AutoDeployment startup triggers assume a full webapp deployment, a RESTXQ registry, an autodeploy directory, neither present nor wanted in an isolated test fixture, so they're dropped by default; restored per-fixture via $extra-triggers if needed. + XQueryStartupTrigger is dropped too: it requires /db/system/autostart infrastructure not + present in test fixtures. Re-add via $extra-triggers when needed. --> + From 9ec6fd7ec96123932a449f511997e39e0b53a648 Mon Sep 17 00:00:00 2001 From: duncdrum Date: Sun, 5 Jul 2026 16:36:47 +0200 Subject: [PATCH 2/4] [feature] Complete @enabled coverage: startup triggers with enabled="yes", scheduler jobs as live enabled="no" entries, @enabled on and in conf.xsd; bump schema to 2.5.0 Co-Authored-By: Claude Sonnet 4.6 --- exist-distribution/src/main/config/conf.xml | 41 +++++++++------------ schema/conf.xsd | 16 +++++++- 2 files changed, 33 insertions(+), 24 deletions(-) diff --git a/exist-distribution/src/main/config/conf.xml b/exist-distribution/src/main/config/conf.xml index e614827b319..c8a3dcaa40b 100644 --- a/exist-distribution/src/main/config/conf.xml +++ b/exist-distribution/src/main/config/conf.xml @@ -58,7 +58,7 @@ - http://exist-db.org/exist/apps/doc/documentation.xml --> - + - + - + @@ -212,12 +212,12 @@ - - - - - + --> + @@ -662,8 +662,7 @@ backup Set to "yes" to create a backup whenever the job runs, not just when it detects errors. --> - - - - diff --git a/schema/conf.xsd b/schema/conf.xsd index 89be6c9ff52..940c93baf3a 100644 --- a/schema/conf.xsd +++ b/schema/conf.xsd @@ -8,7 +8,7 @@ + version="2.5.0"> @@ -43,6 +43,13 @@ + + + + Set to "no" to disable this parameter without removing it from the configuration. + + + @@ -918,6 +925,13 @@ + + + + Set to "no" to disable this property without removing it from the configuration. + + + From fcb5d34756fbe1aa27fd29970c35ee68f0c648ac Mon Sep 17 00:00:00 2001 From: duncdrum Date: Sun, 5 Jul 2026 16:14:43 +0200 Subject: [PATCH 3/4] [feature] Tighten conf.xsd types, patterns, and docs; bump schema to 2.6.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add memorySizeType (pattern [0-9]+[KkMmGgTt]?|-1); apply to cacheSize, collectionCache, minDiskSpace, recovery/@size - pool/@min, @max: xs:integer → xs:positiveInteger - lock-table/@trace-stack-depth: xs:int → xs:nonNegativeInteger - indexer/create/@type: xs:anySimpleType → xs:string - transformer/@caching: xs:string → yes_no with default="yes" - scheduler/job/@period: xs:string → xs:positiveInteger - vector-models/model/@dimension: xs:integer → xs:positiveInteger - Fix swapped docs on raise-error-on-failed-retrieval / enforce-index-use - Fix "group-comit" typo in recovery/@group-commit doc - Fix rpc-server in-memory-size default 4196 → 4096 - Fill in TODO docs: indexer/create attrs, flushAfter, n, xquery module attrs (class/uri/src), xupdate/@growth-factor Co-Authored-By: Claude Sonnet 4.6 --- exist-distribution/src/main/config/conf.xml | 2 +- schema/conf.xsd | 98 +++++++++++++-------- 2 files changed, 62 insertions(+), 38 deletions(-) diff --git a/exist-distribution/src/main/config/conf.xml b/exist-distribution/src/main/config/conf.xml index c8a3dcaa40b..4aa436deaea 100644 --- a/exist-distribution/src/main/config/conf.xml +++ b/exist-distribution/src/main/config/conf.xml @@ -58,7 +58,7 @@ - http://exist-db.org/exist/apps/doc/documentation.xml --> - + + + + + + @@ -95,14 +105,14 @@ - + Maximum number of connections allowed. - + Minimum number of connections to keep alive. @@ -172,7 +182,7 @@ it will wait until the current file buffer (32kb) is really full. This can speed up eXist on some systems where a file sync is an expensive operation (mainly windows - XP; not necessary on Linux). However, group-comit="yes" + XP; not necessary on Linux). However, group-commit="yes" will increase the risk of an already committed operation being rolled back after a database crash. @@ -187,7 +197,7 @@ - + This attributes sets the maximum allowed size of the journal @@ -288,7 +298,7 @@ - + The maximum amount of memory to use for database page buffers. @@ -324,7 +334,7 @@ - + Maximum amount of memory (in megabytes) to use for collection caches. @@ -363,7 +373,7 @@ - + The amount of disk space (in megabytes) which should be available for @@ -470,7 +480,7 @@ - + When set above 0, this captures n frames of each threads stack that performs a try/lock/release @@ -640,14 +650,18 @@ - TODO + Number of documents to index before the n-gram index + is flushed to disk. Higher values improve throughput + at the cost of memory during bulk ingest. - TODO + The n in n-gram: the number of characters per token. + Default 3 produces trigrams, which support efficient + substring searches via the ngram:contains() function. @@ -678,21 +692,25 @@ - TODO + XPath expression to the node to index (e.g. "//book/title"). + Mutually exclusive with qname. - TODO + Qualified name of the element or attribute to index + (e.g. "title" or "@id"). Mutually exclusive with path. - + - TODO + XQuery/XML Schema type to cast node values to when indexing + (e.g. "xs:integer", "xs:dateTime"). Determines the comparison + semantics available on this index. @@ -826,7 +844,7 @@ - + Can be used to define an explicit period for firing the job instead @@ -1154,11 +1172,10 @@ - + - You can enable or disable xsl caching by this option. - This option is set to "yes" by default. + Set to "no" to disable XSL stylesheet caching. @@ -1252,21 +1269,27 @@ - TODO + Fully-qualified class name of the Java module implementation. + The class must implement org.exist.xquery.Module. + Mutually exclusive with src. - TODO + Namespace URI that this module is bound to + (e.g. "http://exist-db.org/xquery/math"). + Must match the URI declared inside the module source. - TODO + Path to an XQuery library module source file. + Used instead of class for XQuery-implemented modules. + Mutually exclusive with class. @@ -1318,24 +1341,23 @@ - When set to "strict", eXist will not use a range index unless all - collections in the context sequence define it. When set to - "always", the query engine will still use an index, even if only - one collection has it defined. It thus leaves it to the user to - properly define indexes and if you forget to specify an index on - a particular collection, it will be missing in the results. + Set to "yes" if a call to doc(), xmldb:document(), collection() or + xmldb:xcollection() should raise an error (FODC0002) when an + XML resource cannot be retrieved. + Set to "no" (default) if such a call should return an empty sequence + when the resource cannot be retrieved. - Set to "yes" if a call to doc(), xmldb:document(), collection() or - xmldb:xcollection() should raise an error (FODC0002) when an - XML resource can not be retrieved. - Set to "no" if a call to doc(), xmldb:document(), collection() or - xmldb:xcollection() should return an empty sequence when an - XML resource can not be retrieved. + Controls whether range indexes must be defined on all collections + in the context sequence before the query engine will use them. + "strict" — the index is used only if every collection in the context + defines it; otherwise the engine falls back to a full scan. + "always" — the engine uses an available index even if only some + collections define it; results may be incomplete if others lack the index. @@ -1371,7 +1393,9 @@ - TODO + Percentage by which the DOM storage file grows when it needs to + be expanded to accommodate new data. A value of 20 means the + file grows by 20% of its current size each time it is extended. @@ -1410,7 +1434,7 @@ - + Defines the maximum amount of bytes stored in memory for each content file instance. @@ -1467,7 +1491,7 @@ Local path or HuggingFace/API URL - + Embedding dimension (default 384) From e80ba7afe4c441c03468431203be40351bdb6fca Mon Sep 17 00:00:00 2001 From: duncdrum Date: Sun, 5 Jul 2026 20:04:15 +0200 Subject: [PATCH 4/4] [bugfix] Fix enabled check case-sensitivity; strip @enabled from fixture triggers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ParametersExtractor.parseProperties() used case-sensitive .equals("no") while every other enabled check in Configuration.java uses .equalsIgnoreCase(). An enabled="NO" parameter would be silently included instead of skipped. generate-conf-fixture.xsl stripped @enabled from kept module/index nodes but not from surviving triggers, so BouncyCastle and URLStreamHandler emitted an explicit enabled="yes" in generated fixtures — inconsistent with the module treatment and noise in fixture diffs. Co-Authored-By: Claude Sonnet 4.6 --- .../src/main/java/org/exist/util/ParametersExtractor.java | 2 +- schema/generate-conf-fixture.xsl | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/exist-core/src/main/java/org/exist/util/ParametersExtractor.java b/exist-core/src/main/java/org/exist/util/ParametersExtractor.java index 7fc78febab0..3454fef082d 100644 --- a/exist-core/src/main/java/org/exist/util/ParametersExtractor.java +++ b/exist-core/src/main/java/org/exist/util/ParametersExtractor.java @@ -255,7 +255,7 @@ private static Properties parseProperties(final Node container, final String ele for (int i = 0; i < params.getLength(); i++) { final Element param = ((Element) params.item(i)); - if ("no".equals(param.getAttribute("enabled"))) { + if ("no".equalsIgnoreCase(param.getAttribute("enabled"))) { continue; } diff --git a/schema/generate-conf-fixture.xsl b/schema/generate-conf-fixture.xsl index f5e931d6a3d..542fcd4a8e2 100644 --- a/schema/generate-conf-fixture.xsl +++ b/schema/generate-conf-fixture.xsl @@ -159,6 +159,9 @@ + +