This is an automated email from the ASF dual-hosted git repository.

tballison pushed a commit to branch TIKA-4856-presets
in repository https://gitbox.apache.org/repos/asf/tika.git


The following commit(s) were added to refs/heads/TIKA-4856-presets by this push:
     new 38887515ca improve documentation
38887515ca is described below

commit 38887515cac15d7e7836b593aa400bb01b2185e8
Author: tallison <[email protected]>
AuthorDate: Wed Sep 2 16:03:49 2026 -0400

    improve documentation
---
 CHANGES.txt                                        | 24 +++----
 docs/modules/ROOT/pages/pipes/configuration.adoc   |  2 +-
 docs/modules/ROOT/pages/pipes/plugins/json.adoc    |  2 +-
 .../ROOT/pages/using-tika/server/index.adoc        | 42 ++++++------
 .../org/apache/tika/pipes/api/FetchEmitTuple.java  | 10 ++-
 .../serialization/FetchEmitTupleDeserializer.java  |  5 +-
 .../apache/tika/pipes/core/server/PipesServer.java |  4 +-
 .../pipes/core/server/PresetNotFoundException.java |  7 +-
 .../apache/tika/config/loader/PresetRegistry.java  | 74 ++++++++--------------
 .../server/core/resource/PipesParsingHelper.java   |  6 +-
 .../tika/server/core/resource/PresetSelection.java | 12 ++--
 .../core/resource/RecursiveMetadataResource.java   |  5 +-
 .../tika/server/core/resource/TikaResource.java    | 23 +++----
 .../server/core/resource/UnpackerResource.java     |  7 +-
 14 files changed, 93 insertions(+), 130 deletions(-)

diff --git a/CHANGES.txt b/CHANGES.txt
index d18d621da8..01c9f054c3 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -3,21 +3,17 @@ Release 4.1.0 - unreleased
    * tika-server: named configuration presets (TIKA-4856). A preset is a
      vetted parse-context fragment activated in the server config (top-level
      "presets" key: an object defines one in place, true activates a
-     definition from the classpath catalog so its content tracks the Tika
-     version) and selected whole by inserting preset/{name} after the
-     resource root: /tika/preset/{name}[/text|...],
+     classpath-catalog definition) and selected whole via preset/{name}
+     after the resource root: /tika/preset/{name}[/text|...],
      /rmeta/preset/{name}[/{handlerType}], /unpack/preset/{name}[/all].
