Skip to content

Commit e7161b7

Browse files
authored
TIKA-4545 - clean up media registry (#2411)
1 parent 7b96164 commit e7161b7

2 files changed

Lines changed: 48 additions & 36 deletions

File tree

tika-serialization/src/main/java/org/apache/tika/config/loader/ParserLoader.java

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,10 @@
3333
import org.slf4j.Logger;
3434
import org.slf4j.LoggerFactory;
3535

36+
import org.apache.tika.detect.EncodingDetector;
3637
import org.apache.tika.exception.TikaConfigException;
3738
import org.apache.tika.mime.MediaType;
38-
import org.apache.tika.mime.MediaTypeRegistry;
39+
import org.apache.tika.parser.AbstractEncodingDetectorParser;
3940
import org.apache.tika.parser.CompositeParser;
4041
import org.apache.tika.parser.Parser;
4142
import org.apache.tika.parser.ParserDecorator;
@@ -52,7 +53,7 @@ public class ParserLoader {
5253

5354
private final ClassLoader classLoader;
5455
private final ObjectMapper objectMapper;
55-
private final MediaTypeRegistry mediaTypeRegistry;
56+
private final EncodingDetector encodingDetector;
5657

5758
/**
5859
* Holds parsed config data before decoration is applied.
@@ -71,10 +72,10 @@ private static class ParsedParserConfig {
7172
}
7273

7374
public ParserLoader(ClassLoader classLoader, ObjectMapper objectMapper,
74-
MediaTypeRegistry mediaTypeRegistry) {
75+
EncodingDetector encodingDetector) {
7576
this.classLoader = classLoader;
7677
this.objectMapper = objectMapper;
77-
this.mediaTypeRegistry = mediaTypeRegistry;
78+
this.encodingDetector = encodingDetector;
7879
}
7980

8081
/**
@@ -85,6 +86,8 @@ public ParserLoader(ClassLoader classLoader, ObjectMapper objectMapper,
8586
* @throws TikaConfigException if loading fails
8687
*/
8788
public CompositeParser load(TikaJsonConfig config) throws TikaConfigException {
89+
//TODO -- need to handle multiparsers at some point
90+
//TODO -- add special handling for external parsers?
8891
List<Parser> parserList = new ArrayList<>();
8992

9093
// Load configured parsers
@@ -185,7 +188,7 @@ public CompositeParser load(TikaJsonConfig config) throws TikaConfigException {
185188
parserList.addAll(spiParsers);
186189
}
187190

188-
return new CompositeParser(mediaTypeRegistry, parserList);
191+
return new CompositeParser(TikaLoader.getMediaTypeRegistry(), parserList);
189192
}
190193

191194
private ParsedParserConfig loadConfiguredParser(String name, JsonNode configNode,
@@ -213,16 +216,32 @@ private Parser instantiateParser(Class<?> parserClass, String configJson)
213216
throws TikaConfigException {
214217

215218
try {
219+
Parser parser;
220+
216221
// Try constructor with String parameter (JSON config)
217222
try {
223+
//TODO -- change this from String to JsonConfig or simple wrapper class
218224
Constructor<?> constructor = parserClass.getConstructor(String.class);
219-
return (Parser) constructor.newInstance(configJson);
225+
parser = (Parser) constructor.newInstance(configJson);
220226
} catch (NoSuchMethodException e) {
221-
// TODO -- entrypoint for actual configuration
222-
// Fall back to zero-arg constructor
223-
return (Parser) ServiceLoaderUtils.newInstance(parserClass,
224-
new org.apache.tika.config.ServiceLoader(classLoader));
227+
// Try constructor with EncodingDetector parameter (for AbstractEncodingDetectorParser)
228+
if (AbstractEncodingDetectorParser.class.isAssignableFrom(parserClass)) {
229+
try {
230+
Constructor<?> constructor = parserClass.getConstructor(EncodingDetector.class);
231+
parser = (Parser) constructor.newInstance(encodingDetector);
232+
} catch (NoSuchMethodException ex) {
233+
// Fall back to zero-arg constructor
234+
parser = (Parser) ServiceLoaderUtils.newInstance(parserClass,
235+
new org.apache.tika.config.ServiceLoader(classLoader));
236+
}
237+
} else {
238+
// Fall back to zero-arg constructor
239+
parser = (Parser) ServiceLoaderUtils.newInstance(parserClass,
240+
new org.apache.tika.config.ServiceLoader(classLoader));
241+
}
225242
}
243+
244+
return parser;
226245
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
227246
throw new TikaConfigException("Failed to instantiate parser: " +
228247
parserClass.getName(), e);
@@ -268,7 +287,7 @@ private Parser applyFallbacks(Parser parser, FrameworkConfig.ParserDecoration de
268287
fallbackParsers.add(fallbackConfig.parser);
269288
}
270289

271-
return new FallbackParser(mediaTypeRegistry, MetadataPolicy.KEEP_ALL, fallbackParsers);
290+
return new FallbackParser(TikaLoader.getMediaTypeRegistry(), MetadataPolicy.KEEP_ALL, fallbackParsers);
272291
}
273292

274293
private List<Parser> loadSpiParsers(Set<Class<?>> excludeClasses) {

tika-serialization/src/main/java/org/apache/tika/config/loader/TikaLoader.java

Lines changed: 18 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -74,22 +74,20 @@ public class TikaLoader {
7474
private final TikaJsonConfig config;
7575
private final ClassLoader classLoader;
7676
private final ObjectMapper objectMapper;
77-
private final MediaTypeRegistry mediaTypeRegistry;
7877

7978
// Cached instances (lazy loaded)
79+
private static MediaTypeRegistry mediaTypeRegistry;
8080
private Parser parsers;
8181
private Detector detectors;
8282
private EncodingDetector encodingDetectors;
8383
private MetadataFilter metadataFilter;
8484
private Renderer renderers;
8585
private ConfigLoader configLoader;
8686

87-
private TikaLoader(TikaJsonConfig config, ClassLoader classLoader,
88-
MediaTypeRegistry mediaTypeRegistry) {
87+
private TikaLoader(TikaJsonConfig config, ClassLoader classLoader) {
8988
this.config = config;
9089
this.classLoader = classLoader;
9190
this.objectMapper = TikaJsonConfig.getObjectMapper();
92-
this.mediaTypeRegistry = mediaTypeRegistry;
9391
}
9492

9593
/**
@@ -114,36 +112,26 @@ public static TikaLoader load(Path configPath) throws TikaConfigException {
114112
public static TikaLoader load(Path configPath, ClassLoader classLoader)
115113
throws TikaConfigException {
116114
TikaJsonConfig config = TikaJsonConfig.load(configPath);
117-
MediaTypeRegistry registry = MediaTypeRegistry.getDefaultRegistry();
118-
return new TikaLoader(config, classLoader, registry);
119-
}
120-
121-
/**
122-
* Loads a Tika configuration with custom media type registry.
123-
*
124-
* @param configPath the path to the JSON configuration file
125-
* @param classLoader the class loader to use for loading components
126-
* @param mediaTypeRegistry the media type registry to use
127-
* @return the Tika loader
128-
* @throws TikaConfigException if loading or parsing fails
129-
*/
130-
public static TikaLoader load(Path configPath, ClassLoader classLoader,
131-
MediaTypeRegistry mediaTypeRegistry)
132-
throws TikaConfigException {
133-
TikaJsonConfig config = TikaJsonConfig.load(configPath);
134-
return new TikaLoader(config, classLoader, mediaTypeRegistry);
115+
return new TikaLoader(config, classLoader);
135116
}
136117

137118
/**
138119
* Loads and returns all parsers.
139120
* Results are cached - subsequent calls return the same instance.
121+
* <p>
122+
* Note: This method ensures EncodingDetectors are loaded first,
123+
* as some parsers require them during construction (e.g., AbstractEncodingDetectorParser
124+
* requires an EncodingDetector).
140125
*
141126
* @return the parser (typically a CompositeParser internally)
142127
* @throws TikaConfigException if loading fails
143128
*/
144129
public synchronized Parser loadParsers() throws TikaConfigException {
145130
if (parsers == null) {
146-
ParserLoader loader = new ParserLoader(classLoader, objectMapper, mediaTypeRegistry);
131+
// Load EncodingDetectors first - some parsers need them during construction
132+
EncodingDetector encodingDetector = loadEncodingDetectors();
133+
134+
ParserLoader loader = new ParserLoader(classLoader, objectMapper, encodingDetector);
147135
parsers = loader.load(config);
148136
}
149137
return parsers;
@@ -163,7 +151,7 @@ public synchronized Detector loadDetectors() throws TikaConfigException {
163151
CompositeComponentLoader<Detector> loader = new CompositeComponentLoader<>(
164152
Detector.class, "detectors", "detectors", classLoader, objectMapper);
165153
List<Detector> detectorList = loader.loadFromArray(config);
166-
detectors = new CompositeDetector(mediaTypeRegistry, detectorList);
154+
detectors = new CompositeDetector(getMediaTypeRegistry(), detectorList);
167155
}
168156
return detectors;
169157
}
@@ -277,10 +265,15 @@ public ClassLoader getClassLoader() {
277265

278266
/**
279267
* Gets the media type registry.
268+
* Lazily loads the default registry if not already set.
269+
* This is a static singleton shared across all TikaLoader instances.
280270
*
281271
* @return the media type registry
282272
*/
283-
public MediaTypeRegistry getMediaTypeRegistry() {
273+
public static synchronized MediaTypeRegistry getMediaTypeRegistry() {
274+
if (mediaTypeRegistry == null) {
275+
mediaTypeRegistry = MediaTypeRegistry.getDefaultRegistry();
276+
}
284277
return mediaTypeRegistry;
285278
}
286279
}

0 commit comments

Comments
 (0)