Skip to content
This repository was archived by the owner on Jul 8, 2025. It is now read-only.

[pull] develop from eXist-db:develop#383

Open
pull[bot] wants to merge 1335 commits into
EIDO-Systems:developfrom
eXist-db:develop
Open

[pull] develop from eXist-db:develop#383
pull[bot] wants to merge 1335 commits into
EIDO-Systems:developfrom
eXist-db:develop

Conversation

@pull
Copy link
Copy Markdown

@pull pull Bot commented Jun 5, 2025

See Commits and Changes for more details.


Created by pull[bot] (v2.0.0-alpha.1)

Can you help keep this open source service alive? 💖 Please sponsor : )

@pull pull Bot added the ⤵️ pull label Jun 5, 2025
line-o and others added 29 commits May 1, 2026 11:24
fix: restore support for declare option exist:timeout "-1" to disable timeout
Add W3C XInclude test suite and improve XInclude conformance
Reduce QT4 fn-format-number failures from 37 to 11 by addressing edge
cases in picture analysis, map-form options, and exponent formatting:

* Irregular grouping: per XPath 4.0, when integer-part separator
  positions are irregular, place separators only at the explicit
  positions instead of extrapolating the rightmost group size. Track
  the integer-part digit count to bound the regularity check at
  digit-count - 1, which makes pictures like '####,##' irregular while
  keeping '##,##,##' regular.

* Picture analysis after the exponent: passive characters (letters,
  punctuation) are now allowed as suffix material, while active
  characters (% and per-mille) raise FODF1310. A second occurrence of
  the exponent-separator that would itself be active (preceded and
  followed by digits) is rejected. Pictures like '9.9999e99end' work;
  '9.9999e999%' errors.

* Adjusted variables: when minimum-fractional-part-size is forced to 1
  by the integer-zero/maximum-frac-zero/exponent rule, mark the
  sub-picture as having a decimal separator so step 12 does not strip
  it from output ('#e0' formats 0.2 as '0.2e0').

* Exponent rendering: convert ASCII exponent digits to the
  decimal-digit family using zero-digit; support multi-character
  minus-sign on negative exponents.

* Multi-character minus-sign: change DecimalFormat.minusSign from int
  to String so renditions like 'minus ' work in negative-prefix and
  exponent-sign output.

* Map-form options:
  - Accept xs:QName (or string) for format-name, including via the
    bare-string overload, so namespaced decimal formats resolve via
    the QName item directly.
  - Atomize property values (sequences and singleton arrays) before
    applying them.
  - Reject multi-codepoint values for single-character properties
    (FODF1290), unless the value uses the X:rendition pattern.
  - After applying overrides, validate distinctness of all eight
    picture-string properties, that zero-digit is a Unicode digit
    with numeric value zero, and that digit is not a member of the
    decimal digit family. Each violation raises FODF1290.

* New error code: ErrorCodes.FODF1290 (Invalid decimal format
  property value).

Closes the fn-format-number portion of post-90-fixes phase 2.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* FnFormatDates.formatTimeZone: NPath 1200 -> below threshold by
  extracting formatNamedTimeZone, formatNumericTimeZone, and
  appendNumericTimeZoneMinutes helpers.

* FunParseIetfDate.tzoffset: convert traditional switch with break
  statements to arrow-form switch (case 1, 2 ->) for the no-colon
  digit-count branch.

* FnFormatNumbers.applyRenditions: stop reassigning the 'result'
  parameter; rename it to 'input' and accumulate into a local 'out'.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The fn:format-number conformance commit changed DecimalFormat.minusSign
from int to String to support multi-character renditions (XPath 4.0).
That broke binary compatibility with the published exist-xqts-runner
JAR, which references the field as int and crashes the JVM with
NoSuchFieldError mid-suite -- causing the XQTS CI job to abort after
~1k tests instead of running the full ~31k.

Restore minusSign as the int marker codepoint and add a separate
String minusSignRendition field, mirroring the marker/rendition split
already used for decimalSeparator, exponentSeparator, etc. The output
paths in FnFormatNumbers (negate prefix, negative-exponent sign) now
read minusSignRendition; map-form processing accepts a multi-character
minus-sign string and derives the marker codepoint from its first
codepoint.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…mes-apache-mime4j-core-0.8.14

Bump org.apache.james:apache-mime4j-core from 0.8.13 to 0.8.14
…na-mina-core-2.2.7

