blob: 22a85a7b29f796d958c4f462f8b9099a75f07fa8 [file] [log] [blame]
/*
* 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.jackrabbit.oak.plugins.tika;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.tika.config.TikaConfig;
import org.apache.tika.exception.TikaException;
import org.apache.tika.mime.MediaType;
import org.apache.tika.parser.AutoDetectParser;
import org.apache.tika.parser.CompositeParser;
import org.apache.tika.parser.EmptyParser;
import org.apache.tika.parser.ParseContext;
import org.apache.tika.parser.Parser;
import org.apache.tika.parser.ParserDecorator;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.SAXException;
class TikaHelper {
private static final String DEFAULT_TIKA_CONFIG = "/org/apache/jackrabbit/oak/plugins/index/lucene/tika-config.xml";
private static final Logger log = LoggerFactory.getLogger(TikaHelper.class);
private final AutoDetectParser parser;
private final Set<MediaType> supportedMediaTypes;
private static AtomicBoolean supportedTypesLogged = new AtomicBoolean();
public TikaHelper(@Nullable File tikaConfig) throws IOException {
try {
parser = new AutoDetectParser(getTikaConfig(tikaConfig));
supportedMediaTypes = parser.getSupportedTypes(new ParseContext());
logSupportedTypesOnce(supportedMediaTypes);
} catch (TikaException e) {
throw new RuntimeException(e);
} catch (SAXException e) {
throw new RuntimeException(e);
}
}
public Parser getParser() {
return parser;
}
public boolean isSupportedMediaType(String type) {
return supportedMediaTypes.contains(MediaType.parse(type));
}
/**
* This method should only be used for information purpose and not be relied
* upon to determine if the given type is indexed or not. It relies on Tika
* implementation detail to determine if a given type is meant to be indexed
*
* @param type mimeType to check
* @return true if the given type is supported and indexed
*/
public boolean isIndexed(String type) {
if (!isSupportedMediaType(type)){
return false;
}
MediaType mediaType = MediaType.parse(type);
Parser p = getSupportingParser(parser, mediaType);
if (p == null){
return false;
}
p = unwrap(p);
if (p instanceof EmptyParser){
return false;
}
return true;
}
private static TikaConfig getTikaConfig(File tikaConfig) throws TikaException, IOException, SAXException {
TikaConfig config;
if (tikaConfig == null) {
URL configUrl = TextExtractor.class.getResource(DEFAULT_TIKA_CONFIG);
if (configUrl != null) {
log.info("Loading default Tika config from {}", configUrl);
config = new TikaConfig(configUrl);
} else {
log.info("Using default Tika config");
config = TikaConfig.getDefaultConfig();
}
} else {
log.info("Loading external Tika config from {}", tikaConfig);
config = new TikaConfig(tikaConfig);
}
return config;
}
private static Parser getSupportingParser(Parser p, MediaType mediaType){
if (p instanceof CompositeParser){
Map<MediaType, Parser> parsers = ((CompositeParser) p).getParsers();
return getSupportingParser(parsers.get(mediaType), mediaType);
}
return p;
}
private static Parser unwrap(Parser p){
if (p instanceof ParserDecorator){
return unwrap(((ParserDecorator) p).getWrappedParser());
}
return p;
}
private static void logSupportedTypesOnce(Set<MediaType> supportedMediaTypes) {
boolean alreadyLogged = supportedTypesLogged.getAndSet(true);
if (!alreadyLogged) {
log.info("Supported media types {}", supportedMediaTypes);
}
}
}