-     Exactly one preset per request, never combined with a config part, and
-     usable without allowPerRequestConfig -- the preset routes are network-
-     addressable separately from the /config endpoints, and nothing on the
-     classpath can activate a preset by itself. Only the preset's name
-     travels: the forked worker resolves the content from its own config at
-     config-tier trust, so presets may bind wire-blocked components and
-     raise timeout limits above the per-request clamp, and every active
-     preset resolves at startup or fails it. FetchEmitTuples submitted to
-     /pipes and /async may carry a "preset" field, resolved the same way
-     (unknown names answer the new PRESET_NOT_FOUND task status / HTTP 400;
-     the REST preset routes 404 before submission).
+     One preset per request, never combined with a config part, usable
+     without allowPerRequestConfig, and network-addressable separately from
+     /config. Only the name travels: the forked worker resolves the content
+     from its own config at config-tier trust, so presets may bind
+     wire-blocked components and raise timeout limits above the per-request
+     clamp; every active preset resolves at startup or fails it.
+     FetchEmitTuples on /pipes and /async may carry a "preset" field
+     (unknown names: new PRESET_NOT_FOUND status / HTTP 400).
 
    * Raster previews for the vector thumbnails of Office documents: the new
      poi-metafile-renderer draws EMF and WMF images through POI (a PNG of
diff --git a/docs/modules/ROOT/pages/pipes/configuration.adoc 
b/docs/modules/ROOT/pages/pipes/configuration.adoc
index fb1c205117..b88756be5d 100644
--- a/docs/modules/ROOT/pages/pipes/configuration.adoc
+++ b/docs/modules/ROOT/pages/pipes/configuration.adoc
@@ -113,7 +113,7 @@ See also xref:pipes/timeouts.adoc[Timeouts] for the full 
timeout model.
 
 |`maxTotalTaskTimeoutMillis`
 |`3600000`
-|Ceiling for *request-supplied* timeout limits: a per-request `timeout-limits` 
override may lower its timeouts freely but can never raise 
`totalTaskTimeoutMillis` or `progressTimeoutMillis` above this value (values 
over the cap are clamped with a warning). Limits set in the server's own 
`parse-context` are trusted and not subject to this cap.
+|Ceiling for *request-supplied* timeout limits: a per-request `timeout-limits` 
override may lower its timeouts freely but can never raise 
`totalTaskTimeoutMillis` or `progressTimeoutMillis` above this value (values 
over the cap are clamped with a warning). Limits set in the server's own 
`parse-context` — or in a preset a request selects — are trusted and not 
subject to this cap.
 
 |`maxWaitForClientMillis`
 |`60000`
diff --git a/docs/modules/ROOT/pages/pipes/plugins/json.adoc 
b/docs/modules/ROOT/pages/pipes/plugins/json.adoc
index 62301adc8f..52b1ebba9d 100644
--- a/docs/modules/ROOT/pages/pipes/plugins/json.adoc
+++ b/docs/modules/ROOT/pages/pipes/plugins/json.adoc
@@ -57,6 +57,6 @@ Unlike the other iterators, this one takes no `fetcherId` / 
`emitterId`: each li
 == Notes
 
 * The file format is JSON-lines (also called NDJSON) — one valid JSON object 
per line, no surrounding array brackets.
-* Each line must be a serialized `FetchEmitTuple`: `id`, `fetcher`, 
`fetchKey`, `emitter`, `emitKey`, and optionally `fetchRangeStart`, 
`fetchRangeEnd`, `metadata`, `parse-context`, `onParseException`. Any other
+* Each line must be a serialized `FetchEmitTuple`: `id`, `fetcher`, 
`fetchKey`, `emitter`, `emitKey`, and optionally `fetchRangeStart`, 
`fetchRangeEnd`, `metadata`, `parse-context`, `onParseException`, `preset`. Any 
other
   field is rejected — the deserializer does not tolerate unknown keys.
 * For columnar work items in a CSV, use the xref:pipes/plugins/csv.adoc[CSV 
iterator] instead.
diff --git a/docs/modules/ROOT/pages/using-tika/server/index.adoc 
b/docs/modules/ROOT/pages/using-tika/server/index.adoc
index 80a4a3e234..3ad3f58cc1 100644
--- a/docs/modules/ROOT/pages/using-tika/server/index.adoc
+++ b/docs/modules/ROOT/pages/using-tika/server/index.adoc
@@ -110,6 +110,8 @@ callers change how documents are parsed, widening what 
anyone who can reach the
 A *preset* is a named, vetted parse-context fragment: parser and component 
configurations keyed
 by friendly name, defined once in the server config (or shipped with Tika) and 
selected whole by
 name. Callers apply one by inserting `preset/{name}` directly after the 
resource root:
+`/tika/preset/{name}[/text|/html|/xml|/md|/json[/{handlerType}]]`,
+`/rmeta/preset/{name}[/{handlerType}]`, `/unpack/preset/{name}[/all]`.
 
 [source,bash]
 ----
@@ -136,30 +138,28 @@ the catalog fails startup:
 ----
 
 Presets are deliberately narrow: a request selects exactly one, the preset 
routes take no
-`config` part, and a preset never combines with request-supplied configuration 
— a caller who
-needs a variant asks the operator to define it as another preset. Because the 
content of a
-preset is operator- or Tika-vetted, the preset routes do *not* require 
`allowPerRequestConfig`:
-they are the safe public knob, while free-form `/config` stays the privileged 
one. The
-`preset/{name}` path segment also gives network controls an addressable 
surface — a reverse
-proxy can allow `/rmeta/preset/render-thumbnails` (or all of `/rmeta/preset/`) 
while blocking
-`/rmeta/config` entirely. An unknown preset name answers `404`. Preset names 
may not start
-with `config` (that path fragment gates the `/config` endpoints).
+`config` part, and a preset never combines with request-supplied configuration 
— a variant is
+another preset. Because preset content is operator- or Tika-vetted, the preset 
routes do *not*
+require `allowPerRequestConfig`, and the `preset/{name}` path segment gives 
network controls an
+addressable surface — a reverse proxy can allow `/rmeta/preset/` while 
blocking `/rmeta/config`
+entirely. An unknown preset name answers `404`. Names are letters, digits, 
`.`, `_`, `-`
+(max 100 chars) and may not start with `config` (that path fragment gates the 
`/config`
+endpoints).
 
 Only the preset's *name* travels with a request: the forked parse worker 
resolves the content
 from its own copy of the server config, with the same trust as the config's own
-`parse-context` block. A preset can therefore configure components that 
per-request `/config`
-input may not (detectors, embedded-document extraction, exception reporting, 
...) and raise
-timeout limits above the per-request clamp. Every active preset is fully 
resolved at startup,
-so a preset that cannot resolve fails the server rather than its first request.
-
-Output format on the preset routes: an explicit format segment in the URL
-(`/tika/preset/{name}/text`, `/rmeta/preset/{name}/xml`) always wins. Without 
one, a
-`ContentHandlerFactory` the preset itself binds decides the format; otherwise 
the config's
-factory, and finally the endpoint's usual default (Markdown).
-
-Presets also work on the batch surfaces: a `FetchEmitTuple` submitted to 
`/pipes` or `/async`
-may carry a top-level `"preset": "name"` field, resolved the same way and 
overlaid beneath
-whatever `parseContext` the tuple itself supplies.
+`parse-context` block. A preset can therefore bind components per-request 
`/config` input may
+not (detectors, embedded-document extraction, exception reporting, ...) and 
raise timeout
+limits above the per-request clamp. Every active preset resolves at startup, 
so a bad preset
+fails the server, not its first request.
+
+Output format on the preset routes: an explicit format segment 
(`/tika/preset/{name}/text`)
+always wins; without one, a `ContentHandlerFactory` the preset binds decides, 
then the
+config's, then the endpoint default (Markdown).
+
+On the batch surfaces, a `FetchEmitTuple` submitted to `/pipes` or `/async` 
may carry a
+top-level `"preset": "name"` field, resolved the same way beneath the tuple's 
own
+`parseContext`; an unknown name there answers the `PRESET_NOT_FOUND` status 
(HTTP `400`).
 
 === `allowPipes` — the `/pipes` and `/async` endpoints
 
diff --git 
a/tika-pipes/tika-pipes-api/src/main/java/org/apache/tika/pipes/api/FetchEmitTuple.java
 
b/tika-pipes/tika-pipes-api/src/main/java/org/apache/tika/pipes/api/FetchEmitTuple.java
index 16ac3023ae..2e9440112f 100644
--- 
a/tika-pipes/tika-pipes-api/src/main/java/org/apache/tika/pipes/api/FetchEmitTuple.java
+++ 
b/tika-pipes/tika-pipes-api/src/main/java/org/apache/tika/pipes/api/FetchEmitTuple.java
@@ -38,8 +38,7 @@ public class FetchEmitTuple implements Serializable {
     private final Metadata metadata;
     private final ParseContext parseContext;
     private final ON_PARSE_EXCEPTION onParseException;
-    // Name of an operator-defined preset the server resolves from its own 
config
-    // at config-tier trust; only the name travels, never the preset's content.
+    // Preset selector only: the server resolves the content from its own 
config
     private final String presetName;
 
     public FetchEmitTuple(String id, FetchKey fetchKey, EmitKey emitKey) {
@@ -58,6 +57,7 @@ public class FetchEmitTuple implements Serializable {
         this(id, fetchKey, emitKey, metadata, parseContext, onParseException, 
null);
     }
 
+    /** @since Apache Tika 4.1.0 */
     public FetchEmitTuple(String id, FetchKey fetchKey, EmitKey emitKey, 
Metadata metadata, ParseContext parseContext,
                           ON_PARSE_EXCEPTION onParseException, String 
presetName) {
         this.id = id;
@@ -95,7 +95,11 @@ public class FetchEmitTuple implements Serializable {
         return onParseException;
     }
 
-    /** The selected preset's name, or null for none. */
+    /**
+     * The selected preset's name, or null for none.
+     *
+     * @since Apache Tika 4.1.0
+     */
     public String getPresetName() {
         return presetName;
     }
diff --git 
a/tika-pipes/tika-pipes-core/src/main/java/org/apache/tika/pipes/core/serialization/FetchEmitTupleDeserializer.java
 
b/tika-pipes/tika-pipes-core/src/main/java/org/apache/tika/pipes/core/serialization/FetchEmitTupleDeserializer.java
index 3baf55647f..90df40149f 100644
--- 
a/tika-pipes/tika-pipes-core/src/main/java/org/apache/tika/pipes/core/serialization/FetchEmitTupleDeserializer.java
+++ 
b/tika-pipes/tika-pipes-core/src/main/java/org/apache/tika/pipes/core/serialization/FetchEmitTupleDeserializer.java
@@ -150,10 +150,7 @@ public class FetchEmitTupleDeserializer extends 
JsonDeserializer<FetchEmitTuple>
         }
     }
 
-    /**
-     * A preset name is only a selector: the server resolves it against its 
own config,
-     * so the sole check here is the shared name syntax (which also bounds its 
length).
-     */
+    // A preset name is only a selector; the shared syntax rule also bounds 
its length.
     private static String readPresetName(JsonNode root) throws IOException {
         String presetName = readVal(PRESET, root, null, false);
         if (presetName != null && !PresetRegistry.isValidName(presetName)) {
diff --git 
a/tika-pipes/tika-pipes-core/src/main/java/org/apache/tika/pipes/core/server/PipesServer.java
 
b/tika-pipes/tika-pipes-core/src/main/java/org/apache/tika/pipes/core/server/PipesServer.java
index e496ca7f8f..f19ac05064 100644
--- 
a/tika-pipes/tika-pipes-core/src/main/java/org/apache/tika/pipes/core/server/PipesServer.java
+++ 
b/tika-pipes/tika-pipes-core/src/main/java/org/apache/tika/pipes/core/server/PipesServer.java
@@ -761,8 +761,8 @@ public class PipesServer implements AutoCloseable {
 
     /**
      * Overlays the named preset, resolved from this server's own config at 
config-tier
-     * trust. Only the name arrived on the wire; the caller's untrusted delta 
is copied
-     * on top afterwards and remains subject to the wire screens and timeout 
clamping.
+     * trust; only the name arrived on the wire. The caller's untrusted delta 
is copied
+     * on top afterwards and stays subject to wire screening and timeout 
clamping.
      */
     static void mergePreset(PresetRegistry registry, String presetName, 
ParseContext merged)
             throws TikaConfigException {
diff --git 
a/tika-pipes/tika-pipes-core/src/main/java/org/apache/tika/pipes/core/server/PresetNotFoundException.java
 
b/tika-pipes/tika-pipes-core/src/main/java/org/apache/tika/pipes/core/server/PresetNotFoundException.java
index b3198b223f..6d03da7b0f 100644
--- 
a/tika-pipes/tika-pipes-core/src/main/java/org/apache/tika/pipes/core/server/PresetNotFoundException.java
+++ 
b/tika-pipes/tika-pipes-core/src/main/java/org/apache/tika/pipes/core/server/PresetNotFoundException.java
@@ -19,9 +19,10 @@ package org.apache.tika.pipes.core.server;
 import org.apache.tika.exception.TikaConfigException;
 
 /**
- * A request selected a preset name this server's config does not activate. A 
caller
- * error, not a server fault: answered with a {@code PRESET_NOT_FOUND} result 
rather
- * than the crash path other pre-parse failures take.
+ * A request named a preset this server's config does not activate: a caller 
error,
+ * answered with a {@code PRESET_NOT_FOUND} result rather than the crash path.
+ *
+ * @since Apache Tika 4.1.0
  */
 public class PresetNotFoundException extends TikaConfigException {
 
diff --git 
a/tika-serialization/src/main/java/org/apache/tika/config/loader/PresetRegistry.java
 
b/tika-serialization/src/main/java/org/apache/tika/config/loader/PresetRegistry.java
index c4892392f6..13ee3e629e 100644
--- 
a/tika-serialization/src/main/java/org/apache/tika/config/loader/PresetRegistry.java
+++ 
b/tika-serialization/src/main/java/org/apache/tika/config/loader/PresetRegistry.java
@@ -39,35 +39,27 @@ import org.apache.tika.serialization.ParseContextUtils;
 import org.apache.tika.serialization.serdes.ParseContextDeserializer;
 
 /**
- * Named, vetted parse-context fragments a caller can select whole ("presets").
- * A preset's content has the shape of a {@code parse-context} block: parser 
and
- * component configurations keyed by friendly name. A caller references a 
preset
- * by name only, so the configuration itself stays in Tika and in the server's
- * config rather than in consuming applications.
+ * Named, vetted parse-context fragments a caller selects whole, by name only 
("presets").
+ * A preset is operator config, not caller input: resolved with the same trust 
as the
+ * config's own {@code parse-context} block, and fully resolved at load so a 
bad preset
+ * fails startup, not its first request.
  * <p>
- * A preset is operator-authored config, not caller input: it is resolved with
- * the same trust as the config's own {@code parse-context} block (no 
wire-block
- * screening), and only its <em>name</em> ever travels on a request. Every
- * active preset is fully resolved at load time, so a preset that cannot
- * resolve fails startup rather than its first request.
+ * Nothing is active unless the config's {@code presets} block names it: 
{@code true}
+ * activates the classpath-catalog definition of that name (error if absent), 
an object
+ * defines the preset in place (replacing any catalog definition wholesale),
+ * {@code false}/{@code null} is an explicit no-op. Catalog jars can never 
activate
+ * themselves. Presets do not compose.
  * <p>
- * Nothing is active unless the config's {@code presets} block names it: an
- * entry with value {@code true} activates the catalog definition of that name
- * (content shipped on the classpath, so it tracks the Tika version); an object
- * value defines the preset in place (replacing any catalog definition
- * wholesale); {@code false} or {@code null} is an explicit no-op. Catalog jars
- * can never activate themselves -- every active preset is a visible line in
- * the operator's config. Presets do not compose.
- * <p>
- * The catalog is discovered from {@code META-INF/tika/presets.idx} resources,
- * each line {@code name=/classpath/resource.json}. Blank lines and {@code #}
- * comments are ignored.
+ * The catalog is discovered from {@code META-INF/tika/presets.idx} resources, 
each line
+ * {@code name=/classpath/resource.json}; blank lines and {@code #} comments 
ignored.
  * <pre>
  * "presets": {
  *   "some-catalog-preset": true,
  *   "ocr-heavy": { "pdf-parser": { "ocr": { "strategy": 
"OCR_AND_TEXT_EXTRACTION" } } }
  * }
  * </pre>
+ *
+ * @since Apache Tika 4.1.0
  */
 public final class PresetRegistry {
 
@@ -90,16 +82,12 @@ public final class PresetRegistry {
     }
 
     /**
-     * Builds the active roster from the config's {@code presets} block: only
-     * names it lists are active. {@code true} activates a catalog definition
-     * (startup error if the catalog has no such name); an object defines the
-     * preset in place; {@code false}/{@code null} deactivates explicitly.
-     * Every active preset is resolved here, so a preset whose content cannot
-     * bind is a startup error.
+     * Builds the active roster from the config's {@code presets} block (see 
the class
+     * javadoc for the value semantics), resolving every active preset.
      *
      * @param config the loaded config, may be null (empty roster)
-     * @param classLoader loader to scan for catalog preset indexes and resolve
-     *                    preset components, may be null for the thread 
context loader
+     * @param classLoader for catalog scanning and component resolution; null 
for the
+     *                    thread context loader
      */
     public static PresetRegistry load(TikaJsonConfig config, ClassLoader 
classLoader)
             throws TikaConfigException {
@@ -147,10 +135,7 @@ public final class PresetRegistry {
         return new PresetRegistry(presets, withContentHandlerFactory, loader);
     }
 
-    /**
-     * Trusted-tier resolution: presets are operator config, so no wire-block 
screening
-     * -- identical treatment to the config's own {@code parse-context} block.
-     */
+    // Trusted-tier resolution: operator config, so no wire-block screening.
     private static ParseContext resolve(String name, JsonNode content, 
ClassLoader loader)
             throws TikaConfigException {
         try {
@@ -232,10 +217,9 @@ public final class PresetRegistry {
     }
 
     /**
-     * True if {@code name} is a legal preset name: the character/length rule 
above, and
-     * not starting with "config" (tika-server gates {@code /config} endpoints 
on that
-     * path fragment, so such a name would be unreachable there). Public so 
wire
-     * deserializers can bound a preset-name field with the same rule.
+     * Legal preset name: the NAME rule, and not "config"-prefixed 
(tika-server gates
+     * {@code /config} endpoints on that path fragment). Public so wire 
deserializers
+     * can bound a preset-name field with the same rule.
      */
     public static boolean isValidName(String name) {
         return name != null && NAME.matcher(name).matches()
@@ -250,29 +234,23 @@ public final class PresetRegistry {
         return name != null && presets.containsKey(name);
     }
 
-    /**
-     * The preset's content -- a {@code parse-context}-shaped JSON object of
-     * component configurations -- or null if no preset has this name.
-     */
+    /** The preset's {@code parse-context}-shaped JSON, or null for an unknown 
name. */
     public String parseContextJson(String name) {
         JsonNode node = name == null ? null : presets.get(name);
         return node == null ? null : node.toString();
     }
 
     /**
-     * A fresh, fully resolved ParseContext for the named preset, or null if 
no preset
-     * has this name. Fresh per call: callers mutate the result per request.
+     * A fully resolved ParseContext for the preset, or null for an unknown 
name.
+     * Fresh per call: callers mutate the result per request.
      */
     public ParseContext newParseContext(String name) throws 
TikaConfigException {
         JsonNode content = name == null ? null : presets.get(name);
         return content == null ? null : resolve(name, content, classLoader);
     }
 
-    /**
-     * True if the named preset binds a {@link ContentHandlerFactory}: a route 
with no
-     * explicit format segment should then leave the choice to the preset 
rather than
-     * forcing its own default.
-     */
+    /** True if the preset binds a {@link ContentHandlerFactory} (it then owns 
the
+     * output format on routes with no explicit format segment). */
     public boolean suppliesContentHandlerFactory(String name) {
         return name != null && withContentHandlerFactory.contains(name);
     }
diff --git 
a/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/PipesParsingHelper.java
 
b/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/PipesParsingHelper.java
index 5732661194..37ad1ffa23 100644
--- 
a/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/PipesParsingHelper.java
+++ 
b/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/PipesParsingHelper.java
@@ -245,11 +245,7 @@ public class PipesParsingHelper {
         }
     }
 
-    /**
-     * Lifts the in-process {@link PresetSelection} carrier out of the context 
and onto the
-     * tuple's own preset field: only the name travels; the forked worker 
resolves the
-     * preset's content from its own config at config-tier trust.
-     */
+    // Only the name travels: the worker resolves the preset from its own 
config.
     private static String liftPresetSelection(ParseContext parseContext) {
         PresetSelection preset = parseContext.get(PresetSelection.class);
         if (preset == null) {
diff --git 
a/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/PresetSelection.java
 
b/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/PresetSelection.java
index 264c1bc262..f1360a73ad 100644
--- 
a/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/PresetSelection.java
+++ 
b/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/PresetSelection.java
@@ -17,12 +17,12 @@
 package org.apache.tika.server.core.resource;
 
 /**
- * In-process carrier for a request's selected preset name, riding the request
- * ParseContext between the resource and {@link PipesParsingHelper}, which 
lifts it
- * onto the tuple's own preset field before serialization. Never travels on 
the wire
- * itself (the wire serializer refuses unregistered context entries, so a leak 
fails
- * loudly). The preset's content is resolved by the forked worker from its own 
config
- * at config-tier trust.
+ * In-process carrier for a request's selected preset name: rides the request
+ * ParseContext until {@link PipesParsingHelper} lifts it onto the tuple's 
preset
+ * field. Never serialized (the wire serializer refuses unregistered entries, 
so a
+ * leak fails loudly).
+ *
+ * @since Apache Tika 4.1.0
  */
 public record PresetSelection(String name) {
 }
diff --git 
a/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/RecursiveMetadataResource.java
 
b/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/RecursiveMetadataResource.java
index b3126b4f7d..4d8091d85e 100644
--- 
a/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/RecursiveMetadataResource.java
+++ 
b/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/RecursiveMetadataResource.java
@@ -161,9 +161,8 @@ public class RecursiveMetadataResource {
                                           @PathParam(HANDLER_TYPE_PARAM) 
String handlerTypeName)
             throws Exception {
         ParseContext context = tikaResource.createPresetContext(presetName);
-        // An explicit format segment wins over a factory the preset itself 
binds; with no
-        // segment, parseMetadataWithContext defers to the preset's factory, 
then the
-        // config's, then the endpoint default.
+        // Explicit format segment wins over the preset's own factory; without 
one,
+        // parseMetadataWithContext defers preset -> config -> default.
         if (handlerTypeName != null && !handlerTypeName.isBlank()) {
             tikaResource.setupContentHandlerFactory(context, handlerTypeName);
         }
diff --git 
a/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/TikaResource.java
 
b/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/TikaResource.java
index 1033d1324c..f85fbaa603 100644
--- 
a/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/TikaResource.java
+++ 
b/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/TikaResource.java
@@ -131,12 +131,10 @@ public class TikaResource {
     }
 
     /**
-     * A request context carrying the named preset selection. Only the name is 
recorded
-     * here: the forked worker resolves the preset from its own copy of this 
config at
-     * config-tier trust, so preset content is never treated as 
caller-supplied wire
-     * data (which would screen out wire-blocked components and clamp its 
timeouts).
-     * A preset is selected whole and exclusively -- the {@code preset} routes 
take
-     * no config part, so it never combines with request-supplied 
configuration.
+     * A request context carrying only the preset selection: the forked worker 
resolves
+     * the content from its own copy of this config at config-tier trust, so a 
preset is
+     * never treated as caller-supplied wire data (which would screen out 
wire-blocked
+     * components and clamp its timeouts).
      *
      * @throws NotFoundException if no preset has this name
      */
@@ -622,15 +620,12 @@ public class TikaResource {
 
     // ==================== PUT preset endpoints ====================
 
-    // Mirrors of the PUT endpoints above with a vetted, named parse-context 
fragment
-    // applied: 
/tika/preset/{name}[/text|/html|/xml|/md|/json[/{handlerType}]]. The
-    // preset segment sits directly after the resource root so network-layer 
rules can
-    // address /tika/preset/* -- or a single preset -- independently of 
/tika/config*.
+    // Mirrors of the PUT endpoints above: 
/tika/preset/{name}[/text|/html|/xml|/md|
+    // /json[/{handlerType}]]. The preset segment sits directly after the 
resource root
+    // so network-layer rules can address /tika/preset/* independently of 
/tika/config*.
     // These routes take no config part; a preset never combines with request 
config.
-
-    // explicitHandlerType semantics: non-null (an explicit format segment in 
the URL) wins
-    // over everything, including a factory the preset itself binds; null 
defers to the
-    // preset's factory, then the config's, then the endpoint default.
+    // explicitHandlerType: non-null (an explicit format segment) wins over 
everything,
+    // including the preset's own factory; null defers preset -> config -> 
default.
 
     private Response putRawPreset(InputStream is, HttpHeaders httpHeaders, 
String presetName,
                                   String explicitHandlerType) throws 
IOException {
diff --git 
a/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/UnpackerResource.java
 
b/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/UnpackerResource.java
index 4acaa959d5..f47243795e 100644
--- 
a/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/UnpackerResource.java
+++ 
b/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/UnpackerResource.java
@@ -145,11 +145,8 @@ public class UnpackerResource {
      * @param info URI info
      * @return streaming zip response
      */
-    /**
-     * The wildcard {@code id} on the pre-existing routes would otherwise 
silently absorb a
-     * transposed preset URL ({@code /unpack/all/preset/x}, {@code 
/unpack/preset} with no
-     * name) and run with no preset applied -- a silent wrong-config success.
-     */
+    // The wildcard id would otherwise absorb a transposed preset URL 
(/unpack/all/preset/x)
+    // and silently run with no preset applied.
     private static void rejectPresetInWildcard(UriInfo info) {
         String id = info.getPathParameters().getFirst("id");
         if (id != null && (id.equals("/preset") || id.startsWith("/preset/"))) 
{

Reply via email to