Bump org.apache.mina:mina-core from 2.2.6 to 2.2.7
reducing the number of PRs by bumping multiple deps per PR
e.g actions, jetty, lucene, logging, junit, ...
…si-4.0.14

Bump org.jline:jansi from 4.0.13 to 4.0.14
…ne-4.0.14

Bump org.jline:jline from 4.0.13 to 4.0.14
…warning in container bats

Two follow-ups to the security-hardening PR (#6283):

1. RESTServer's AUTHENTICATED_USERS_ONLY gate (introduced in
   ee7a139, 2017) compared the current subject's id against
   RealmImpl.GUEST_GROUP_ID. By coincidence, GUEST_GROUP_ID and
   ADMIN_ACCOUNT_ID share the same numeric value (1048574) -- account
   ids and group ids live in different namespaces, but the constants
   collide. The intended check is "reject the guest account"; the
   actual effect was the inverse: admin received 403 while guest
   passed the gate. This was invisible while the shipped default for
   xquery-submission/xupdate-submission was 'enabled'. C2 of this PR
   changes the default to 'authenticated', which exposes the bug.
   Fix by comparing against GUEST_ACCOUNT_ID instead.

2. The container bats suite (01-connect-spec.bats) greps the eXist
   logs for the literal token 'ERROR' to confirm a clean startup. C1
   of this PR emits a SEVERE warning at log level ERROR when the
   admin account is reachable with the empty default password --
   which is exactly the state of a freshly-started container image.
   Exclude that specific line from the grep so the test continues to
   guard against unexpected ERROR-level log output without masking
   the new warning.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
