You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tika.apache.org by ta...@apache.org on 2025/11/25 20:46:36 UTC
(tika) branch main updated: TIKA-4545 -- propagate annotation through parsers and improve TikaLoader (#2404)
This is an automated email from the ASF dual-hosted git repository.
tallison pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tika.git
The following commit(s) were added to refs/heads/main by this push:
new e9d8d3182 TIKA-4545 -- propagate annotation through parsers and improve TikaLoader (#2404)
e9d8d3182 is described below
commit e9d8d31821e044dbb7fd68152d8a3c072f1336b7
Author: Tim Allison <ta...@apache.org>
AuthorDate: Tue Nov 25 15:46:31 2025 -0500
TIKA-4545 -- propagate annotation through parsers and improve TikaLoader (#2404)
* TIKA-4545 -- baseline improvements to support integration
Generated-by: Claude Sonnet 4.5 (claude-sonnet-4-5-20250929)
Significant design and implementation on ConfigLoader with Claude
Other commits were fully human or with light assist
---
tika-annotation-processor/pom.xml | 9 -
.../tika/annotation/TikaComponentProcessor.java | 38 +-
.../java/org/apache/tika/config/TikaComponent.java | 5 +-
tika-core/pom.xml | 22 +
.../org/apache/tika/parser/AutoDetectParser.java | 10 +
.../org/apache/tika/parser/CompositeParser.java | 4 +
tika-parsers/pom.xml | 26 +
.../apache/tika/parser/envi/EnviHeaderParser.java | 2 +
.../org/apache/tika/parser/gdal/GDALParser.java | 2 +
.../geoinfo/GeographicInformationParser.java | 3 +-
.../org/apache/tika/parser/grib/GribParser.java | 2 +
.../java/org/apache/tika/parser/hdf/HDFParser.java | 2 +
.../apache/tika/parser/isatab/ISArchiveParser.java | 2 +
.../apache/tika/parser/netcdf/NetCDFParser.java | 2 +
.../services/org.apache.tika.parser.Parser | 23 -
.../apache/tika/parser/geopkg/GeoPkgParser.java | 2 +
.../apache/tika/parser/sqlite3/SQLite3Parser.java | 2 +
.../services/org.apache.tika.parser.Parser | 17 -
.../apache/tika/parser/geo/topic/GeoParser.java | 2 +
.../tika/parser/journal/GrobidRESTParser.java | 2 +
.../apache/tika/parser/journal/JournalParser.java | 2 +
.../parser/sentiment/SentimentAnalysisParser.java | 2 +
.../services/org.apache.tika.parser.Parser | 18 -
.../parser/transcribe/aws/AmazonTranscribe.java | 2 +
.../apache/tika/detect/apple/BPListDetector.java | 2 +
.../tika/parser/apple/AppleSingleFileParser.java | 2 +
.../org/apache/tika/parser/apple/PListParser.java | 2 +
.../tika/parser/iwork/IWorkPackageParser.java | 2 +
.../parser/iwork/iwana/IWork13PackageParser.java | 2 +
.../parser/iwork/iwana/IWork18PackageParser.java | 2 +
.../services/org.apache.tika.detect.Detector | 16 -
.../services/org.apache.tika.parser.Parser | 22 -
.../org/apache/tika/detect/MatroskaDetector.java | 2 +
.../org/apache/tika/parser/audio/AudioParser.java | 2 +
.../org/apache/tika/parser/audio/MidiParser.java | 2 +
.../java/org/apache/tika/parser/mp3/Mp3Parser.java | 2 +
.../java/org/apache/tika/parser/mp4/MP4Parser.java | 2 +
.../org/apache/tika/parser/video/FLVParser.java | 2 +
.../services/org.apache.tika.detect.Detector | 16 -
.../services/org.apache.tika.parser.Parser | 22 -
.../org/apache/tika/parser/dgn/DGN8Parser.java | 2 +
.../java/org/apache/tika/parser/dwg/DWGParser.java | 2 +
.../org/apache/tika/parser/dwg/DWGReadParser.java | 3 +-
.../java/org/apache/tika/parser/prt/PRTParser.java | 3 +-
.../services/org.apache.tika.parser.Parser | 19 -
.../org/apache/tika/parser/asm/ClassParser.java | 2 +
.../apache/tika/parser/code/SourceCodeParser.java | 2 +
.../tika/parser/executable/ExecutableParser.java | 2 +
.../executable/UniversalExecutableParser.java | 2 +
.../java/org/apache/tika/parser/mat/MatParser.java | 3 +-
.../org/apache/tika/parser/sas/SAS7BDATParser.java | 2 +
.../services/org.apache.tika.parser.Parser | 22 -
.../org/apache/tika/parser/crypto/Pkcs7Parser.java | 2 +
.../org/apache/tika/parser/crypto/TSDParser.java | 2 +
.../services/org.apache.tika.parser.Parser | 17 -
.../tika/parser/font/AdobeFontMetricParser.java | 2 +
.../apache/tika/parser/font/TrueTypeParser.java | 2 +
.../services/org.apache.tika.parser.Parser | 18 -
.../tika/parser/html/HtmlEncodingDetector.java | 2 +
.../org/apache/tika/parser/html/JSoupParser.java | 2 +
.../StandardHtmlEncodingDetector.java | 2 +
.../org.apache.tika.detect.EncodingDetector | 6 +-
.../services/org.apache.tika.parser.Parser | 15 -
.../org/apache/tika/parser/image/BPGParser.java | 2 +
.../org/apache/tika/parser/image/HeifParser.java | 2 +
.../org/apache/tika/parser/image/ICNSParser.java | 2 +
.../org/apache/tika/parser/image/ImageParser.java | 2 +
.../org/apache/tika/parser/image/JXLParser.java | 2 +
.../org/apache/tika/parser/image/JpegParser.java | 2 +
.../org/apache/tika/parser/image/PSDParser.java | 2 +
.../org/apache/tika/parser/image/TiffParser.java | 2 +
.../org/apache/tika/parser/image/WebPParser.java | 3 +-
.../services/org.apache.tika.parser.Parser | 26 -
.../org/apache/tika/parser/mail/RFC822Parser.java | 2 +
.../org/apache/tika/parser/mbox/MboxParser.java | 2 +
.../services/org.apache.tika.parser.Parser | 19 -
.../detect/microsoft/POIFSContainerDetector.java | 2 +
.../apache/tika/parser/microsoft/EMFParser.java | 2 +
.../tika/parser/microsoft/JackcessParser.java | 2 +
.../tika/parser/microsoft/MSOwnerFileParser.java | 2 +
.../apache/tika/parser/microsoft/OfficeParser.java | 2 +
.../tika/parser/microsoft/OldExcelParser.java | 2 +
.../apache/tika/parser/microsoft/TNEFParser.java | 2 +
.../apache/tika/parser/microsoft/WMFParser.java | 2 +
.../microsoft/activemime/ActiveMimeParser.java | 2 +
.../tika/parser/microsoft/chm/ChmParser.java | 2 +
.../tika/parser/microsoft/libpst/LibPstParser.java | 2 +
.../parser/microsoft/onenote/OneNoteParser.java | 2 +
.../tika/parser/microsoft/ooxml/OOXMLParser.java | 2 +
.../ooxml/xwpf/ml2006/Word2006MLParser.java | 3 +-
.../parser/microsoft/pst/OutlookPSTParser.java | 2 +
.../parser/microsoft/pst/PSTMailItemParser.java | 2 +
.../tika/parser/microsoft/rtf/RTFParser.java | 2 +
.../parser/microsoft/xml/SpreadsheetMLParser.java | 2 +
.../tika/parser/microsoft/xml/WordMLParser.java | 2 +
.../services/org.apache.tika.detect.Detector | 16 -
.../services/org.apache.tika.parser.Parser | 31 -
.../apache/tika/detect/ole/MiscOLEDetector.java | 2 +
.../java/org/apache/tika/parser/dbf/DBFParser.java | 2 +
.../java/org/apache/tika/parser/dif/DIFParser.java | 2 +
.../org/apache/tika/parser/epub/EpubParser.java | 2 +
.../org/apache/tika/parser/hwp/HwpV5Parser.java | 2 +
.../apache/tika/parser/indesign/IDMLParser.java | 2 +
.../java/org/apache/tika/parser/mif/MIFParser.java | 2 +
.../tika/parser/odf/FlatOpenDocumentParser.java | 2 +
.../apache/tika/parser/odf/OpenDocumentParser.java | 2 +
.../tika/parser/wordperfect/QuattroProParser.java | 2 +
.../tika/parser/wordperfect/WordPerfectParser.java | 2 +
.../services/org.apache.tika.detect.Detector | 16 -
.../services/org.apache.tika.parser.Parser | 24 -
.../org/apache/tika/parser/feed/FeedParser.java | 2 +
.../apache/tika/parser/iptc/IptcAnpaParser.java | 2 +
.../services/org.apache.tika.parser.Parser | 17 -
.../apache/tika/parser/ocr/TesseractOCRParser.java | 2 +
.../services/org.apache.tika.parser.Parser | 15 -
.../java/org/apache/tika/parser/pdf/PDFParser.java | 2 +
.../services/org.apache.tika.parser.Parser | 15 -
.../detect/gzip/GZipSpecializationDetector.java | 2 +
.../apache/tika/parser/pkg/CompressorParser.java | 2 +
.../org/apache/tika/parser/pkg/PackageParser.java | 2 +
.../java/org/apache/tika/parser/pkg/RarParser.java | 2 +
.../org/apache/tika/parser/pkg/UnrarParser.java | 2 +
.../services/org.apache.tika.detect.Detector | 16 -
.../services/org.apache.tika.parser.Parser | 18 -
.../apache/tika/parser/csv/TextAndCSVParser.java | 2 +
.../tika/parser/strings/Latin1StringsParser.java | 2 +
.../apache/tika/parser/strings/StringsParser.java | 2 +
.../org/apache/tika/parser/txt/BOMDetector.java | 5 +
.../tika/parser/txt/Icu4jEncodingDetector.java | 2 +
.../java/org/apache/tika/parser/txt/TXTParser.java | 2 +
.../tika/parser/txt/UniversalEncodingDetector.java | 2 +
.../org.apache.tika.detect.EncodingDetector | 4 +
.../services/org.apache.tika.parser.Parser | 22 -
.../org/apache/tika/parser/http/HttpParser.java | 2 +
.../org/apache/tika/parser/wacz/WACZParser.java | 2 +
.../org/apache/tika/parser/warc/WARCParser.java | 2 +
.../services/org.apache.tika.parser.Parser | 19 -
.../java/org/apache/tika/parser/tmx/TMXParser.java | 2 +
.../apache/tika/parser/xliff/XLIFF12Parser.java | 2 +
.../org/apache/tika/parser/xliff/XLZParser.java | 2 +
.../org/apache/tika/parser/xml/DcXMLParser.java | 2 +
.../apache/tika/parser/xml/FictionBookParser.java | 2 +
.../java/org/apache/tika/parser/xml/XMLParser.java | 2 +
.../org/apache/tika/parser/xml/XMLProfiler.java | 2 +
.../services/org.apache.tika.parser.Parser | 22 -
.../detect/zip/DefaultZipContainerDetector.java | 2 +
.../services/org.apache.tika.detect.Detector | 16 -
...org.apache.tika.detect.zip.ZipContainerDetector | 2 +
.../tika-parsers-standard-package/pom.xml | 11 +
.../config/ComponentRegistryIntegrationTest.java | 299 ++++++++++
.../test/resources/configs/test-dc-xml-parser.json | 5 +
.../resources/configs/test-default-parser.json | 5 +
.../configs/test-default-with-exclusions.json | 9 +
.../src/test/resources/configs/test-detectors.json | 5 +
.../resources/configs/test-specific-parsers.json | 7 +
tika-serialization/pom.xml | 20 +
.../apache/tika/config/loader/ConfigLoader.java | 349 +++++++++++
.../tika/config/loader/KebabCaseConverter.java | 72 +++
.../apache/tika/config/loader/ParserLoader.java | 2 +
.../apache/tika/config/loader/TikaJsonConfig.java | 21 +-
.../org/apache/tika/config/loader/TikaLoader.java | 35 ++
.../tika/config/loader/ConfigLoaderTest.java | 646 +++++++++++++++++++++
.../services/org.apache.tika.parser.Parser | 4 -
.../src/test/resources/META-INF/tika/parsers.idx | 5 -
.../test/resources/configs/test-config-loader.json | 32 +
.../resources/configs/test-interface-no-type.json | 6 +
.../test/resources/configs/test-invalid-class.json | 3 +
.../resources/configs/test-partial-config.json | 15 +
.../resources/configs/test-unexpected-field.json | 8 +
.../test/resources/configs/test-wrong-type.json | 3 +
170 files changed, 1889 insertions(+), 547 deletions(-)
diff --git a/tika-annotation-processor/pom.xml b/tika-annotation-processor/pom.xml
index 9c93eb9ac..459dc4ea6 100644
--- a/tika-annotation-processor/pom.xml
+++ b/tika-annotation-processor/pom.xml
@@ -37,15 +37,6 @@
</description>
<url>https://tika.apache.org</url>
- <dependencies>
- <dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>tika-core</artifactId>
- <version>${project.version}</version>
- <scope>provided</scope>
- </dependency>
- </dependencies>
-
<build>
<plugins>
<plugin>
diff --git a/tika-annotation-processor/src/main/java/org/apache/tika/annotation/TikaComponentProcessor.java b/tika-annotation-processor/src/main/java/org/apache/tika/annotation/TikaComponentProcessor.java
index f37ac1e3f..a9a2254c9 100644
--- a/tika-annotation-processor/src/main/java/org/apache/tika/annotation/TikaComponentProcessor.java
+++ b/tika-annotation-processor/src/main/java/org/apache/tika/annotation/TikaComponentProcessor.java
@@ -19,6 +19,7 @@ package org.apache.tika.annotation;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
@@ -54,7 +55,7 @@ import org.apache.tika.config.TikaComponent;
* to avoid generating SPI files for utility interfaces like Serializable, Initializable, etc.
*/
@SupportedAnnotationTypes("org.apache.tika.config.TikaComponent")
-@SupportedSourceVersion(SourceVersion.RELEASE_11)
+@SupportedSourceVersion(SourceVersion.RELEASE_17)
public class TikaComponentProcessor extends AbstractProcessor {
/**
@@ -145,7 +146,7 @@ public class TikaComponentProcessor extends AbstractProcessor {
.add(className);
}
- // Always add to index files (regardless of SPI setting)
+ // Always add to index files for name-based lookup, regardless of spi value
String indexFileName = SERVICE_INTERFACES.get(serviceInterface);
if (indexFileName != null) {
Map<String, String> index = indexFiles.computeIfAbsent(indexFileName,
@@ -219,14 +220,20 @@ public class TikaComponentProcessor extends AbstractProcessor {
String serviceInterface = entry.getKey();
Set<String> implementations = entry.getValue();
+ // Sort implementations alphabetically for deterministic output
+ List<String> sortedImplementations = new ArrayList<>(implementations);
+ Collections.sort(sortedImplementations);
+
try {
FileObject file = filer.createResource(StandardLocation.CLASS_OUTPUT, "",
"META-INF/services/" + serviceInterface);
try (Writer writer = file.openWriter()) {
+ writeApacheLicenseHeader(writer);
+ writer.write("\n\n");
writer.write("# Generated by TikaComponentProcessor\n");
writer.write("# Do not edit manually\n");
- for (String impl : implementations) {
+ for (String impl : sortedImplementations) {
writer.write(impl);
writer.write("\n");
}
@@ -256,6 +263,7 @@ public class TikaComponentProcessor extends AbstractProcessor {
"META-INF/tika/" + fileName + ".idx");
try (Writer writer = file.openWriter()) {
+ writeApacheLicenseHeader(writer);
writer.write("# Generated by TikaComponentProcessor\n");
writer.write("# Do not edit manually\n");
writer.write("# Format: component-name=fully.qualified.ClassName\n");
@@ -277,4 +285,28 @@ public class TikaComponentProcessor extends AbstractProcessor {
}
}
}
+
+ /**
+ * Writes the Apache License 2.0 header to a file.
+ */
+ private void writeApacheLicenseHeader(Writer writer) throws IOException {
+ String header = """
+ # 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.
+
+ """;
+ writer.write(header);
+ }
}
diff --git a/tika-core/src/main/java/org/apache/tika/config/TikaComponent.java b/tika-annotation-processor/src/main/java/org/apache/tika/config/TikaComponent.java
similarity index 93%
rename from tika-core/src/main/java/org/apache/tika/config/TikaComponent.java
rename to tika-annotation-processor/src/main/java/org/apache/tika/config/TikaComponent.java
index 8696ab2db..6632bdeb7 100644
--- a/tika-core/src/main/java/org/apache/tika/config/TikaComponent.java
+++ b/tika-annotation-processor/src/main/java/org/apache/tika/config/TikaComponent.java
@@ -34,6 +34,9 @@ import java.lang.annotation.Target;
* <li>Component index files (META-INF/tika/{type}.idx) for name-based lookup</li>
* </ul>
*
+ * <p>This annotation is only used at compile time by the annotation processor.
+ * It is retained in .class files for tooling but not loaded by the runtime JVM.
+ *
* <p>Example usage:
* <pre>
* {@code @TikaComponent}
@@ -54,7 +57,7 @@ import java.lang.annotation.Target;
*
* @since 3.1.0
*/
-@Retention(RetentionPolicy.RUNTIME)
+@Retention(RetentionPolicy.CLASS)
@Target(ElementType.TYPE)
public @interface TikaComponent {
diff --git a/tika-core/pom.xml b/tika-core/pom.xml
index e0c408e34..5a12c4e3a 100644
--- a/tika-core/pom.xml
+++ b/tika-core/pom.xml
@@ -64,6 +64,15 @@
<scope>provided</scope>
</dependency>
+ <!-- Annotation processor - contains @TikaComponent and ensures build order.
+ "provided" because it is only used at compile time -->
+ <dependency>
+ <groupId>org.apache.tika</groupId>
+ <artifactId>tika-annotation-processor</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
<!-- Test dependencies -->
<dependency>
<groupId>com.google.guava</groupId>
@@ -130,6 +139,19 @@
</execution>
</executions>
</plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <annotationProcessorPaths>
+ <path>
+ <groupId>org.apache.tika</groupId>
+ <artifactId>tika-annotation-processor</artifactId>
+ <version>${project.version}</version>
+ </path>
+ </annotationProcessorPaths>
+ </configuration>
+ </plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
diff --git a/tika-core/src/main/java/org/apache/tika/parser/AutoDetectParser.java b/tika-core/src/main/java/org/apache/tika/parser/AutoDetectParser.java
index 86eae692a..7fd9e0b0b 100644
--- a/tika-core/src/main/java/org/apache/tika/parser/AutoDetectParser.java
+++ b/tika-core/src/main/java/org/apache/tika/parser/AutoDetectParser.java
@@ -90,6 +90,16 @@ public class AutoDetectParser extends CompositeParser {
setAutoDetectParserConfig(AutoDetectParserConfig.DEFAULT);
}
+ public AutoDetectParser(CompositeParser parser, Detector detector, AutoDetectParserConfig autoDetectParserConfig) {
+ super(parser);
+ setDetector(detector);
+ setAutoDetectParserConfig(autoDetectParserConfig);
+ }
+
+ public static Parser build(CompositeParser parser, Detector detector, AutoDetectParserConfig autoDetectParserConfig) {
+ return new AutoDetectParser(parser, detector, autoDetectParserConfig);
+ }
+
public AutoDetectParser(TikaConfig config) {
super(config.getMediaTypeRegistry(), getParser(config));
setFallback(buildFallbackParser(config));
diff --git a/tika-core/src/main/java/org/apache/tika/parser/CompositeParser.java b/tika-core/src/main/java/org/apache/tika/parser/CompositeParser.java
index 3b50b4da7..b3aaebf7a 100644
--- a/tika-core/src/main/java/org/apache/tika/parser/CompositeParser.java
+++ b/tika-core/src/main/java/org/apache/tika/parser/CompositeParser.java
@@ -97,6 +97,10 @@ public class CompositeParser implements Parser {
this(new MediaTypeRegistry());
}
+ public CompositeParser(CompositeParser compositeParser) {
+ this(compositeParser.registry, compositeParser);
+ }
+
public Map<MediaType, Parser> getParsers(ParseContext context) {
Map<MediaType, Parser> map = new HashMap<>();
for (Parser parser : parsers) {
diff --git a/tika-parsers/pom.xml b/tika-parsers/pom.xml
index 0b078ac05..1985a044c 100644
--- a/tika-parsers/pom.xml
+++ b/tika-parsers/pom.xml
@@ -41,6 +41,14 @@
</modules>
<dependencies>
+ <!-- Annotation processor - contains @TikaComponent and ensures build order.
+ "provided" because it is only used at compile time -->
+ <dependency>
+ <groupId>org.apache.tika</groupId>
+ <artifactId>tika-annotation-processor</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
<!-- test dependencies -->
<dependency>
<groupId>org.junit.jupiter</groupId>
@@ -93,6 +101,24 @@
</execution>
</executions>
</plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <annotationProcessorPaths>
+ <path>
+ <groupId>org.apache.tika</groupId>
+ <artifactId>tika-annotation-processor</artifactId>
+ <version>${project.version}</version>
+ </path>
+ <path>
+ <groupId>org.apache.tika</groupId>
+ <artifactId>tika-core</artifactId>
+ <version>${project.version}</version>
+ </path>
+ </annotationProcessorPaths>
+ </configuration>
+ </plugin>
<plugin>
<groupId>org.apache.rat</groupId>
<artifactId>apache-rat-plugin</artifactId>
diff --git a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/envi/EnviHeaderParser.java b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/envi/EnviHeaderParser.java
index 483e258d7..abedbb89d 100644
--- a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/envi/EnviHeaderParser.java
+++ b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/envi/EnviHeaderParser.java
@@ -31,6 +31,7 @@ import org.slf4j.LoggerFactory;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.detect.AutoDetectReader;
import org.apache.tika.detect.EncodingDetector;
import org.apache.tika.exception.TikaException;
@@ -40,6 +41,7 @@ import org.apache.tika.parser.AbstractEncodingDetectorParser;
import org.apache.tika.parser.ParseContext;
import org.apache.tika.sax.XHTMLContentHandler;
+@TikaComponent
public class EnviHeaderParser extends AbstractEncodingDetectorParser {
public static final String ENVI_MIME_TYPE = "application/envi.hdr";
diff --git a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/gdal/GDALParser.java b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/gdal/GDALParser.java
index 1ba196942..11f0c2862 100644
--- a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/gdal/GDALParser.java
+++ b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/gdal/GDALParser.java
@@ -41,6 +41,7 @@ import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.apache.tika.config.Field;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.config.TikaTaskTimeout;
import org.apache.tika.exception.TikaException;
import org.apache.tika.io.TemporaryResources;
@@ -74,6 +75,7 @@ import org.apache.tika.utils.ProcessUtils;
* {@link ContentHandler} in the
* {@link #parse(InputStream, ContentHandler, Metadata, ParseContext)} method.
*/
+@TikaComponent
public class GDALParser implements Parser {
private static final long serialVersionUID = -3869130527323941401L;
diff --git a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/geoinfo/GeographicInformationParser.java b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/geoinfo/GeographicInformationParser.java
index beabe6593..0af28f924 100644
--- a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/geoinfo/GeographicInformationParser.java
+++ b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/geoinfo/GeographicInformationParser.java
@@ -61,6 +61,7 @@ import org.slf4j.LoggerFactory;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.io.TemporaryResources;
import org.apache.tika.io.TikaInputStream;
@@ -71,7 +72,7 @@ import org.apache.tika.parser.Parser;
import org.apache.tika.sax.XHTMLContentHandler;
import org.apache.tika.utils.DateUtils;
-
+@TikaComponent
public class GeographicInformationParser implements Parser {
public static final String geoInfoType = "text/iso19139+xml";
diff --git a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/grib/GribParser.java b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/grib/GribParser.java
index b974a481e..60f9e9bee 100644
--- a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/grib/GribParser.java
+++ b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/grib/GribParser.java
@@ -34,6 +34,7 @@ import ucar.nc2.NetcdfFile;
import ucar.nc2.Variable;
import ucar.nc2.dataset.NetcdfDataset;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.metadata.Property;
@@ -43,6 +44,7 @@ import org.apache.tika.parser.ParseContext;
import org.apache.tika.parser.Parser;
import org.apache.tika.sax.XHTMLContentHandler;
+@TikaComponent
public class GribParser implements Parser {
public static final String GRIB_MIME_TYPE = "application/x-grib2";
diff --git a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/hdf/HDFParser.java b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/hdf/HDFParser.java
index 14098f3b6..06e163a56 100644
--- a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/hdf/HDFParser.java
+++ b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/hdf/HDFParser.java
@@ -32,6 +32,7 @@ import ucar.nc2.Attribute;
import ucar.nc2.Group;
import ucar.nc2.NetcdfFile;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.metadata.TikaCoreProperties;
@@ -48,6 +49,7 @@ import org.apache.tika.sax.XHTMLContentHandler;
* "http://www.unidata.ucar.edu/software/netcdf-java/formats/FileTypes.html"
* >this link</a> for more information.
*/
+@TikaComponent
public class HDFParser implements Parser {
/**
diff --git a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/isatab/ISArchiveParser.java b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/isatab/ISArchiveParser.java
index 6c7975f82..8c0777b68 100644
--- a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/isatab/ISArchiveParser.java
+++ b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/isatab/ISArchiveParser.java
@@ -25,6 +25,7 @@ import java.util.Set;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.io.TemporaryResources;
import org.apache.tika.io.TikaInputStream;
@@ -34,6 +35,7 @@ import org.apache.tika.parser.ParseContext;
import org.apache.tika.parser.Parser;
import org.apache.tika.sax.XHTMLContentHandler;
+@TikaComponent
public class ISArchiveParser implements Parser {
/**
diff --git a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/netcdf/NetCDFParser.java b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/netcdf/NetCDFParser.java
index 9f4ef020c..464ea6803 100644
--- a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/netcdf/NetCDFParser.java
+++ b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/netcdf/NetCDFParser.java
@@ -31,6 +31,7 @@ import ucar.nc2.Dimension;
import ucar.nc2.NetcdfFile;
import ucar.nc2.Variable;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.io.TemporaryResources;
import org.apache.tika.io.TikaInputStream;
@@ -49,6 +50,7 @@ import org.apache.tika.sax.XHTMLContentHandler;
* href="http://www.unidata.ucar.edu/software/netcdf-java/">NetCDF for Java</a>
* API.
*/
+@TikaComponent
public class NetCDFParser implements Parser {
/**
diff --git a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser
deleted file mode 100644
index e8f355d3b..000000000
--- a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser
+++ /dev/null
@@ -1,23 +0,0 @@
-# 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.
-
-org.apache.tika.parser.envi.EnviHeaderParser
-org.apache.tika.parser.hdf.HDFParser
-org.apache.tika.parser.netcdf.NetCDFParser
-org.apache.tika.parser.gdal.GDALParser
-org.apache.tika.parser.grib.GribParser
-org.apache.tika.parser.isatab.ISArchiveParser
-org.apache.tika.parser.geoinfo.GeographicInformationParser
-org.apache.tika.parser.external.CompositeExternalParser
diff --git a/tika-parsers/tika-parsers-extended/tika-parser-sqlite3-module/src/main/java/org/apache/tika/parser/geopkg/GeoPkgParser.java b/tika-parsers/tika-parsers-extended/tika-parser-sqlite3-module/src/main/java/org/apache/tika/parser/geopkg/GeoPkgParser.java
index e157a09c9..358c03c67 100644
--- a/tika-parsers/tika-parsers-extended/tika-parser-sqlite3-module/src/main/java/org/apache/tika/parser/geopkg/GeoPkgParser.java
+++ b/tika-parsers/tika-parsers-extended/tika-parser-sqlite3-module/src/main/java/org/apache/tika/parser/geopkg/GeoPkgParser.java
@@ -31,6 +31,7 @@ import org.xml.sax.SAXException;
import org.apache.tika.config.Field;
import org.apache.tika.config.InitializableProblemHandler;
import org.apache.tika.config.Param;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaConfigException;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
@@ -65,6 +66,7 @@ import org.apache.tika.parser.sqlite3.SQLite3Parser;
* <p>
* Or use an empty list to parse all columns.
*/
+@TikaComponent
public class GeoPkgParser extends SQLite3Parser {
/**
diff --git a/tika-parsers/tika-parsers-extended/tika-parser-sqlite3-module/src/main/java/org/apache/tika/parser/sqlite3/SQLite3Parser.java b/tika-parsers/tika-parsers-extended/tika-parser-sqlite3-module/src/main/java/org/apache/tika/parser/sqlite3/SQLite3Parser.java
index 34aab4d10..174be66ea 100644
--- a/tika-parsers/tika-parsers-extended/tika-parser-sqlite3-module/src/main/java/org/apache/tika/parser/sqlite3/SQLite3Parser.java
+++ b/tika-parsers/tika-parsers-extended/tika-parser-sqlite3-module/src/main/java/org/apache/tika/parser/sqlite3/SQLite3Parser.java
@@ -29,6 +29,7 @@ import org.xml.sax.SAXException;
import org.apache.tika.config.Initializable;
import org.apache.tika.config.InitializableProblemHandler;
import org.apache.tika.config.Param;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaConfigException;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
@@ -53,6 +54,7 @@ import org.apache.tika.parser.Parser;
* If using a TikaInputStream, make sure to close it to delete the temp file
* that has to be created.
*/
+@TikaComponent
public class SQLite3Parser implements Parser, Initializable {
public static final String SQLITE3_PREFIX = "sqlite3:";
diff --git a/tika-parsers/tika-parsers-extended/tika-parser-sqlite3-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser b/tika-parsers/tika-parsers-extended/tika-parser-sqlite3-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser
deleted file mode 100644
index 14509c812..000000000
--- a/tika-parsers/tika-parsers-extended/tika-parser-sqlite3-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser
+++ /dev/null
@@ -1,17 +0,0 @@
-# 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.
-
-org.apache.tika.parser.geopkg.GeoPkgParser
-org.apache.tika.parser.sqlite3.SQLite3Parser
diff --git a/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/main/java/org/apache/tika/parser/geo/topic/GeoParser.java b/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/main/java/org/apache/tika/parser/geo/topic/GeoParser.java
index cfa52e7e2..164874555 100644
--- a/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/main/java/org/apache/tika/parser/geo/topic/GeoParser.java
+++ b/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/main/java/org/apache/tika/parser/geo/topic/GeoParser.java
@@ -36,6 +36,7 @@ import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.apache.tika.config.Field;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.mime.MediaType;
@@ -44,6 +45,7 @@ import org.apache.tika.parser.Parser;
import org.apache.tika.parser.geo.topic.gazetteer.GeoGazetteerClient;
import org.apache.tika.parser.geo.topic.gazetteer.Location;
+@TikaComponent
public class GeoParser implements Parser {
private static final long serialVersionUID = -2241391757440215491L;
private static final Logger LOG = LoggerFactory.getLogger(GeoParser.class);
diff --git a/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/main/java/org/apache/tika/parser/journal/GrobidRESTParser.java b/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/main/java/org/apache/tika/parser/journal/GrobidRESTParser.java
index 08968989e..c7b9e5ad1 100644
--- a/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/main/java/org/apache/tika/parser/journal/GrobidRESTParser.java
+++ b/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/main/java/org/apache/tika/parser/journal/GrobidRESTParser.java
@@ -33,10 +33,12 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.ContentHandler;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.parser.ParseContext;
+@TikaComponent
public class GrobidRESTParser {
private static final Logger LOG = LoggerFactory.getLogger(GrobidRESTParser.class);
diff --git a/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/main/java/org/apache/tika/parser/journal/JournalParser.java b/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/main/java/org/apache/tika/parser/journal/JournalParser.java
index 92f3fffae..c16049d99 100644
--- a/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/main/java/org/apache/tika/parser/journal/JournalParser.java
+++ b/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/main/java/org/apache/tika/parser/journal/JournalParser.java
@@ -27,6 +27,7 @@ import java.util.Set;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.io.TemporaryResources;
import org.apache.tika.io.TikaInputStream;
@@ -36,6 +37,7 @@ import org.apache.tika.parser.ParseContext;
import org.apache.tika.parser.Parser;
import org.apache.tika.parser.pdf.PDFParser;
+@TikaComponent
public class JournalParser implements Parser {
/**
diff --git a/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/main/java/org/apache/tika/parser/sentiment/SentimentAnalysisParser.java b/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/main/java/org/apache/tika/parser/sentiment/SentimentAnalysisParser.java
index c6fd5597c..775b8836e 100644
--- a/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/main/java/org/apache/tika/parser/sentiment/SentimentAnalysisParser.java
+++ b/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/main/java/org/apache/tika/parser/sentiment/SentimentAnalysisParser.java
@@ -37,6 +37,7 @@ import org.apache.tika.config.Field;
import org.apache.tika.config.Initializable;
import org.apache.tika.config.InitializableProblemHandler;
import org.apache.tika.config.Param;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaConfigException;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
@@ -48,6 +49,7 @@ import org.apache.tika.parser.Parser;
* This parser classifies documents based on the sentiment of document.
* The classifier is powered by Apache OpenNLP's Maximum Entropy Classifier
*/
+@TikaComponent(spi = false)
public class SentimentAnalysisParser implements Parser, Initializable {
public static final String DEF_MODEL =
diff --git a/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser b/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser
deleted file mode 100644
index 76fcbfed8..000000000
--- a/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser
+++ /dev/null
@@ -1,18 +0,0 @@
-# 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.
-
-org.apache.tika.parser.geo.topic.GeoParser
-org.apache.tika.parser.journal.JournalParser
-org.apache.tika.parser.sentiment.SentimentAnalysisParser
\ No newline at end of file
diff --git a/tika-parsers/tika-parsers-ml/tika-transcribe-aws/src/main/java/org/apache/tika/parser/transcribe/aws/AmazonTranscribe.java b/tika-parsers/tika-parsers-ml/tika-transcribe-aws/src/main/java/org/apache/tika/parser/transcribe/aws/AmazonTranscribe.java
index 2d5215cd6..67a02bf55 100644
--- a/tika-parsers/tika-parsers-ml/tika-transcribe-aws/src/main/java/org/apache/tika/parser/transcribe/aws/AmazonTranscribe.java
+++ b/tika-parsers/tika-parsers-ml/tika-transcribe-aws/src/main/java/org/apache/tika/parser/transcribe/aws/AmazonTranscribe.java
@@ -67,6 +67,7 @@ import org.apache.tika.config.Field;
import org.apache.tika.config.Initializable;
import org.apache.tika.config.InitializableProblemHandler;
import org.apache.tika.config.Param;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaConfigException;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
@@ -88,6 +89,7 @@ import org.apache.tika.sax.XHTMLContentHandler;
* @since Tika 2.0
*/
+@TikaComponent
public class AmazonTranscribe implements Parser, Initializable {
private static final Logger LOG = LoggerFactory.getLogger(AmazonTranscribe.class);
private TranscribeAsyncClient amazonTranscribeAsync;
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/detect/apple/BPListDetector.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/detect/apple/BPListDetector.java
index bdbd19ccb..35244435f 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/detect/apple/BPListDetector.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/detect/apple/BPListDetector.java
@@ -31,6 +31,7 @@ import com.dd.plist.PropertyListParser;
import org.apache.commons.io.IOUtils;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.detect.Detector;
import org.apache.tika.io.TikaInputStream;
import org.apache.tika.metadata.Metadata;
@@ -45,6 +46,7 @@ import org.apache.tika.mime.MediaType;
*
* @since 1.25
*/
+@TikaComponent
public class BPListDetector implements Detector {
//xml versions
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/parser/apple/AppleSingleFileParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/parser/apple/AppleSingleFileParser.java
index d97ed1ba7..87b1b8b6e 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/parser/apple/AppleSingleFileParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/parser/apple/AppleSingleFileParser.java
@@ -29,6 +29,7 @@ import org.apache.commons.io.IOUtils;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.exception.TikaMemoryLimitException;
import org.apache.tika.extractor.EmbeddedDocumentExtractor;
@@ -49,6 +50,7 @@ import org.apache.tika.sax.XHTMLContentHandler;
* <p>
* See <a href="http://kaiser-edv.de/documents/AppleSingle_AppleDouble.pdf">spec document</a>.
*/
+@TikaComponent
public class AppleSingleFileParser implements Parser {
private static final int MAX_FIELD_LENGTH = 1_073_741_824;
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/parser/apple/PListParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/parser/apple/PListParser.java
index e90324ba2..66ff971bd 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/parser/apple/PListParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/parser/apple/PListParser.java
@@ -43,6 +43,7 @@ import com.dd.plist.UID;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.detect.apple.BPListDetector;
import org.apache.tika.exception.TikaException;
import org.apache.tika.extractor.EmbeddedDocumentExtractor;
@@ -63,6 +64,7 @@ import org.apache.tika.sax.XHTMLContentHandler;
*
* @since 1.25
*/
+@TikaComponent
public class PListParser implements Parser {
private static final String ARR = "array";
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/parser/iwork/IWorkPackageParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/parser/iwork/IWorkPackageParser.java
index 87074304f..8af51bce9 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/parser/iwork/IWorkPackageParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/parser/iwork/IWorkPackageParser.java
@@ -35,6 +35,7 @@ import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.detect.XmlRootExtractor;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
@@ -55,6 +56,7 @@ import org.apache.tika.utils.XMLReaderUtils;
* <li>Numbers format version 1.x. Currently only tested with Numbers version 2.0.x
* </ol>
*/
+@TikaComponent
public class IWorkPackageParser implements Parser {
/**
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/parser/iwork/iwana/IWork13PackageParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/parser/iwork/iwana/IWork13PackageParser.java
index ac65ff587..dc039d476 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/parser/iwork/iwana/IWork13PackageParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/parser/iwork/iwana/IWork13PackageParser.java
@@ -39,6 +39,7 @@ import org.apache.commons.io.IOUtils;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.extractor.EmbeddedDocumentExtractor;
import org.apache.tika.extractor.EmbeddedDocumentUtil;
@@ -52,6 +53,7 @@ import org.apache.tika.parser.ParseContext;
import org.apache.tika.parser.Parser;
import org.apache.tika.sax.XHTMLContentHandler;
+@TikaComponent
public class IWork13PackageParser implements Parser {
/**
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/parser/iwork/iwana/IWork18PackageParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/parser/iwork/iwana/IWork18PackageParser.java
index 28a699039..d1abc984c 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/parser/iwork/iwana/IWork18PackageParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/parser/iwork/iwana/IWork18PackageParser.java
@@ -31,6 +31,7 @@ import org.apache.commons.compress.archivers.zip.ZipFile;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.io.TikaInputStream;
import org.apache.tika.metadata.Metadata;
@@ -42,6 +43,7 @@ import org.apache.tika.parser.Parser;
* For now, this parser isn't even registered. It contains
* code that will detect the newer 2018 .keynote, .numbers, .pages files.
*/
+@TikaComponent
public class IWork18PackageParser implements Parser {
private final static Set<MediaType> supportedTypes = Collections.unmodifiableSet(
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/resources/META-INF/services/org.apache.tika.detect.Detector b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/resources/META-INF/services/org.apache.tika.detect.Detector
deleted file mode 100644
index 0ccb99ec3..000000000
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/resources/META-INF/services/org.apache.tika.detect.Detector
+++ /dev/null
@@ -1,16 +0,0 @@
-# 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.
-
-org.apache.tika.detect.apple.BPListDetector
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser
deleted file mode 100644
index c922b2e33..000000000
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser
+++ /dev/null
@@ -1,22 +0,0 @@
-# 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.
-
-org.apache.tika.parser.apple.AppleSingleFileParser
-org.apache.tika.parser.apple.PListParser
-org.apache.tika.parser.iwork.iwana.IWork13PackageParser
-org.apache.tika.parser.iwork.iwana.IWork18PackageParser
-org.apache.tika.parser.iwork.IWorkPackageParser
-
-
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/detect/MatroskaDetector.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/detect/MatroskaDetector.java
index b2b25f606..48b9bedb3 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/detect/MatroskaDetector.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/detect/MatroskaDetector.java
@@ -22,12 +22,14 @@ import java.io.InputStream;
import org.apache.commons.io.IOUtils;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.mime.MediaType;
/**
* Detector for Matroska (MKV and WEBM) files based on the EBML header.
*/
+@TikaComponent
public class MatroskaDetector implements Detector {
/** For serialization compatibility. */
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/audio/AudioParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/audio/AudioParser.java
index 64596b9ac..a00573a59 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/audio/AudioParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/audio/AudioParser.java
@@ -36,6 +36,7 @@ import org.apache.commons.io.input.ProxyInputStream;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.metadata.TikaCoreProperties;
@@ -45,6 +46,7 @@ import org.apache.tika.parser.ParseContext;
import org.apache.tika.parser.Parser;
import org.apache.tika.sax.XHTMLContentHandler;
+@TikaComponent
public class AudioParser implements Parser {
/**
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/audio/MidiParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/audio/MidiParser.java
index d7622e97a..4ae7e657b 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/audio/MidiParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/audio/MidiParser.java
@@ -36,6 +36,7 @@ import javax.sound.midi.Track;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.mime.MediaType;
@@ -43,6 +44,7 @@ import org.apache.tika.parser.ParseContext;
import org.apache.tika.parser.Parser;
import org.apache.tika.sax.XHTMLContentHandler;
+@TikaComponent
public class MidiParser implements Parser {
/**
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp3/Mp3Parser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp3/Mp3Parser.java
index a8ff69efa..a3e9a7b96 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp3/Mp3Parser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp3/Mp3Parser.java
@@ -27,6 +27,7 @@ import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.apache.tika.config.Field;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.io.TailStream;
import org.apache.tika.metadata.Metadata;
@@ -46,6 +47,7 @@ import org.apache.tika.sax.XHTMLContentHandler;
* @see <a href="https://id3.org/id3v2.4.0-structure">MP3 ID3 Version 2.4 Structure Specification</a>
* @see <a href="https://id3.org/id3v2.4.0-frames">MP3 ID3 Version 2.4 Frames Specification</a>
*/
+@TikaComponent
public class Mp3Parser implements Parser {
/**
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp4/MP4Parser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp4/MP4Parser.java
index 0b7e30b2a..6a2aaf6a5 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp4/MP4Parser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp4/MP4Parser.java
@@ -43,6 +43,7 @@ import com.drew.metadata.mp4.media.Mp4VideoDirectory;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.RuntimeSAXException;
import org.apache.tika.exception.TikaException;
import org.apache.tika.io.TemporaryResources;
@@ -63,6 +64,7 @@ import org.apache.tika.utils.StringUtils;
* <p>
* This uses Drew Noakes' metadata-extractor: https://github.com/drewnoakes/metadata-extractor
*/
+@TikaComponent
public class MP4Parser implements Parser {
/**
* Serial version UID
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/video/FLVParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/video/FLVParser.java
index 0040989fd..51c7f9cdb 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/video/FLVParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/video/FLVParser.java
@@ -33,6 +33,7 @@ import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.mime.MediaType;
@@ -63,6 +64,7 @@ import org.apache.tika.sax.XHTMLContentHandler;
* hasCuePoints width, cuePoints, lasttimestamp, canSeekToEnd, datasize,
* duration, videosize, filesize, audiodatarate, hasAudio, stereo audiodelay
*/
+@TikaComponent
public class FLVParser implements Parser {
/**
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/resources/META-INF/services/org.apache.tika.detect.Detector b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/resources/META-INF/services/org.apache.tika.detect.Detector
deleted file mode 100644
index 1428c6c4d..000000000
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/resources/META-INF/services/org.apache.tika.detect.Detector
+++ /dev/null
@@ -1,16 +0,0 @@
-# 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.
-
-org.apache.tika.detect.MatroskaDetector
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser
deleted file mode 100644
index 53bc7ab9f..000000000
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser
+++ /dev/null
@@ -1,22 +0,0 @@
-# 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.
-
-org.apache.tika.parser.audio.AudioParser
-org.apache.tika.parser.audio.MidiParser
-org.apache.tika.parser.mp3.Mp3Parser
-org.apache.tika.parser.mp4.MP4Parser
-org.apache.tika.parser.video.FLVParser
-
-
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-cad-module/src/main/java/org/apache/tika/parser/dgn/DGN8Parser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-cad-module/src/main/java/org/apache/tika/parser/dgn/DGN8Parser.java
index a0eba36c1..a5f391439 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-cad-module/src/main/java/org/apache/tika/parser/dgn/DGN8Parser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-cad-module/src/main/java/org/apache/tika/parser/dgn/DGN8Parser.java
@@ -28,6 +28,7 @@ import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.io.TikaInputStream;
import org.apache.tika.metadata.Metadata;
@@ -40,6 +41,7 @@ import org.apache.tika.sax.XHTMLContentHandler;
/**
* This is a VERY LIMITED parser. It parses metadata out of dgn8 files.
*/
+@TikaComponent
public class DGN8Parser implements Parser {
Set<MediaType> SUPPORTED_TYPES = Collections.singleton(MediaType.image("vnd.dgn; version=8"));
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-cad-module/src/main/java/org/apache/tika/parser/dwg/DWGParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-cad-module/src/main/java/org/apache/tika/parser/dwg/DWGParser.java
index a433cb258..40e5bfcf7 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-cad-module/src/main/java/org/apache/tika/parser/dwg/DWGParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-cad-module/src/main/java/org/apache/tika/parser/dwg/DWGParser.java
@@ -26,6 +26,7 @@ import org.apache.poi.util.StringUtil;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.io.EndianUtils;
import org.apache.tika.metadata.Metadata;
@@ -41,6 +42,7 @@ import org.apache.tika.sax.XHTMLContentHandler;
* Note that we use Apache POI for various parts of the processing, as
* lots of the low level string/int/short concepts are the same.
*/
+@TikaComponent
public class DWGParser extends AbstractDWGParser {
public static String DWG_CUSTOM_META_PREFIX = "dwg-custom:";
/**
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-cad-module/src/main/java/org/apache/tika/parser/dwg/DWGReadParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-cad-module/src/main/java/org/apache/tika/parser/dwg/DWGReadParser.java
index 241aa738e..55ae21c1c 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-cad-module/src/main/java/org/apache/tika/parser/dwg/DWGReadParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-cad-module/src/main/java/org/apache/tika/parser/dwg/DWGReadParser.java
@@ -48,6 +48,7 @@ import org.slf4j.LoggerFactory;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.metadata.TikaCoreProperties;
@@ -82,7 +83,7 @@ import org.apache.tika.utils.ProcessUtils;
* <p>
* String : cleanDwgReadReplaceWith - * replacement characters dwgReadExecutable
*/
-
+@TikaComponent(spi = false)
public class DWGReadParser extends AbstractDWGParser {
private static final Logger LOG = LoggerFactory.getLogger(DWGReadParser.class);
/**
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-cad-module/src/main/java/org/apache/tika/parser/prt/PRTParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-cad-module/src/main/java/org/apache/tika/parser/prt/PRTParser.java
index 4e978329e..4eee2abf8 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-cad-module/src/main/java/org/apache/tika/parser/prt/PRTParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-cad-module/src/main/java/org/apache/tika/parser/prt/PRTParser.java
@@ -28,6 +28,7 @@ import org.apache.commons.io.IOUtils;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.io.EndianUtils;
import org.apache.tika.metadata.Metadata;
@@ -41,7 +42,7 @@ import org.apache.tika.sax.XHTMLContentHandler;
* A basic text extracting parser for the CADKey PRT (CAD Drawing)
* format. It outputs text from note entries.
*/
-
+@TikaComponent
public class PRTParser implements Parser {
public static final String PRT_MIME_TYPE = "application/x-prt";
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-cad-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-cad-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser
deleted file mode 100644
index b3b6bd593..000000000
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-cad-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser
+++ /dev/null
@@ -1,19 +0,0 @@
-# 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.
-
-org.apache.tika.parser.dgn.DGN8Parser
-org.apache.tika.parser.dwg.DWGParser
-org.apache.tika.parser.prt.PRTParser
-
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-code-module/src/main/java/org/apache/tika/parser/asm/ClassParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-code-module/src/main/java/org/apache/tika/parser/asm/ClassParser.java
index 1b42334a2..58c488df7 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-code-module/src/main/java/org/apache/tika/parser/asm/ClassParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-code-module/src/main/java/org/apache/tika/parser/asm/ClassParser.java
@@ -24,6 +24,7 @@ import java.util.Set;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.mime.MediaType;
@@ -33,6 +34,7 @@ import org.apache.tika.parser.Parser;
/**
* Parser for Java .class files.
*/
+@TikaComponent
public class ClassParser implements Parser {
/**
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-code-module/src/main/java/org/apache/tika/parser/code/SourceCodeParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-code-module/src/main/java/org/apache/tika/parser/code/SourceCodeParser.java
index c11f20d36..e6580a6ce 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-code-module/src/main/java/org/apache/tika/parser/code/SourceCodeParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-code-module/src/main/java/org/apache/tika/parser/code/SourceCodeParser.java
@@ -46,6 +46,7 @@ import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.detect.AutoDetectReader;
import org.apache.tika.detect.EncodingDetector;
import org.apache.tika.exception.TikaException;
@@ -63,6 +64,7 @@ import org.apache.tika.sax.XHTMLContentHandler;
* @author Hong-Thai.Nguyen
* @since 1.6
*/
+@TikaComponent
public class SourceCodeParser extends AbstractEncodingDetectorParser {
private static final long serialVersionUID = -4543476498190054160L;
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-code-module/src/main/java/org/apache/tika/parser/executable/ExecutableParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-code-module/src/main/java/org/apache/tika/parser/executable/ExecutableParser.java
index e8ed04aeb..18a1b4053 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-code-module/src/main/java/org/apache/tika/parser/executable/ExecutableParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-code-module/src/main/java/org/apache/tika/parser/executable/ExecutableParser.java
@@ -28,6 +28,7 @@ import org.apache.commons.io.IOUtils;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.io.EndianUtils;
import org.apache.tika.metadata.MachineMetadata;
@@ -41,6 +42,7 @@ import org.apache.tika.sax.XHTMLContentHandler;
/**
* Parser for executable files. Currently supports ELF and PE
*/
+@TikaComponent
public class ExecutableParser implements Parser, MachineMetadata {
/**
* Serial version UID
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-code-module/src/main/java/org/apache/tika/parser/executable/UniversalExecutableParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-code-module/src/main/java/org/apache/tika/parser/executable/UniversalExecutableParser.java
index 20e12a564..8e2c28a28 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-code-module/src/main/java/org/apache/tika/parser/executable/UniversalExecutableParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-code-module/src/main/java/org/apache/tika/parser/executable/UniversalExecutableParser.java
@@ -28,6 +28,7 @@ import org.apache.commons.lang3.tuple.Pair;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.exception.UnsupportedFormatException;
import org.apache.tika.extractor.EmbeddedDocumentExtractor;
@@ -43,6 +44,7 @@ import org.apache.tika.sax.XHTMLContentHandler;
/**
* Parser for universal executable files.
*/
+@TikaComponent
public class UniversalExecutableParser implements Parser {
private static final long serialVersionUID = 1L;
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-code-module/src/main/java/org/apache/tika/parser/mat/MatParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-code-module/src/main/java/org/apache/tika/parser/mat/MatParser.java
index 042d1db5e..d114791de 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-code-module/src/main/java/org/apache/tika/parser/mat/MatParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-code-module/src/main/java/org/apache/tika/parser/mat/MatParser.java
@@ -33,6 +33,7 @@ import com.jmatio.types.MLStructure;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.io.TemporaryResources;
import org.apache.tika.io.TikaInputStream;
@@ -44,7 +45,7 @@ import org.apache.tika.sax.XHTMLContentHandler;
//JMatIO imports
-
+@TikaComponent
public class MatParser implements Parser {
public static final String MATLAB_MIME_TYPE = "application/x-matlab-data";
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-code-module/src/main/java/org/apache/tika/parser/sas/SAS7BDATParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-code-module/src/main/java/org/apache/tika/parser/sas/SAS7BDATParser.java
index 4dab3499d..807e78919 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-code-module/src/main/java/org/apache/tika/parser/sas/SAS7BDATParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-code-module/src/main/java/org/apache/tika/parser/sas/SAS7BDATParser.java
@@ -32,6 +32,7 @@ import com.epam.parso.impl.SasFileReaderImpl;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Database;
import org.apache.tika.metadata.HttpHeaders;
@@ -49,6 +50,7 @@ import org.apache.tika.sax.XHTMLContentHandler;
* Processes the SAS7BDAT data columnar database file used by SAS and
* other similar languages.
*/
+@TikaComponent
public class SAS7BDATParser implements Parser {
private static final long serialVersionUID = -2775485539937983150L;
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-code-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-code-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser
deleted file mode 100644
index 9b73c5db1..000000000
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-code-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser
+++ /dev/null
@@ -1,22 +0,0 @@
-# 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.
-
-org.apache.tika.parser.asm.ClassParser
-org.apache.tika.parser.code.SourceCodeParser
-org.apache.tika.parser.executable.ExecutableParser
-org.apache.tika.parser.executable.UniversalExecutableParser
-org.apache.tika.parser.mat.MatParser
-org.apache.tika.parser.sas.SAS7BDATParser
-
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-crypto-module/src/main/java/org/apache/tika/parser/crypto/Pkcs7Parser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-crypto-module/src/main/java/org/apache/tika/parser/crypto/Pkcs7Parser.java
index 0c5ade368..96e020e08 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-crypto-module/src/main/java/org/apache/tika/parser/crypto/Pkcs7Parser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-crypto-module/src/main/java/org/apache/tika/parser/crypto/Pkcs7Parser.java
@@ -30,6 +30,7 @@ import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.mime.MediaType;
@@ -40,6 +41,7 @@ import org.apache.tika.parser.Parser;
/**
* Basic parser for PKCS7 data.
*/
+@TikaComponent
public class Pkcs7Parser implements Parser {
/**
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-crypto-module/src/main/java/org/apache/tika/parser/crypto/TSDParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-crypto-module/src/main/java/org/apache/tika/parser/crypto/TSDParser.java
index 2a0e4a0f9..e975fb6ff 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-crypto-module/src/main/java/org/apache/tika/parser/crypto/TSDParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-crypto-module/src/main/java/org/apache/tika/parser/crypto/TSDParser.java
@@ -50,6 +50,7 @@ import org.slf4j.LoggerFactory;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.exception.WriteLimitReachedException;
import org.apache.tika.extractor.EmbeddedDocumentExtractor;
@@ -65,6 +66,7 @@ import org.apache.tika.utils.RereadableInputStream;
/**
* Tika parser for Time Stamped Data Envelope (application/timestamped-data)
*/
+@TikaComponent
public class TSDParser implements Parser {
public static final String TSD_MIME_TYPE = "application/timestamped-data";
private static final long serialVersionUID = 3268158344501763323L;
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-crypto-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-crypto-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser
deleted file mode 100644
index a4e54aba8..000000000
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-crypto-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser
+++ /dev/null
@@ -1,17 +0,0 @@
-# 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.
-
-org.apache.tika.parser.crypto.Pkcs7Parser
-org.apache.tika.parser.crypto.TSDParser
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-font-module/src/main/java/org/apache/tika/parser/font/AdobeFontMetricParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-font-module/src/main/java/org/apache/tika/parser/font/AdobeFontMetricParser.java
index aa4c3fed8..3a9614367 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-font-module/src/main/java/org/apache/tika/parser/font/AdobeFontMetricParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-font-module/src/main/java/org/apache/tika/parser/font/AdobeFontMetricParser.java
@@ -28,6 +28,7 @@ import org.apache.fontbox.afm.FontMetrics;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.metadata.Property;
@@ -40,6 +41,7 @@ import org.apache.tika.sax.XHTMLContentHandler;
/**
* Parser for AFM Font Files
*/
+@TikaComponent
public class AdobeFontMetricParser implements Parser {
// TIKA-1325 Replace these with properties, from a well known standard
static final String MET_AVG_CHAR_WIDTH = "AvgCharacterWidth";
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-font-module/src/main/java/org/apache/tika/parser/font/TrueTypeParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-font-module/src/main/java/org/apache/tika/parser/font/TrueTypeParser.java
index b88ffdb74..f22018d17 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-font-module/src/main/java/org/apache/tika/parser/font/TrueTypeParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-font-module/src/main/java/org/apache/tika/parser/font/TrueTypeParser.java
@@ -32,6 +32,7 @@ import org.apache.pdfbox.io.RandomAccessReadBufferedFile;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.io.TikaInputStream;
import org.apache.tika.metadata.Metadata;
@@ -44,6 +45,7 @@ import org.apache.tika.sax.XHTMLContentHandler;
/**
* Parser for TrueType font files (TTF).
*/
+@TikaComponent
public class TrueTypeParser implements Parser {
/**
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-font-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-font-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser
deleted file mode 100644
index 200afade9..000000000
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-font-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser
+++ /dev/null
@@ -1,18 +0,0 @@
-# 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.
-
-org.apache.tika.parser.font.AdobeFontMetricParser
-org.apache.tika.parser.font.TrueTypeParser
-
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-html-module/src/main/java/org/apache/tika/parser/html/HtmlEncodingDetector.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-html-module/src/main/java/org/apache/tika/parser/html/HtmlEncodingDetector.java
index 9f66c9ac0..9e74614df 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-html-module/src/main/java/org/apache/tika/parser/html/HtmlEncodingDetector.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-html-module/src/main/java/org/apache/tika/parser/html/HtmlEncodingDetector.java
@@ -31,6 +31,7 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.tika.config.Field;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.detect.EncodingDetector;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.utils.CharsetUtils;
@@ -44,6 +45,7 @@ import org.apache.tika.utils.CharsetUtils;
*
* @since Apache Tika 1.2
*/
+@TikaComponent(spi = false)
public class HtmlEncodingDetector implements EncodingDetector {
// TIKA-357 - use bigger buffer for meta tag sniffing (was 4K)
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-html-module/src/main/java/org/apache/tika/parser/html/JSoupParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-html-module/src/main/java/org/apache/tika/parser/html/JSoupParser.java
index 36115a08f..3be1054fc 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-html-module/src/main/java/org/apache/tika/parser/html/JSoupParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-html-module/src/main/java/org/apache/tika/parser/html/JSoupParser.java
@@ -46,6 +46,7 @@ import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
import org.apache.tika.config.Field;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.detect.EncodingDetector;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
@@ -59,6 +60,7 @@ import org.apache.tika.parser.ParseContext;
* and post-processes the events to produce XHTML and metadata expected by
* Tika clients.
*/
+@TikaComponent
public class JSoupParser extends AbstractEncodingDetectorParser {
/**
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-html-module/src/main/java/org/apache/tika/parser/html/charsetdetector/StandardHtmlEncodingDetector.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-html-module/src/main/java/org/apache/tika/parser/html/charsetdetector/StandardHtmlEncodingDetector.java
index 90af81e18..7408f9737 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-html-module/src/main/java/org/apache/tika/parser/html/charsetdetector/StandardHtmlEncodingDetector.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-html-module/src/main/java/org/apache/tika/parser/html/charsetdetector/StandardHtmlEncodingDetector.java
@@ -25,6 +25,7 @@ import java.nio.charset.Charset;
import org.apache.commons.io.input.BoundedInputStream;
import org.apache.tika.config.Field;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.detect.EncodingDetector;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.mime.MediaType;
@@ -51,6 +52,7 @@ import org.apache.tika.mime.MediaType;
* }</pre>
* <p>
*/
+@TikaComponent(spi = false)
public final class StandardHtmlEncodingDetector implements EncodingDetector {
private static final int META_TAG_BUFFER_SIZE = 8192;
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-html-module/src/main/resources/META-INF/services/org.apache.tika.detect.EncodingDetector b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-html-module/src/main/resources/META-INF/services/org.apache.tika.detect.EncodingDetector
index 2d7b38cf6..9025ca781 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-html-module/src/main/resources/META-INF/services/org.apache.tika.detect.EncodingDetector
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-html-module/src/main/resources/META-INF/services/org.apache.tika.detect.EncodingDetector
@@ -12,4 +12,8 @@
# 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.
-org.apache.tika.parser.html.HtmlEncodingDetector
\ No newline at end of file
+
+# TODO: This is a manual service file because EncodingDetectors are not re-sorted at runtime
+# (unlike Parsers/Detectors which call ServiceLoaderUtils.sortLoadedClasses()).
+# Need to implement a runtime priority mechanism for proper ordering across modules.
+org.apache.tika.parser.html.HtmlEncodingDetector
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-html-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-html-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser
deleted file mode 100644
index 274e0bd4a..000000000
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-html-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser
+++ /dev/null
@@ -1,15 +0,0 @@
-# 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.
-org.apache.tika.parser.html.JSoupParser
\ No newline at end of file
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/BPGParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/BPGParser.java
index 1b7bb96d8..03c66bc37 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/BPGParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/BPGParser.java
@@ -28,6 +28,7 @@ import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.apache.tika.config.Field;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.exception.TikaMemoryLimitException;
import org.apache.tika.io.EndianUtils;
@@ -43,6 +44,7 @@ import org.apache.tika.parser.ParseContext;
* Documentation on the file format is available from
* http://bellard.org/bpg/bpg_spec.txt
*/
+@TikaComponent
public class BPGParser extends AbstractImageParser {
protected static final int EXTENSION_TAG_EXIF = 1;
protected static final int EXTENSION_TAG_ICC_PROFILE = 2;
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/HeifParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/HeifParser.java
index 79dc9c498..403f8ba76 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/HeifParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/HeifParser.java
@@ -25,12 +25,14 @@ import java.util.Set;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.mime.MediaType;
import org.apache.tika.parser.ParseContext;
+@TikaComponent
public class HeifParser extends AbstractImageParser {
private static final Set<MediaType> SUPPORTED_TYPES = new HashSet<>(
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/ICNSParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/ICNSParser.java
index 4cb9c65d6..298738567 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/ICNSParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/ICNSParser.java
@@ -28,6 +28,7 @@ import org.apache.commons.io.IOUtils;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.exception.TikaMemoryLimitException;
import org.apache.tika.metadata.Metadata;
@@ -39,6 +40,7 @@ import org.apache.tika.sax.XHTMLContentHandler;
/**
* A basic parser class for Apple ICNS icon files
*/
+@TikaComponent
public class ICNSParser implements Parser {
public static final String ICNS_MIME_TYPE = "image/icns";
private static final long serialVersionUID = 922010233654248327L;
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/ImageParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/ImageParser.java
index 0bee1042c..aeff0b535 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/ImageParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/ImageParser.java
@@ -37,6 +37,7 @@ import org.w3c.dom.Node;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.metadata.Property;
@@ -44,6 +45,7 @@ import org.apache.tika.metadata.TikaCoreProperties;
import org.apache.tika.mime.MediaType;
import org.apache.tika.parser.ParseContext;
+@TikaComponent
public class ImageParser extends AbstractImageParser {
/**
* Serial version UID
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/JXLParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/JXLParser.java
index 499af8cfa..6ef25e9da 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/JXLParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/JXLParser.java
@@ -24,6 +24,7 @@ import java.util.Set;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.mime.MediaType;
@@ -34,6 +35,7 @@ import org.apache.tika.parser.xmp.JempboxExtractor;
/**
* Tries to scrape XMP out of JXL
*/
+@TikaComponent
public class JXLParser implements Parser {
private static final Set<MediaType> SUPPORTED_TYPES = Collections.singleton(MediaType.image(
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/JpegParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/JpegParser.java
index c64cd98af..b9b998c83 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/JpegParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/JpegParser.java
@@ -24,6 +24,7 @@ import java.util.Set;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.io.TemporaryResources;
import org.apache.tika.io.TikaInputStream;
@@ -32,6 +33,7 @@ import org.apache.tika.mime.MediaType;
import org.apache.tika.parser.ParseContext;
import org.apache.tika.parser.xmp.JempboxExtractor;
+@TikaComponent
public class JpegParser extends AbstractImageParser {
/**
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/PSDParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/PSDParser.java
index 0a4437dce..10329dc25 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/PSDParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/PSDParser.java
@@ -31,6 +31,7 @@ import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.apache.tika.config.Field;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.exception.TikaMemoryLimitException;
import org.apache.tika.io.EndianUtils;
@@ -53,6 +54,7 @@ import org.apache.tika.sax.XHTMLContentHandler;
* An MIT-licensed python parser with test files is:
* https://github.com/psd-tools/psd-tools
*/
+@TikaComponent
public class PSDParser implements Parser {
/**
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/TiffParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/TiffParser.java
index 89e507cc1..570a0b6ec 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/TiffParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/TiffParser.java
@@ -24,6 +24,7 @@ import java.util.Set;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.io.TemporaryResources;
import org.apache.tika.io.TikaInputStream;
@@ -32,6 +33,7 @@ import org.apache.tika.mime.MediaType;
import org.apache.tika.parser.ParseContext;
import org.apache.tika.parser.xmp.JempboxExtractor;
+@TikaComponent
public class TiffParser extends AbstractImageParser {
/**
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/WebPParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/WebPParser.java
index c01cec26d..d66ac2061 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/WebPParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/WebPParser.java
@@ -24,6 +24,7 @@ import java.util.Set;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.io.TemporaryResources;
import org.apache.tika.io.TikaInputStream;
@@ -33,7 +34,7 @@ import org.apache.tika.parser.ParseContext;
import org.apache.tika.parser.Parser;
import org.apache.tika.sax.XHTMLContentHandler;
-
+@TikaComponent
public class WebPParser implements Parser {
/**
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser
deleted file mode 100644
index 6a6da530f..000000000
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser
+++ /dev/null
@@ -1,26 +0,0 @@
-# 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.
-
-org.apache.tika.parser.image.BPGParser
-org.apache.tika.parser.image.ImageParser
-org.apache.tika.parser.image.PSDParser
-org.apache.tika.parser.image.TiffParser
-org.apache.tika.parser.image.WebPParser
-org.apache.tika.parser.image.JpegParser
-org.apache.tika.parser.image.HeifParser
-org.apache.tika.parser.image.ICNSParser
-org.apache.tika.parser.image.JXLParser
-
-
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-mail-module/src/main/java/org/apache/tika/parser/mail/RFC822Parser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-mail-module/src/main/java/org/apache/tika/parser/mail/RFC822Parser.java
index b2b552122..b40343d57 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-mail-module/src/main/java/org/apache/tika/parser/mail/RFC822Parser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-mail-module/src/main/java/org/apache/tika/parser/mail/RFC822Parser.java
@@ -29,6 +29,7 @@ import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.apache.tika.config.Field;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.detect.Detector;
import org.apache.tika.exception.TikaException;
import org.apache.tika.exception.ZeroByteFileException;
@@ -49,6 +50,7 @@ import org.apache.tika.sax.XHTMLContentHandler;
*
* @author jnioche@digitalpebble.com
*/
+@TikaComponent
public class RFC822Parser implements Parser {
/**
* Serial version UID
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-mail-module/src/main/java/org/apache/tika/parser/mbox/MboxParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-mail-module/src/main/java/org/apache/tika/parser/mbox/MboxParser.java
index f4834337b..7f4879302 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-mail-module/src/main/java/org/apache/tika/parser/mbox/MboxParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-mail-module/src/main/java/org/apache/tika/parser/mbox/MboxParser.java
@@ -37,6 +37,7 @@ import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.extractor.EmbeddedDocumentExtractor;
import org.apache.tika.extractor.EmbeddedDocumentUtil;
@@ -55,6 +56,7 @@ import org.apache.tika.utils.StringUtils;
* Mbox (mailbox) parser. This version extracts each mail from Mbox and uses the
* DelegatingParser to process each mail.
*/
+@TikaComponent
public class MboxParser implements Parser {
public static final String MBOX_MIME_TYPE = "application/mbox";
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-mail-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-mail-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser
deleted file mode 100644
index 03f511c05..000000000
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-mail-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser
+++ /dev/null
@@ -1,19 +0,0 @@
-# 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.
-
-org.apache.tika.parser.mail.RFC822Parser
-org.apache.tika.parser.mbox.MboxParser
-
-
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/detect/microsoft/POIFSContainerDetector.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/detect/microsoft/POIFSContainerDetector.java
index ef36eaed3..07c6263f4 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/detect/microsoft/POIFSContainerDetector.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/detect/microsoft/POIFSContainerDetector.java
@@ -44,6 +44,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.tika.config.Field;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.detect.Detector;
import org.apache.tika.io.BoundedInputStream;
import org.apache.tika.io.TikaInputStream;
@@ -57,6 +58,7 @@ import org.apache.tika.parser.microsoft.OfficeParser;
* This should work for all OLE2 documents, whether
* they are ones supported by POI or not.
*/
+@TikaComponent
public class POIFSContainerDetector implements Detector {
/**
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/EMFParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/EMFParser.java
index a5ff9ea20..eb6114dd5 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/EMFParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/EMFParser.java
@@ -36,6 +36,7 @@ import org.apache.poi.util.StringUtil;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.extractor.EmbeddedDocumentExtractor;
import org.apache.tika.extractor.EmbeddedDocumentUtil;
@@ -62,6 +63,7 @@ import org.apache.tika.sax.XHTMLContentHandler;
* We'd have to do something like what PDFBox or XPS do to sort the
* runs and then put the cow back together from the hamburger...lol...
*/
+@TikaComponent
public class EMFParser implements Parser {
public static Property EMF_ICON_ONLY = Property.internalBoolean("emf:iconOnly");
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/JackcessParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/JackcessParser.java
index 3e5ff0cb9..a234946a1 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/JackcessParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/JackcessParser.java
@@ -31,6 +31,7 @@ import com.healthmarketscience.jackcess.util.LinkResolver;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.EncryptedDocumentException;
import org.apache.tika.exception.TikaException;
import org.apache.tika.exception.UnsupportedFormatException;
@@ -51,6 +52,7 @@ import org.apache.tika.sax.XHTMLContentHandler;
* Many, many thanks to LexisNexis®/Health Market Science (HMS), Brian O'Neill,
* and James Ahlborn for relicensing Jackcess to Apache v2.0!
*/
+@TikaComponent
public class JackcessParser implements Parser {
public static final String SUMMARY_PROPERTY_PREFIX =
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/MSOwnerFileParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/MSOwnerFileParser.java
index f319b6d0a..752ed6f09 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/MSOwnerFileParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/MSOwnerFileParser.java
@@ -26,6 +26,7 @@ import org.apache.commons.io.IOUtils;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.metadata.TikaCoreProperties;
@@ -38,6 +39,7 @@ import org.apache.tika.sax.XHTMLContentHandler;
* Parser for temporary MSOFfice files.
* This currently only extracts the owner's name.
*/
+@TikaComponent
public class MSOwnerFileParser implements Parser {
private static final int ASCII_CHUNK_LENGTH = 54;
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/OfficeParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/OfficeParser.java
index dade2ca5f..045ffe744 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/OfficeParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/OfficeParser.java
@@ -45,6 +45,7 @@ import org.apache.poi.util.LocaleUtil;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.detect.microsoft.POIFSContainerDetector;
import org.apache.tika.exception.EncryptedDocumentException;
import org.apache.tika.exception.TikaException;
@@ -65,6 +66,7 @@ import org.apache.tika.utils.StringUtils;
/**
* Defines a Microsoft document content extractor.
*/
+@TikaComponent
public class OfficeParser extends AbstractOfficeParser {
/**
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/OldExcelParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/OldExcelParser.java
index 7c8ca2e63..f977c876a 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/OldExcelParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/OldExcelParser.java
@@ -29,6 +29,7 @@ import org.apache.poi.hssf.extractor.OldExcelExtractor;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.mime.MediaType;
@@ -40,6 +41,7 @@ import org.apache.tika.sax.XHTMLContentHandler;
* A POI-powered Tika Parser for very old versions of Excel, from
* pre-OLE2 days, such as Excel 4.
*/
+@TikaComponent
public class OldExcelParser implements Parser {
private static final long serialVersionUID = 4611820730372823452L;
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/TNEFParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/TNEFParser.java
index 9cd09fea6..23163d9f3 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/TNEFParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/TNEFParser.java
@@ -31,6 +31,7 @@ import org.apache.poi.hsmf.datatypes.MAPIProperty;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.extractor.EmbeddedDocumentExtractor;
import org.apache.tika.extractor.EmbeddedDocumentUtil;
@@ -47,6 +48,7 @@ import org.apache.tika.sax.XHTMLContentHandler;
* A POI-powered Tika Parser for TNEF (Transport Neutral
* Encoding Format) messages, aka winmail.dat
*/
+@TikaComponent
public class TNEFParser implements Parser {
private static final long serialVersionUID = 4611820730372823452L;
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/WMFParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/WMFParser.java
index 3c55a14b0..65264c129 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/WMFParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/WMFParser.java
@@ -34,6 +34,7 @@ import org.apache.poi.util.RecordFormatException;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.mime.MediaType;
@@ -45,6 +46,7 @@ import org.apache.tika.sax.XHTMLContentHandler;
* This parser offers a very rough capability to extract text if there
* is text stored in the WMF files.
*/
+@TikaComponent
public class WMFParser implements Parser {
private static final MediaType MEDIA_TYPE = MediaType.image("wmf");
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/activemime/ActiveMimeParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/activemime/ActiveMimeParser.java
index 5ac13fda5..b9b51049a 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/activemime/ActiveMimeParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/activemime/ActiveMimeParser.java
@@ -28,6 +28,7 @@ import org.apache.poi.util.LittleEndian;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.extractor.EmbeddedDocumentExtractor;
import org.apache.tika.extractor.EmbeddedDocumentUtil;
@@ -42,6 +43,7 @@ import org.apache.tika.sax.XHTMLContentHandler;
* ActiveMime is a macro container format used in some mso files. See, e.g.
* <a href="https://mastodon.social/@Ange/110027138524274526">Ange's toot</a>.
*/
+@TikaComponent
public class ActiveMimeParser implements Parser {
private static final MediaType MEDIA_TYPE = MediaType.application("x-activemime");
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/chm/ChmParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/chm/ChmParser.java
index 06b2dd518..00b8ee46f 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/chm/ChmParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/chm/ChmParser.java
@@ -26,6 +26,7 @@ import java.util.Set;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.extractor.EmbeddedDocumentUtil;
import org.apache.tika.io.TikaInputStream;
@@ -38,6 +39,7 @@ import org.apache.tika.sax.BodyContentHandler;
import org.apache.tika.sax.EmbeddedContentHandler;
import org.apache.tika.sax.XHTMLContentHandler;
+@TikaComponent
public class ChmParser implements Parser {
/**
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/libpst/LibPstParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/libpst/LibPstParser.java
index 83e88a38c..4afc4030a 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/libpst/LibPstParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/libpst/LibPstParser.java
@@ -37,6 +37,7 @@ import org.apache.tika.config.Field;
import org.apache.tika.config.Initializable;
import org.apache.tika.config.InitializableProblemHandler;
import org.apache.tika.config.Param;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaConfigException;
import org.apache.tika.exception.TikaException;
import org.apache.tika.io.TemporaryResources;
@@ -55,6 +56,7 @@ import org.apache.tika.utils.StringUtils;
* the GPL-3 libpst/readpst commandline tool and configuring
* Tika to call this library via tika-config.xml
*/
+@TikaComponent(spi = false)
public class LibPstParser implements Parser, Initializable {
public static final MediaType MS_OUTLOOK_PST_MIMETYPE = MediaType.application("vnd.ms-outlook-pst");
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/onenote/OneNoteParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/onenote/OneNoteParser.java
index 55913515f..e7d72d828 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/onenote/OneNoteParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/onenote/OneNoteParser.java
@@ -31,6 +31,7 @@ import org.apache.commons.lang3.tuple.Pair;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.io.TemporaryResources;
import org.apache.tika.io.TikaInputStream;
@@ -50,6 +51,7 @@ import org.apache.tika.sax.XHTMLContentHandler;
* <p>
* Based on the Microsoft specs MS-ONE and MS-ONESTORE.
*/
+@TikaComponent
public class OneNoteParser implements Parser {
public static final String ONE_NOTE_PREFIX = "onenote:";
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/ooxml/OOXMLParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/ooxml/OOXMLParser.java
index f365dc94f..73bd9c4db 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/ooxml/OOXMLParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/ooxml/OOXMLParser.java
@@ -27,6 +27,7 @@ import org.apache.poi.openxml4j.util.ZipSecureFile;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.mime.MediaType;
@@ -36,6 +37,7 @@ import org.apache.tika.parser.microsoft.AbstractOfficeParser;
/**
* Office Open XML (OOXML) parser.
*/
+@TikaComponent
public class OOXMLParser extends AbstractOfficeParser {
protected static final String SIGNATURE_RELATIONSHIP =
"http://schemas.openxmlformats.org/package/2006/relationships/digital-signature/origin";
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/ooxml/xwpf/ml2006/Word2006MLParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/ooxml/xwpf/ml2006/Word2006MLParser.java
index e2fe9d080..8cbad69f7 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/ooxml/xwpf/ml2006/Word2006MLParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/ooxml/xwpf/ml2006/Word2006MLParser.java
@@ -26,6 +26,7 @@ import org.apache.commons.io.input.CloseShieldInputStream;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.mime.MediaType;
@@ -35,7 +36,7 @@ import org.apache.tika.sax.EmbeddedContentHandler;
import org.apache.tika.sax.XHTMLContentHandler;
import org.apache.tika.utils.XMLReaderUtils;
-
+@TikaComponent
public class Word2006MLParser extends AbstractOfficeParser {
protected static final Set<MediaType> SUPPORTED_TYPES =
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/pst/OutlookPSTParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/pst/OutlookPSTParser.java
index 08f49daf3..136c8f693 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/pst/OutlookPSTParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/pst/OutlookPSTParser.java
@@ -31,6 +31,7 @@ import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.extractor.EmbeddedDocumentExtractor;
import org.apache.tika.extractor.EmbeddedDocumentUtil;
@@ -46,6 +47,7 @@ import org.apache.tika.sax.XHTMLContentHandler;
/**
* Parser for MS Outlook PST email storage files
*/
+@TikaComponent
public class OutlookPSTParser implements Parser {
public static final MediaType MS_OUTLOOK_PST_MIMETYPE =
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/pst/PSTMailItemParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/pst/PSTMailItemParser.java
index 00ee7c571..c1f3ffa9a 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/pst/PSTMailItemParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/pst/PSTMailItemParser.java
@@ -31,6 +31,7 @@ import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.extractor.EmbeddedDocumentExtractor;
import org.apache.tika.extractor.EmbeddedDocumentUtil;
@@ -50,6 +51,7 @@ import org.apache.tika.sax.EmbeddedContentHandler;
import org.apache.tika.sax.XHTMLContentHandler;
import org.apache.tika.utils.StringUtils;
+@TikaComponent
public class PSTMailItemParser implements Parser {
//this is a synthetic file type to represent a notional "pst item"
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/rtf/RTFParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/rtf/RTFParser.java
index 8b17575a7..67d8c2e2d 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/rtf/RTFParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/rtf/RTFParser.java
@@ -26,6 +26,7 @@ import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.apache.tika.config.Field;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.mime.MediaType;
@@ -36,6 +37,7 @@ import org.apache.tika.sax.XHTMLContentHandler;
/**
* RTF parser
*/
+@TikaComponent
public class RTFParser implements Parser {
/**
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/xml/SpreadsheetMLParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/xml/SpreadsheetMLParser.java
index 677751e75..d0d94af12 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/xml/SpreadsheetMLParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/xml/SpreadsheetMLParser.java
@@ -27,6 +27,7 @@ import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
import org.xml.sax.helpers.DefaultHandler;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.mime.MediaType;
import org.apache.tika.parser.ParseContext;
@@ -39,6 +40,7 @@ import org.apache.tika.sax.XHTMLContentHandler;
* <p>
* See <a href="https://en.wikipedia.org/wiki/Microsoft_Office_XML_formats">https://en.wikipedia.org/wiki/Microsoft_Office_XML_formats</a>
*/
+@TikaComponent
public class SpreadsheetMLParser extends AbstractXML2003Parser {
final static String CELL = "cell";
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/xml/WordMLParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/xml/WordMLParser.java
index 0590568d2..aaedc12c7 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/xml/WordMLParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/xml/WordMLParser.java
@@ -33,6 +33,7 @@ import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
import org.xml.sax.helpers.DefaultHandler;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.extractor.EmbeddedDocumentExtractor;
import org.apache.tika.extractor.EmbeddedDocumentUtil;
import org.apache.tika.io.TikaInputStream;
@@ -49,6 +50,7 @@ import org.apache.tika.sax.XHTMLContentHandler;
* <p>
* See <a href="https://en.wikipedia.org/wiki/Microsoft_Office_XML_formats">https://en.wikipedia.org/wiki/Microsoft_Office_XML_formats</a>
*/
+@TikaComponent
public class WordMLParser extends AbstractXML2003Parser {
//map between wordml and xhtml entities
private static final Map<String, String> WORDML_TO_XHTML;
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/resources/META-INF/services/org.apache.tika.detect.Detector b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/resources/META-INF/services/org.apache.tika.detect.Detector
deleted file mode 100644
index 409f1e570..000000000
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/resources/META-INF/services/org.apache.tika.detect.Detector
+++ /dev/null
@@ -1,16 +0,0 @@
-# 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.
-
-org.apache.tika.detect.microsoft.POIFSContainerDetector
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser
deleted file mode 100644
index 2096380b8..000000000
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser
+++ /dev/null
@@ -1,31 +0,0 @@
-# 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.
-org.apache.tika.parser.microsoft.rtf.RTFParser
-org.apache.tika.parser.microsoft.EMFParser
-org.apache.tika.parser.microsoft.WMFParser
-org.apache.tika.parser.microsoft.JackcessParser
-org.apache.tika.parser.microsoft.MSOwnerFileParser
-org.apache.tika.parser.microsoft.OfficeParser
-org.apache.tika.parser.microsoft.OldExcelParser
-org.apache.tika.parser.microsoft.TNEFParser
-org.apache.tika.parser.microsoft.activemime.ActiveMimeParser
-org.apache.tika.parser.microsoft.onenote.OneNoteParser
-org.apache.tika.parser.microsoft.ooxml.OOXMLParser
-org.apache.tika.parser.microsoft.ooxml.xwpf.ml2006.Word2006MLParser
-org.apache.tika.parser.microsoft.xml.WordMLParser
-org.apache.tika.parser.microsoft.xml.SpreadsheetMLParser
-org.apache.tika.parser.microsoft.chm.ChmParser
-org.apache.tika.parser.microsoft.pst.OutlookPSTParser
-org.apache.tika.parser.microsoft.pst.PSTMailItemParser
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/detect/ole/MiscOLEDetector.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/detect/ole/MiscOLEDetector.java
index b6372903e..db522f7a3 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/detect/ole/MiscOLEDetector.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/detect/ole/MiscOLEDetector.java
@@ -31,6 +31,7 @@ import org.apache.poi.poifs.filesystem.Entry;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.tika.config.Field;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.detect.Detector;
import org.apache.tika.io.TikaInputStream;
import org.apache.tika.metadata.Metadata;
@@ -45,6 +46,7 @@ import org.apache.tika.mime.MediaType;
* This should work for all OLE2 documents, whether
* they are ones supported by POI or not.
*/
+@TikaComponent
public class MiscOLEDetector implements Detector {
/**
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/dbf/DBFParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/dbf/DBFParser.java
index da47cee94..e17f3c73d 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/dbf/DBFParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/dbf/DBFParser.java
@@ -31,6 +31,7 @@ import java.util.Set;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.detect.EncodingDetector;
import org.apache.tika.exception.TikaException;
import org.apache.tika.io.TikaInputStream;
@@ -50,6 +51,7 @@ import org.apache.tika.sax.XHTMLContentHandler;
* It caches the first 10 rows and then runs encoding dectection
* on the "character" cells.
*/
+@TikaComponent
public class DBFParser implements Parser {
private static final int ROWS_TO_BUFFER_FOR_CHARSET_DETECTION = 10;
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/dif/DIFParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/dif/DIFParser.java
index b42270718..d132357a9 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/dif/DIFParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/dif/DIFParser.java
@@ -26,6 +26,7 @@ import org.apache.commons.io.input.CloseShieldInputStream;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.mime.MediaType;
@@ -36,6 +37,7 @@ import org.apache.tika.sax.TaggedContentHandler;
import org.apache.tika.sax.XHTMLContentHandler;
import org.apache.tika.utils.XMLReaderUtils;
+@TikaComponent
public class DIFParser implements Parser {
/**
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/epub/EpubParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/epub/EpubParser.java
index f7ac587be..b5eed282a 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/epub/EpubParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/epub/EpubParser.java
@@ -47,6 +47,7 @@ import org.xml.sax.helpers.AttributesImpl;
import org.xml.sax.helpers.DefaultHandler;
import org.apache.tika.config.Field;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.EncryptedDocumentException;
import org.apache.tika.exception.TikaException;
import org.apache.tika.exception.WriteLimitReachedException;
@@ -72,6 +73,7 @@ import org.apache.tika.zip.utils.ZipSalvager;
/**
* Epub parser
*/
+@TikaComponent
public class EpubParser implements Parser {
/**
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/hwp/HwpV5Parser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/hwp/HwpV5Parser.java
index 0fe186c4e..24e1a814e 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/hwp/HwpV5Parser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/hwp/HwpV5Parser.java
@@ -24,6 +24,7 @@ import java.util.Set;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.mime.MediaType;
@@ -31,6 +32,7 @@ import org.apache.tika.parser.ParseContext;
import org.apache.tika.parser.Parser;
import org.apache.tika.sax.XHTMLContentHandler;
+@TikaComponent
public class HwpV5Parser implements Parser {
public static final String HWP_MIME_TYPE = "application/x-hwp-v5";
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/indesign/IDMLParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/indesign/IDMLParser.java
index a76bf90b1..a486202b4 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/indesign/IDMLParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/indesign/IDMLParser.java
@@ -31,6 +31,7 @@ import org.apache.commons.io.IOUtils;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.io.TikaInputStream;
import org.apache.tika.metadata.Metadata;
@@ -45,6 +46,7 @@ import org.apache.tika.sax.XHTMLContentHandler;
/**
* Adobe InDesign IDML Parser.
*/
+@TikaComponent
public class IDMLParser implements Parser {
/**
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/mif/MIFParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/mif/MIFParser.java
index fe200e429..d20208f41 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/mif/MIFParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/mif/MIFParser.java
@@ -29,6 +29,7 @@ import org.apache.commons.io.input.CloseShieldInputStream;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.detect.AutoDetectReader;
import org.apache.tika.detect.EncodingDetector;
import org.apache.tika.exception.TikaException;
@@ -39,6 +40,7 @@ import org.apache.tika.parser.ParseContext;
import org.apache.tika.sax.EndDocumentShieldingContentHandler;
import org.apache.tika.sax.XHTMLContentHandler;
+@TikaComponent
public class MIFParser extends AbstractEncodingDetectorParser {
private static final Set<MediaType> SUPPORTED_TYPES = Collections.unmodifiableSet(new HashSet<>(
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/odf/FlatOpenDocumentParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/odf/FlatOpenDocumentParser.java
index 5f2f1ef4d..0ecac4607 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/odf/FlatOpenDocumentParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/odf/FlatOpenDocumentParser.java
@@ -30,6 +30,7 @@ import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import org.apache.tika.config.Field;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.mime.MediaType;
@@ -40,6 +41,7 @@ import org.apache.tika.sax.EmbeddedContentHandler;
import org.apache.tika.sax.XHTMLContentHandler;
import org.apache.tika.utils.XMLReaderUtils;
+@TikaComponent
public class FlatOpenDocumentParser implements Parser {
static final MediaType FLAT_OD =
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/odf/OpenDocumentParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/odf/OpenDocumentParser.java
index 1ed7f7649..cfd205e8c 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/odf/OpenDocumentParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/odf/OpenDocumentParser.java
@@ -35,6 +35,7 @@ import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import org.apache.tika.config.Field;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.EncryptedDocumentException;
import org.apache.tika.exception.TikaException;
import org.apache.tika.extractor.EmbeddedDocumentUtil;
@@ -52,6 +53,7 @@ import org.apache.tika.utils.XMLReaderUtils;
/**
* OpenOffice parser
*/
+@TikaComponent
public class OpenDocumentParser implements Parser {
/**
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/wordperfect/QuattroProParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/wordperfect/QuattroProParser.java
index c24f30685..ff600264b 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/wordperfect/QuattroProParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/wordperfect/QuattroProParser.java
@@ -24,6 +24,7 @@ import java.util.Set;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.mime.MediaType;
@@ -39,6 +40,7 @@ import org.apache.tika.sax.XHTMLContentHandler;
*
* @author Pascal Essiembre
*/
+@TikaComponent
public class QuattroProParser implements Parser {
private static final long serialVersionUID = 8941810225917012232L;
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/wordperfect/WordPerfectParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/wordperfect/WordPerfectParser.java
index bd81e088c..1d5ff8acb 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/wordperfect/WordPerfectParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/wordperfect/WordPerfectParser.java
@@ -27,6 +27,7 @@ import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.apache.tika.config.Field;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.EncryptedDocumentException;
import org.apache.tika.exception.TikaException;
import org.apache.tika.exception.UnsupportedFormatException;
@@ -43,6 +44,7 @@ import org.apache.tika.sax.XHTMLContentHandler;
*
* @author Pascal Essiembre
*/
+@TikaComponent
public class WordPerfectParser implements Parser {
final static MediaType WP_BASE = MediaType.application("vnd.wordperfect");
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/resources/META-INF/services/org.apache.tika.detect.Detector b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/resources/META-INF/services/org.apache.tika.detect.Detector
deleted file mode 100644
index da1bd19c8..000000000
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/resources/META-INF/services/org.apache.tika.detect.Detector
+++ /dev/null
@@ -1,16 +0,0 @@
-# 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.
-
-org.apache.tika.detect.ole.MiscOLEDetector
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser
deleted file mode 100644
index 22d33395f..000000000
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser
+++ /dev/null
@@ -1,24 +0,0 @@
-# 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.
-org.apache.tika.parser.hwp.HwpV5Parser
-org.apache.tika.parser.mif.MIFParser
-org.apache.tika.parser.odf.FlatOpenDocumentParser
-org.apache.tika.parser.odf.OpenDocumentParser
-org.apache.tika.parser.wordperfect.QuattroProParser
-org.apache.tika.parser.wordperfect.WordPerfectParser
-org.apache.tika.parser.epub.EpubParser
-org.apache.tika.parser.dif.DIFParser
-org.apache.tika.parser.dbf.DBFParser
-org.apache.tika.parser.indesign.IDMLParser
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-news-module/src/main/java/org/apache/tika/parser/feed/FeedParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-news-module/src/main/java/org/apache/tika/parser/feed/FeedParser.java
index cfa5d3d47..a8c1ab233 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-news-module/src/main/java/org/apache/tika/parser/feed/FeedParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-news-module/src/main/java/org/apache/tika/parser/feed/FeedParser.java
@@ -33,6 +33,7 @@ import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.metadata.TikaCoreProperties;
@@ -47,6 +48,7 @@ import org.apache.tika.sax.XHTMLContentHandler;
* Uses Rome for parsing the feeds. A feed description is put in a paragraph
* with its link and title in an anchor.
*/
+@TikaComponent
public class FeedParser implements Parser {
/**
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-news-module/src/main/java/org/apache/tika/parser/iptc/IptcAnpaParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-news-module/src/main/java/org/apache/tika/parser/iptc/IptcAnpaParser.java
index dfe38a995..50a951ef9 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-news-module/src/main/java/org/apache/tika/parser/iptc/IptcAnpaParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-news-module/src/main/java/org/apache/tika/parser/iptc/IptcAnpaParser.java
@@ -32,6 +32,7 @@ import java.util.TimeZone;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.metadata.TikaCoreProperties;
@@ -43,6 +44,7 @@ import org.apache.tika.sax.XHTMLContentHandler;
/**
* Parser for IPTC ANPA New Wire Feeds
*/
+@TikaComponent
public class IptcAnpaParser implements Parser {
/**
* Serial version UID
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-news-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-news-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser
deleted file mode 100644
index cbfceac2d..000000000
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-news-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser
+++ /dev/null
@@ -1,17 +0,0 @@
-# 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.
-
-org.apache.tika.parser.feed.FeedParser
-org.apache.tika.parser.iptc.IptcAnpaParser
\ No newline at end of file
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-ocr-module/src/main/java/org/apache/tika/parser/ocr/TesseractOCRParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-ocr-module/src/main/java/org/apache/tika/parser/ocr/TesseractOCRParser.java
index e06db7d4d..0a79d6cd4 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-ocr-module/src/main/java/org/apache/tika/parser/ocr/TesseractOCRParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-ocr-module/src/main/java/org/apache/tika/parser/ocr/TesseractOCRParser.java
@@ -62,6 +62,7 @@ import org.apache.tika.config.Field;
import org.apache.tika.config.Initializable;
import org.apache.tika.config.InitializableProblemHandler;
import org.apache.tika.config.Param;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.config.TikaTaskTimeout;
import org.apache.tika.exception.TikaConfigException;
import org.apache.tika.exception.TikaException;
@@ -94,6 +95,7 @@ import org.apache.tika.utils.XMLReaderUtils;
* parseContext.set(TesseractOCRConfig.class, config);<br>
* </p>
*/
+@TikaComponent
public class TesseractOCRParser extends AbstractExternalProcessParser implements Initializable {
public static final String TESS_META = "tess:";
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-ocr-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-ocr-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser
deleted file mode 100644
index 797066800..000000000
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-ocr-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser
+++ /dev/null
@@ -1,15 +0,0 @@
-# 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.
-org.apache.tika.parser.ocr.TesseractOCRParser
\ No newline at end of file
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/src/main/java/org/apache/tika/parser/pdf/PDFParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/src/main/java/org/apache/tika/parser/pdf/PDFParser.java
index 40228bfe4..6c29c364a 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/src/main/java/org/apache/tika/parser/pdf/PDFParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/src/main/java/org/apache/tika/parser/pdf/PDFParser.java
@@ -62,6 +62,7 @@ import org.apache.tika.config.Field;
import org.apache.tika.config.Initializable;
import org.apache.tika.config.InitializableProblemHandler;
import org.apache.tika.config.Param;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.EncryptedDocumentException;
import org.apache.tika.exception.TikaConfigException;
import org.apache.tika.exception.TikaException;
@@ -122,6 +123,7 @@ import org.apache.tika.sax.XHTMLContentHandler;
* If your PDFs contain marked content or tags, consider
* {@link PDFParserConfig#setExtractMarkedContent(boolean)}
*/
+@TikaComponent
public class PDFParser implements Parser, RenderingParser, Initializable {
public static final MediaType MEDIA_TYPE = MediaType.application("pdf");
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser
deleted file mode 100644
index 25b9c9f69..000000000
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser
+++ /dev/null
@@ -1,15 +0,0 @@
-# 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.
-org.apache.tika.parser.pdf.PDFParser
\ No newline at end of file
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/main/java/org/apache/tika/detect/gzip/GZipSpecializationDetector.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/main/java/org/apache/tika/detect/gzip/GZipSpecializationDetector.java
index 301cbbcdc..c6ffc3061 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/main/java/org/apache/tika/detect/gzip/GZipSpecializationDetector.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/main/java/org/apache/tika/detect/gzip/GZipSpecializationDetector.java
@@ -26,6 +26,7 @@ import org.apache.commons.io.IOUtils;
import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream;
import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.detect.Detector;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.mime.MediaType;
@@ -34,6 +35,7 @@ import org.apache.tika.mime.MediaType;
* This is designed to detect commonly gzipped file types such as warc.gz.
* This is a first step. We still need to implement tar.gz and svg.gz and ???
*/
+@TikaComponent
public class GZipSpecializationDetector implements Detector {
public static MediaType GZ = MediaType.application("gzip");
public static MediaType WARC_GZ = MediaType.application("warc+gz");
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/main/java/org/apache/tika/parser/pkg/CompressorParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/main/java/org/apache/tika/parser/pkg/CompressorParser.java
index 6028d5016..0a76f0933 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/main/java/org/apache/tika/parser/pkg/CompressorParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/main/java/org/apache/tika/parser/pkg/CompressorParser.java
@@ -61,6 +61,7 @@ import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.apache.tika.config.Field;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.exception.TikaMemoryLimitException;
import org.apache.tika.extractor.EmbeddedDocumentExtractor;
@@ -76,6 +77,7 @@ import org.apache.tika.sax.XHTMLContentHandler;
/**
* Parser for various compression formats.
*/
+@TikaComponent
public class CompressorParser implements Parser {
/**
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/main/java/org/apache/tika/parser/pkg/PackageParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/main/java/org/apache/tika/parser/pkg/PackageParser.java
index bfd2a1168..de2d61764 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/main/java/org/apache/tika/parser/pkg/PackageParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/main/java/org/apache/tika/parser/pkg/PackageParser.java
@@ -60,6 +60,7 @@ import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
import org.apache.tika.config.Field;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.detect.EncodingDetector;
import org.apache.tika.exception.EncryptedDocumentException;
import org.apache.tika.exception.TikaException;
@@ -86,6 +87,7 @@ import org.apache.tika.sax.XHTMLContentHandler;
* are not installed, an IOException will be thrown, and potentially
* wrapped in a TikaException.
*/
+@TikaComponent
public class PackageParser extends AbstractEncodingDetectorParser {
//We used to avoid overwriting file types if the file type
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/main/java/org/apache/tika/parser/pkg/RarParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/main/java/org/apache/tika/parser/pkg/RarParser.java
index 11a6e52a4..c14dc50f3 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/main/java/org/apache/tika/parser/pkg/RarParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/main/java/org/apache/tika/parser/pkg/RarParser.java
@@ -27,6 +27,7 @@ import com.github.junrar.rarfile.FileHeader;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.EncryptedDocumentException;
import org.apache.tika.exception.TikaException;
import org.apache.tika.exception.UnsupportedFormatException;
@@ -43,6 +44,7 @@ import org.apache.tika.sax.XHTMLContentHandler;
/**
* Parser for Rar files.
*/
+@TikaComponent
public class RarParser implements Parser {
private static final long serialVersionUID = 6157727985054451501L;
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/main/java/org/apache/tika/parser/pkg/UnrarParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/main/java/org/apache/tika/parser/pkg/UnrarParser.java
index f4005b526..67796a608 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/main/java/org/apache/tika/parser/pkg/UnrarParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/main/java/org/apache/tika/parser/pkg/UnrarParser.java
@@ -32,6 +32,7 @@ import org.apache.commons.io.IOUtils;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.EncryptedDocumentException;
import org.apache.tika.exception.TikaException;
import org.apache.tika.exception.TikaTimeoutException;
@@ -52,6 +53,7 @@ import org.apache.tika.utils.ProcessUtils;
* and on the path. This is not the default rar parser and must
* be selected via the tika-config.xml.
*/
+@TikaComponent(spi = false)
public class UnrarParser implements Parser {
private static final long serialVersionUID = 6157727985054451501L;
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/main/resources/META-INF/services/org.apache.tika.detect.Detector b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/main/resources/META-INF/services/org.apache.tika.detect.Detector
deleted file mode 100644
index a5d143217..000000000
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/main/resources/META-INF/services/org.apache.tika.detect.Detector
+++ /dev/null
@@ -1,16 +0,0 @@
-# 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.
-
-org.apache.tika.detect.gzip.GZipSpecializationDetector
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser
deleted file mode 100644
index 89ce8c87b..000000000
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser
+++ /dev/null
@@ -1,18 +0,0 @@
-# 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.
-
-org.apache.tika.parser.pkg.CompressorParser
-org.apache.tika.parser.pkg.PackageParser
-org.apache.tika.parser.pkg.RarParser
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-text-module/src/main/java/org/apache/tika/parser/csv/TextAndCSVParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-text-module/src/main/java/org/apache/tika/parser/csv/TextAndCSVParser.java
index 8feb63e1f..4fdde18d8 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-text-module/src/main/java/org/apache/tika/parser/csv/TextAndCSVParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-text-module/src/main/java/org/apache/tika/parser/csv/TextAndCSVParser.java
@@ -39,6 +39,7 @@ import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.apache.tika.config.Field;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.detect.AutoDetectReader;
import org.apache.tika.detect.EncodingDetector;
import org.apache.tika.exception.TikaConfigException;
@@ -69,6 +70,7 @@ import org.apache.tika.sax.XHTMLContentHandler;
* {@link org.apache.commons.csv.CSVParser} is lost.
* </p>
*/
+@TikaComponent
public class TextAndCSVParser extends AbstractEncodingDetectorParser {
static final MediaType CSV = MediaType.text("csv");
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-text-module/src/main/java/org/apache/tika/parser/strings/Latin1StringsParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-text-module/src/main/java/org/apache/tika/parser/strings/Latin1StringsParser.java
index 8657237dc..6476ac3ff 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-text-module/src/main/java/org/apache/tika/parser/strings/Latin1StringsParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-text-module/src/main/java/org/apache/tika/parser/strings/Latin1StringsParser.java
@@ -25,6 +25,7 @@ import java.util.Set;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.mime.MediaType;
import org.apache.tika.parser.ParseContext;
@@ -47,6 +48,7 @@ import org.apache.tika.sax.XHTMLContentHandler;
* <p>
* The implementation is optimized for fast parsing with only one pass.
*/
+@TikaComponent(spi = false)
public class Latin1StringsParser implements Parser {
private static final long serialVersionUID = 1L;
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-text-module/src/main/java/org/apache/tika/parser/strings/StringsParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-text-module/src/main/java/org/apache/tika/parser/strings/StringsParser.java
index 63b6a88be..ef3071c4c 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-text-module/src/main/java/org/apache/tika/parser/strings/StringsParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-text-module/src/main/java/org/apache/tika/parser/strings/StringsParser.java
@@ -39,6 +39,7 @@ import org.apache.tika.config.Field;
import org.apache.tika.config.Initializable;
import org.apache.tika.config.InitializableProblemHandler;
import org.apache.tika.config.Param;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.detect.FileCommandDetector;
import org.apache.tika.exception.TikaConfigException;
import org.apache.tika.exception.TikaException;
@@ -60,6 +61,7 @@ import org.apache.tika.utils.SystemUtils;
*
* @author gtotaro
*/
+@TikaComponent(spi = false)
public class StringsParser implements Parser, Initializable {
/**
* Serial version UID
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-text-module/src/main/java/org/apache/tika/parser/txt/BOMDetector.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-text-module/src/main/java/org/apache/tika/parser/txt/BOMDetector.java
index c96bfda5d..82138be84 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-text-module/src/main/java/org/apache/tika/parser/txt/BOMDetector.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-text-module/src/main/java/org/apache/tika/parser/txt/BOMDetector.java
@@ -24,9 +24,14 @@ import java.nio.charset.UnsupportedCharsetException;
import org.apache.commons.io.ByteOrderMark;
import org.apache.commons.io.IOUtils;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.detect.EncodingDetector;
import org.apache.tika.metadata.Metadata;
+/*
+ This is an optional detector that is not loaded automatically by SPI. You need to configure it.
+ */
+@TikaComponent(spi = false)
public class BOMDetector implements EncodingDetector {
private static final ByteOrderMark[] BOMS =
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-text-module/src/main/java/org/apache/tika/parser/txt/Icu4jEncodingDetector.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-text-module/src/main/java/org/apache/tika/parser/txt/Icu4jEncodingDetector.java
index 2677a4d34..f521b7cac 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-text-module/src/main/java/org/apache/tika/parser/txt/Icu4jEncodingDetector.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-text-module/src/main/java/org/apache/tika/parser/txt/Icu4jEncodingDetector.java
@@ -26,11 +26,13 @@ import java.util.List;
import java.util.Set;
import org.apache.tika.config.Field;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.detect.EncodingDetector;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.mime.MediaType;
import org.apache.tika.utils.CharsetUtils;
+@TikaComponent(spi = false)
public class Icu4jEncodingDetector implements EncodingDetector {
@Field
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-text-module/src/main/java/org/apache/tika/parser/txt/TXTParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-text-module/src/main/java/org/apache/tika/parser/txt/TXTParser.java
index f39a2fe01..b010b1f70 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-text-module/src/main/java/org/apache/tika/parser/txt/TXTParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-text-module/src/main/java/org/apache/tika/parser/txt/TXTParser.java
@@ -26,6 +26,7 @@ import org.apache.commons.io.input.CloseShieldInputStream;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.detect.AutoDetectReader;
import org.apache.tika.detect.EncodingDetector;
import org.apache.tika.exception.TikaException;
@@ -48,6 +49,7 @@ import org.apache.tika.sax.XHTMLContentHandler;
* <dd><code>text/plain; charset=...</code></dd>
* </dl>
*/
+@TikaComponent(spi = false)
public class TXTParser extends AbstractEncodingDetectorParser {
/**
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-text-module/src/main/java/org/apache/tika/parser/txt/UniversalEncodingDetector.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-text-module/src/main/java/org/apache/tika/parser/txt/UniversalEncodingDetector.java
index 9dadbb6b3..2c6f1f816 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-text-module/src/main/java/org/apache/tika/parser/txt/UniversalEncodingDetector.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-text-module/src/main/java/org/apache/tika/parser/txt/UniversalEncodingDetector.java
@@ -21,9 +21,11 @@ import java.io.InputStream;
import java.nio.charset.Charset;
import org.apache.tika.config.Field;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.detect.EncodingDetector;
import org.apache.tika.metadata.Metadata;
+@TikaComponent(spi = false)
public class UniversalEncodingDetector implements EncodingDetector {
private static final int BUFSIZE = 1024;
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-text-module/src/main/resources/META-INF/services/org.apache.tika.detect.EncodingDetector b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-text-module/src/main/resources/META-INF/services/org.apache.tika.detect.EncodingDetector
index e60217c3d..506ca15f5 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-text-module/src/main/resources/META-INF/services/org.apache.tika.detect.EncodingDetector
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-text-module/src/main/resources/META-INF/services/org.apache.tika.detect.EncodingDetector
@@ -13,5 +13,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+# TODO: This is a manual service file because EncodingDetectors are not re-sorted at runtime
+# (unlike Parsers/Detectors which call ServiceLoaderUtils.sortLoadedClasses()).
+# Order matters here - first detector that returns non-null wins.
+# Need to implement a runtime priority mechanism for proper ordering across modules.
org.apache.tika.parser.txt.UniversalEncodingDetector
org.apache.tika.parser.txt.Icu4jEncodingDetector
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-text-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-text-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser
deleted file mode 100644
index 4e6ea01b3..000000000
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-text-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser
+++ /dev/null
@@ -1,22 +0,0 @@
-# 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.
-
-
-org.apache.tika.parser.csv.TextAndCSVParser
-#org.apache.tika.parser.strings.Latin1StringsParser
-#org.apache.tika.parser.strings.StringsParser
-#org.apache.tika.parser.xml.DcXMLParser
-#org.apache.tika.parser.xml.FictionBookParser
-#org.apache.tika.parser.xml.XMLParser
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-webarchive-module/src/main/java/org/apache/tika/parser/http/HttpParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-webarchive-module/src/main/java/org/apache/tika/parser/http/HttpParser.java
index 3bfa09a8f..ab1431a3f 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-webarchive-module/src/main/java/org/apache/tika/parser/http/HttpParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-webarchive-module/src/main/java/org/apache/tika/parser/http/HttpParser.java
@@ -32,6 +32,7 @@ import org.netpreserve.jwarc.MessageHeaders;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.extractor.EmbeddedDocumentExtractor;
import org.apache.tika.extractor.EmbeddedDocumentUtil;
@@ -42,6 +43,7 @@ import org.apache.tika.parser.ParseContext;
import org.apache.tika.parser.Parser;
import org.apache.tika.sax.XHTMLContentHandler;
+@TikaComponent
public class HttpParser implements Parser {
private static final MediaType MEDIA_TYPE = MediaType.application("x-httpresponse");
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-webarchive-module/src/main/java/org/apache/tika/parser/wacz/WACZParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-webarchive-module/src/main/java/org/apache/tika/parser/wacz/WACZParser.java
index fcf4042df..d9f6fdb80 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-webarchive-module/src/main/java/org/apache/tika/parser/wacz/WACZParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-webarchive-module/src/main/java/org/apache/tika/parser/wacz/WACZParser.java
@@ -34,6 +34,7 @@ import org.apache.commons.io.input.CloseShieldInputStream;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.extractor.EmbeddedDocumentExtractor;
import org.apache.tika.extractor.EmbeddedDocumentUtil;
@@ -45,6 +46,7 @@ import org.apache.tika.parser.ParseContext;
import org.apache.tika.parser.Parser;
import org.apache.tika.sax.XHTMLContentHandler;
+@TikaComponent
public class WACZParser implements Parser {
private static final Set<MediaType> SUPPORTED_TYPES = Collections.unmodifiableSet(
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-webarchive-module/src/main/java/org/apache/tika/parser/warc/WARCParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-webarchive-module/src/main/java/org/apache/tika/parser/warc/WARCParser.java
index 9aa1e2f2f..d893914c7 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-webarchive-module/src/main/java/org/apache/tika/parser/warc/WARCParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-webarchive-module/src/main/java/org/apache/tika/parser/warc/WARCParser.java
@@ -34,6 +34,7 @@ import org.netpreserve.jwarc.WarcResponse;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.exception.WriteLimitReachedException;
import org.apache.tika.extractor.EmbeddedDocumentExtractor;
@@ -52,6 +53,7 @@ import org.apache.tika.utils.StringUtils;
/**
* This uses jwarc to parse warc files and arc files
*/
+@TikaComponent
public class WARCParser implements Parser {
private static final Set<MediaType> SUPPORTED_TYPES = Collections.unmodifiableSet(
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-webarchive-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-webarchive-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser
deleted file mode 100644
index 087707900..000000000
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-webarchive-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser
+++ /dev/null
@@ -1,19 +0,0 @@
-# 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.
-
-org.apache.tika.parser.http.HttpParser
-org.apache.tika.parser.warc.WARCParser
-org.apache.tika.parser.wacz.WACZParser
-
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-xml-module/src/main/java/org/apache/tika/parser/tmx/TMXParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-xml-module/src/main/java/org/apache/tika/parser/tmx/TMXParser.java
index 5fce5de20..5d6622415 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-xml-module/src/main/java/org/apache/tika/parser/tmx/TMXParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-xml-module/src/main/java/org/apache/tika/parser/tmx/TMXParser.java
@@ -25,6 +25,7 @@ import org.apache.commons.io.input.CloseShieldInputStream;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.mime.MediaType;
@@ -36,6 +37,7 @@ import org.apache.tika.utils.XMLReaderUtils;
/**
* Parser for Translation Memory eXchange (TMX) files.
*/
+@TikaComponent
public class TMXParser implements Parser {
/**
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-xml-module/src/main/java/org/apache/tika/parser/xliff/XLIFF12Parser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-xml-module/src/main/java/org/apache/tika/parser/xliff/XLIFF12Parser.java
index bd789802f..129aced98 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-xml-module/src/main/java/org/apache/tika/parser/xliff/XLIFF12Parser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-xml-module/src/main/java/org/apache/tika/parser/xliff/XLIFF12Parser.java
@@ -25,6 +25,7 @@ import org.apache.commons.io.input.CloseShieldInputStream;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.mime.MediaType;
@@ -36,6 +37,7 @@ import org.apache.tika.utils.XMLReaderUtils;
/**
* Parser for XLIFF 1.2 files.
*/
+@TikaComponent
public class XLIFF12Parser implements Parser {
/**
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-xml-module/src/main/java/org/apache/tika/parser/xliff/XLZParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-xml-module/src/main/java/org/apache/tika/parser/xliff/XLZParser.java
index 4bd947923..045d8a2cc 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-xml-module/src/main/java/org/apache/tika/parser/xliff/XLZParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-xml-module/src/main/java/org/apache/tika/parser/xliff/XLZParser.java
@@ -28,6 +28,7 @@ import java.util.zip.ZipInputStream;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.io.TikaInputStream;
import org.apache.tika.metadata.Metadata;
@@ -40,6 +41,7 @@ import org.apache.tika.sax.XHTMLContentHandler;
/**
* Parser for XLZ Archives.
*/
+@TikaComponent
public class XLZParser implements Parser {
/**
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-xml-module/src/main/java/org/apache/tika/parser/xml/DcXMLParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-xml-module/src/main/java/org/apache/tika/parser/xml/DcXMLParser.java
index a3c50c6cb..d87811ad4 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-xml-module/src/main/java/org/apache/tika/parser/xml/DcXMLParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-xml-module/src/main/java/org/apache/tika/parser/xml/DcXMLParser.java
@@ -18,6 +18,7 @@ package org.apache.tika.parser.xml;
import org.xml.sax.ContentHandler;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.metadata.DublinCore;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.metadata.Property;
@@ -28,6 +29,7 @@ import org.apache.tika.sax.TeeContentHandler;
/**
* Dublin Core metadata parser
*/
+@TikaComponent
public class DcXMLParser extends XMLParser {
/**
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-xml-module/src/main/java/org/apache/tika/parser/xml/FictionBookParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-xml-module/src/main/java/org/apache/tika/parser/xml/FictionBookParser.java
index 094db7cc9..46300a1a7 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-xml-module/src/main/java/org/apache/tika/parser/xml/FictionBookParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-xml-module/src/main/java/org/apache/tika/parser/xml/FictionBookParser.java
@@ -26,6 +26,7 @@ import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.extractor.EmbeddedDocumentExtractor;
import org.apache.tika.extractor.EmbeddedDocumentUtil;
import org.apache.tika.io.TikaInputStream;
@@ -34,6 +35,7 @@ import org.apache.tika.metadata.TikaCoreProperties;
import org.apache.tika.mime.MediaType;
import org.apache.tika.parser.ParseContext;
+@TikaComponent
public class FictionBookParser extends XMLParser {
private static final long serialVersionUID = 4195954546491524374L;
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-xml-module/src/main/java/org/apache/tika/parser/xml/XMLParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-xml-module/src/main/java/org/apache/tika/parser/xml/XMLParser.java
index 30d48ea1d..b67395e9f 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-xml-module/src/main/java/org/apache/tika/parser/xml/XMLParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-xml-module/src/main/java/org/apache/tika/parser/xml/XMLParser.java
@@ -27,6 +27,7 @@ import org.apache.commons.io.input.CloseShieldInputStream;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.mime.MediaType;
@@ -41,6 +42,7 @@ import org.apache.tika.utils.XMLReaderUtils;
/**
* XML parser.
*/
+@TikaComponent(spi = false)
public class XMLParser implements Parser {
/**
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-xml-module/src/main/java/org/apache/tika/parser/xml/XMLProfiler.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-xml-module/src/main/java/org/apache/tika/parser/xml/XMLProfiler.java
index 86957ad7f..321f641cb 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-xml-module/src/main/java/org/apache/tika/parser/xml/XMLProfiler.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-xml-module/src/main/java/org/apache/tika/parser/xml/XMLProfiler.java
@@ -33,6 +33,7 @@ import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.metadata.Property;
@@ -66,6 +67,7 @@ import org.apache.tika.utils.XMLReaderUtils;
* xmp in other file formats. Please open a ticket.
* </p>
*/
+@TikaComponent(spi = false)
public class XMLProfiler implements Parser {
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-xml-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-xml-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser
deleted file mode 100644
index 20d78d69c..000000000
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-xml-module/src/main/resources/META-INF/services/org.apache.tika.parser.Parser
+++ /dev/null
@@ -1,22 +0,0 @@
-# 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.
-
-org.apache.tika.parser.tmx.TMXParser
-org.apache.tika.parser.xliff.XLIFF12Parser
-org.apache.tika.parser.xliff.XLZParser
-org.apache.tika.parser.xml.DcXMLParser
-org.apache.tika.parser.xml.FictionBookParser
-
-
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-zip-commons/src/main/java/org/apache/tika/detect/zip/DefaultZipContainerDetector.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-zip-commons/src/main/java/org/apache/tika/detect/zip/DefaultZipContainerDetector.java
index af6f0e68c..80bebf1e6 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-zip-commons/src/main/java/org/apache/tika/detect/zip/DefaultZipContainerDetector.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-zip-commons/src/main/java/org/apache/tika/detect/zip/DefaultZipContainerDetector.java
@@ -39,6 +39,7 @@ import org.slf4j.LoggerFactory;
import org.apache.tika.config.Field;
import org.apache.tika.config.LoadErrorHandler;
import org.apache.tika.config.ServiceLoader;
+import org.apache.tika.config.TikaComponent;
import org.apache.tika.detect.Detector;
import org.apache.tika.io.BoundedInputStream;
import org.apache.tika.io.TikaInputStream;
@@ -59,6 +60,7 @@ import org.apache.tika.mime.MediaType;
* Finally, if the file is not detected as an archive format, this runs
* commons-compress' compressor format detector.
*/
+@TikaComponent
public class DefaultZipContainerDetector implements Detector {
//Regrettably, some tiff files can be incorrectly identified
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-zip-commons/src/main/resources/META-INF/services/org.apache.tika.detect.Detector b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-zip-commons/src/main/resources/META-INF/services/org.apache.tika.detect.Detector
deleted file mode 100644
index e01e464da..000000000
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-zip-commons/src/main/resources/META-INF/services/org.apache.tika.detect.Detector
+++ /dev/null
@@ -1,16 +0,0 @@
-# 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.
-
-org.apache.tika.detect.zip.DefaultZipContainerDetector
\ No newline at end of file
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-zip-commons/src/main/resources/META-INF/services/org.apache.tika.detect.zip.ZipContainerDetector b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-zip-commons/src/main/resources/META-INF/services/org.apache.tika.detect.zip.ZipContainerDetector
index 1d5544519..eb2bfe277 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-zip-commons/src/main/resources/META-INF/services/org.apache.tika.detect.zip.ZipContainerDetector
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-zip-commons/src/main/resources/META-INF/services/org.apache.tika.detect.zip.ZipContainerDetector
@@ -12,6 +12,8 @@
# 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.
+#These are a special type of detector, and we're currently relying on this
+#manual file.
org.apache.tika.detect.zip.IPADetector
org.apache.tika.detect.zip.JarDetector
org.apache.tika.detect.zip.KMZDetector
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-package/pom.xml b/tika-parsers/tika-parsers-standard/tika-parsers-standard-package/pom.xml
index f3df5629e..b1ca71e1a 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-package/pom.xml
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-package/pom.xml
@@ -176,6 +176,11 @@
<version>${zstd.version}</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>tika-serialization</artifactId>
+ <scope>test</scope>
+ </dependency>
<!-- For legal reasons (incompatible license), jai-imageio-jpeg2000 is to be used
only in the tests and may not be distributed. See also LEGAL-195 -->
<dependency>
@@ -190,6 +195,12 @@
<version>${project.version}</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>tika-serialization</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>tika-core</artifactId>
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-package/src/test/java/org/apache/tika/config/ComponentRegistryIntegrationTest.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-package/src/test/java/org/apache/tika/config/ComponentRegistryIntegrationTest.java
new file mode 100644
index 000000000..c30f1b0ec
--- /dev/null
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-package/src/test/java/org/apache/tika/config/ComponentRegistryIntegrationTest.java
@@ -0,0 +1,299 @@
+/*
+ * 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.config;
+
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.jupiter.api.Test;
+
+import org.apache.tika.config.loader.TikaLoader;
+import org.apache.tika.detect.Detector;
+import org.apache.tika.parser.AutoDetectParser;
+import org.apache.tika.parser.Parser;
+
+/**
+ * Integration tests to verify that the annotation processor correctly generated
+ * component index files mapping human-readable names to class names, and that
+ * JSON configuration can load components using these names.
+ */
+public class ComponentRegistryIntegrationTest {
+
+ @Test
+ public void testLoadDetectorByName() throws Exception {
+ // Load config that uses "poifs-container-detector" by name
+ Path jsonConfig = Paths.get(
+ getClass().getResource("/configs/test-detectors.json").toURI());
+ assertNotNull(jsonConfig, "test-detectors.json should exist");
+
+ TikaLoader loader = TikaLoader.load(jsonConfig);
+ Detector detector = loader.loadDetectors();
+
+ assertNotNull(detector, "Detector should be loaded");
+ // The detector will be wrapped in a CompositeDetector, so we need to check differently
+ // For now, just verify it loaded successfully
+ }
+
+ @Test
+ public void testLoadDefaultParser() throws Exception {
+ // Load config that uses "default-parser" by name
+ Path jsonConfig = Paths.get(
+ getClass().getResource("/configs/test-default-parser.json").toURI());
+ assertNotNull(jsonConfig, "test-default-parser.json should exist");
+
+ TikaLoader loader = TikaLoader.load(jsonConfig);
+ Parser parser = loader.loadAutoDetectParser();
+
+ assertNotNull(parser, "Parser should be loaded");
+ assertTrue(parser instanceof AutoDetectParser,
+ "Should have loaded AutoDetectParser (default-parser)");
+ }
+
+ @Test
+ public void testLoadDefaultParserWithExclusions() throws Exception {
+ // Load config that excludes "pdf-parser" and "html-parser" by name
+ // This verifies that the component names can be used in exclusion lists
+ Path jsonConfig = Paths.get(
+ getClass().getResource(
+ "/configs/test-default-with-exclusions.json").toURI());
+ assertNotNull(jsonConfig, "test-default-with-exclusions.json should exist");
+
+ TikaLoader loader = TikaLoader.load(jsonConfig);
+ Parser parser = loader.loadAutoDetectParser();
+
+ assertNotNull(parser, "Parser should be loaded");
+ assertTrue(parser instanceof AutoDetectParser,
+ "Should have loaded AutoDetectParser with exclusions");
+
+ // The config loaded successfully, which means it was able to resolve
+ // the component names "pdf-parser" and "html-parser" for exclusion
+ }
+
+ @Test
+ public void testLoadDcXmlParserByName() throws Exception {
+ // Load config that uses "dc-xml-parser" by name
+ // XMLParser has spi=false, but DcXMLParser should be available
+ Path jsonConfig = Paths.get(
+ getClass().getResource("/configs/test-dc-xml-parser.json").toURI());
+ assertNotNull(jsonConfig, "test-dc-xml-parser.json should exist");
+
+ TikaLoader loader = TikaLoader.load(jsonConfig);
+ Parser parser = loader.loadParsers();
+
+ assertNotNull(parser, "Parser should be loaded");
+ // The parser will be wrapped in a CompositeParser, check that it loaded successfully
+ }
+
+ @Test
+ public void testSpiFalseParserInIndexButNotInSpi() throws Exception {
+ // XMLParser has spi=false:
+ // - SHOULD be in index (for name-based configuration)
+ // - should NOT be in SPI (for auto-discovery via ServiceLoader)
+ Map<String, String> parserIndex = readAllIndexFiles("META-INF/tika/parsers.idx");
+
+ // Verify xml-parser IS in index for name-based config
+ assertTrue(parserIndex.containsKey("xml-parser"),
+ "xml-parser should be in index (spi=false still allows name-based config)");
+ assertEquals("org.apache.tika.parser.xml.XMLParser",
+ parserIndex.get("xml-parser"),
+ "xml-parser should map to XMLParser class");
+
+ // Verify dc-xml-parser is also in index
+ assertTrue(parserIndex.containsKey("dc-xml-parser"),
+ "dc-xml-parser should be in index");
+ assertEquals("org.apache.tika.parser.xml.DcXMLParser",
+ parserIndex.get("dc-xml-parser"),
+ "dc-xml-parser should map to DcXMLParser class");
+
+ // Verify xml-parser is NOT in SPI file
+ Map<String, Boolean> spiParsers = readAllSpiFiles("META-INF/services/org.apache.tika.parser.Parser");
+ assertFalse(spiParsers.containsKey("org.apache.tika.parser.xml.XMLParser"),
+ "XMLParser should NOT be in SPI (spi=false prevents auto-discovery)");
+ }
+
+ @Test
+ public void testIndexFilesFollowKebabCaseConvention() throws Exception {
+ // Test that all component names follow kebab-case convention
+ Map<String, String> parserIndex = readAllIndexFiles("META-INF/tika/parsers.idx");
+ Map<String, String> detectorIndex = readAllIndexFiles("META-INF/tika/detectors.idx");
+
+ assertFalse(parserIndex.isEmpty(), "Parser index should not be empty");
+ assertFalse(detectorIndex.isEmpty(), "Detector index should not be empty");
+
+ // Verify all names follow kebab-case convention
+ for (String name : parserIndex.keySet()) {
+ assertTrue(name.matches("[a-z0-9-]+"),
+ "Parser name should be kebab-case: " + name);
+ }
+
+ for (String name : detectorIndex.keySet()) {
+ assertTrue(name.matches("[a-z0-9-]+"),
+ "Detector name should be kebab-case: " + name);
+ }
+ }
+
+ @Test
+ public void testIndexFilesHaveCorrectFormat() throws Exception {
+ // Verify index files have Apache license and correct format
+ Enumeration<URL> resources = getClass().getClassLoader()
+ .getResources("META-INF/tika/parsers.idx");
+
+ assertTrue(resources.hasMoreElements(), "At least one parsers.idx should exist");
+
+ URL url = resources.nextElement();
+ try (BufferedReader reader = new BufferedReader(
+ new InputStreamReader(url.openStream(), StandardCharsets.UTF_8))) {
+ String firstLine = reader.readLine();
+ assertTrue(firstLine.contains("Licensed to the Apache Software Foundation"),
+ "First line should contain Apache license");
+
+ String line;
+ boolean foundFormatComment = false;
+ boolean foundEntry = false;
+
+ while ((line = reader.readLine()) != null) {
+ if (line.startsWith("# Format:")) {
+ foundFormatComment = true;
+ }
+ if (!line.startsWith("#") && !line.trim().isEmpty()) {
+ foundEntry = true;
+ // Verify format: name=fully.qualified.ClassName
+ assertTrue(line.matches("[a-z0-9-]+=\\S+"),
+ "Line should match format 'name=ClassName': " + line);
+ }
+ }
+
+ assertTrue(foundFormatComment, "Should have format comment");
+ assertTrue(foundEntry, "Should have at least one entry");
+ }
+ }
+
+ @Test
+ public void testNoDuplicateComponentNames() throws Exception {
+ // Verify no duplicate names across all index files
+ Map<String, String> parserIndex = readAllIndexFiles("META-INF/tika/parsers.idx");
+ Map<String, String> detectorIndex = readAllIndexFiles("META-INF/tika/detectors.idx");
+
+ // Check for duplicates within each index (readAllIndexFiles already handles this)
+ // The fact that we can build the maps without issues means no duplicates within files
+
+ // Verify all class names are fully qualified
+ for (Map.Entry<String, String> entry : parserIndex.entrySet()) {
+ String className = entry.getValue();
+ assertTrue(className.contains("."),
+ "Parser class name should be fully qualified: " + className);
+ assertTrue(className.startsWith("org.apache.tika."),
+ "Parser class should be in org.apache.tika package: " + className);
+ }
+
+ for (Map.Entry<String, String> entry : detectorIndex.entrySet()) {
+ String className = entry.getValue();
+ assertTrue(className.contains("."),
+ "Detector class name should be fully qualified: " + className);
+ assertTrue(className.startsWith("org.apache.tika."),
+ "Detector class should be in org.apache.tika package: " + className);
+ }
+ }
+
+ /**
+ * Reads all index files with the given resource path from all JARs on the classpath
+ * and merges them into a single map.
+ */
+ private Map<String, String> readAllIndexFiles(String resourcePath) throws Exception {
+ Map<String, String> mergedIndex = new HashMap<>();
+ Enumeration<URL> resources = getClass().getClassLoader().getResources(resourcePath);
+
+ assertTrue(resources.hasMoreElements(),
+ "At least one " + resourcePath + " file should exist");
+
+ while (resources.hasMoreElements()) {
+ URL url = resources.nextElement();
+ try (InputStream stream = url.openStream()) {
+ Map<String, String> index = readIndexFile(stream);
+ mergedIndex.putAll(index);
+ }
+ }
+
+ return mergedIndex;
+ }
+
+ /**
+ * Reads an index file in the format: name=fully.qualified.ClassName
+ */
+ private Map<String, String> readIndexFile(InputStream stream) throws Exception {
+ Map<String, String> index = new HashMap<>();
+ try (BufferedReader reader = new BufferedReader(
+ new InputStreamReader(stream, StandardCharsets.UTF_8))) {
+ String line;
+ while ((line = reader.readLine()) != null) {
+ // Skip comments and empty lines
+ if (line.startsWith("#") || line.trim().isEmpty()) {
+ continue;
+ }
+ String[] parts = line.split("=", 2);
+ if (parts.length == 2) {
+ index.put(parts[0].trim(), parts[1].trim());
+ }
+ }
+ }
+ return index;
+ }
+
+ /**
+ * Reads all SPI service files from all JARs on the classpath.
+ * Returns a map of class names (as keys) to true for easy lookup.
+ */
+ private Map<String, Boolean> readAllSpiFiles(String resourcePath) throws Exception {
+ Map<String, Boolean> spiClasses = new HashMap<>();
+ Enumeration<URL> resources = getClass().getClassLoader().getResources(resourcePath);
+
+ assertTrue(resources.hasMoreElements(),
+ "At least one " + resourcePath + " file should exist");
+
+ while (resources.hasMoreElements()) {
+ URL url = resources.nextElement();
+ try (BufferedReader reader = new BufferedReader(
+ new InputStreamReader(url.openStream(), StandardCharsets.UTF_8))) {
+ String line;
+ while ((line = reader.readLine()) != null) {
+ // Skip comments and empty lines
+ line = line.trim();
+ if (line.isEmpty() || line.startsWith("#")) {
+ continue;
+ }
+ spiClasses.put(line, true);
+ }
+ }
+ }
+
+ return spiClasses;
+ }
+}
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-package/src/test/resources/configs/test-dc-xml-parser.json b/tika-parsers/tika-parsers-standard/tika-parsers-standard-package/src/test/resources/configs/test-dc-xml-parser.json
new file mode 100644
index 000000000..9d21ebd1b
--- /dev/null
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-package/src/test/resources/configs/test-dc-xml-parser.json
@@ -0,0 +1,5 @@
+{
+ "parsers": [
+ {"dc-xml-parser": {}}
+ ]
+}
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-package/src/test/resources/configs/test-default-parser.json b/tika-parsers/tika-parsers-standard/tika-parsers-standard-package/src/test/resources/configs/test-default-parser.json
new file mode 100644
index 000000000..69fa32d42
--- /dev/null
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-package/src/test/resources/configs/test-default-parser.json
@@ -0,0 +1,5 @@
+{
+ "parsers": [
+ {"default-parser": {}}
+ ]
+}
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-package/src/test/resources/configs/test-default-with-exclusions.json b/tika-parsers/tika-parsers-standard/tika-parsers-standard-package/src/test/resources/configs/test-default-with-exclusions.json
new file mode 100644
index 000000000..ab69615f3
--- /dev/null
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-package/src/test/resources/configs/test-default-with-exclusions.json
@@ -0,0 +1,9 @@
+{
+ "parsers": [
+ {
+ "default-parser": {
+ "exclude": ["pdf-parser", "html-parser"]
+ }
+ }
+ ]
+}
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-package/src/test/resources/configs/test-detectors.json b/tika-parsers/tika-parsers-standard/tika-parsers-standard-package/src/test/resources/configs/test-detectors.json
new file mode 100644
index 000000000..6c6461a67
--- /dev/null
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-package/src/test/resources/configs/test-detectors.json
@@ -0,0 +1,5 @@
+{
+ "detectors": [
+ {"poifs-container-detector": {}}
+ ]
+}
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-package/src/test/resources/configs/test-specific-parsers.json b/tika-parsers/tika-parsers-standard/tika-parsers-standard-package/src/test/resources/configs/test-specific-parsers.json
new file mode 100644
index 000000000..0b2ec60d4
--- /dev/null
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-package/src/test/resources/configs/test-specific-parsers.json
@@ -0,0 +1,7 @@
+{
+ "parsers": [
+ {"pdf-parser": {}},
+ {"html-parser": {}},
+ {"xml-parser": {}}
+ ]
+}
diff --git a/tika-serialization/pom.xml b/tika-serialization/pom.xml
index f5eea54f9..2d8d28450 100644
--- a/tika-serialization/pom.xml
+++ b/tika-serialization/pom.xml
@@ -47,6 +47,13 @@
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
+ <!-- Annotation processor - contains @TikaComponent -->
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>tika-annotation-processor</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
@@ -64,6 +71,19 @@
</dependencies>
<build>
<plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <annotationProcessorPaths>
+ <path>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>tika-annotation-processor</artifactId>
+ <version>${project.version}</version>
+ </path>
+ </annotationProcessorPaths>
+ </configuration>
+ </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
diff --git a/tika-serialization/src/main/java/org/apache/tika/config/loader/ConfigLoader.java b/tika-serialization/src/main/java/org/apache/tika/config/loader/ConfigLoader.java
new file mode 100644
index 000000000..c0085e549
--- /dev/null
+++ b/tika-serialization/src/main/java/org/apache/tika/config/loader/ConfigLoader.java
@@ -0,0 +1,349 @@
+/*
+ * 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.config.loader;
+
+import java.lang.reflect.Modifier;
+import java.util.Set;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+import org.apache.tika.exception.TikaConfigException;
+
+/**
+ * Loader for simple configuration objects from JSON.
+ * <p>
+ * This class handles straightforward POJOs that can be deserialized directly from JSON.
+ * For complex components like Parsers, Detectors, etc., use the specific methods on
+ * {@link TikaLoader} instead (e.g., {@code loadParsers()}, {@code loadDetectors()}).
+ *
+ * <p>Usage:
+ * <pre>
+ * TikaLoader loader = TikaLoader.load(configPath);
+ *
+ * // Load by explicit key
+ * HandlerConfig config = loader.configs().load("handler-config", HandlerConfig.class);
+ *
+ * // Load by class name (auto-converts to kebab-case)
+ * HandlerConfig config = loader.configs().load(HandlerConfig.class);
+ * </pre>
+ */
+public class ConfigLoader {
+
+ /**
+ * Reserved keys for complex components that require special handling.
+ * These cannot be loaded via ConfigLoader - use TikaLoader methods instead.
+ */
+ private static final Set<String> PROHIBITED_KEYS =
+ Set.of("parsers", "detectors", "encoding-detectors", "encodingDetectors", "metadata-filters", "metadataFilters", "renderers", "translators");
+
+ private static final Set<String> PROHIBITED_CLASSES =
+ Set.of("org.apache.tika.parser.Parser", "org.apache.tika.detect.Detector",
+ "org.apache.tika.renderer.Renderer",
+ "org.apache.tika.detect.EncodingDetector", "org.apache.tika.metadata.filter.MetadataFilter");
+
+ private final TikaJsonConfig config;
+ private final ObjectMapper objectMapper;
+
+ ConfigLoader(TikaJsonConfig config, ObjectMapper objectMapper) {
+ this.config = config;
+ this.objectMapper = objectMapper;
+ }
+
+ /**
+ * Loads a configuration object using the class name converted to kebab-case.
+ * <p>
+ * For example, {@code HandlerConfig.class} will look for key "handler-config".
+ * Class name suffixes like "Config", "Configuration", "Settings" are stripped first.
+ * <p>
+ * For interfaces, the JSON must specify the implementation (see {@link #load(String, Class)}).
+ *
+ * @param clazz The class to deserialize into (can be interface, abstract, or concrete)
+ * @param <T> The type to load
+ * @return the deserialized object, or null if key not found in config
+ * @throws TikaConfigException if loading fails or class is not instantiable
+ */
+ public <T> T load(Class<T> clazz) throws TikaConfigException {
+ String key = deriveKeyFromClass(clazz);
+ return load(key, clazz);
+ }
+
+ /**
+ * Loads a configuration object using the class name, with a default value.
+ *
+ * @param clazz The class to deserialize into
+ * @param defaultValue The value to return if key not found in config
+ * @param <T> The type to load
+ * @return the deserialized object, or defaultValue if not present
+ * @throws TikaConfigException if loading fails or class is not instantiable
+ */
+ public <T> T load(Class<T> clazz, T defaultValue) throws TikaConfigException {
+ T result = load(clazz);
+ return result != null ? result : defaultValue;
+ }
+
+ /**
+ * Loads a configuration object from the specified JSON key.
+ * <p>
+ * Supports three formats for interfaces:
+ * <ul>
+ * <li>String value: treated as class name or component name to look up</li>
+ * <li>Object with "@class": explicit type specification</li>
+ * <li>Object without "@class": attempts direct deserialization (works for concrete classes)</li>
+ * </ul>
+ *
+ * @param key The JSON key to load from
+ * @param clazz The class to deserialize into (can be interface, abstract, or concrete)
+ * @param <T> The type to load
+ * @return the deserialized object, or null if key not found
+ * @throws TikaConfigException if loading fails or class cannot be instantiated
+ */
+ public <T> T load(String key, Class<T> clazz) throws TikaConfigException {
+ validateKey(key);
+ validateClass(clazz);
+
+ JsonNode node = config.getRootNode().get(key);
+ if (node == null || node.isNull()) {
+ return null;
+ }
+
+ try {
+ // Strategy 1: String value - treat as class name
+ if (node.isTextual()) {
+ return loadFromClassName(node.asText(), clazz);
+ }
+
+ // Strategy 2: Object with @class field - explicit type
+ if (node.isObject() && node.has("@class")) {
+ String className = node.get("@class").asText();
+ Class<?> targetClass = Class.forName(className);
+ if (!clazz.isAssignableFrom(targetClass)) {
+ throw new TikaConfigException(
+ "Class " + className + " is not assignable to " + clazz.getName());
+ }
+ // Remove @class field before deserializing (Jackson doesn't recognize it)
+ ObjectNode objectNode = ((ObjectNode) node).deepCopy();
+ objectNode.remove("@class");
+ return objectMapper.treeToValue(objectNode, (Class<T>) targetClass);
+ }
+
+ // Strategy 3: Direct deserialization (for concrete classes)
+ if (clazz.isInterface() || Modifier.isAbstract(clazz.getModifiers())) {
+ throw new TikaConfigException(
+ "Cannot deserialize " + clazz.getName() + " - it is " +
+ (clazz.isInterface() ? "an interface" : "abstract") + ". " +
+ "Specify implementation using:\n" +
+ " - String value: \"" + key + "\": \"com.example.MyImpl\"\n" +
+ " - Object with @class: \"" + key + "\": {\"@class\": \"com.example.MyImpl\", ...}");
+ }
+
+ return objectMapper.treeToValue(node, clazz);
+ } catch (ClassNotFoundException e) {
+ throw new TikaConfigException(
+ "Class not found for '" + key + "': " + e.getMessage(), e);
+ } catch (JsonProcessingException e) {
+ throw new TikaConfigException(
+ "Failed to deserialize '" + key + "' into " + clazz.getName(), e);
+ }
+ }
+
+ /**
+ * Loads a class from a string (fully qualified class name).
+ */
+ @SuppressWarnings("unchecked")
+ private <T> T loadFromClassName(String className, Class<T> expectedType)
+ throws TikaConfigException {
+ try {
+ Class<?> clazz = Class.forName(className);
+ if (!expectedType.isAssignableFrom(clazz)) {
+ throw new TikaConfigException(
+ "Class " + className + " is not assignable to " + expectedType.getName());
+ }
+
+ // Try to instantiate with no-arg constructor
+ return (T) clazz.getDeclaredConstructor().newInstance();
+ } catch (ClassNotFoundException e) {
+ throw new TikaConfigException("Class not found: " + className, e);
+ } catch (ReflectiveOperationException e) {
+ throw new TikaConfigException(
+ "Failed to instantiate " + className +
+ ". Ensure it has a public no-argument constructor.", e);
+ }
+ }
+
+ /**
+ * Loads a configuration object from the specified JSON key, with a default value.
+ *
+ * @param key The JSON key to load from
+ * @param clazz The class to deserialize into
+ * @param defaultValue The value to return if key not found in config
+ * @param <T> The type to load
+ * @return the deserialized object, or defaultValue if not present
+ * @throws TikaConfigException if loading fails or class is not instantiable
+ */
+ public <T> T load(String key, Class<T> clazz, T defaultValue) throws TikaConfigException {
+ T result = load(key, clazz);
+ return result != null ? result : defaultValue;
+ }
+
+ /**
+ * Loads a configuration object by merging JSON properties into a copy of the default instance.
+ * <p>
+ * This allows partial configuration where only some properties are specified in JSON,
+ * and the rest retain their default values. The original defaultValue object is NOT modified.
+ *
+ * <p>Example:
+ * <pre>
+ * HandlerConfig defaults = new HandlerConfig();
+ * defaults.setTimeout(30000);
+ * defaults.setRetries(2);
+ * defaults.setEnabled(false);
+ *
+ * // JSON: { "enabled": true }
+ * // Result: timeout=30000, retries=2, enabled=true (merged!)
+ * // Note: 'defaults' object remains unchanged
+ * HandlerConfig config = loader.configs().loadWithDefaults("handler-config",
+ * HandlerConfig.class,
+ * defaults);
+ * </pre>
+ *
+ * @param key The JSON key to load from
+ * @param clazz The class type (not used for deserialization, but for type safety)
+ * @param defaultValue The object with default values (will NOT be modified)
+ * @param <T> The type to load
+ * @return a new object with defaults merged with JSON properties, or the original default if key not found
+ * @throws TikaConfigException if loading fails
+ */
+ public <T> T loadWithDefaults(String key, Class<T> clazz, T defaultValue)
+ throws TikaConfigException {
+ validateKey(key);
+ validateClass(clazz);
+
+ JsonNode node = config.getRootNode().get(key);
+ if (node == null || node.isNull()) {
+ return defaultValue;
+ }
+
+ try {
+ // Create a deep copy of defaultValue to avoid mutating the original
+ // Using convertValue is efficient and doesn't require serializing to bytes
+ @SuppressWarnings("unchecked")
+ T copy = objectMapper.convertValue(defaultValue, (Class<T>) defaultValue.getClass());
+
+ // Merge JSON properties into the copy
+ return objectMapper.readerForUpdating(copy).readValue(node);
+ } catch (Exception e) {
+ throw new TikaConfigException(
+ "Failed to merge '" + key + "' into " + clazz.getName(), e);
+ }
+ }
+
+ /**
+ * Loads a configuration object by class name with defaults, merging JSON properties.
+ *
+ * @param clazz The class to deserialize into
+ * @param defaultValue The object with default values to merge into
+ * @param <T> The type to load
+ * @return the default object updated with JSON properties, or the original default if key not found
+ * @throws TikaConfigException if loading fails
+ */
+ public <T> T loadWithDefaults(Class<T> clazz, T defaultValue) throws TikaConfigException {
+ String key = deriveKeyFromClass(clazz);
+ return loadWithDefaults(key, clazz, defaultValue);
+ }
+
+ /**
+ * Checks if a configuration key exists in the JSON config.
+ *
+ * @param key The JSON key to check
+ * @return true if the key exists and is not null
+ */
+ public boolean hasKey(String key) {
+ JsonNode node = config.getRootNode().get(key);
+ return node != null && !node.isNull();
+ }
+
+ /**
+ * Derives a kebab-case key from a class name.
+ * <p>
+ * Uses the full class name converted to kebab-case for consistency with
+ * the annotation processor's component naming.
+ *
+ * @param clazz the class to derive the key from
+ * @return kebab-case version of the class name
+ */
+ private String deriveKeyFromClass(Class<?> clazz) {
+ String simpleName = clazz.getSimpleName();
+ return toKebabCase(simpleName);
+ }
+
+ /**
+ * Converts a camelCase or PascalCase string to kebab-case.
+ * Delegates to {@link KebabCaseConverter} for consistent behavior
+ * with the annotation processor.
+ */
+ private String toKebabCase(String name) {
+ return KebabCaseConverter.toKebabCase(name);
+ }
+
+ /**
+ * Validates that the key is not reserved for complex components.
+ */
+ private void validateKey(String key) throws TikaConfigException {
+ if (PROHIBITED_KEYS.contains(key)) {
+ throw new TikaConfigException(
+ "Cannot load '" + key + "' via ConfigLoader. " +
+ "This is a complex component that requires special handling. " +
+ "Use TikaLoader.load" + toPascalCase(key) + "() instead.");
+ }
+ }
+
+ /**
+ * Validates that complex Tika components aren't loaded via this method.
+ * Interfaces and abstract classes are allowed, but require explicit type info in JSON.
+ */
+ private void validateClass(Class<?> clazz) throws TikaConfigException {
+ // Check for known complex component types (defense in depth)
+ String className = clazz.getName();
+ if (PROHIBITED_CLASSES.contains(className)) {
+ throw new TikaConfigException(
+ clazz.getSimpleName() + " is a Tika component interface. " +
+ "Use the appropriate TikaLoader method (e.g., loadParsers(), loadDetectors()).");
+ }
+ }
+
+ /**
+ * Converts kebab-case to PascalCase for error messages.
+ */
+ private String toPascalCase(String kebabCase) {
+ StringBuilder result = new StringBuilder();
+ boolean capitalizeNext = true;
+ for (char c : kebabCase.toCharArray()) {
+ if (c == '-') {
+ capitalizeNext = true;
+ } else if (capitalizeNext) {
+ result.append(Character.toUpperCase(c));
+ capitalizeNext = false;
+ } else {
+ result.append(c);
+ }
+ }
+ return result.toString();
+ }
+}
diff --git a/tika-serialization/src/main/java/org/apache/tika/config/loader/KebabCaseConverter.java b/tika-serialization/src/main/java/org/apache/tika/config/loader/KebabCaseConverter.java
new file mode 100644
index 000000000..8a12a5033
--- /dev/null
+++ b/tika-serialization/src/main/java/org/apache/tika/config/loader/KebabCaseConverter.java
@@ -0,0 +1,72 @@
+/*
+ * 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.config.loader;
+
+import java.util.Locale;
+
+/**
+ * Utility for converting Java class names to kebab-case.
+ * Used for automatic component name generation from class names.
+ *
+ * <p><strong>Note:</strong> This is a copy of the implementation in
+ * {@code org.apache.tika.annotation.KebabCaseConverter} to avoid
+ * a runtime dependency on the annotation processor module. The two
+ * implementations must be kept in sync.
+ *
+ * <p>Examples:
+ * <ul>
+ * <li>PDFParser → pdf-parser</li>
+ * <li>OCRParser → ocr-parser</li>
+ * <li>HTMLParser → html-parser</li>
+ * <li>DefaultParser → default-parser</li>
+ * <li>TesseractOCRParser → tesseract-ocr-parser</li>
+ * </ul>
+ */
+class KebabCaseConverter {
+
+ private KebabCaseConverter() {
+ // Utility class
+ }
+
+ /**
+ * Converts a Java class name to kebab-case.
+ *
+ * @param className the simple class name (without package)
+ * @return the kebab-case version of the name
+ */
+ static String toKebabCase(String className) {
+ if (className == null || className.isEmpty()) {
+ return className;
+ }
+
+ // Insert hyphen before uppercase letters that follow lowercase letters
+ // or before uppercase letters that are followed by lowercase letters
+ String result = className
+ // Insert hyphen between lowercase and uppercase: "aB" -> "a-B"
+ .replaceAll("([a-z])([A-Z])", "$1-$2")
+ // Insert hyphen before uppercase letter followed by lowercase
+ // in a sequence of uppercase letters: "HTMLParser" -> "HTML-Parser"
+ .replaceAll("([A-Z]+)([A-Z][a-z])", "$1-$2")
+ // Insert hyphen between letter and digit: "PDF2Text" -> "PDF2-Text"
+ .replaceAll("([a-zA-Z])(\\d)", "$1-$2")
+ // Insert hyphen between digit and letter: "2Text" -> "2-Text"
+ .replaceAll("(\\d)([a-zA-Z])", "$1-$2")
+ .toLowerCase(Locale.ROOT);
+
+ return result;
+ }
+}
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 96f668af8..5cfc3cd11 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
@@ -211,12 +211,14 @@ public class ParserLoader {
@SuppressWarnings("unchecked")
private Parser instantiateParser(Class<?> parserClass, String configJson)
throws TikaConfigException {
+
try {
// Try constructor with String parameter (JSON config)
try {
Constructor<?> constructor = parserClass.getConstructor(String.class);
return (Parser) constructor.newInstance(configJson);
} catch (NoSuchMethodException e) {
+ // TODO -- entrypoint for actual configuration
// Fall back to zero-arg constructor
return (Parser) ServiceLoaderUtils.newInstance(parserClass,
new org.apache.tika.config.ServiceLoader(classLoader));
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 7b7bf1c0b..fe8464dd3 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
@@ -26,6 +26,7 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -57,7 +58,25 @@ import org.apache.tika.exception.TikaConfigException;
*/
public class TikaJsonConfig {
- private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
+ private static final ObjectMapper OBJECT_MAPPER = createObjectMapper();
+
+ private static ObjectMapper createObjectMapper() {
+ ObjectMapper mapper = new ObjectMapper();
+
+ // Fail on unknown properties to catch configuration errors early
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true);
+
+ // Prevent null values being assigned to primitive fields (int, boolean, etc.)
+ mapper.configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, true);
+
+ // Ensure enums are properly validated (not just numeric values)
+ mapper.configure(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS, true);
+
+ // Catch duplicate keys in JSON objects
+ mapper.configure(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY, true);
+
+ return mapper;
+ }
private final JsonNode rootNode;
private final Map<String, Map<String, JsonNode>> componentsByType;
diff --git a/tika-serialization/src/main/java/org/apache/tika/config/loader/TikaLoader.java b/tika-serialization/src/main/java/org/apache/tika/config/loader/TikaLoader.java
index 867481d45..2432ed28a 100644
--- a/tika-serialization/src/main/java/org/apache/tika/config/loader/TikaLoader.java
+++ b/tika-serialization/src/main/java/org/apache/tika/config/loader/TikaLoader.java
@@ -16,6 +16,7 @@
*/
package org.apache.tika.config.loader;
+import java.io.IOException;
import java.nio.file.Path;
import java.util.List;
@@ -29,6 +30,9 @@ import org.apache.tika.exception.TikaConfigException;
import org.apache.tika.metadata.filter.CompositeMetadataFilter;
import org.apache.tika.metadata.filter.MetadataFilter;
import org.apache.tika.mime.MediaTypeRegistry;
+import org.apache.tika.parser.AutoDetectParser;
+import org.apache.tika.parser.AutoDetectParserConfig;
+import org.apache.tika.parser.CompositeParser;
import org.apache.tika.parser.Parser;
import org.apache.tika.renderer.CompositeRenderer;
import org.apache.tika.renderer.Renderer;
@@ -78,6 +82,7 @@ public class TikaLoader {
private EncodingDetector encodingDetectors;
private MetadataFilter metadataFilter;
private Renderer renderers;
+ private ConfigLoader configLoader;
private TikaLoader(TikaJsonConfig config, ClassLoader classLoader,
MediaTypeRegistry mediaTypeRegistry) {
@@ -222,6 +227,36 @@ public class TikaLoader {
return renderers;
}
+ public Parser loadAutoDetectParser() throws TikaConfigException, IOException {
+ AutoDetectParserConfig adpConfig = configs().load(AutoDetectParserConfig.class);
+ if (adpConfig == null) {
+ adpConfig = new AutoDetectParserConfig();
+ }
+ return AutoDetectParser.build((CompositeParser)loadParsers(), loadDetectors(), adpConfig);
+ }
+
+ /**
+ * Returns a ConfigLoader for loading simple configuration objects.
+ * <p>
+ * Use this for POJOs and simple config classes. For complex components like
+ * Parsers, Detectors, etc., use the specific load methods on TikaLoader.
+ *
+ * <p>Usage:
+ * <pre>
+ * HandlerConfig config = loader.configs().load("handler-config", HandlerConfig.class);
+ * // Or use kebab-case auto-conversion:
+ * HandlerConfig config = loader.configs().load(HandlerConfig.class);
+ * </pre>
+ *
+ * @return the ConfigLoader instance
+ */
+ public synchronized ConfigLoader configs() {
+ if (configLoader == null) {
+ configLoader = new ConfigLoader(config, objectMapper);
+ }
+ return configLoader;
+ }
+
/**
* Gets the underlying JSON configuration.
*
diff --git a/tika-serialization/src/test/java/org/apache/tika/config/loader/ConfigLoaderTest.java b/tika-serialization/src/test/java/org/apache/tika/config/loader/ConfigLoaderTest.java
new file mode 100644
index 000000000..be207dba3
--- /dev/null
+++ b/tika-serialization/src/test/java/org/apache/tika/config/loader/ConfigLoaderTest.java
@@ -0,0 +1,646 @@
+/*
+ * 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.config.loader;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import org.apache.tika.exception.TikaConfigException;
+
+/**
+ * Unit tests for {@link ConfigLoader}.
+ */
+public class ConfigLoaderTest {
+
+ private TikaLoader tikaLoader;
+ private ConfigLoader configLoader;
+
+ @BeforeEach
+ public void setUp() throws Exception {
+ Path configPath = Paths.get(
+ getClass().getResource("/configs/test-config-loader.json").toURI());
+ tikaLoader = TikaLoader.load(configPath);
+ configLoader = tikaLoader.configs();
+ }
+
+ // ==================== Test POJOs ====================
+
+ /**
+ * Simple config POJO with properties.
+ */
+ public static class HandlerConfig {
+ private int timeout;
+ private int retries;
+ private boolean enabled;
+
+ public int getTimeout() {
+ return timeout;
+ }
+
+ public void setTimeout(int timeout) {
+ this.timeout = timeout;
+ }
+
+ public int getRetries() {
+ return retries;
+ }
+
+ public void setRetries(int retries) {
+ this.retries = retries;
+ }
+
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ }
+ }
+
+ /**
+ * Config class with suffix that should be stripped.
+ */
+ public static class TikaTaskTimeout {
+ private long millis;
+
+ public long getMillis() {
+ return millis;
+ }
+
+ public void setMillis(long millis) {
+ this.millis = millis;
+ }
+ }
+
+ /**
+ * Config class with "Settings" suffix.
+ */
+ public static class MyFeatureSettings {
+ private String featureName;
+ private int priority;
+
+ public String getFeatureName() {
+ return featureName;
+ }
+
+ public void setFeatureName(String featureName) {
+ this.featureName = featureName;
+ }
+
+ public int getPriority() {
+ return priority;
+ }
+
+ public void setPriority(int priority) {
+ this.priority = priority;
+ }
+ }
+
+ /**
+ * Interface for testing interface handling.
+ */
+ public interface TestHandler {
+ String getName();
+ }
+
+ /**
+ * Simple implementation with no-arg constructor.
+ */
+ public static class SimpleHandlerImpl implements TestHandler {
+ public SimpleHandlerImpl() {
+ }
+
+ @Override
+ public String getName() {
+ return "simple";
+ }
+ }
+
+ /**
+ * Implementation with configuration properties.
+ */
+ public static class ConfiguredHandlerImpl implements TestHandler {
+ private int maxSize;
+ private String prefix;
+
+ public ConfiguredHandlerImpl() {
+ }
+
+ @Override
+ public String getName() {
+ return "configured";
+ }
+
+ public int getMaxSize() {
+ return maxSize;
+ }
+
+ public void setMaxSize(int maxSize) {
+ this.maxSize = maxSize;
+ }
+
+ public String getPrefix() {
+ return prefix;
+ }
+
+ public void setPrefix(String prefix) {
+ this.prefix = prefix;
+ }
+ }
+
+ /**
+ * Abstract class for testing abstract class handling.
+ */
+ public abstract static class AbstractHandler implements TestHandler {
+ public abstract void doSomething();
+ }
+
+ // ==================== Tests ====================
+
+ @Test
+ public void testLoadByExplicitKey() throws Exception {
+ HandlerConfig config = configLoader.load("handler-config", HandlerConfig.class);
+
+ assertNotNull(config);
+ assertEquals(5000, config.getTimeout());
+ assertEquals(3, config.getRetries());
+ assertTrue(config.isEnabled());
+ }
+
+ @Test
+ public void testLoadByClassNameKebabCase() throws Exception {
+ HandlerConfig config = configLoader.load(HandlerConfig.class);
+
+ assertNotNull(config);
+ assertEquals(5000, config.getTimeout());
+ }
+
+ @Test
+ public void testLoadByClassNameTikaTaskTimeout() throws Exception {
+ // TikaTaskTimeout -> "tika-task-timeout" (no suffix stripping)
+ // JSON has "tika-task-timeout"
+ TikaTaskTimeout timeout = configLoader.load(TikaTaskTimeout.class);
+
+ assertNotNull(timeout);
+ assertEquals(30000, timeout.getMillis());
+ }
+
+ @Test
+ public void testLoadByClassNameMyFeatureSettings() throws Exception {
+ // MyFeatureSettings -> "my-feature-settings" (full name, no suffix stripping)
+ // JSON has "my-feature-settings"
+ MyFeatureSettings settings = configLoader.load(MyFeatureSettings.class);
+
+ assertNotNull(settings);
+ assertEquals("test-feature", settings.getFeatureName());
+ assertEquals(10, settings.getPriority());
+ }
+
+ @Test
+ public void testLoadWithDefaultValue() throws Exception {
+ HandlerConfig config = configLoader.load("handler-config", HandlerConfig.class);
+ assertNotNull(config);
+
+ // Non-existent key with default
+ HandlerConfig defaultConfig = new HandlerConfig();
+ defaultConfig.setTimeout(9999);
+
+ HandlerConfig result = configLoader.load("non-existent", HandlerConfig.class, defaultConfig);
+ assertEquals(9999, result.getTimeout());
+ }
+
+ @Test
+ public void testLoadMissingKeyReturnsNull() throws Exception {
+ HandlerConfig config = configLoader.load("non-existent-key", HandlerConfig.class);
+ assertNull(config);
+ }
+
+ @Test
+ public void testLoadInterfaceAsString() throws Exception {
+ // JSON: "simple-handler": "org.apache.tika.config.loader.ConfigLoaderTest$SimpleHandlerImpl"
+ TestHandler handler = configLoader.load("simple-handler", TestHandler.class);
+
+ assertNotNull(handler);
+ assertTrue(handler instanceof SimpleHandlerImpl);
+ assertEquals("simple", handler.getName());
+ }
+
+ @Test
+ public void testLoadInterfaceWithAtClassAndProperties() throws Exception {
+ // JSON: "configured-handler": { "@class": "...", "maxSize": 100000, ... }
+ TestHandler handler = configLoader.load("configured-handler", TestHandler.class);
+
+ assertNotNull(handler);
+ assertTrue(handler instanceof ConfiguredHandlerImpl);
+ assertEquals("configured", handler.getName());
+
+ ConfiguredHandlerImpl impl = (ConfiguredHandlerImpl) handler;
+ assertEquals(100000, impl.getMaxSize());
+ assertEquals("test-", impl.getPrefix());
+ }
+
+ @Test
+ public void testLoadInterfaceWithoutTypeInfoFails() throws Exception {
+ // Create a minimal config with just properties, no @class
+ Path configPath = Paths.get(
+ getClass().getResource("/configs/test-interface-no-type.json").toURI());
+ TikaLoader loader = TikaLoader.load(configPath);
+
+ TikaConfigException ex = assertThrows(TikaConfigException.class, () ->
+ loader.configs().load("handler-no-type", TestHandler.class));
+
+ assertTrue(ex.getMessage().contains("interface"));
+ assertTrue(ex.getMessage().contains("@class"));
+ }
+
+ @Test
+ public void testLoadAbstractClassFails() throws Exception {
+ TikaConfigException ex = assertThrows(TikaConfigException.class, () ->
+ configLoader.load("abstract-handler", AbstractHandler.class));
+
+ assertTrue(ex.getMessage().contains("abstract"));
+ }
+
+ @Test
+ public void testLoadProhibitedKeyParsers() throws Exception {
+ TikaConfigException ex = assertThrows(TikaConfigException.class, () ->
+ configLoader.load("parsers", Object.class));
+
+ assertTrue(ex.getMessage().contains("Cannot load 'parsers'"));
+ assertTrue(ex.getMessage().contains("TikaLoader"));
+ }
+
+ @Test
+ public void testLoadProhibitedKeyDetectors() throws Exception {
+ TikaConfigException ex = assertThrows(TikaConfigException.class, () ->
+ configLoader.load("detectors", Object.class));
+
+ assertTrue(ex.getMessage().contains("Cannot load 'detectors'"));
+ }
+
+ @Test
+ public void testLoadProhibitedKeyMetadataFilters() throws Exception {
+ TikaConfigException ex = assertThrows(TikaConfigException.class, () ->
+ configLoader.load("metadata-filters", Object.class));
+
+ assertTrue(ex.getMessage().contains("Cannot load 'metadata-filters'"));
+ }
+
+ @Test
+ public void testHasKey() throws Exception {
+ assertTrue(configLoader.hasKey("handler-config"));
+ assertTrue(configLoader.hasKey("simple-handler"));
+ assertFalse(configLoader.hasKey("non-existent"));
+ }
+
+ @Test
+ public void testLoadInvalidClassName() throws Exception {
+ Path configPath = Paths.get(
+ getClass().getResource("/configs/test-invalid-class.json").toURI());
+ TikaLoader loader = TikaLoader.load(configPath);
+
+ TikaConfigException ex = assertThrows(TikaConfigException.class, () ->
+ loader.configs().load("handler", TestHandler.class));
+
+ assertTrue(ex.getMessage().contains("Class not found"));
+ }
+
+ @Test
+ public void testLoadWrongTypeAssignment() throws Exception {
+ // String class name that doesn't implement the interface
+ Path configPath = Paths.get(
+ getClass().getResource("/configs/test-wrong-type.json").toURI());
+ TikaLoader loader = TikaLoader.load(configPath);
+
+ TikaConfigException ex = assertThrows(TikaConfigException.class, () ->
+ loader.configs().load("handler", TestHandler.class));
+
+ assertTrue(ex.getMessage().contains("not assignable"));
+ }
+
+ @Test
+ public void testLoadWithUnexpectedFieldFails() throws Exception {
+ // Verify that unexpected/unrecognized fields cause an exception
+ Path configPath = Paths.get(
+ getClass().getResource("/configs/test-unexpected-field.json").toURI());
+ TikaLoader loader = TikaLoader.load(configPath);
+
+ TikaConfigException ex = assertThrows(TikaConfigException.class, () ->
+ loader.configs().load("handler-config", HandlerConfig.class));
+
+ // Should contain information about the unrecognized field
+ assertTrue(ex.getMessage().contains("handler-config") ||
+ ex.getCause().getMessage().contains("Unrecognized") ||
+ ex.getCause().getMessage().contains("unexpectedField"),
+ "Exception should mention the unrecognized field");
+ }
+
+ @Test
+ public void testKebabCaseConversion() throws Exception {
+ // Test that kebab-case conversion works correctly
+ // MyFeatureSettings should look for "my-feature-settings" (full kebab-case, no stripping)
+ MyFeatureSettings settings = configLoader.load(MyFeatureSettings.class);
+ assertNotNull(settings);
+ assertEquals("test-feature", settings.getFeatureName());
+ }
+
+ @Test
+ public void testLoadByClassWithDefault() throws Exception {
+ HandlerConfig config = configLoader.load(HandlerConfig.class);
+ assertNotNull(config);
+
+ // Non-existent class
+ TikaTaskTimeout defaultTimeout = new TikaTaskTimeout();
+ defaultTimeout.setMillis(60000);
+
+ // Use a class name that won't match
+ TikaTaskTimeout result = configLoader.load("NonExistentConfig.class",
+ TikaTaskTimeout.class,
+ defaultTimeout);
+ assertEquals(60000, result.getMillis());
+ }
+
+ // ==================== Tests for loadWithDefaults (Partial Config) ====================
+
+ @Test
+ public void testLoadWithDefaultsPartialConfig() throws Exception {
+ // Load config that merges defaults with partial JSON
+ Path configPath = Paths.get(
+ getClass().getResource("/configs/test-partial-config.json").toURI());
+ TikaLoader loader = TikaLoader.load(configPath);
+
+ // Set up defaults
+ HandlerConfig defaults = new HandlerConfig();
+ defaults.setTimeout(30000);
+ defaults.setRetries(2);
+ defaults.setEnabled(false);
+
+ // JSON only has: { "enabled": true }
+ HandlerConfig config = loader.configs().loadWithDefaults("handler-config",
+ HandlerConfig.class,
+ defaults);
+
+ assertNotNull(config);
+ assertEquals(30000, config.getTimeout()); // ✅ From defaults
+ assertEquals(2, config.getRetries()); // ✅ From defaults
+ assertTrue(config.isEnabled()); // ✅ From JSON (overridden)
+ }
+
+ @Test
+ public void testLoadWithDefaultsFullOverride() throws Exception {
+ // Test that JSON can override all defaults
+ Path configPath = Paths.get(
+ getClass().getResource("/configs/test-partial-config.json").toURI());
+ TikaLoader loader = TikaLoader.load(configPath);
+
+ HandlerConfig defaults = new HandlerConfig();
+ defaults.setTimeout(30000);
+ defaults.setRetries(2);
+ defaults.setEnabled(false);
+
+ // JSON has: { "timeout": 10000, "retries": 5, "enabled": false }
+ HandlerConfig config = loader.configs().loadWithDefaults("handler-config-full",
+ HandlerConfig.class,
+ defaults);
+
+ assertNotNull(config);
+ assertEquals(10000, config.getTimeout()); // All overridden
+ assertEquals(5, config.getRetries());
+ assertFalse(config.isEnabled());
+ }
+
+ @Test
+ public void testLoadWithDefaultsMissingKey() throws Exception {
+ // When key doesn't exist, should return original defaults unchanged
+ HandlerConfig defaults = new HandlerConfig();
+ defaults.setTimeout(30000);
+ defaults.setRetries(2);
+ defaults.setEnabled(false);
+
+ HandlerConfig config = configLoader.loadWithDefaults("non-existent-key",
+ HandlerConfig.class,
+ defaults);
+
+ assertNotNull(config);
+ assertEquals(30000, config.getTimeout());
+ assertEquals(2, config.getRetries());
+ assertFalse(config.isEnabled());
+ }
+
+ @Test
+ public void testLoadWithDefaultsByClass() throws Exception {
+ // Test the class-name version
+ Path configPath = Paths.get(
+ getClass().getResource("/configs/test-partial-config.json").toURI());
+ TikaLoader loader = TikaLoader.load(configPath);
+
+ HandlerConfig defaults = new HandlerConfig();
+ defaults.setTimeout(30000);
+ defaults.setRetries(2);
+ defaults.setEnabled(false);
+
+ // Uses kebab-case: HandlerConfig -> "handler-config"
+ HandlerConfig config = loader.configs().loadWithDefaults(HandlerConfig.class, defaults);
+
+ assertNotNull(config);
+ assertEquals(30000, config.getTimeout());
+ assertEquals(2, config.getRetries());
+ assertTrue(config.isEnabled()); // Overridden from JSON
+ }
+
+ @Test
+ public void testLoadVsLoadWithDefaults() throws Exception {
+ // Demonstrate difference between load() and loadWithDefaults()
+ Path configPath = Paths.get(
+ getClass().getResource("/configs/test-partial-config.json").toURI());
+ TikaLoader loader = TikaLoader.load(configPath);
+
+ HandlerConfig defaults = new HandlerConfig();
+ defaults.setTimeout(30000);
+ defaults.setRetries(2);
+ defaults.setEnabled(false);
+
+ // Using load() - creates new object, loses defaults
+ HandlerConfig config1 = loader.configs().load("handler-config", HandlerConfig.class);
+ assertEquals(0, config1.getTimeout()); // ❌ Lost default!
+ assertEquals(0, config1.getRetries()); // ❌ Lost default!
+ assertTrue(config1.isEnabled()); // ✅ From JSON
+
+ // Using loadWithDefaults() - merges into defaults
+ HandlerConfig config2 = loader.configs().loadWithDefaults("handler-config",
+ HandlerConfig.class,
+ defaults);
+ assertEquals(30000, config2.getTimeout()); // ✅ Kept default!
+ assertEquals(2, config2.getRetries()); // ✅ Kept default!
+ assertTrue(config2.isEnabled()); // ✅ From JSON
+ }
+
+ // ==================== Immutability Tests ====================
+
+ @Test
+ public void testLoadWithDefaultsDoesNotMutateOriginal() throws Exception {
+ // Verify that the original defaults object is NOT modified
+ Path configPath = Paths.get(
+ getClass().getResource("/configs/test-partial-config.json").toURI());
+ TikaLoader loader = TikaLoader.load(configPath);
+
+ HandlerConfig defaults = new HandlerConfig();
+ defaults.setTimeout(30000);
+ defaults.setRetries(2);
+ defaults.setEnabled(false);
+
+ // Load config with partial override (JSON only has "enabled": true)
+ HandlerConfig result = loader.configs().loadWithDefaults("handler-config",
+ HandlerConfig.class,
+ defaults);
+
+ // Verify result has merged values
+ assertEquals(30000, result.getTimeout());
+ assertEquals(2, result.getRetries());
+ assertTrue(result.isEnabled()); // Overridden from JSON
+
+ // CRITICAL: Verify original defaults object is unchanged
+ assertEquals(30000, defaults.getTimeout()); // ✅ Still original value
+ assertEquals(2, defaults.getRetries()); // ✅ Still original value
+ assertFalse(defaults.isEnabled()); // ✅ Still original value (NOT changed!)
+
+ // Verify they are different objects
+ assertNotEquals(System.identityHashCode(defaults),
+ System.identityHashCode(result),
+ "Result should be a different object than defaults");
+ }
+
+ @Test
+ public void testLoadWithDefaultsReusableDefaults() throws Exception {
+ // Verify defaults can be safely reused for multiple loads
+ Path configPath = Paths.get(
+ getClass().getResource("/configs/test-partial-config.json").toURI());
+ TikaLoader loader = TikaLoader.load(configPath);
+
+ HandlerConfig defaults = new HandlerConfig();
+ defaults.setTimeout(30000);
+ defaults.setRetries(2);
+ defaults.setEnabled(false);
+
+ // Load multiple times with same defaults
+ HandlerConfig config1 = loader.configs().loadWithDefaults("handler-config",
+ HandlerConfig.class,
+ defaults);
+ HandlerConfig config2 = loader.configs().loadWithDefaults("handler-config-full",
+ HandlerConfig.class,
+ defaults);
+
+ // Verify results are different
+ assertTrue(config1.isEnabled()); // From partial config
+ assertFalse(config2.isEnabled()); // From full config
+
+ // Verify defaults still unchanged and can be used again
+ assertEquals(30000, defaults.getTimeout());
+ assertEquals(2, defaults.getRetries());
+ assertFalse(defaults.isEnabled());
+
+ // Use defaults one more time
+ HandlerConfig config3 = loader.configs().loadWithDefaults("non-existent",
+ HandlerConfig.class,
+ defaults);
+ assertEquals(defaults, config3); // Should return original when key missing
+ }
+
+ @Test
+ public void testLoadWithDefaultsComplexObjectImmutability() throws Exception {
+ // Test with nested/complex objects to ensure deep copy works
+ Path configPath = Paths.get(
+ getClass().getResource("/configs/test-partial-config.json").toURI());
+ TikaLoader loader = TikaLoader.load(configPath);
+
+ TikaTaskTimeout defaults = new TikaTaskTimeout();
+ defaults.setMillis(60000);
+
+ // Note: tika-task-timeout in JSON has millis: 30000
+ TikaTaskTimeout result = loader.configs().loadWithDefaults("tika-task-timeout",
+ TikaTaskTimeout.class,
+ defaults);
+
+ // Result should have JSON value
+ assertEquals(30000, result.getMillis());
+
+ // Original should be unchanged
+ assertEquals(60000, defaults.getMillis());
+ }
+
+ @Test
+ public void testLoadWithDefaultsMissingKeyDoesNotClone() throws Exception {
+ // When key is missing, should return the original object (no unnecessary cloning)
+ HandlerConfig defaults = new HandlerConfig();
+ defaults.setTimeout(30000);
+ defaults.setRetries(2);
+ defaults.setEnabled(false);
+
+ HandlerConfig result = configLoader.loadWithDefaults("non-existent-key",
+ HandlerConfig.class,
+ defaults);
+
+ // Should return the exact same object when key is missing
+ assertEquals(defaults, result);
+ assertEquals(System.identityHashCode(defaults),
+ System.identityHashCode(result),
+ "Should return same object when key missing (no unnecessary clone)");
+ }
+
+ @Test
+ public void testLoadWithDefaultsThreadSafety() throws Exception {
+ // Demonstrate that defaults can be safely shared across threads
+ Path configPath = Paths.get(
+ getClass().getResource("/configs/test-partial-config.json").toURI());
+ TikaLoader loader = TikaLoader.load(configPath);
+
+ // Shared defaults object
+ HandlerConfig sharedDefaults = new HandlerConfig();
+ sharedDefaults.setTimeout(30000);
+ sharedDefaults.setRetries(2);
+ sharedDefaults.setEnabled(false);
+
+ // Simulate concurrent usage (not a real concurrency test, just demonstrates safety)
+ HandlerConfig result1 = loader.configs().loadWithDefaults("handler-config",
+ HandlerConfig.class,
+ sharedDefaults);
+ HandlerConfig result2 = loader.configs().loadWithDefaults("handler-config-full",
+ HandlerConfig.class,
+ sharedDefaults);
+
+ // Both results should be valid
+ assertNotNull(result1);
+ assertNotNull(result2);
+
+ // Shared defaults should still be unchanged
+ assertEquals(30000, sharedDefaults.getTimeout());
+ assertEquals(2, sharedDefaults.getRetries());
+ assertFalse(sharedDefaults.isEnabled());
+ }
+}
diff --git a/tika-serialization/src/test/resources/META-INF/services/org.apache.tika.parser.Parser b/tika-serialization/src/test/resources/META-INF/services/org.apache.tika.parser.Parser
deleted file mode 100644
index fbf6d840b..000000000
--- a/tika-serialization/src/test/resources/META-INF/services/org.apache.tika.parser.Parser
+++ /dev/null
@@ -1,4 +0,0 @@
-# Test parsers for tika-serialization module
-org.apache.tika.config.loader.ConfigurableTestParser
-org.apache.tika.config.loader.FallbackTestParser
-org.apache.tika.config.loader.MinimalTestParser
diff --git a/tika-serialization/src/test/resources/META-INF/tika/parsers.idx b/tika-serialization/src/test/resources/META-INF/tika/parsers.idx
deleted file mode 100644
index 99a58d8ed..000000000
--- a/tika-serialization/src/test/resources/META-INF/tika/parsers.idx
+++ /dev/null
@@ -1,5 +0,0 @@
-# Test parsers index for tika-serialization module tests
-configurable-test-parser=org.apache.tika.config.loader.ConfigurableTestParser
-fallback-test-parser=org.apache.tika.config.loader.FallbackTestParser
-minimal-test-parser=org.apache.tika.config.loader.MinimalTestParser
-opt-in-test-parser=org.apache.tika.config.loader.OptInTestParser
diff --git a/tika-serialization/src/test/resources/configs/test-config-loader.json b/tika-serialization/src/test/resources/configs/test-config-loader.json
new file mode 100644
index 000000000..8f6e89a8c
--- /dev/null
+++ b/tika-serialization/src/test/resources/configs/test-config-loader.json
@@ -0,0 +1,32 @@
+{
+ "handler-config": {
+ "timeout": 5000,
+ "retries": 3,
+ "enabled": true
+ },
+
+ "simple-handler": "org.apache.tika.config.loader.ConfigLoaderTest$SimpleHandlerImpl",
+
+ "configured-handler": {
+ "@class": "org.apache.tika.config.loader.ConfigLoaderTest$ConfiguredHandlerImpl",
+ "maxSize": 100000,
+ "prefix": "test-"
+ },
+
+ "tika-task-timeout": {
+ "millis": 30000
+ },
+
+ "parsers": [
+ {"pdf-parser": {}}
+ ],
+
+ "my-feature-settings": {
+ "featureName": "test-feature",
+ "priority": 10
+ },
+
+ "abstract-handler": {
+ "someProperty": "value"
+ }
+}
diff --git a/tika-serialization/src/test/resources/configs/test-interface-no-type.json b/tika-serialization/src/test/resources/configs/test-interface-no-type.json
new file mode 100644
index 000000000..15a3d35b2
--- /dev/null
+++ b/tika-serialization/src/test/resources/configs/test-interface-no-type.json
@@ -0,0 +1,6 @@
+{
+ "handler-no-type": {
+ "maxSize": 50000,
+ "prefix": "no-type-"
+ }
+}
diff --git a/tika-serialization/src/test/resources/configs/test-invalid-class.json b/tika-serialization/src/test/resources/configs/test-invalid-class.json
new file mode 100644
index 000000000..f0bf4bf4e
--- /dev/null
+++ b/tika-serialization/src/test/resources/configs/test-invalid-class.json
@@ -0,0 +1,3 @@
+{
+ "handler": "com.example.NonExistentClass"
+}
diff --git a/tika-serialization/src/test/resources/configs/test-partial-config.json b/tika-serialization/src/test/resources/configs/test-partial-config.json
new file mode 100644
index 000000000..fb010c3e8
--- /dev/null
+++ b/tika-serialization/src/test/resources/configs/test-partial-config.json
@@ -0,0 +1,15 @@
+{
+ "handler-config": {
+ "enabled": true
+ },
+
+ "handler-config-full": {
+ "timeout": 10000,
+ "retries": 5,
+ "enabled": false
+ },
+
+ "tika-task-timeout": {
+ "millis": 30000
+ }
+}
diff --git a/tika-serialization/src/test/resources/configs/test-unexpected-field.json b/tika-serialization/src/test/resources/configs/test-unexpected-field.json
new file mode 100644
index 000000000..ada7f9bdf
--- /dev/null
+++ b/tika-serialization/src/test/resources/configs/test-unexpected-field.json
@@ -0,0 +1,8 @@
+{
+ "handler-config": {
+ "timeout": 5000,
+ "retries": 3,
+ "enabled": true,
+ "unexpectedField": "this should cause an error"
+ }
+}
diff --git a/tika-serialization/src/test/resources/configs/test-wrong-type.json b/tika-serialization/src/test/resources/configs/test-wrong-type.json
new file mode 100644
index 000000000..b25e9f644
--- /dev/null
+++ b/tika-serialization/src/test/resources/configs/test-wrong-type.json
@@ -0,0 +1,3 @@
+{
+ "handler": "java.lang.String"
+}