forkedJvmArgs) {
this.pipesConfig = new PipesConfigOverride(numClients,
- startupTimeoutMillis, maxFilesProcessedPerProcess, forkedJvmArgs);
+ maxFilesProcessedPerProcess, forkedJvmArgs);
return this;
}
diff --git a/tika-pipes/tika-pipes-core/src/test/java/org/apache/tika/pipes/core/config/ConfigMergerTest.java b/tika-pipes/tika-pipes-core/src/test/java/org/apache/tika/pipes/core/config/ConfigMergerTest.java
index a76e27ad8aa..fea3fcbfae8 100644
--- a/tika-pipes/tika-pipes-core/src/test/java/org/apache/tika/pipes/core/config/ConfigMergerTest.java
+++ b/tika-pipes/tika-pipes-core/src/test/java/org/apache/tika/pipes/core/config/ConfigMergerTest.java
@@ -209,7 +209,7 @@ public void testJvmArgs() throws IOException {
@Test
public void testFullPipesConfig() throws IOException {
ConfigOverrides overrides = ConfigOverrides.builder()
- .setPipesConfig(8, 300000, 5000, List.of("-Xmx1g"))
+ .setPipesConfig(8, 5000, List.of("-Xmx1g"))
.build();
ConfigMerger.MergeResult result = ConfigMerger.mergeOrCreate(null, overrides);
@@ -219,7 +219,6 @@ public void testFullPipesConfig() throws IOException {
JsonNode pipes = root.get("pipes");
assertEquals(8, pipes.get("numClients").asInt());
- assertEquals(300000, pipes.get("startupTimeoutMillis").asLong());
assertEquals(5000, pipes.get("maxFilesProcessedPerProcess").asInt());
Files.deleteIfExists(result.configPath());
diff --git a/tika-pipes/tika-pipes-core/src/test/java/org/apache/tika/pipes/core/testutil/AbstractConfigExamplesTest.java b/tika-pipes/tika-pipes-core/src/test/java/org/apache/tika/pipes/core/testutil/AbstractConfigExamplesTest.java
new file mode 100644
index 00000000000..98144d71b2e
--- /dev/null
+++ b/tika-pipes/tika-pipes-core/src/test/java/org/apache/tika/pipes/core/testutil/AbstractConfigExamplesTest.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tika.pipes.core.testutil;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.junit.jupiter.api.io.TempDir;
+
+import org.apache.tika.config.loader.TikaLoader;
+
+/**
+ * Shared base class for plugin {@code ConfigExamplesTest}s. Loads JSON
+ * configuration examples from {@code /config-examples/} on the test
+ * classpath, validates that {@link TikaLoader} can parse them, and exposes
+ * helpers for drilling into the inner component config block.
+ */
+public abstract class AbstractConfigExamplesTest {
+
+ private static final String EXAMPLES_DIR = "/config-examples/";
+ private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
+
+ @TempDir
+ protected Path tempDir;
+
+ /**
+ * Reads a JSON example from the {@code /config-examples/} classpath dir.
+ */
+ protected String readExample(String resourceName) throws Exception {
+ try (InputStream is = getClass().getResourceAsStream(EXAMPLES_DIR + resourceName)) {
+ assertNotNull(is, "Resource not found: " + EXAMPLES_DIR + resourceName);
+ return new String(is.readAllBytes(), StandardCharsets.UTF_8);
+ }
+ }
+
+ /**
+ * Reads the named example, writes it to a temp file, and asserts that
+ * {@link TikaLoader#load(Path)} returns a non-null config.
+ */
+ protected void loadAndValidate(String resourceName) throws Exception {
+ String json = readExample(resourceName);
+ Path configFile = tempDir.resolve("tika-config.json");
+ Files.writeString(configFile, json, StandardCharsets.UTF_8);
+ assertNotNull(TikaLoader.load(configFile));
+ }
+
+ /**
+ * Returns the inner component-config node from a Tika pipes JSON document.
+ *
+ * Tika pipes configs nest fetchers/emitters as
+ * {@code section -> id -> type -> {config}}, while pipes-iterators and
+ * reporters omit the id level: {@code section -> type -> {config}}. Pass
+ * {@code id == null} to skip that level.
+ */
+ protected JsonNode innerComponent(String json, String section, String id, String type)
+ throws Exception {
+ JsonNode root = OBJECT_MAPPER.readTree(json);
+ JsonNode node = root.get(section);
+ assertNotNull(node, "Missing section '" + section + "' in JSON");
+ if (id != null) {
+ node = node.get(id);
+ assertNotNull(node, "Missing id '" + id + "' under section '" + section + "'");
+ }
+ JsonNode inner = node.get(type);
+ assertNotNull(inner, "Missing type '" + type + "' under "
+ + (id != null ? "id '" + id + "'" : "section '" + section + "'"));
+ return inner;
+ }
+}
diff --git a/tika-pipes/tika-pipes-fork-parser/src/main/java/org/apache/tika/pipes/fork/PipesForkParser.java b/tika-pipes/tika-pipes-fork-parser/src/main/java/org/apache/tika/pipes/fork/PipesForkParser.java
index b9e7bb6d572..8c572728273 100644
--- a/tika-pipes/tika-pipes-fork-parser/src/main/java/org/apache/tika/pipes/fork/PipesForkParser.java
+++ b/tika-pipes/tika-pipes-fork-parser/src/main/java/org/apache/tika/pipes/fork/PipesForkParser.java
@@ -385,7 +385,6 @@ private ConfigMerger.MergeResult createTikaConfigFile() throws IOException {
// Set pipes configuration
.setPipesConfig(
pc.getNumClients(),
- pc.getStartupTimeoutMillis(),
pc.getMaxFilesProcessedPerProcess(),
pc.getForkedJvmArgs())
// Use PASSBACK_ALL strategy - results returned through socket
diff --git a/tika-pipes/tika-pipes-fork-parser/src/main/java/org/apache/tika/pipes/fork/PipesForkParserConfig.java b/tika-pipes/tika-pipes-fork-parser/src/main/java/org/apache/tika/pipes/fork/PipesForkParserConfig.java
index 06d42b97c2a..8c498d2ad10 100644
--- a/tika-pipes/tika-pipes-fork-parser/src/main/java/org/apache/tika/pipes/fork/PipesForkParserConfig.java
+++ b/tika-pipes/tika-pipes-fork-parser/src/main/java/org/apache/tika/pipes/fork/PipesForkParserConfig.java
@@ -283,17 +283,6 @@ public int getNumClients() {
return pipesConfig.getNumClients();
}
- /**
- * Set the startup timeout in milliseconds.
- *
- * @param startupTimeoutMillis the startup timeout
- * @return this config for chaining
- */
- public PipesForkParserConfig setStartupTimeoutMillis(long startupTimeoutMillis) {
- pipesConfig.setStartupTimeoutMillis(startupTimeoutMillis);
- return this;
- }
-
/**
* Get the plugins directory.
*
diff --git a/tika-pipes/tika-pipes-plugins/pom.xml b/tika-pipes/tika-pipes-plugins/pom.xml
index 9eab9b49e77..ae19e2253c8 100644
--- a/tika-pipes/tika-pipes-plugins/pom.xml
+++ b/tika-pipes/tika-pipes-plugins/pom.xml
@@ -80,6 +80,13 @@
test
test-jar
+
+ org.apache.tika
+ tika-pipes-core
+ ${project.version}
+ test
+ test-jar
+
diff --git a/tika-pipes/tika-pipes-plugins/tika-pipes-atlassian-jwt/src/test/java/org/apache/tika/pipes/atlassianjwt/ConfigExamplesTest.java b/tika-pipes/tika-pipes-plugins/tika-pipes-atlassian-jwt/src/test/java/org/apache/tika/pipes/atlassianjwt/ConfigExamplesTest.java
index e1802d01029..2479830b5bb 100644
--- a/tika-pipes/tika-pipes-plugins/tika-pipes-atlassian-jwt/src/test/java/org/apache/tika/pipes/atlassianjwt/ConfigExamplesTest.java
+++ b/tika-pipes/tika-pipes-plugins/tika-pipes-atlassian-jwt/src/test/java/org/apache/tika/pipes/atlassianjwt/ConfigExamplesTest.java
@@ -19,46 +19,23 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
-import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-
import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.io.TempDir;
-import org.apache.tika.config.loader.TikaLoader;
+import org.apache.tika.pipes.core.testutil.AbstractConfigExamplesTest;
import org.apache.tika.pipes.fetcher.atlassianjwt.config.AtlassianJwtFetcherConfig;
/**
* Validates Atlassian JWT fetcher configuration examples used in documentation.
*/
-public class ConfigExamplesTest {
-
- private static final String EXAMPLES_DIR = "/config-examples/";
- private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
-
- @TempDir
- Path tempDir;
-
- private String readExample(String resourceName) throws Exception {
- try (InputStream is = getClass().getResourceAsStream(EXAMPLES_DIR + resourceName)) {
- assertNotNull(is, "Resource not found: " + resourceName);
- return new String(is.readAllBytes(), StandardCharsets.UTF_8);
- }
- }
+public class ConfigExamplesTest extends AbstractConfigExamplesTest {
@Test
public void testAtlassianJwtFetcherConfig() throws Exception {
- String json = readExample("atlassian-jwt-fetcher.json");
- Path configFile = tempDir.resolve("tika-config.json");
- Files.writeString(configFile, json, StandardCharsets.UTF_8);
- assertNotNull(TikaLoader.load(configFile));
+ loadAndValidate("atlassian-jwt-fetcher.json");
- JsonNode inner = OBJECT_MAPPER.readTree(json)
- .get("fetchers").get("ajwt").get("atlassian-jwt-fetcher");
+ JsonNode inner = innerComponent(readExample("atlassian-jwt-fetcher.json"),
+ "fetchers", "ajwt", "atlassian-jwt-fetcher");
AtlassianJwtFetcherConfig config = AtlassianJwtFetcherConfig.load(inner.toString());
assertEquals("tika-pipes-app-key", config.getIssuer());
assertNotNull(config.getSharedSecret());
diff --git a/tika-pipes/tika-pipes-plugins/tika-pipes-az-blob/src/test/java/org/apache/tika/pipes/azblob/ConfigExamplesTest.java b/tika-pipes/tika-pipes-plugins/tika-pipes-az-blob/src/test/java/org/apache/tika/pipes/azblob/ConfigExamplesTest.java
index 0a083f608a8..cf1b3959bc2 100644
--- a/tika-pipes/tika-pipes-plugins/tika-pipes-az-blob/src/test/java/org/apache/tika/pipes/azblob/ConfigExamplesTest.java
+++ b/tika-pipes/tika-pipes-plugins/tika-pipes-az-blob/src/test/java/org/apache/tika/pipes/azblob/ConfigExamplesTest.java
@@ -19,17 +19,9 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
-import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.io.TempDir;
-import org.apache.tika.config.loader.TikaLoader;
+import org.apache.tika.pipes.core.testutil.AbstractConfigExamplesTest;
import org.apache.tika.pipes.emitter.azblob.AZBlobEmitterConfig;
import org.apache.tika.pipes.fetcher.azblob.config.AZBlobFetcherConfig;
import org.apache.tika.pipes.iterator.azblob.AZBlobPipesIteratorConfig;
@@ -40,48 +32,15 @@
* The JSON configuration examples are stored in {@code src/test/resources/config-examples/}
* and are included directly in the AsciiDoc documentation via the {@code include::} directive.
*/
-public class ConfigExamplesTest {
-
- private static final String EXAMPLES_DIR = "/config-examples/";
- private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
-
- @TempDir
- Path tempDir;
-
- private String readExample(String resourceName) throws Exception {
- try (InputStream is = getClass().getResourceAsStream(EXAMPLES_DIR + resourceName)) {
- assertNotNull(is, "Resource not found: " + resourceName);
- return new String(is.readAllBytes(), StandardCharsets.UTF_8);
- }
- }
-
- private void loadViaTikaLoader(String resourceName) throws Exception {
- String json = readExample(resourceName);
- Path configFile = tempDir.resolve("tika-config.json");
- Files.writeString(configFile, json, StandardCharsets.UTF_8);
- TikaLoader loader = TikaLoader.load(configFile);
- assertNotNull(loader, "TikaLoader should not be null for: " + resourceName);
- }
-
- private JsonNode innerComponent(String json, String section, String id, String typeName)
- throws Exception {
- JsonNode root = OBJECT_MAPPER.readTree(json);
- JsonNode sectionNode = root.get(section);
- assertNotNull(sectionNode, "Missing section: " + section);
- JsonNode idNode = id == null ? sectionNode : sectionNode.get(id);
- assertNotNull(idNode, "Missing id: " + id);
- JsonNode typed = idNode.get(typeName);
- assertNotNull(typed, "Missing type: " + typeName);
- return typed;
- }
+public class ConfigExamplesTest extends AbstractConfigExamplesTest {
@Test
public void testAZBlobFetcherConfig() throws Exception {
- loadViaTikaLoader("az-blob-fetcher.json");
+ loadAndValidate("az-blob-fetcher.json");
- JsonNode inner = innerComponent(readExample("az-blob-fetcher.json"),
- "fetchers", "azf", "az-blob-fetcher");
- AZBlobFetcherConfig config = AZBlobFetcherConfig.load(inner.toString());
+ AZBlobFetcherConfig config = AZBlobFetcherConfig.load(
+ innerComponent(readExample("az-blob-fetcher.json"),
+ "fetchers", "azf", "az-blob-fetcher").toString());
assertEquals("tika-input", config.getContainer());
assertEquals("https://myaccount.blob.core.windows.net", config.getEndpoint());
assertNotNull(config.getSasToken());
@@ -89,11 +48,11 @@ public void testAZBlobFetcherConfig() throws Exception {
@Test
public void testAZBlobEmitterConfig() throws Exception {
- loadViaTikaLoader("az-blob-emitter.json");
+ loadAndValidate("az-blob-emitter.json");
- JsonNode inner = innerComponent(readExample("az-blob-emitter.json"),
- "emitters", "aze", "az-blob-emitter");
- AZBlobEmitterConfig config = AZBlobEmitterConfig.load(inner.toString());
+ AZBlobEmitterConfig config = AZBlobEmitterConfig.load(
+ innerComponent(readExample("az-blob-emitter.json"),
+ "emitters", "aze", "az-blob-emitter").toString());
assertEquals("tika-output", config.container());
assertEquals("json", config.fileExtension());
config.validate();
@@ -102,11 +61,11 @@ public void testAZBlobEmitterConfig() throws Exception {
@Test
public void testAZBlobIteratorConfig() throws Exception {
- loadViaTikaLoader("az-blob-pipes-iterator.json");
+ loadAndValidate("az-blob-pipes-iterator.json");
- JsonNode inner = innerComponent(readExample("az-blob-pipes-iterator.json"),
- "pipes-iterator", null, "az-blob-pipes-iterator");
- AZBlobPipesIteratorConfig config = AZBlobPipesIteratorConfig.load(inner.toString());
+ AZBlobPipesIteratorConfig config = AZBlobPipesIteratorConfig.load(
+ innerComponent(readExample("az-blob-pipes-iterator.json"),
+ "pipes-iterator", null, "az-blob-pipes-iterator").toString());
assertEquals("tika-input", config.getContainer());
assertEquals("incoming/", config.getPrefix());
assertEquals(360000L, config.getTimeoutMillis());
@@ -116,7 +75,7 @@ public void testAZBlobIteratorConfig() throws Exception {
@Test
public void testAZBlobPipelineConfig() throws Exception {
- loadViaTikaLoader("az-blob-pipeline.json");
+ loadAndValidate("az-blob-pipeline.json");
String json = readExample("az-blob-pipeline.json");
AZBlobFetcherConfig fetcher = AZBlobFetcherConfig.load(
diff --git a/tika-pipes/tika-pipes-plugins/tika-pipes-csv/src/test/java/org/apache/tika/pipes/csv/ConfigExamplesTest.java b/tika-pipes/tika-pipes-plugins/tika-pipes-csv/src/test/java/org/apache/tika/pipes/csv/ConfigExamplesTest.java
index 75ca4429186..e814ad68f1b 100644
--- a/tika-pipes/tika-pipes-plugins/tika-pipes-csv/src/test/java/org/apache/tika/pipes/csv/ConfigExamplesTest.java
+++ b/tika-pipes/tika-pipes-plugins/tika-pipes-csv/src/test/java/org/apache/tika/pipes/csv/ConfigExamplesTest.java
@@ -19,46 +19,23 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
-import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-
import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.io.TempDir;
-import org.apache.tika.config.loader.TikaLoader;
+import org.apache.tika.pipes.core.testutil.AbstractConfigExamplesTest;
import org.apache.tika.pipes.iterator.csv.CSVPipesIteratorConfig;
/**
* Validates CSV iterator configuration example used in documentation.
*/
-public class ConfigExamplesTest {
-
- private static final String EXAMPLES_DIR = "/config-examples/";
- private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
-
- @TempDir
- Path tempDir;
-
- private String readExample(String resourceName) throws Exception {
- try (InputStream is = getClass().getResourceAsStream(EXAMPLES_DIR + resourceName)) {
- assertNotNull(is, "Resource not found: " + resourceName);
- return new String(is.readAllBytes(), StandardCharsets.UTF_8);
- }
- }
+public class ConfigExamplesTest extends AbstractConfigExamplesTest {
@Test
public void testCsvIteratorConfig() throws Exception {
- String json = readExample("csv-pipes-iterator.json");
- Path configFile = tempDir.resolve("tika-config.json");
- Files.writeString(configFile, json, StandardCharsets.UTF_8);
- assertNotNull(TikaLoader.load(configFile));
+ loadAndValidate("csv-pipes-iterator.json");
- JsonNode inner = OBJECT_MAPPER.readTree(json)
- .get("pipes-iterator").get("csv-pipes-iterator");
+ JsonNode inner = innerComponent(readExample("csv-pipes-iterator.json"),
+ "pipes-iterator", null, "csv-pipes-iterator");
CSVPipesIteratorConfig config = CSVPipesIteratorConfig.load(inner.toString());
assertNotNull(config.getCsvPath());
assertEquals("doc_id", config.getIdColumn());
diff --git a/tika-pipes/tika-pipes-plugins/tika-pipes-es/src/test/java/org/apache/tika/pipes/es/ConfigExamplesTest.java b/tika-pipes/tika-pipes-plugins/tika-pipes-es/src/test/java/org/apache/tika/pipes/es/ConfigExamplesTest.java
index b1be5faa4be..6a5f8d3d14e 100644
--- a/tika-pipes/tika-pipes-plugins/tika-pipes-es/src/test/java/org/apache/tika/pipes/es/ConfigExamplesTest.java
+++ b/tika-pipes/tika-pipes-plugins/tika-pipes-es/src/test/java/org/apache/tika/pipes/es/ConfigExamplesTest.java
@@ -21,17 +21,9 @@
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.io.TempDir;
-import org.apache.tika.config.loader.TikaLoader;
+import org.apache.tika.pipes.core.testutil.AbstractConfigExamplesTest;
import org.apache.tika.pipes.emitter.es.ESEmitterConfig;
import org.apache.tika.pipes.reporter.es.ESReporterConfig;
@@ -41,48 +33,15 @@
* The JSON configuration examples are stored in {@code src/test/resources/config-examples/}
* and are included directly in the AsciiDoc documentation via the {@code include::} directive.
*/
-public class ConfigExamplesTest {
-
- private static final String EXAMPLES_DIR = "/config-examples/";
- private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
-
- @TempDir
- Path tempDir;
-
- private String readExample(String resourceName) throws Exception {
- try (InputStream is = getClass().getResourceAsStream(EXAMPLES_DIR + resourceName)) {
- assertNotNull(is, "Resource not found: " + resourceName);
- return new String(is.readAllBytes(), StandardCharsets.UTF_8);
- }
- }
-
- private void loadViaTikaLoader(String resourceName) throws Exception {
- String json = readExample(resourceName);
- Path configFile = tempDir.resolve("tika-config.json");
- Files.writeString(configFile, json, StandardCharsets.UTF_8);
- TikaLoader loader = TikaLoader.load(configFile);
- assertNotNull(loader, "TikaLoader should not be null for: " + resourceName);
- }
-
- private JsonNode innerComponent(String json, String section, String id, String typeName)
- throws Exception {
- JsonNode root = OBJECT_MAPPER.readTree(json);
- JsonNode sectionNode = root.get(section);
- assertNotNull(sectionNode, "Missing section: " + section);
- JsonNode idNode = id == null ? sectionNode : sectionNode.get(id);
- assertNotNull(idNode, "Missing id: " + id);
- JsonNode typed = idNode.get(typeName);
- assertNotNull(typed, "Missing type: " + typeName);
- return typed;
- }
+public class ConfigExamplesTest extends AbstractConfigExamplesTest {
@Test
public void testESEmitterConfig() throws Exception {
- loadViaTikaLoader("es-emitter.json");
+ loadAndValidate("es-emitter.json");
- JsonNode inner = innerComponent(readExample("es-emitter.json"),
- "emitters", "ese", "es-emitter");
- ESEmitterConfig config = ESEmitterConfig.load(inner.toString());
+ ESEmitterConfig config = ESEmitterConfig.load(
+ innerComponent(readExample("es-emitter.json"),
+ "emitters", "ese", "es-emitter").toString());
assertEquals("doc_id", config.idField());
assertEquals(ESEmitterConfig.AttachmentStrategy.PARENT_CHILD,
config.attachmentStrategy());
@@ -97,11 +56,11 @@ public void testESEmitterConfig() throws Exception {
@Test
public void testESReporterConfig() throws Exception {
- loadViaTikaLoader("es-reporter.json");
+ loadAndValidate("es-reporter.json");
- JsonNode inner = innerComponent(readExample("es-reporter.json"),
- "pipes-reporters", null, "es-pipes-reporter");
- ESReporterConfig config = ESReporterConfig.load(inner.toString());
+ ESReporterConfig config = ESReporterConfig.load(
+ innerComponent(readExample("es-reporter.json"),
+ "pipes-reporters", null, "es-pipes-reporter").toString());
assertTrue(config.esUrl().contains("tika-status"));
assertEquals("tika_", config.keyPrefix());
assertTrue(config.includeRouting());
@@ -112,7 +71,7 @@ public void testESReporterConfig() throws Exception {
@Test
public void testESPipelineConfig() throws Exception {
- loadViaTikaLoader("es-pipeline.json");
+ loadAndValidate("es-pipeline.json");
String json = readExample("es-pipeline.json");
ESEmitterConfig emitter = ESEmitterConfig.load(
diff --git a/tika-pipes/tika-pipes-plugins/tika-pipes-file-system/src/test/java/org/apache/tika/pipes/fs/ConfigExamplesTest.java b/tika-pipes/tika-pipes-plugins/tika-pipes-file-system/src/test/java/org/apache/tika/pipes/fs/ConfigExamplesTest.java
index 70fe7947bb3..041e079e15e 100644
--- a/tika-pipes/tika-pipes-plugins/tika-pipes-file-system/src/test/java/org/apache/tika/pipes/fs/ConfigExamplesTest.java
+++ b/tika-pipes/tika-pipes-plugins/tika-pipes-file-system/src/test/java/org/apache/tika/pipes/fs/ConfigExamplesTest.java
@@ -16,17 +16,9 @@
*/
package org.apache.tika.pipes.fs;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-
-import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-
import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.io.TempDir;
-import org.apache.tika.config.loader.TikaLoader;
+import org.apache.tika.pipes.core.testutil.AbstractConfigExamplesTest;
/**
* Validates file system fetcher/emitter configuration examples used in documentation.
@@ -34,23 +26,7 @@
* The JSON configuration examples are stored in {@code src/test/resources/config-examples/}
* and are included directly in the AsciiDoc documentation via the {@code include::} directive.
*/
-public class ConfigExamplesTest {
-
- private static final String EXAMPLES_DIR = "/config-examples/";
-
- @TempDir
- Path tempDir;
-
- private void loadAndValidate(String resourceName) throws Exception {
- try (InputStream is = getClass().getResourceAsStream(EXAMPLES_DIR + resourceName)) {
- assertNotNull(is, "Resource not found: " + resourceName);
- String json = new String(is.readAllBytes(), StandardCharsets.UTF_8);
- Path configFile = tempDir.resolve("tika-config.json");
- Files.writeString(configFile, json, StandardCharsets.UTF_8);
- TikaLoader loader = TikaLoader.load(configFile);
- assertNotNull(loader, "TikaLoader should not be null for: " + resourceName);
- }
- }
+public class ConfigExamplesTest extends AbstractConfigExamplesTest {
@Test
public void testFileSystemFetcherConfig() throws Exception {
diff --git a/tika-pipes/tika-pipes-plugins/tika-pipes-file-system/src/test/resources/config-examples/file-system-emitter.json b/tika-pipes/tika-pipes-plugins/tika-pipes-file-system/src/test/resources/config-examples/file-system-emitter.json
index 4f01761e450..8ee447892f7 100644
--- a/tika-pipes/tika-pipes-plugins/tika-pipes-file-system/src/test/resources/config-examples/file-system-emitter.json
+++ b/tika-pipes/tika-pipes-plugins/tika-pipes-file-system/src/test/resources/config-examples/file-system-emitter.json
@@ -1,13 +1,12 @@
{
- "emitters": [
- {
+ "emitters": {
+ "my-emitter": {
"file-system-emitter": {
- "id": "my-emitter",
"basePath": "/data/output",
"fileExtension": "json",
"onExists": "REPLACE",
"prettyPrint": true
}
}
- ]
+ }
}
diff --git a/tika-pipes/tika-pipes-plugins/tika-pipes-file-system/src/test/resources/config-examples/file-system-fetcher.json b/tika-pipes/tika-pipes-plugins/tika-pipes-file-system/src/test/resources/config-examples/file-system-fetcher.json
index 201d4fa099e..cd60dd3b2ca 100644
--- a/tika-pipes/tika-pipes-plugins/tika-pipes-file-system/src/test/resources/config-examples/file-system-fetcher.json
+++ b/tika-pipes/tika-pipes-plugins/tika-pipes-file-system/src/test/resources/config-examples/file-system-fetcher.json
@@ -1,11 +1,10 @@
{
- "fetchers": [
- {
+ "fetchers": {
+ "my-fetcher": {
"file-system-fetcher": {
- "id": "my-fetcher",
"basePath": "/data/documents",
"extractFileSystemMetadata": true
}
}
- ]
+ }
}
diff --git a/tika-pipes/tika-pipes-plugins/tika-pipes-file-system/src/test/resources/config-examples/file-system-pipeline.json b/tika-pipes/tika-pipes-plugins/tika-pipes-file-system/src/test/resources/config-examples/file-system-pipeline.json
index 3d95755eff9..646c0f7b018 100644
--- a/tika-pipes/tika-pipes-plugins/tika-pipes-file-system/src/test/resources/config-examples/file-system-pipeline.json
+++ b/tika-pipes/tika-pipes-plugins/tika-pipes-file-system/src/test/resources/config-examples/file-system-pipeline.json
@@ -1,24 +1,22 @@
{
- "fetchers": [
- {
+ "fetchers": {
+ "input-fetcher": {
"file-system-fetcher": {
- "id": "input-fetcher",
"basePath": "/data/input",
"extractFileSystemMetadata": true
}
}
- ],
- "emitters": [
- {
+ },
+ "emitters": {
+ "output-emitter": {
"file-system-emitter": {
- "id": "output-emitter",
"basePath": "/data/output",
"fileExtension": "json",
"onExists": "SKIP",
"prettyPrint": false
}
}
- ],
+ },
"parsers": [
{
"default-parser": {}
diff --git a/tika-pipes/tika-pipes-plugins/tika-pipes-gcs/src/test/java/org/apache/tika/pipes/gcs/ConfigExamplesTest.java b/tika-pipes/tika-pipes-plugins/tika-pipes-gcs/src/test/java/org/apache/tika/pipes/gcs/ConfigExamplesTest.java
index 7cfc1f3fb16..52ce0a1fe56 100644
--- a/tika-pipes/tika-pipes-plugins/tika-pipes-gcs/src/test/java/org/apache/tika/pipes/gcs/ConfigExamplesTest.java
+++ b/tika-pipes/tika-pipes-plugins/tika-pipes-gcs/src/test/java/org/apache/tika/pipes/gcs/ConfigExamplesTest.java
@@ -17,19 +17,11 @@
package org.apache.tika.pipes.gcs;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-
-import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.io.TempDir;
-import org.apache.tika.config.loader.TikaLoader;
+import org.apache.tika.pipes.core.testutil.AbstractConfigExamplesTest;
import org.apache.tika.pipes.emitter.gcs.GCSEmitterConfig;
import org.apache.tika.pipes.fetcher.gcs.config.GCSFetcherConfig;
import org.apache.tika.pipes.iterator.gcs.GCSPipesIteratorConfig;
@@ -40,44 +32,11 @@
* The JSON configuration examples are stored in {@code src/test/resources/config-examples/}
* and are included directly in the AsciiDoc documentation via the {@code include::} directive.
*/
-public class ConfigExamplesTest {
-
- private static final String EXAMPLES_DIR = "/config-examples/";
- private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
-
- @TempDir
- Path tempDir;
-
- private String readExample(String resourceName) throws Exception {
- try (InputStream is = getClass().getResourceAsStream(EXAMPLES_DIR + resourceName)) {
- assertNotNull(is, "Resource not found: " + resourceName);
- return new String(is.readAllBytes(), StandardCharsets.UTF_8);
- }
- }
-
- private void loadViaTikaLoader(String resourceName) throws Exception {
- String json = readExample(resourceName);
- Path configFile = tempDir.resolve("tika-config.json");
- Files.writeString(configFile, json, StandardCharsets.UTF_8);
- TikaLoader loader = TikaLoader.load(configFile);
- assertNotNull(loader, "TikaLoader should not be null for: " + resourceName);
- }
-
- private JsonNode innerComponent(String json, String section, String id, String typeName)
- throws Exception {
- JsonNode root = OBJECT_MAPPER.readTree(json);
- JsonNode sectionNode = root.get(section);
- assertNotNull(sectionNode, "Missing section: " + section);
- JsonNode idNode = id == null ? sectionNode : sectionNode.get(id);
- assertNotNull(idNode, "Missing id: " + id);
- JsonNode typed = idNode.get(typeName);
- assertNotNull(typed, "Missing type: " + typeName);
- return typed;
- }
+public class ConfigExamplesTest extends AbstractConfigExamplesTest {
@Test
public void testGCSFetcherConfig() throws Exception {
- loadViaTikaLoader("gcs-fetcher.json");
+ loadAndValidate("gcs-fetcher.json");
JsonNode inner = innerComponent(readExample("gcs-fetcher.json"),
"fetchers", "gcsf", "gcs-fetcher");
@@ -88,7 +47,7 @@ public void testGCSFetcherConfig() throws Exception {
@Test
public void testGCSEmitterConfig() throws Exception {
- loadViaTikaLoader("gcs-emitter.json");
+ loadAndValidate("gcs-emitter.json");
JsonNode inner = innerComponent(readExample("gcs-emitter.json"),
"emitters", "gcse", "gcs-emitter");
@@ -102,7 +61,7 @@ public void testGCSEmitterConfig() throws Exception {
@Test
public void testGCSIteratorConfig() throws Exception {
- loadViaTikaLoader("gcs-pipes-iterator.json");
+ loadAndValidate("gcs-pipes-iterator.json");
JsonNode inner = innerComponent(readExample("gcs-pipes-iterator.json"),
"pipes-iterator", null, "gcs-pipes-iterator");
@@ -115,7 +74,7 @@ public void testGCSIteratorConfig() throws Exception {
@Test
public void testGCSPipelineConfig() throws Exception {
- loadViaTikaLoader("gcs-pipeline.json");
+ loadAndValidate("gcs-pipeline.json");
String json = readExample("gcs-pipeline.json");
GCSFetcherConfig fetcher = GCSFetcherConfig.load(
diff --git a/tika-pipes/tika-pipes-plugins/tika-pipes-google-drive/src/test/java/org/apache/tika/pipes/googledrive/ConfigExamplesTest.java b/tika-pipes/tika-pipes-plugins/tika-pipes-google-drive/src/test/java/org/apache/tika/pipes/googledrive/ConfigExamplesTest.java
index 7ee99ebca28..9d8bb365d73 100644
--- a/tika-pipes/tika-pipes-plugins/tika-pipes-google-drive/src/test/java/org/apache/tika/pipes/googledrive/ConfigExamplesTest.java
+++ b/tika-pipes/tika-pipes-plugins/tika-pipes-google-drive/src/test/java/org/apache/tika/pipes/googledrive/ConfigExamplesTest.java
@@ -20,46 +20,23 @@
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-
import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.io.TempDir;
-import org.apache.tika.config.loader.TikaLoader;
+import org.apache.tika.pipes.core.testutil.AbstractConfigExamplesTest;
import org.apache.tika.pipes.fetcher.googledrive.config.GoogleDriveFetcherConfig;
/**
* Validates Google Drive fetcher configuration examples used in documentation.
*/
-public class ConfigExamplesTest {
-
- private static final String EXAMPLES_DIR = "/config-examples/";
- private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
-
- @TempDir
- Path tempDir;
-
- private String readExample(String resourceName) throws Exception {
- try (InputStream is = getClass().getResourceAsStream(EXAMPLES_DIR + resourceName)) {
- assertNotNull(is, "Resource not found: " + resourceName);
- return new String(is.readAllBytes(), StandardCharsets.UTF_8);
- }
- }
+public class ConfigExamplesTest extends AbstractConfigExamplesTest {
@Test
public void testGoogleDriveFetcherConfig() throws Exception {
- String json = readExample("google-drive-fetcher.json");
- Path configFile = tempDir.resolve("tika-config.json");
- Files.writeString(configFile, json, StandardCharsets.UTF_8);
- assertNotNull(TikaLoader.load(configFile));
+ loadAndValidate("google-drive-fetcher.json");
- JsonNode inner = OBJECT_MAPPER.readTree(json)
- .get("fetchers").get("gdf").get("google-drive-fetcher");
+ JsonNode inner = innerComponent(readExample("google-drive-fetcher.json"),
+ "fetchers", "gdf", "google-drive-fetcher");
GoogleDriveFetcherConfig config = GoogleDriveFetcherConfig.load(inner.toString());
assertEquals("tika-pipes", config.getApplicationName());
assertEquals("user@example.com", config.getSubjectUser());
diff --git a/tika-pipes/tika-pipes-plugins/tika-pipes-http/src/test/java/org/apache/tika/pipes/http/ConfigExamplesTest.java b/tika-pipes/tika-pipes-plugins/tika-pipes-http/src/test/java/org/apache/tika/pipes/http/ConfigExamplesTest.java
index ff447df2a3c..33f737d6388 100644
--- a/tika-pipes/tika-pipes-plugins/tika-pipes-http/src/test/java/org/apache/tika/pipes/http/ConfigExamplesTest.java
+++ b/tika-pipes/tika-pipes-plugins/tika-pipes-http/src/test/java/org/apache/tika/pipes/http/ConfigExamplesTest.java
@@ -17,49 +17,25 @@
package org.apache.tika.pipes.http;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-
import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.io.TempDir;
-import org.apache.tika.config.loader.TikaLoader;
+import org.apache.tika.pipes.core.testutil.AbstractConfigExamplesTest;
import org.apache.tika.pipes.fetcher.http.config.HttpFetcherConfig;
/**
* Validates HTTP fetcher configuration examples used in documentation.
*/
-public class ConfigExamplesTest {
-
- private static final String EXAMPLES_DIR = "/config-examples/";
- private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
-
- @TempDir
- Path tempDir;
-
- private String readExample(String resourceName) throws Exception {
- try (InputStream is = getClass().getResourceAsStream(EXAMPLES_DIR + resourceName)) {
- assertNotNull(is, "Resource not found: " + resourceName);
- return new String(is.readAllBytes(), StandardCharsets.UTF_8);
- }
- }
+public class ConfigExamplesTest extends AbstractConfigExamplesTest {
@Test
public void testHttpFetcherConfig() throws Exception {
- String json = readExample("http-fetcher.json");
- Path configFile = tempDir.resolve("tika-config.json");
- Files.writeString(configFile, json, StandardCharsets.UTF_8);
- assertNotNull(TikaLoader.load(configFile));
+ loadAndValidate("http-fetcher.json");
- JsonNode inner = OBJECT_MAPPER.readTree(json)
- .get("fetchers").get("httpf").get("http-fetcher");
+ JsonNode inner = innerComponent(readExample("http-fetcher.json"),
+ "fetchers", "httpf", "http-fetcher");
HttpFetcherConfig config = HttpFetcherConfig.load(inner.toString());
assertEquals("tika", config.getUserName());
assertEquals("basic", config.getAuthScheme());
diff --git a/tika-pipes/tika-pipes-plugins/tika-pipes-jdbc/src/test/java/org/apache/tika/pipes/jdbc/ConfigExamplesTest.java b/tika-pipes/tika-pipes-plugins/tika-pipes-jdbc/src/test/java/org/apache/tika/pipes/jdbc/ConfigExamplesTest.java
index 05b657362c0..f431d3881f6 100644
--- a/tika-pipes/tika-pipes-plugins/tika-pipes-jdbc/src/test/java/org/apache/tika/pipes/jdbc/ConfigExamplesTest.java
+++ b/tika-pipes/tika-pipes-plugins/tika-pipes-jdbc/src/test/java/org/apache/tika/pipes/jdbc/ConfigExamplesTest.java
@@ -20,17 +20,10 @@
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-
import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.io.TempDir;
-import org.apache.tika.config.loader.TikaLoader;
+import org.apache.tika.pipes.core.testutil.AbstractConfigExamplesTest;
import org.apache.tika.pipes.emitter.jdbc.JDBCEmitterConfig;
import org.apache.tika.pipes.iterator.jdbc.JDBCPipesIteratorConfig;
import org.apache.tika.pipes.reporter.jdbc.JDBCPipesReporterConfig;
@@ -41,44 +34,11 @@
* The JSON configuration examples are stored in {@code src/test/resources/config-examples/}
* and are included directly in the AsciiDoc documentation via the {@code include::} directive.
*/
-public class ConfigExamplesTest {
-
- private static final String EXAMPLES_DIR = "/config-examples/";
- private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
-
- @TempDir
- Path tempDir;
-
- private String readExample(String resourceName) throws Exception {
- try (InputStream is = getClass().getResourceAsStream(EXAMPLES_DIR + resourceName)) {
- assertNotNull(is, "Resource not found: " + resourceName);
- return new String(is.readAllBytes(), StandardCharsets.UTF_8);
- }
- }
-
- private void loadViaTikaLoader(String resourceName) throws Exception {
- String json = readExample(resourceName);
- Path configFile = tempDir.resolve("tika-config.json");
- Files.writeString(configFile, json, StandardCharsets.UTF_8);
- TikaLoader loader = TikaLoader.load(configFile);
- assertNotNull(loader, "TikaLoader should not be null for: " + resourceName);
- }
-
- private JsonNode innerComponent(String json, String section, String id, String typeName)
- throws Exception {
- JsonNode root = OBJECT_MAPPER.readTree(json);
- JsonNode sectionNode = root.get(section);
- assertNotNull(sectionNode, "Missing section: " + section);
- JsonNode idNode = id == null ? sectionNode : sectionNode.get(id);
- assertNotNull(idNode, "Missing id: " + id);
- JsonNode typed = idNode.get(typeName);
- assertNotNull(typed, "Missing type: " + typeName);
- return typed;
- }
+public class ConfigExamplesTest extends AbstractConfigExamplesTest {
@Test
public void testJDBCEmitterConfig() throws Exception {
- loadViaTikaLoader("jdbc-emitter.json");
+ loadAndValidate("jdbc-emitter.json");
JsonNode inner = innerComponent(readExample("jdbc-emitter.json"),
"emitters", "jdbce", "jdbc-emitter");
@@ -98,7 +58,7 @@ public void testJDBCEmitterConfig() throws Exception {
@Test
public void testJDBCIteratorConfig() throws Exception {
- loadViaTikaLoader("jdbc-pipes-iterator.json");
+ loadAndValidate("jdbc-pipes-iterator.json");
JsonNode inner = innerComponent(readExample("jdbc-pipes-iterator.json"),
"pipes-iterator", null, "jdbc-pipes-iterator");
@@ -116,7 +76,7 @@ public void testJDBCIteratorConfig() throws Exception {
@Test
public void testJDBCReporterConfig() throws Exception {
- loadViaTikaLoader("jdbc-reporter.json");
+ loadAndValidate("jdbc-reporter.json");
JsonNode inner = innerComponent(readExample("jdbc-reporter.json"),
"pipes-reporters", null, "jdbc-reporter");
@@ -133,7 +93,7 @@ public void testJDBCReporterConfig() throws Exception {
@Test
public void testJDBCPipelineConfig() throws Exception {
- loadViaTikaLoader("jdbc-pipeline.json");
+ loadAndValidate("jdbc-pipeline.json");
String json = readExample("jdbc-pipeline.json");
JDBCEmitterConfig emitter = JDBCEmitterConfig.load(
diff --git a/tika-pipes/tika-pipes-plugins/tika-pipes-json/src/test/java/org/apache/tika/pipes/json/ConfigExamplesTest.java b/tika-pipes/tika-pipes-plugins/tika-pipes-json/src/test/java/org/apache/tika/pipes/json/ConfigExamplesTest.java
index d96140eae50..d7f09ca524f 100644
--- a/tika-pipes/tika-pipes-plugins/tika-pipes-json/src/test/java/org/apache/tika/pipes/json/ConfigExamplesTest.java
+++ b/tika-pipes/tika-pipes-plugins/tika-pipes-json/src/test/java/org/apache/tika/pipes/json/ConfigExamplesTest.java
@@ -19,46 +19,23 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
-import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-
import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.io.TempDir;
-import org.apache.tika.config.loader.TikaLoader;
+import org.apache.tika.pipes.core.testutil.AbstractConfigExamplesTest;
import org.apache.tika.pipes.pipesiterator.json.JsonPipesIteratorConfig;
/**
* Validates JSON iterator configuration example used in documentation.
*/
-public class ConfigExamplesTest {
-
- private static final String EXAMPLES_DIR = "/config-examples/";
- private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
-
- @TempDir
- Path tempDir;
-
- private String readExample(String resourceName) throws Exception {
- try (InputStream is = getClass().getResourceAsStream(EXAMPLES_DIR + resourceName)) {
- assertNotNull(is, "Resource not found: " + resourceName);
- return new String(is.readAllBytes(), StandardCharsets.UTF_8);
- }
- }
+public class ConfigExamplesTest extends AbstractConfigExamplesTest {
@Test
public void testJsonIteratorConfig() throws Exception {
- String json = readExample("json-pipes-iterator.json");
- Path configFile = tempDir.resolve("tika-config.json");
- Files.writeString(configFile, json, StandardCharsets.UTF_8);
- assertNotNull(TikaLoader.load(configFile));
+ loadAndValidate("json-pipes-iterator.json");
- JsonNode inner = OBJECT_MAPPER.readTree(json)
- .get("pipes-iterator").get("json-pipes-iterator");
+ JsonNode inner = innerComponent(readExample("json-pipes-iterator.json"),
+ "pipes-iterator", null, "json-pipes-iterator");
JsonPipesIteratorConfig config = JsonPipesIteratorConfig.load(inner.toString());
assertNotNull(config.getJsonPath());
assertEquals("fsf", config.getFetcherId());
diff --git a/tika-pipes/tika-pipes-plugins/tika-pipes-kafka/src/test/java/org/apache/tika/pipes/kafka/ConfigExamplesTest.java b/tika-pipes/tika-pipes-plugins/tika-pipes-kafka/src/test/java/org/apache/tika/pipes/kafka/ConfigExamplesTest.java
index 43c9a4daefb..9951f55959b 100644
--- a/tika-pipes/tika-pipes-plugins/tika-pipes-kafka/src/test/java/org/apache/tika/pipes/kafka/ConfigExamplesTest.java
+++ b/tika-pipes/tika-pipes-plugins/tika-pipes-kafka/src/test/java/org/apache/tika/pipes/kafka/ConfigExamplesTest.java
@@ -17,20 +17,12 @@
package org.apache.tika.pipes.kafka;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-
import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.io.TempDir;
-import org.apache.tika.config.loader.TikaLoader;
+import org.apache.tika.pipes.core.testutil.AbstractConfigExamplesTest;
import org.apache.tika.pipes.emitter.kafka.KafkaEmitterConfig;
import org.apache.tika.pipes.iterator.kafka.KafkaPipesIteratorConfig;
@@ -40,44 +32,11 @@
* The JSON configuration examples are stored in {@code src/test/resources/config-examples/}
* and are included directly in the AsciiDoc documentation via the {@code include::} directive.
*/
-public class ConfigExamplesTest {
-
- private static final String EXAMPLES_DIR = "/config-examples/";
- private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
-
- @TempDir
- Path tempDir;
-
- private String readExample(String resourceName) throws Exception {
- try (InputStream is = getClass().getResourceAsStream(EXAMPLES_DIR + resourceName)) {
- assertNotNull(is, "Resource not found: " + resourceName);
- return new String(is.readAllBytes(), StandardCharsets.UTF_8);
- }
- }
-
- private void loadViaTikaLoader(String resourceName) throws Exception {
- String json = readExample(resourceName);
- Path configFile = tempDir.resolve("tika-config.json");
- Files.writeString(configFile, json, StandardCharsets.UTF_8);
- TikaLoader loader = TikaLoader.load(configFile);
- assertNotNull(loader, "TikaLoader should not be null for: " + resourceName);
- }
-
- private JsonNode innerComponent(String json, String section, String id, String typeName)
- throws Exception {
- JsonNode root = OBJECT_MAPPER.readTree(json);
- JsonNode sectionNode = root.get(section);
- assertNotNull(sectionNode, "Missing section: " + section);
- JsonNode idNode = id == null ? sectionNode : sectionNode.get(id);
- assertNotNull(idNode, "Missing id: " + id);
- JsonNode typed = idNode.get(typeName);
- assertNotNull(typed, "Missing type: " + typeName);
- return typed;
- }
+public class ConfigExamplesTest extends AbstractConfigExamplesTest {
@Test
public void testKafkaEmitterConfig() throws Exception {
- loadViaTikaLoader("kafka-emitter.json");
+ loadAndValidate("kafka-emitter.json");
JsonNode inner = innerComponent(readExample("kafka-emitter.json"),
"emitters", "kafe", "kafka-emitter");
@@ -92,7 +51,7 @@ public void testKafkaEmitterConfig() throws Exception {
@Test
public void testKafkaIteratorConfig() throws Exception {
- loadViaTikaLoader("kafka-pipes-iterator.json");
+ loadAndValidate("kafka-pipes-iterator.json");
JsonNode inner = innerComponent(readExample("kafka-pipes-iterator.json"),
"pipes-iterator", null, "kafka-pipes-iterator");
@@ -108,7 +67,7 @@ public void testKafkaIteratorConfig() throws Exception {
@Test
public void testKafkaPipelineConfig() throws Exception {
- loadViaTikaLoader("kafka-pipeline.json");
+ loadAndValidate("kafka-pipeline.json");
String json = readExample("kafka-pipeline.json");
KafkaEmitterConfig emitter = KafkaEmitterConfig.load(
diff --git a/tika-pipes/tika-pipes-plugins/tika-pipes-microsoft-graph/src/test/java/org/apache/tika/pipes/microsoftgraph/ConfigExamplesTest.java b/tika-pipes/tika-pipes-plugins/tika-pipes-microsoft-graph/src/test/java/org/apache/tika/pipes/microsoftgraph/ConfigExamplesTest.java
index 83159ba65ba..1b5b0e29ebe 100644
--- a/tika-pipes/tika-pipes-plugins/tika-pipes-microsoft-graph/src/test/java/org/apache/tika/pipes/microsoftgraph/ConfigExamplesTest.java
+++ b/tika-pipes/tika-pipes-plugins/tika-pipes-microsoft-graph/src/test/java/org/apache/tika/pipes/microsoftgraph/ConfigExamplesTest.java
@@ -20,46 +20,23 @@
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-
import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.io.TempDir;
-import org.apache.tika.config.loader.TikaLoader;
+import org.apache.tika.pipes.core.testutil.AbstractConfigExamplesTest;
import org.apache.tika.pipes.fetchers.microsoftgraph.config.MicrosoftGraphFetcherConfig;
/**
* Validates Microsoft Graph fetcher configuration examples used in documentation.
*/
-public class ConfigExamplesTest {
-
- private static final String EXAMPLES_DIR = "/config-examples/";
- private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
-
- @TempDir
- Path tempDir;
-
- private String readExample(String resourceName) throws Exception {
- try (InputStream is = getClass().getResourceAsStream(EXAMPLES_DIR + resourceName)) {
- assertNotNull(is, "Resource not found: " + resourceName);
- return new String(is.readAllBytes(), StandardCharsets.UTF_8);
- }
- }
+public class ConfigExamplesTest extends AbstractConfigExamplesTest {
@Test
public void testMicrosoftGraphFetcherConfig() throws Exception {
- String json = readExample("microsoft-graph-fetcher.json");
- Path configFile = tempDir.resolve("tika-config.json");
- Files.writeString(configFile, json, StandardCharsets.UTF_8);
- assertNotNull(TikaLoader.load(configFile));
+ loadAndValidate("microsoft-graph-fetcher.json");
- JsonNode inner = OBJECT_MAPPER.readTree(json)
- .get("fetchers").get("msgf").get("microsoft-graph-fetcher");
+ JsonNode inner = innerComponent(readExample("microsoft-graph-fetcher.json"),
+ "fetchers", "msgf", "microsoft-graph-fetcher");
MicrosoftGraphFetcherConfig config = MicrosoftGraphFetcherConfig.load(inner.toString());
assertNotNull(config.getClientSecretCredentialsConfig());
assertEquals("REDACTED-TENANT-UUID",
diff --git a/tika-pipes/tika-pipes-plugins/tika-pipes-opensearch/src/test/java/org/apache/tika/pipes/opensearch/ConfigExamplesTest.java b/tika-pipes/tika-pipes-plugins/tika-pipes-opensearch/src/test/java/org/apache/tika/pipes/opensearch/ConfigExamplesTest.java
index d0c0a9eefa4..e673f25b881 100644
--- a/tika-pipes/tika-pipes-plugins/tika-pipes-opensearch/src/test/java/org/apache/tika/pipes/opensearch/ConfigExamplesTest.java
+++ b/tika-pipes/tika-pipes-plugins/tika-pipes-opensearch/src/test/java/org/apache/tika/pipes/opensearch/ConfigExamplesTest.java
@@ -20,17 +20,10 @@
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-
import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.io.TempDir;
-import org.apache.tika.config.loader.TikaLoader;
+import org.apache.tika.pipes.core.testutil.AbstractConfigExamplesTest;
import org.apache.tika.pipes.emitter.opensearch.OpenSearchEmitterConfig;
import org.apache.tika.pipes.reporter.opensearch.OpenSearchReporterConfig;
@@ -40,44 +33,11 @@
* The JSON configuration examples are stored in {@code src/test/resources/config-examples/}
* and are included directly in the AsciiDoc documentation via the {@code include::} directive.
*/
-public class ConfigExamplesTest {
-
- private static final String EXAMPLES_DIR = "/config-examples/";
- private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
-
- @TempDir
- Path tempDir;
-
- private String readExample(String resourceName) throws Exception {
- try (InputStream is = getClass().getResourceAsStream(EXAMPLES_DIR + resourceName)) {
- assertNotNull(is, "Resource not found: " + resourceName);
- return new String(is.readAllBytes(), StandardCharsets.UTF_8);
- }
- }
-
- private void loadViaTikaLoader(String resourceName) throws Exception {
- String json = readExample(resourceName);
- Path configFile = tempDir.resolve("tika-config.json");
- Files.writeString(configFile, json, StandardCharsets.UTF_8);
- TikaLoader loader = TikaLoader.load(configFile);
- assertNotNull(loader, "TikaLoader should not be null for: " + resourceName);
- }
-
- private JsonNode innerComponent(String json, String section, String id, String typeName)
- throws Exception {
- JsonNode root = OBJECT_MAPPER.readTree(json);
- JsonNode sectionNode = root.get(section);
- assertNotNull(sectionNode, "Missing section: " + section);
- JsonNode idNode = id == null ? sectionNode : sectionNode.get(id);
- assertNotNull(idNode, "Missing id: " + id);
- JsonNode typed = idNode.get(typeName);
- assertNotNull(typed, "Missing type: " + typeName);
- return typed;
- }
+public class ConfigExamplesTest extends AbstractConfigExamplesTest {
@Test
public void testOpenSearchEmitterConfig() throws Exception {
- loadViaTikaLoader("opensearch-emitter.json");
+ loadAndValidate("opensearch-emitter.json");
JsonNode inner = innerComponent(readExample("opensearch-emitter.json"),
"emitters", "ose", "opensearch-emitter");
@@ -94,7 +54,7 @@ public void testOpenSearchEmitterConfig() throws Exception {
@Test
public void testOpenSearchReporterConfig() throws Exception {
- loadViaTikaLoader("opensearch-reporter.json");
+ loadAndValidate("opensearch-reporter.json");
JsonNode inner = innerComponent(readExample("opensearch-reporter.json"),
"pipes-reporters", null, "opensearch-pipes-reporter");
@@ -109,7 +69,7 @@ public void testOpenSearchReporterConfig() throws Exception {
@Test
public void testOpenSearchPipelineConfig() throws Exception {
- loadViaTikaLoader("opensearch-pipeline.json");
+ loadAndValidate("opensearch-pipeline.json");
String json = readExample("opensearch-pipeline.json");
OpenSearchEmitterConfig emitter = OpenSearchEmitterConfig.load(
diff --git a/tika-pipes/tika-pipes-plugins/tika-pipes-s3/src/test/java/org/apache/tika/pipes/s3/ConfigExamplesTest.java b/tika-pipes/tika-pipes-plugins/tika-pipes-s3/src/test/java/org/apache/tika/pipes/s3/ConfigExamplesTest.java
index f248d8194e4..36f67cb8bba 100644
--- a/tika-pipes/tika-pipes-plugins/tika-pipes-s3/src/test/java/org/apache/tika/pipes/s3/ConfigExamplesTest.java
+++ b/tika-pipes/tika-pipes-plugins/tika-pipes-s3/src/test/java/org/apache/tika/pipes/s3/ConfigExamplesTest.java
@@ -17,19 +17,11 @@
package org.apache.tika.pipes.s3;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-
-import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.io.TempDir;
-import org.apache.tika.config.loader.TikaLoader;
+import org.apache.tika.pipes.core.testutil.AbstractConfigExamplesTest;
import org.apache.tika.pipes.emitter.s3.S3EmitterConfig;
import org.apache.tika.pipes.fetcher.s3.config.S3FetcherConfig;
import org.apache.tika.pipes.iterator.s3.S3PipesIteratorConfig;
@@ -40,44 +32,11 @@
* The JSON configuration examples are stored in {@code src/test/resources/config-examples/}
* and are included directly in the AsciiDoc documentation via the {@code include::} directive.
*/
-public class ConfigExamplesTest {
-
- private static final String EXAMPLES_DIR = "/config-examples/";
- private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
-
- @TempDir
- Path tempDir;
-
- private String readExample(String resourceName) throws Exception {
- try (InputStream is = getClass().getResourceAsStream(EXAMPLES_DIR + resourceName)) {
- assertNotNull(is, "Resource not found: " + resourceName);
- return new String(is.readAllBytes(), StandardCharsets.UTF_8);
- }
- }
-
- private void loadViaTikaLoader(String resourceName) throws Exception {
- String json = readExample(resourceName);
- Path configFile = tempDir.resolve("tika-config.json");
- Files.writeString(configFile, json, StandardCharsets.UTF_8);
- TikaLoader loader = TikaLoader.load(configFile);
- assertNotNull(loader, "TikaLoader should not be null for: " + resourceName);
- }
-
- private JsonNode innerComponent(String json, String section, String id, String typeName)
- throws Exception {
- JsonNode root = OBJECT_MAPPER.readTree(json);
- JsonNode sectionNode = root.get(section);
- assertNotNull(sectionNode, "Missing section: " + section);
- JsonNode idNode = id == null ? sectionNode : sectionNode.get(id);
- assertNotNull(idNode, "Missing id: " + id);
- JsonNode typed = idNode.get(typeName);
- assertNotNull(typed, "Missing type: " + typeName);
- return typed;
- }
+public class ConfigExamplesTest extends AbstractConfigExamplesTest {
@Test
public void testS3FetcherConfig() throws Exception {
- loadViaTikaLoader("s3-fetcher.json");
+ loadAndValidate("s3-fetcher.json");
JsonNode inner = innerComponent(readExample("s3-fetcher.json"),
"fetchers", "s3f", "s3-fetcher");
@@ -90,7 +49,7 @@ public void testS3FetcherConfig() throws Exception {
@Test
public void testS3EmitterConfig() throws Exception {
- loadViaTikaLoader("s3-emitter.json");
+ loadAndValidate("s3-emitter.json");
JsonNode inner = innerComponent(readExample("s3-emitter.json"),
"emitters", "s3e", "s3-emitter");
@@ -105,7 +64,7 @@ public void testS3EmitterConfig() throws Exception {
@Test
public void testS3IteratorConfig() throws Exception {
- loadViaTikaLoader("s3-pipes-iterator.json");
+ loadAndValidate("s3-pipes-iterator.json");
JsonNode inner = innerComponent(readExample("s3-pipes-iterator.json"),
"pipes-iterator", null, "s3-pipes-iterator");
@@ -118,7 +77,7 @@ public void testS3IteratorConfig() throws Exception {
@Test
public void testS3PipelineConfig() throws Exception {
- loadViaTikaLoader("s3-pipeline.json");
+ loadAndValidate("s3-pipeline.json");
String json = readExample("s3-pipeline.json");
S3FetcherConfig fetcher = S3FetcherConfig.load(
diff --git a/tika-pipes/tika-pipes-plugins/tika-pipes-solr/src/test/java/org/apache/tika/pipes/solr/ConfigExamplesTest.java b/tika-pipes/tika-pipes-plugins/tika-pipes-solr/src/test/java/org/apache/tika/pipes/solr/ConfigExamplesTest.java
index 65d06c37cc9..cc07a18fc52 100644
--- a/tika-pipes/tika-pipes-plugins/tika-pipes-solr/src/test/java/org/apache/tika/pipes/solr/ConfigExamplesTest.java
+++ b/tika-pipes/tika-pipes-plugins/tika-pipes-solr/src/test/java/org/apache/tika/pipes/solr/ConfigExamplesTest.java
@@ -20,17 +20,10 @@
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-
import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.io.TempDir;
-import org.apache.tika.config.loader.TikaLoader;
+import org.apache.tika.pipes.core.testutil.AbstractConfigExamplesTest;
import org.apache.tika.pipes.emitter.solr.SolrEmitterConfig;
import org.apache.tika.pipes.iterator.solr.SolrPipesIteratorConfig;
@@ -40,44 +33,11 @@
* The JSON configuration examples are stored in {@code src/test/resources/config-examples/}
* and are included directly in the AsciiDoc documentation via the {@code include::} directive.
*/
-public class ConfigExamplesTest {
-
- private static final String EXAMPLES_DIR = "/config-examples/";
- private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
-
- @TempDir
- Path tempDir;
-
- private String readExample(String resourceName) throws Exception {
- try (InputStream is = getClass().getResourceAsStream(EXAMPLES_DIR + resourceName)) {
- assertNotNull(is, "Resource not found: " + resourceName);
- return new String(is.readAllBytes(), StandardCharsets.UTF_8);
- }
- }
-
- private void loadViaTikaLoader(String resourceName) throws Exception {
- String json = readExample(resourceName);
- Path configFile = tempDir.resolve("tika-config.json");
- Files.writeString(configFile, json, StandardCharsets.UTF_8);
- TikaLoader loader = TikaLoader.load(configFile);
- assertNotNull(loader, "TikaLoader should not be null for: " + resourceName);
- }
-
- private JsonNode innerComponent(String json, String section, String id, String typeName)
- throws Exception {
- JsonNode root = OBJECT_MAPPER.readTree(json);
- JsonNode sectionNode = root.get(section);
- assertNotNull(sectionNode, "Missing section: " + section);
- JsonNode idNode = id == null ? sectionNode : sectionNode.get(id);
- assertNotNull(idNode, "Missing id: " + id);
- JsonNode typed = idNode.get(typeName);
- assertNotNull(typed, "Missing type: " + typeName);
- return typed;
- }
+public class ConfigExamplesTest extends AbstractConfigExamplesTest {
@Test
public void testSolrEmitterUrlsConfig() throws Exception {
- loadViaTikaLoader("solr-emitter.json");
+ loadAndValidate("solr-emitter.json");
JsonNode inner = innerComponent(readExample("solr-emitter.json"),
"emitters", "solre", "solr-emitter");
@@ -94,7 +54,7 @@ public void testSolrEmitterUrlsConfig() throws Exception {
@Test
public void testSolrEmitterZkConfig() throws Exception {
- loadViaTikaLoader("solr-emitter-zk.json");
+ loadAndValidate("solr-emitter-zk.json");
JsonNode inner = innerComponent(readExample("solr-emitter-zk.json"),
"emitters", "solre", "solr-emitter");
@@ -109,7 +69,7 @@ public void testSolrEmitterZkConfig() throws Exception {
@Test
public void testSolrIteratorConfig() throws Exception {
- loadViaTikaLoader("solr-pipes-iterator.json");
+ loadAndValidate("solr-pipes-iterator.json");
JsonNode inner = innerComponent(readExample("solr-pipes-iterator.json"),
"pipes-iterator", null, "solr-pipes-iterator");
@@ -123,7 +83,7 @@ public void testSolrIteratorConfig() throws Exception {
@Test
public void testSolrPipelineConfig() throws Exception {
- loadViaTikaLoader("solr-pipeline.json");
+ loadAndValidate("solr-pipeline.json");
String json = readExample("solr-pipeline.json");
SolrEmitterConfig emitter = SolrEmitterConfig.load(
diff --git a/tika-serialization/src/main/java/org/apache/tika/config/loader/AbstractSpiComponentLoader.java b/tika-serialization/src/main/java/org/apache/tika/config/loader/AbstractSpiComponentLoader.java
index 7be0c37a148..191d5b164d1 100644
--- a/tika-serialization/src/main/java/org/apache/tika/config/loader/AbstractSpiComponentLoader.java
+++ b/tika-serialization/src/main/java/org/apache/tika/config/loader/AbstractSpiComponentLoader.java
@@ -19,6 +19,8 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -241,11 +243,24 @@ protected T decorateDefaultComposite(T composite, JsonNode configNode,
// ==================== Shared implementation ====================
+ /**
+ * The set of keys permitted inside a marker config (e.g., inside
+ * {@code default-parser}). Subclasses extend this when they consume additional
+ * framework-level decorators on the marker.
+ *
+ * Default: just {@code "exclude"}. ParserLoader adds the mime-filter decorators.
+ */
+ protected Set getAllowedMarkerKeys() {
+ return Set.of("exclude");
+ }
+
private DefaultMarkerConfig findDefaultMarker(List> entries,
- LoaderContext context) {
+ LoaderContext context)
+ throws TikaConfigException {
int index = 0;
for (Map.Entry entry : entries) {
if (defaultMarkerName.equals(entry.getKey())) {
+ validateMarkerKeys(entry.getValue());
Set> exclusions =
parseExclusions(entry.getValue(), context);
return new DefaultMarkerConfig<>(true, index, exclusions, entry.getValue());
@@ -255,6 +270,34 @@ private DefaultMarkerConfig findDefaultMarker(List(false, -1, Collections.emptySet(), null);
}
+ /**
+ * Rejects any unknown key inside a marker's config. The marker schema is fixed
+ * and tiny — silently ignoring an unrecognized key (e.g., {@code _exclude}
+ * instead of {@code exclude}) means the directive is dropped on the floor and
+ * the user only discovers it at runtime, if at all.
+ */
+ private void validateMarkerKeys(JsonNode markerConfig) throws TikaConfigException {
+ if (markerConfig == null || !markerConfig.isObject()) {
+ return;
+ }
+ Set allowed = getAllowedMarkerKeys();
+ Set unknown = new LinkedHashSet<>();
+ Iterator it = markerConfig.fieldNames();
+ while (it.hasNext()) {
+ String key = it.next();
+ if (!allowed.contains(key)) {
+ unknown.add(key);
+ }
+ }
+ if (!unknown.isEmpty()) {
+ throw new TikaConfigException(
+ "Unknown key(s) " + unknown + " inside '" + defaultMarkerName
+ + "'. Allowed keys: " + allowed
+ + ". (Did you mean 'exclude'? The leading-underscore form"
+ + " '_exclude' is not recognized.)");
+ }
+ }
+
@SuppressWarnings("unchecked")
private Set> parseExclusions(JsonNode configNode,
LoaderContext context) {
diff --git a/tika-serialization/src/main/java/org/apache/tika/config/loader/ComponentInstantiator.java b/tika-serialization/src/main/java/org/apache/tika/config/loader/ComponentInstantiator.java
index 4b87ba78ca3..4dcc9303535 100644
--- a/tika-serialization/src/main/java/org/apache/tika/config/loader/ComponentInstantiator.java
+++ b/tika-serialization/src/main/java/org/apache/tika/config/loader/ComponentInstantiator.java
@@ -305,9 +305,17 @@ private static Constructor> findJsonConfigConstructor(Class> clazz) {
}
/**
- * Strips decorator fields (_mime-include, _mime-exclude) from config node.
- * These fields are handled by TikaLoader for wrapping, not by the component itself.
- * Note: _exclude is NOT stripped as it's used by DefaultParser for SPI exclusions.
+ * Strips decorator fields ({@code _mime-include}, {@code _mime-exclude}) from a real
+ * component's config node. These directives are applied by {@link
+ * org.apache.tika.config.loader.TikaLoader} as a wrapper around the component, not
+ * consumed by the component itself, so they must be stripped before deserialization.
+ *
+ * Convention: directives that share a JSON object with a real component's own
+ * config properties carry a leading underscore to avoid namespace collisions
+ * (e.g., a parser could legitimately have a config key named {@code mime-include}).
+ * Directives on marker entries that have no component-config namespace —
+ * {@code "exclude"} on {@code default-parser}/{@code default-detector} — need no
+ * prefix; those are read directly by {@link AbstractSpiComponentLoader}.
*/
private static JsonNode stripDecoratorFields(JsonNode configNode) {
if (configNode == null || !configNode.isObject()) {
diff --git a/tika-serialization/src/main/java/org/apache/tika/config/loader/ParserLoader.java b/tika-serialization/src/main/java/org/apache/tika/config/loader/ParserLoader.java
index ec1f8ff42ac..1c37c68fffa 100644
--- a/tika-serialization/src/main/java/org/apache/tika/config/loader/ParserLoader.java
+++ b/tika-serialization/src/main/java/org/apache/tika/config/loader/ParserLoader.java
@@ -80,6 +80,13 @@ protected Parser createDefaultComposite(Set> exclusions,
exclusions);
}
+ @Override
+ protected Set getAllowedMarkerKeys() {
+ // ParserLoader honors framework mime-filter decorators on default-parser
+ // in addition to the standard "exclude" key.
+ return Set.of("exclude", "_mime-include", "_mime-exclude");
+ }
+
@Override
protected Parser decorateDefaultComposite(Parser parser, JsonNode configNode,
LoaderContext context) throws TikaConfigException {
diff --git a/tika-serialization/src/main/java/org/apache/tika/config/loader/TikaJsonConfig.java b/tika-serialization/src/main/java/org/apache/tika/config/loader/TikaJsonConfig.java
index 344faa66c78..9989ca2b1a6 100644
--- a/tika-serialization/src/main/java/org/apache/tika/config/loader/TikaJsonConfig.java
+++ b/tika-serialization/src/main/java/org/apache/tika/config/loader/TikaJsonConfig.java
@@ -78,7 +78,7 @@
* ],
* "detectors": [
* "poifs-container-detector", // String shorthand
- * { "default-detector": { "spoolTypes": ["application/zip", "application/pdf"] } }
+ * { "default-detector": { "exclude": ["html-detector"] } }
* ],
*
* // Pipes components (validated by validateKeys())
diff --git a/tika-serialization/src/test/java/org/apache/tika/config/loader/TikaLoaderTest.java b/tika-serialization/src/test/java/org/apache/tika/config/loader/TikaLoaderTest.java
index 403464d9c4b..0d157048c61 100644
--- a/tika-serialization/src/test/java/org/apache/tika/config/loader/TikaLoaderTest.java
+++ b/tika-serialization/src/test/java/org/apache/tika/config/loader/TikaLoaderTest.java
@@ -26,7 +26,6 @@
import java.nio.file.Files;
import java.nio.file.Path;
-import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.xml.sax.helpers.DefaultHandler;
@@ -369,11 +368,10 @@ public void testLoadConfigMissingKeyReturnsDefaults() throws Exception {
assertFalse(config.isThrowOnMaxCount(), "Should return defaults when key missing");
}
- // TODO: TIKA-SERIALIZATION-FOLLOWUP - Jackson may need configuration to fail on unknown properties
- @Disabled("TIKA-SERIALIZATION-FOLLOWUP")
@Test
- public void testInvalidBeanPropertyThrowsException() throws Exception {
- // Config with a property that doesn't exist on DefaultDetector
+ public void testUnknownKeyInDefaultDetectorThrows() throws Exception {
+ // Strict-marker-key validation: an unknown key inside default-detector
+ // must error at load time rather than being silently ignored. (TIKA-4739)
String invalidConfig = """
{
"detectors": [
@@ -389,16 +387,113 @@ public void testInvalidBeanPropertyThrowsException() throws Exception {
Path tempFile = Files.createTempFile("test-invalid-property", ".json");
try {
Files.write(tempFile, invalidConfig.getBytes(StandardCharsets.UTF_8));
+ TikaLoader loader = TikaLoader.load(tempFile);
+ try {
+ loader.loadDetectors();
+ throw new AssertionError("Expected TikaConfigException for unknown marker key");
+ } catch (org.apache.tika.exception.TikaConfigException e) {
+ assertTrue(e.getMessage().contains("nonExistentProperty"),
+ "Error should name the offending key");
+ assertTrue(e.getMessage().contains("default-detector"),
+ "Error should name the marker");
+ }
+ } finally {
+ Files.deleteIfExists(tempFile);
+ }
+ }
+
+ @Test
+ public void testUnderscoreExcludeInDefaultParserThrows() throws Exception {
+ // The canonical form is "exclude" (no underscore). The historical
+ // "_exclude" was silently dropped, leading to ghost configs that did
+ // nothing. Strict validation must catch this at load time. (TIKA-4739)
+ String invalidConfig = """
+ {
+ "parsers": [
+ {
+ "default-parser": {
+ "_exclude": ["pdf-parser"]
+ }
+ }
+ ]
+ }
+ """;
+
+ Path tempFile = Files.createTempFile("test-underscore-exclude", ".json");
+ try {
+ Files.write(tempFile, invalidConfig.getBytes(StandardCharsets.UTF_8));
+ TikaLoader loader = TikaLoader.load(tempFile);
+ try {
+ loader.loadParsers();
+ throw new AssertionError("Expected TikaConfigException for _exclude on default-parser");
+ } catch (org.apache.tika.exception.TikaConfigException e) {
+ assertTrue(e.getMessage().contains("_exclude"),
+ "Error should name the offending key");
+ assertTrue(e.getMessage().contains("default-parser"),
+ "Error should name the marker");
+ }
+ } finally {
+ Files.deleteIfExists(tempFile);
+ }
+ }
+ @Test
+ public void testMimeFilterDecoratorsAllowedOnDefaultParser() throws Exception {
+ // default-parser accepts the framework-level mime-filter decorators
+ // (_mime-include / _mime-exclude). These must NOT be rejected by
+ // strict-marker-key validation. (TIKA-4739)
+ String config = """
+ {
+ "parsers": [
+ {
+ "default-parser": {
+ "exclude": [],
+ "_mime-include": ["application/pdf"]
+ }
+ }
+ ]
+ }
+ """;
+
+ Path tempFile = Files.createTempFile("test-mime-include", ".json");
+ try {
+ Files.write(tempFile, config.getBytes(StandardCharsets.UTF_8));
+ TikaLoader loader = TikaLoader.load(tempFile);
+ Parser parser = loader.loadParsers();
+ assertNotNull(parser, "_mime-include on default-parser must load successfully");
+ } finally {
+ Files.deleteIfExists(tempFile);
+ }
+ }
+
+ @Test
+ public void testMimeFilterDecoratorRejectedOnDefaultDetector() throws Exception {
+ // _mime-include is only meaningful on parsers (it restricts which mime
+ // types a parser handles). On detectors it has no consumer, so strict
+ // validation rejects it rather than silently ignore. (TIKA-4739)
+ String config = """
+ {
+ "detectors": [
+ {
+ "default-detector": {
+ "_mime-include": ["application/pdf"]
+ }
+ }
+ ]
+ }
+ """;
+
+ Path tempFile = Files.createTempFile("test-mime-include-detector", ".json");
+ try {
+ Files.write(tempFile, config.getBytes(StandardCharsets.UTF_8));
TikaLoader loader = TikaLoader.load(tempFile);
try {
loader.loadDetectors();
- throw new AssertionError("Expected TikaConfigException for invalid property");
+ throw new AssertionError(
+ "Expected TikaConfigException for _mime-include on default-detector");
} catch (org.apache.tika.exception.TikaConfigException e) {
- // Expected - Jackson should fail on unknown property
- assertTrue(e.getMessage().contains("nonExistentProperty") ||
- e.getCause().getMessage().contains("nonExistentProperty"),
- "Error should mention the invalid property name");
+ assertTrue(e.getMessage().contains("_mime-include"),
+ "Error should name the offending key");
}
} finally {
Files.deleteIfExists(tempFile);