[ci] add groups to dependabot
Bumps [com.github.ben-manes.caffeine:caffeine](https://github.com/ben-manes/caffeine) from 3.2.3 to 3.2.4.
- [Release notes](https://github.com/ben-manes/caffeine/releases)
- [Commits](ben-manes/caffeine@v3.2.3...v3.2.4)

---
updated-dependencies:
- dependency-name: com.github.ben-manes.caffeine:caffeine
  dependency-version: 3.2.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
- SessionManager: promote SecureRandom to a static final field
  (it is thread-safe; no need for a per-instance instance).
- JMXServlet: drop the org.apache.commons.lang3.StringUtils import
  in favour of native String.isBlank() / null checks for the two
  call sites in this file.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Bumps the maven-plugins-tools group with 1 update: [org.owasp:dependency-check-maven](https://github.com/dependency-check/DependencyCheck).


Updates `org.owasp:dependency-check-maven` from 12.2.1 to 12.2.2
- [Release notes](https://github.com/dependency-check/DependencyCheck/releases)
- [Changelog](https://github.com/dependency-check/DependencyCheck/blob/main/CHANGELOG.md)
- [Commits](dependency-check/DependencyCheck@v12.2.1...v12.2.2)

---
updated-dependencies:
- dependency-name: org.owasp:dependency-check-maven
  dependency-version: 12.2.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: maven-plugins-tools
...

Signed-off-by: dependabot[bot] <support@github.com>
…-tools-182e09a388

Bump org.owasp:dependency-check-maven from 12.2.1 to 12.2.2 in the maven-plugins-tools group
Fix XQuery 3.1 compliance: casting, error codes, fn:not, path dedup, format-date, and more
…reaper

Two follow-ups to duncdrum's review comments:

1. RealmImpl.warnIfAdminPasswordIsEmpty(): demote the empty-admin-password
   notice from LOG.error back to LOG.warn. Booting with the OOTB
   configuration shouldn't produce ERROR-level output. The wording is
   strengthened with a hard-to-miss banner so the warning still stands
   out in operator logs.

   Also reverts the bats grep narrowing in 01-connect-spec.bats added in
   59d406f: the WARN-level message no longer trips an ERROR grep, so
   the test can go back to its original form.

2. SessionManager: add releaseAny(long) and releaseAll() as privileged
   eviction paths that bypass the subject-match check. RESTServer's
   _release parameter now accepts:
     - a numeric session id (existing behavior; DBA callers can release
       any entry, non-DBA callers are still restricted to their own)
     - the literal value 'all' or '*' (DBA-only): force-evicts every
       cached entry. Intended as the "force reaper" duncdrum requested
       so a DBA can reclaim entries stranded by failed client sessions
       (browser closed, network drop, RESTXQ caller crashed) without
       waiting for the per-entry 2-minute timeout.

   Non-DBA callers attempting _release=all receive 403
   PermissionDeniedException; the action is logged at INFO with the
   acting DBA's name and the count evicted.

Verified: RESTServiceTest 43/43 pass on the rebuilt module.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
[bugfix] Harden defaults against unauthenticated REST/XUpdate abuse
Use the OpenRewrite migration output to adopt Path.of consistently in files that only received the mechanical path factory rewrite.
Apply the isolated OpenRewrite text block rewrite in files that did not receive any other Java 21 refactors.
Apply the isolated pattern matching rewrite to files where OpenRewrite only simplified instanceof guards.
Isolate the serial annotation cleanup in files that only received the OpenRewrite @serial modernization.
Use the isolated String.formatted rewrite where OpenRewrite made no other Java 21 changes.
Apply the isolated Optional modernization in files that only switched from negated presence checks to isEmpty.
Isolate the parser-neutral semicolon cleanup in files where OpenRewrite made no other Java 21-related changes.
Apply the isolated Java 21 collection modernization in files that only switched to the sequenced collection APIs.
joewiz and others added 30 commits May 12, 2026 12:58
Convert switch statements to switch-as-expression style in
EvalWebSocketEndpoint.java and EvalWebSocketEndpointTest.java.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…Socket

Patch from Dannes Wessels (dizzzz):

- Fix potential NPE in HttpServletRequestWrapper when getContentType()
  returns null (two call sites)
- Propagate HTTP status code in XQueryURLRewrite.flushError() so error
  responses retain their status
- Add shutdown() methods to WebSocketEndpoint and EvalWebSocketEndpoint
  for proper ExecutorService cleanup
- Tie WebSocket subsystem shutdown to JettyStart lifecycle
- Make WebSocketEndpoint.sendAll() static, removing unnecessary
  per-broadcast object instantiation

Co-Authored-By: Dannes Wessels <dannes@exist-db.org>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Per duncdrum's request on PR #6145 (April 27 community call), make
log4j2.xml the single source of truth for all logging configuration in
the Jetty 12 upgrade.

Changes
-------
- log4j2.xml: add jetty.internal and jetty.requestlog appenders that
  write to logs/jetty/jetty.log and logs/jetty/requests.log respectively;
  add an org.eclipse.jetty WARN logger for Jetty internals (SLF4J-bridged
  via log4j-slf4j2-impl). Request-log level is overridable via
  EXIST_REQUEST_LOG_LEVEL — set OFF to suppress client-IP logging for
  GDPR.
- log4j2-container.xml: new Console-only configuration for container
  deployments. Routes eXist core logs, Jetty internals, and request logs
  to stdout so the container runtime can collect them.
- Dockerfile / Dockerfile-DEBUG: point log4j.configurationFile at
  log4j2-container.xml so containers stream logs by default.
- jetty-requestlog.xml: explicit Slf4jRequestLogWriter with loggerName
  "org.eclipse.jetty.server.RequestLog". The no-arg CustomRequestLog
  defaulted to the Slf4jRequestLogWriter class name in Jetty 12, which
  silently bypassed our log4j2 logger and produced an empty requests.log.
- jetty-logging.xml: removed. It only redirected stdout/stderr (a Jetty
  9-era pattern, useless under SLF4J) and was already commented out in
  both standalone/standard enabled-jetty-configs.
- enabled-jetty-configs: replace the jetty-logging.xml stub with a
  pointer to log4j2.xml.

Verified locally: requests.log captures NCSA-formatted hits, GDPR
suppression works via EXIST_REQUEST_LOG_LEVEL=OFF, and container mode
emits everything to stdout with no on-disk rolling files.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The test asserted the server-side channel count 100 ms after the
client's CountDownLatch fired. The latch counts down once
session.getBasicRemote().sendText() completes on the client, which
only guarantees the message has been buffered; the server's
@OnMessage handler runs on a different thread and may not have
updated the static sessions map yet. On a loaded CI runner (such
as duncdrum's recent run on PR #6145), 100 ms was insufficient and
the test failed with "One subscriber expected:<1> but was:<0>".

Replace the fixed Thread.sleep with a polling helper that waits
up to 2 s for the channel count to reach the expected value. Apply
the same poll on cleanup so a leaked session cannot affect a
subsequent test sharing the static sessions map.

Verified: 3 consecutive local runs pass.
… container log-capture

Two fixes for the container CI run that broke after the log4j2
consolidation in eedb773:

1. Bats test 6 ("logs contain repo.log output") greps docker logs for
   "Deployment.java", which only appears when the layout pattern
   includes %F (file name). The container console pattern was using
   %logger{36} (logger name like org.exist.repo.Deployment) instead.
   Switch to the same %d{DATE} [%t] %-5p (%F [%M]:%L) - %m %n pattern
   used by the standard log4j2.xml so on-disk and container logs match.

2. The "Copy logs on failure" CI step ran docker cp .../logs/exist.log,
   which no longer exists in the container — log4j2-container.xml is
   Console-only. Replace with `docker logs exist-ci > exist.log` so
   the artifact still captures the failure context.

Also addresses duncdrum's GDPR concern: the Docker HEALTHCHECK polls
/exist/xmlrpc continuously, and logging client IPs by default is
unfriendly to operators in EU jurisdictions. Default
EXIST_REQUEST_LOG_LEVEL to "off" in the container only — bare-metal
installs are unaffected and continue to default to "info". Operators
who want access logs in containers can opt back in by setting
EXIST_REQUEST_LOG_LEVEL=info.

Verified locally: all 6 bats connect-spec tests pass, and
`docker logs` shows zero NCSA-formatted request entries after curl +
multiple healthchecks.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Codacy reported 4 PMD issues on the new main-source files:

- EvalWebSocketEndpoint.java:147 — FieldDeclarationsShouldBeAtStartOfClass:
  move MAX_TEXT_MESSAGE_SIZE up next to the other static fields.

- QueryExecutor.java:68 (execute) — NPathComplexity 248 (over the 200
  threshold). Extract reportError() and reportTerminationOrError()
  helpers from the four near-identical catch blocks. Each catch now
  computes the phase-specific timing and delegates the rest. Drops
  NPath under threshold without changing behavior.

- QueryExecutor.java:208 (compile) — UnusedLocalVariable 'broker':
  thread us through XQueryContext via broker.getBrokerPool() instead
  of the field, so the resource is referenced by name.

- WebSocketEndpoint.java:71 — UnnecessaryConstructor: drop the empty
  no-arg constructor; the comment about per-connection instantiation
  belongs in the class javadoc, not a redundant constructor.

Verified: all 26 WebSocket tests pass; PMD reports zero violations
on the new main-source files (down from 4).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- WebSocketEndpoint.sendAll: convert the if/else-if instanceof chain
  on the map value into a switch expression with pattern matching,
  including a `case null` arm.
- WebSocketEndpointTest: replace the two `throw new RuntimeException(e)`
  wrappers around `IOException` with `UncheckedIOException`, which
  is the appropriate JDK type.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three warnings flagged by line-o on the latest review:

- EvalProtocol.ClientMessage: 10-parameter constructor exceeded
  PMD's ExcessiveParameterList threshold. Group `streaming` and
  `chunkSize` into a `StreamConfig` record.

- QueryExecutor.reportTerminationOrError / reportError: 10- and
  9-parameter signatures. Group the four error fields
  (xpe, message, line, column) into a private `ErrorInfo` record
  with named factories (`ErrorInfo.of(xpe)`, `ErrorInfo.of(msg)`,
  `ErrorInfo.of(msg, line, col)`).

- EvalWebSocketEndpointTest: replace bare `throw new
  RuntimeException(e)` for caught IOException with the standard
  `UncheckedIOException(e)`. Applied uniformly across all 24
  test sites for consistency (PMD only flagged one as
  delta-new, but the pattern was identical throughout).
Convert EvalProtocol.ClientMessage to a record (line 83 review comment),
matching reinhapa's preference and eliminating ~25 lines of constructor
boilerplate. Update all callers in EvalWebSocketEndpoint and QueryExecutor
to record-accessor syntax.

Convert the JSON-field switch in parseClientMessage to arrow form
(line 146 review comment). Each case becomes a single labeled-arrow
statement, dropping the verbose break boilerplate.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…et test

Addresses duncdrum's 2026-05-12 review on PR #6145.

- exist-distribution/src/main/config/log4j2.xml: change exist.request.log.level
  default from "info" to "off". Operators who want request logs must opt in by
  setting EXIST_REQUEST_LOG_LEVEL=info. Avoids logging client IPs by default
  per GDPR posture and removes healthcheck-induced log noise in the container.
- exist-core/src/test/java/org/exist/http/ws/EvalWebSocketEndpointTest.java:
  convert TEST_MODULE multi-line +-concat string to a Java 21 text block per
  the project Java-idiom convention.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Upgrade Jetty 11→12 (EE10, Jakarta Servlet 6.0) and add WebSocket module with streaming query evaluation
Bumps org.eclipse.jetty:jetty-server from 12.0.16 to 12.0.32.

---
updated-dependencies:
- dependency-name: org.eclipse.jetty:jetty-server
  dependency-version: 12.0.32
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
[bugfix] fn:xml-to-json: scope StAX reader to input element (+26 XQTS HEAD)
Bumps the logging group with 1 update: org.slf4j:slf4j-api.


Updates `org.slf4j:slf4j-api` from 2.0.17 to 2.0.18

---
updated-dependencies:
- dependency-name: org.slf4j:slf4j-api
  dependency-version: 2.0.18
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: logging
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps [jakarta.websocket:jakarta.websocket-api](https://github.com/eclipse-ee4j/websocket-api) from 2.1.0 to 2.2.0.
- [Commits](jakartaee/websocket@2.1.0-RELEASE...2.2.0-RELEASE)

---
updated-dependencies:
- dependency-name: jakarta.websocket:jakarta.websocket-api
  dependency-version: 2.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps com.oracle.database.jdbc:ojdbc11 from 23.26.1.0.0 to 23.26.2.0.0.

---
updated-dependencies:
- dependency-name: com.oracle.database.jdbc:ojdbc11
  dependency-version: 23.26.2.0.0
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps [jakarta.websocket:jakarta.websocket-client-api](https://github.com/eclipse-ee4j/websocket-api) from 2.1.0 to 2.2.0.
- [Commits](jakartaee/websocket@2.1.0-RELEASE...2.2.0-RELEASE)

---
updated-dependencies:
- dependency-name: jakarta.websocket:jakarta.websocket-client-api
  dependency-version: 2.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps org.eclipse.jetty:jetty-http from 12.0.32 to 12.0.33.

---
updated-dependencies:
- dependency-name: org.eclipse.jetty:jetty-http
  dependency-version: 12.0.33
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
…org.eclipse.jetty-jetty-http-12.0.33

Bump org.eclipse.jetty:jetty-http from 12.0.32 to 12.0.33 in /exist-parent
…cket-jakarta.websocket-client-api-2.2.0

Bump jakarta.websocket:jakarta.websocket-client-api from 2.1.0 to 2.2.0
…tabase.jdbc-ojdbc11-23.26.2.0.0

Bump com.oracle.database.jdbc:ojdbc11 from 23.26.1.0.0 to 23.26.2.0.0
…cket-jakarta.websocket-api-2.2.0

Bump jakarta.websocket:jakarta.websocket-api from 2.1.0 to 2.2.0
…e9289

Bump org.slf4j:slf4j-api from 2.0.17 to 2.0.18 in the logging group
…6379)

JMX uses the JavaBean naming convention to discover MBean attributes:
a method getX() declared on an MBean/MXBean interface is exposed as
attribute X; a bare-named x() is treated as an operation invocation
instead. Commit 9af8663 (2026-05-11) renamed getInstanceId() to
instanceId() on PerInstanceMBean and the 8 concrete implementations,
which silently dropped the InstanceId attribute from all 9 MXBeans
that extend PerInstanceMBean. External JMX consumers (JConsole,
VisualVM, monex, Prometheus exporters, etc.) that previously queried
InstanceId on any of these beans stopped seeing it.

Restore the get prefix in the interface, the 8 impl classes
(Database, CollectionCache, DiskUsage, LockTable, ProcessReport,
SanityReport, Cache, CacheManager), and the 2 call sites in JMXAgent.

BinaryValues is a Java record; its auto-generated instanceId()
accessor matches the record component name but not the JavaBean
convention. Add an explicit getInstanceId() delegate so the JMX
contract is honored without losing the record-style modernization.

Closes #6379

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…d for #6379)

Add XPath assertions to JmxRemoteTest.checkContent() that verify a
representative sample of MXBeans extending PerInstanceMBean still
publish InstanceId as a JMX attribute. Without this guard, an
inadvertent rename of getInstanceId() to a bare-name accessor (as
happened in 9af8663) silently drops the attribute and is only caught
by external integration testing.

Covers Database, ProcessReport, CollectionCache, LockTable, and
SanityReport — the same MXBeans whose //jmx:<Bean> presence is already
asserted by the surrounding test.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…bute

[bugfix] Restore getInstanceId() JavaBean naming on PerInstanceMBean (#6379)
[ci] Upgrade to latest 12.0 version of jetty
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants