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 2021/01/26 19:46:56 UTC
[tika] branch TIKA-3226 updated: TIKA-3226 -- WIP don't merge
This is an automated email from the ASF dual-hosted git repository.
tallison pushed a commit to branch TIKA-3226
in repository https://gitbox.apache.org/repos/asf/tika.git
The following commit(s) were added to refs/heads/TIKA-3226 by this push:
new 1dd15d9 TIKA-3226 -- WIP don't merge
1dd15d9 is described below
commit 1dd15d93c45ee95761bd28306da1ba07ba751503
Author: tballison <ta...@apache.org>
AuthorDate: Tue Jan 26 14:46:40 2021 -0500
TIKA-3226 -- WIP don't merge
---
pom.xml | 3 +-
.../main/java/org/apache/tika/config/Param.java | 8 +-
.../java/org/apache/tika/config/TikaConfig.java | 527 ++++++++++++---------
.../main/java/org/apache/tika/emitter/Emitter.java | 20 -
.../apache/tika/emitter/TikaEmitterException.java | 9 -
.../apache/tika/fetcher/DefaultFetchIterator.java | 57 ---
.../org/apache/tika/fetcher/FetchIterator.java | 141 ------
.../apache/tika/fetcher/FetchPrefixKeyPair.java | 53 ---
.../org/apache/tika/fetcher/FileSystemFetcher.java | 79 ---
.../emitter/AbstractEmitter.java} | 20 +-
.../emitter/Emitter.java} | 21 +-
.../emitter/EmitterManager.java} | 40 +-
.../emitter/EmptyEmitter.java} | 31 +-
.../emitter/TikaEmitterException.java} | 10 +-
.../fetcher/AbstractFetcher.java} | 31 +-
.../fetcher/EmptyFetcher.java} | 21 +-
.../org/apache/tika/pipes/fetcher/FetchId.java | 65 +++
.../fetcher/FetchIdMetadataPair.java} | 40 +-
.../apache/tika/{ => pipes}/fetcher/Fetcher.java | 12 +-
.../fetcher/FetcherManager.java} | 50 +-
.../fetcher/FetcherStringException.java | 2 +-
.../tika/pipes/fetcher/FileSystemFetcher.java | 110 +++++
.../tika/{ => pipes}/fetcher/SimpleUrlFetcher.java | 18 +-
.../fetchiterator/EmptyFetchIterator.java} | 22 +-
.../tika/pipes/fetchiterator/FetchIterator.java | 135 ++++++
.../fetchiterator}/FileSystemFetchIterator.java | 66 +--
.../org/apache/tika/config/TikaConfigTest.java | 67 +++
.../apache/tika/pipes/emitter/MockEmitter.java} | 16 +-
.../tika/pipes/fetcher/FileSystemFetcherTest.java | 54 +++
.../FileSystemFetchIteratorTest.java | 40 +-
.../org/apache/tika/config/emitters-config.xml | 18 +-
.../tika/config/emitters-duplicate-config.xml | 18 +-
.../apache/tika/config/fetch-iterator-config.xml | 14 +-
.../tika/config/fetch-iterator-multiple-config.xml | 20 +-
.../org/apache/tika/config/fetchers-config.xml | 14 +-
.../tika/config/fetchers-duplicate-config.xml | 14 +-
.../tika/config/fetchers-nobasepath-config.xml | 13 +-
.../apache/tika/config/fetchers-noname-config.xml | 13 +-
tika-fetchers/tika-fetcher-jdbc/pom.xml | 122 -----
.../org/apache/tika/fetcher/jdbc/JDBCFetcher.java | 100 ----
tika-pipes/pom.xml | 41 ++
.../tika-emitters}/pom.xml | 6 +-
.../tika-emitters}/tika-emitter-fs/pom.xml | 0
.../apache/tika/emitter/fs/FileSystemEmitter.java | 26 +-
.../tika-emitters}/tika-emitter-solr/pom.xml | 0
.../org/apache/tika/emitter/solr/SolrEmitter.java | 33 +-
.../org/apache/tika/emitter/solr/TestBasic.java | 25 +-
.../src/test/resources/log4j.properties | 0
.../test/resources/tika-config-simple-emitter.xml | 0
.../tika-fetch-iterators}/pom.xml | 21 +-
.../tika-fetch-iterator-csv}/pom.xml | 23 +-
.../pipes/fetchiterator/csv/CSVFetchIterator.java | 121 +++++
.../src/test/java/TestCSVFetchIterator.java | 129 +++++
.../src/test/resources/test-simple.csv | 6 +
.../tika-fetch-iterator-jdbc}/pom.xml | 24 +-
.../fetchiterator/jdbc/JDBCFetchIterator.java | 166 +++++++
.../fetchiterator/jdbc/TestJDBCFetchIterator.java | 178 +++++++
.../src/test/resources/log4j.properties | 4 +-
.../tika-fetch-iterator-s3}/pom.xml | 53 ++-
.../pipes/fetchiterator/s3/S3FetchIterator.java | 109 +++++
.../fetchiterator/s3/TestS3FetchIterator.java | 98 ++++
.../src/test/resources/log4j.properties | 4 +-
.../tika-fetchers}/pom.xml | 5 +-
.../tika-fetchers}/tika-fetcher-s3/pom.xml | 6 +-
.../apache/tika/pipes}/fetcher/s3/S3Fetcher.java | 73 +--
.../tika/pipes}/fetcher/s3/TestS3Fetcher.java | 7 +-
.../src/test/resources/tika-config-s3.xml | 1 +
.../tika-httpclient-commons/pom.xml | 3 +-
.../org/apache/tika/client/HttpClientUtil.java | 0
.../apache/tika/client/TikaClientException.java | 0
.../tika-pipes-integration-tests}/pom.xml | 33 +-
.../apache/tika/pipes/PipeIntegrationTests.java | 162 +++++++
.../src/test/resources/log4j.properties | 4 +-
.../src/test/resources/tika-config-s3ToFs.xml | 22 +
.../apache/tika/server/classic/FetcherTest.java | 5 +-
.../resources/config/tika-config-url-fetcher.xml | 6 +-
.../org/apache/tika/server/client/TikaClient.java | 13 +-
.../apache/tika/server/client/TikaClientCLI.java | 78 +--
.../resources/tika-config-simple-solr-emitter.xml | 4 +-
.../tika/server/core/FetcherStreamFactory.java | 24 +-
.../org/apache/tika/server/core/TikaServerCli.java | 15 +-
.../tika/server/core/resource/EmitterResource.java | 83 ++--
.../apache/tika/server/core/TikaEmitterTest.java | 21 +-
.../core/TikaServerEmitterIntegrationTest.java | 13 +-
.../resources/test-documents/mock/hello_world.xml | 1 +
85 files changed, 2424 insertions(+), 1336 deletions(-)
diff --git a/pom.xml b/pom.xml
index a31f4fe..37389a1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -37,8 +37,7 @@
<modules>
<module>tika-parent</module>
<module>tika-core</module>
- <module>tika-emitters</module>
- <module>tika-fetchers</module>
+ <module>tika-pipes</module>
<module>tika-parsers</module>
<module>tika-bundles</module>
<module>tika-xmp</module>
diff --git a/tika-core/src/main/java/org/apache/tika/config/Param.java b/tika-core/src/main/java/org/apache/tika/config/Param.java
index 3462252..74123ac 100644
--- a/tika-core/src/main/java/org/apache/tika/config/Param.java
+++ b/tika-core/src/main/java/org/apache/tika/config/Param.java
@@ -218,16 +218,16 @@ public class Param<T> implements Serializable {
if (valueAttr != null && (value == null || value.getTextContent() == null)) {
value = valueAttr;
}
- if (typeAttr == null) {
- throw new TikaConfigException("Must specify a \"type\" in: " + node.getLocalName());
- }
-
+
Param<T> ret = new Param<T>();
ret.name = nameAttr.getTextContent();
if (typeAttr != null) {
ret.setTypeString(typeAttr.getTextContent());
} else {
ret.type = (Class<T>)wellKnownMap.get(ret.name);
+ if (ret.type == null) {
+ throw new TikaConfigException("Must specify a \"type\" in: " + node.getLocalName());
+ }
}
if (List.class.isAssignableFrom(ret.type)) {
diff --git a/tika-core/src/main/java/org/apache/tika/config/TikaConfig.java b/tika-core/src/main/java/org/apache/tika/config/TikaConfig.java
index df4c43c..f852c57 100644
--- a/tika-core/src/main/java/org/apache/tika/config/TikaConfig.java
+++ b/tika-core/src/main/java/org/apache/tika/config/TikaConfig.java
@@ -46,14 +46,14 @@ import org.apache.tika.detect.DefaultDetector;
import org.apache.tika.detect.DefaultEncodingDetector;
import org.apache.tika.detect.Detector;
import org.apache.tika.detect.EncodingDetector;
-import org.apache.tika.emitter.DefaultEmitter;
-import org.apache.tika.emitter.Emitter;
+import org.apache.tika.pipes.emitter.Emitter;
import org.apache.tika.exception.TikaConfigException;
import org.apache.tika.exception.TikaException;
-import org.apache.tika.fetcher.DefaultFetchIterator;
-import org.apache.tika.fetcher.DefaultFetcher;
-import org.apache.tika.fetcher.FetchIterator;
-import org.apache.tika.fetcher.Fetcher;
+import org.apache.tika.pipes.emitter.EmitterManager;
+import org.apache.tika.pipes.fetcher.FetcherManager;
+import org.apache.tika.pipes.fetchiterator.EmptyFetchIterator;
+import org.apache.tika.pipes.fetchiterator.FetchIterator;
+import org.apache.tika.pipes.fetcher.Fetcher;
import org.apache.tika.language.translate.DefaultTranslator;
import org.apache.tika.language.translate.Translator;
import org.apache.tika.metadata.filter.CompositeMetadataFilter;
@@ -73,8 +73,6 @@ import org.apache.tika.parser.ParserDecorator;
import org.apache.tika.parser.multiple.AbstractMultipleParser;
import org.apache.tika.utils.AnnotationUtils;
import org.apache.tika.utils.XMLReaderUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
@@ -120,16 +118,16 @@ public class TikaConfig {
return new DefaultMetadataFilter(loader);
}
- private static Fetcher getDefaultFetcher(ServiceLoader loader) {
- return new DefaultFetcher(Collections.EMPTY_LIST);
+ private static FetcherManager getDefaultFetcherManager(ServiceLoader loader) {
+ return new FetcherManager(Collections.EMPTY_LIST);
}
- private static Emitter getDefaultEmitter(ServiceLoader loader) {
- return new DefaultEmitter(Collections.EMPTY_LIST);
+ private static EmitterManager getDefaultEmitterManager(ServiceLoader loader) {
+ return new EmitterManager(Collections.EMPTY_LIST);
}
private static FetchIterator getDefaultFetchIterator(ServiceLoader loader) {
- return new DefaultFetchIterator(Collections.EMPTY_LIST);
+ return new EmptyFetchIterator();
}
//use this to look for unneeded instantiations of TikaConfig
@@ -144,8 +142,8 @@ public class TikaConfig {
private final ExecutorService executorService;
private final EncodingDetector encodingDetector;
private final MetadataFilter metadataFilter;
- private final Fetcher fetcher;
- private final Emitter emitter;
+ private final FetcherManager fetcherManager;
+ private final EmitterManager emitterManager;
private final FetchIterator fetchIterator;
public TikaConfig(String file)
@@ -157,6 +155,7 @@ public class TikaConfig {
throws TikaException, IOException, SAXException {
this(XMLReaderUtils.buildDOM(path));
}
+
public TikaConfig(Path path, ServiceLoader loader)
throws TikaException, IOException, SAXException {
this(XMLReaderUtils.buildDOM(path), loader);
@@ -176,10 +175,12 @@ public class TikaConfig {
throws TikaException, IOException, SAXException {
this(url, ServiceLoader.getContextClassLoader());
}
+
public TikaConfig(URL url, ClassLoader loader)
throws TikaException, IOException, SAXException {
this(XMLReaderUtils.buildDOM(url.toString()).getDocumentElement(), loader);
}
+
public TikaConfig(URL url, ServiceLoader loader)
throws TikaException, IOException, SAXException {
this(XMLReaderUtils.buildDOM(url.toString()).getDocumentElement(), loader);
@@ -193,6 +194,7 @@ public class TikaConfig {
public TikaConfig(Document document) throws TikaException, IOException {
this(document.getDocumentElement());
}
+
public TikaConfig(Document document, ServiceLoader loader) throws TikaException, IOException {
this(document.getDocumentElement(), loader);
}
@@ -226,8 +228,8 @@ public class TikaConfig {
this.translator = translatorLoader.loadOverall(element, mimeTypes, loader);
this.executorService = executorLoader.loadOverall(element, mimeTypes, loader);
this.metadataFilter = metadataFilterXmlLoader.loadOverall(element, mimeTypes, loader);
- this.fetcher = fetcherXmlLoader.loadOverall(element, mimeTypes, loader);
- this.emitter = emitterXmlLoader.loadOverall(element, mimeTypes, loader);
+ this.fetcherManager = fetcherXmlLoader.loadOverall(element, mimeTypes, loader);
+ this.emitterManager = emitterXmlLoader.loadOverall(element, mimeTypes, loader);
this.fetchIterator = fetchIteratorXmlLoader.loadOverall(element, mimeTypes, loader);
this.serviceLoader = loader;
TIMES_INSTANTIATED.incrementAndGet();
@@ -239,11 +241,11 @@ public class TikaConfig {
* {@link ServiceRegistry service provider mechanism} in the given
* class loader.
*
- * @since Apache Tika 0.8
* @param loader the class loader through which parser implementations
* are loaded, or <code>null</code> for no parsers
* @throws MimeTypeException if the built-in media type rules are broken
- * @throws IOException if the built-in media type rules can not be read
+ * @throws IOException if the built-in media type rules can not be read
+ * @since Apache Tika 0.8
*/
public TikaConfig(ClassLoader loader)
throws MimeTypeException, IOException {
@@ -255,8 +257,8 @@ public class TikaConfig {
this.translator = getDefaultTranslator(serviceLoader);
this.executorService = getDefaultExecutorService();
this.metadataFilter = getDefaultMetadataFilter(serviceLoader);
- this.fetcher = getDefaultFetcher(serviceLoader);
- this.emitter = getDefaultEmitter(serviceLoader);
+ this.fetcherManager = getDefaultFetcherManager(serviceLoader);
+ this.emitterManager = getDefaultEmitterManager(serviceLoader);
this.fetchIterator = getDefaultFetchIterator(serviceLoader);
TIMES_INSTANTIATED.incrementAndGet();
}
@@ -275,7 +277,7 @@ public class TikaConfig {
* the {@link ServiceRegistry service provider mechanism} in the context
* class loader of the current thread.</p>
*
- * @throws IOException if the configuration can not be read
+ * @throws IOException if the configuration can not be read
* @throws TikaException if problem with MimeTypes or parsing XML config
*/
public TikaConfig() throws TikaException, IOException {
@@ -294,8 +296,8 @@ public class TikaConfig {
this.translator = getDefaultTranslator(serviceLoader);
this.executorService = getDefaultExecutorService();
this.metadataFilter = getDefaultMetadataFilter(serviceLoader);
- this.fetcher = getDefaultFetcher(serviceLoader);
- this.emitter = getDefaultEmitter(serviceLoader);
+ this.fetcherManager = getDefaultFetcherManager(serviceLoader);
+ this.emitterManager = getDefaultEmitterManager(serviceLoader);
this.fetchIterator = getDefaultFetchIterator(serviceLoader);
} else {
ServiceLoader tmpServiceLoader = new ServiceLoader();
@@ -322,8 +324,8 @@ public class TikaConfig {
this.translator = translatorLoader.loadOverall(element, mimeTypes, serviceLoader);
this.executorService = executorLoader.loadOverall(element, mimeTypes, serviceLoader);
this.metadataFilter = metadataFilterXmlLoader.loadOverall(element, mimeTypes, serviceLoader);
- this.fetcher = fetcherXmlLoader.loadOverall(element, mimeTypes, serviceLoader);
- this.emitter = emitterXmlLoader.loadOverall(element, mimeTypes, serviceLoader);
+ this.fetcherManager = fetcherXmlLoader.loadOverall(element, mimeTypes, serviceLoader);
+ this.emitterManager = emitterXmlLoader.loadOverall(element, mimeTypes, serviceLoader);
this.fetchIterator = fetchIteratorXmlLoader.loadOverall(element, mimeTypes, serviceLoader);
} catch (SAXException e) {
throw new TikaException(
@@ -418,6 +420,7 @@ public class TikaConfig {
/**
* Returns the configured encoding detector instance
+ *
* @return configured encoding detector
*/
public EncodingDetector getEncodingDetector() {
@@ -432,19 +435,19 @@ public class TikaConfig {
public Translator getTranslator() {
return translator;
}
-
+
public ExecutorService getExecutorService() {
return executorService;
}
- public MimeTypes getMimeRepository(){
+ public MimeTypes getMimeRepository() {
return mimeTypes;
}
public MediaTypeRegistry getMediaTypeRegistry() {
return mimeTypes.getMediaTypeRegistry();
}
-
+
public ServiceLoader getServiceLoader() {
return serviceLoader;
}
@@ -453,17 +456,18 @@ public class TikaConfig {
return metadataFilter;
}
- public Fetcher getFetcher() {
- return fetcher;
+ public FetcherManager getFetcherManager() {
+ return fetcherManager;
}
- public Emitter getEmitter() {
- return emitter;
+ public EmitterManager getEmitterManager() {
+ return emitterManager;
}
public FetchIterator getFetchIterator() {
return fetchIterator;
}
+
/**
* Provides a default configuration (TikaConfig). Currently creates a
* new instance each time it's called; we may be able to have it
@@ -494,23 +498,23 @@ public class TikaConfig {
}
return null;
}
- private static List<Element> getTopLevelElementChildren(Element element,
- String parentName, String childrenName) throws TikaException {
+
+ private static List<Element> getTopLevelElementChildren(Element element,
+ String parentName, String childrenName) throws TikaException {
Node parentNode = null;
if (parentName != null) {
// Should be only zero or one <parsers> / <detectors> etc tag
NodeList nodes = element.getElementsByTagName(parentName);
if (nodes.getLength() > 1) {
- throw new TikaException("Properties may not contain multiple "+parentName+" entries");
- }
- else if (nodes.getLength() == 1) {
+ throw new TikaException("Properties may not contain multiple " + parentName + " entries");
+ } else if (nodes.getLength() == 1) {
parentNode = nodes.item(0);
}
} else {
// All children directly on the master element
parentNode = element;
}
-
+
if (parentNode != null) {
// Find only the direct child parser/detector objects
NodeList nodes = parentNode.getChildNodes();
@@ -518,7 +522,7 @@ public class TikaConfig {
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
if (node instanceof Element) {
- Element nodeE = (Element)node;
+ Element nodeE = (Element) node;
if (childrenName.equals(nodeE.getTagName())) {
elements.add(nodeE);
}
@@ -540,16 +544,16 @@ public class TikaConfig {
return getDefaultMimeTypes(null);
}
}
-
+
private static Set<MediaType> mediaTypesListFromDomElement(
- Element node, String tag)
+ Element node, String tag)
throws TikaException, IOException {
Set<MediaType> types = null;
NodeList children = node.getChildNodes();
- for (int i=0; i<children.getLength(); i++) {
+ for (int i = 0; i < children.getLength(); i++) {
Node cNode = children.item(i);
if (cNode instanceof Element) {
- Element cElement = (Element)cNode;
+ Element cElement = (Element) cNode;
if (tag.equals(cElement.getTagName())) {
String mime = getText(cElement);
MediaType type = MediaType.parse(mime);
@@ -566,7 +570,7 @@ public class TikaConfig {
if (types != null) return types;
return Collections.emptySet();
}
-
+
private static ServiceLoader serviceLoaderFromDomElement(Element element, ClassLoader loader) throws TikaConfigException {
Element serviceLoaderElement = getChild(element, "service-loader");
ServiceLoader serviceLoader;
@@ -575,9 +579,9 @@ public class TikaConfig {
boolean dynamic = Boolean.parseBoolean(serviceLoaderElement.getAttribute("dynamic"));
LoadErrorHandler loadErrorHandler = LoadErrorHandler.IGNORE;
String loadErrorHandleConfig = serviceLoaderElement.getAttribute("loadErrorHandler");
- if(LoadErrorHandler.WARN.toString().equalsIgnoreCase(loadErrorHandleConfig)) {
+ if (LoadErrorHandler.WARN.toString().equalsIgnoreCase(loadErrorHandleConfig)) {
loadErrorHandler = LoadErrorHandler.WARN;
- } else if(LoadErrorHandler.THROW.toString().equalsIgnoreCase(loadErrorHandleConfig)) {
+ } else if (LoadErrorHandler.THROW.toString().equalsIgnoreCase(loadErrorHandleConfig)) {
loadErrorHandler = LoadErrorHandler.THROW;
}
InitializableProblemHandler initializableProblemHandler = getInitializableProblemHandler(serviceLoaderElement.getAttribute("initializableProblemHandler"));
@@ -586,7 +590,7 @@ public class TikaConfig {
loader = ServiceLoader.getContextClassLoader();
}
serviceLoader = new ServiceLoader(loader, loadErrorHandler, initializableProblemHandler, dynamic);
- } else if(loader != null) {
+ } else if (loader != null) {
serviceLoader = new ServiceLoader(loader);
} else {
serviceLoader = new ServiceLoader();
@@ -595,7 +599,7 @@ public class TikaConfig {
}
private static InitializableProblemHandler getInitializableProblemHandler(String initializableProblemHandler)
- throws TikaConfigException {
+ throws TikaConfigException {
if (initializableProblemHandler == null || initializableProblemHandler.length() == 0) {
return InitializableProblemHandler.DEFAULT;
}
@@ -614,36 +618,46 @@ public class TikaConfig {
}
- private static abstract class XmlLoader<CT,T> {
+ private static abstract class XmlLoader<CT, T> {
protected static final String PARAMS_TAG_NAME = "params";
+
abstract boolean supportsComposite();
+
abstract String getParentTagName(); // eg parsers
+
abstract String getLoaderTagName(); // eg parser
+
abstract Class<? extends T> getLoaderClass(); // Generics workaround
+
abstract boolean isComposite(T loaded);
+
abstract boolean isComposite(Class<? extends T> loadedClass);
- abstract T preLoadOne(Class<? extends T> loadedClass, String classname,
- MimeTypes mimeTypes) throws TikaException;
+
+ abstract T preLoadOne(Class<? extends T> loadedClass, String classname,
+ MimeTypes mimeTypes) throws TikaException;
+
abstract CT createDefault(MimeTypes mimeTypes, ServiceLoader loader);
+
abstract CT createComposite(List<T> loaded, MimeTypes mimeTypes, ServiceLoader loader);
- abstract T createComposite(Class<? extends T> compositeClass,
- List<T> children, Set<Class<? extends T>> excludeChildren,
- Map<String, Param> params, MimeTypes mimeTypes, ServiceLoader loader)
+
+ abstract T createComposite(Class<? extends T> compositeClass,
+ List<T> children, Set<Class<? extends T>> excludeChildren,
+ Map<String, Param> params, MimeTypes mimeTypes, ServiceLoader loader)
throws InvocationTargetException, IllegalAccessException, InstantiationException;
- abstract T decorate(T created, Element element)
+
+ abstract T decorate(T created, Element element)
throws IOException, TikaException; // eg explicit mime types
-
+
@SuppressWarnings("unchecked")
- CT loadOverall(Element element, MimeTypes mimeTypes,
- ServiceLoader loader) throws TikaException, IOException {
+ CT loadOverall(Element element, MimeTypes mimeTypes,
+ ServiceLoader loader) throws TikaException, IOException {
List<T> loaded = new ArrayList<T>();
-
+
// Find the children of the parent tag, if any
- for (Element le : getTopLevelElementChildren(element, getParentTagName(), getLoaderTagName())) {
- T loadedChild = loadOne(le, mimeTypes, loader);
+ for (Element le : getTopLevelElementChildren(element, getParentTagName(), getLoaderTagName())) {T loadedChild = loadOne(le, mimeTypes, loader);
if (loadedChild != null) loaded.add(loadedChild);
}
-
+
// Build the classes, and wrap as needed
if (loaded.isEmpty()) {
// Nothing defined, create a Default
@@ -652,28 +666,36 @@ public class TikaConfig {
T single = loaded.get(0);
if (isComposite(single)) {
// Single Composite defined, use that
- return (CT)single;
+ return (CT) single;
}
- } else if (! supportsComposite()) {
+ } else if (!supportsComposite()) {
// No composite support, just return the first one
- return (CT)loaded.get(0);
+ if (loaded.size() == 1) {
+ return (CT) loaded.get(0);
+ } else if (loaded.size() > 1) {
+ throw new TikaConfigException("Composite not supported for " +
+ getParentTagName() +
+ ". Must specify only one child!");
+ } else {
+ //throw exception if empty?
+ }
}
// Wrap the defined parsers/detectors up in a Composite
return createComposite(loaded, mimeTypes, loader);
}
- T loadOne(Element element, MimeTypes mimeTypes, ServiceLoader loader)
+ T loadOne(Element element, MimeTypes mimeTypes, ServiceLoader loader)
throws TikaException, IOException {
String name = element.getAttribute("class");
if (name == null) {
- throw new TikaConfigException("class attribute must not be null: "+element);
+ throw new TikaConfigException("class attribute must not be null: " + element);
}
String initProbHandler = element.getAttribute("initializableProblemHandler");
InitializableProblemHandler initializableProblemHandler;
if (initProbHandler == null || initProbHandler.length() == 0) {
initializableProblemHandler = loader.getInitializableProblemHandler();
} else {
- initializableProblemHandler =
+ initializableProblemHandler =
getInitializableProblemHandler(initProbHandler);
}
@@ -687,7 +709,7 @@ public class TikaConfig {
//TODO : allow duplicate instances with different configurations
loaded = preLoadOne(loadedClass, name, mimeTypes);
if (loaded != null) return loaded;
-
+
// Get any parameters / settings for the parser
Map<String, Param> params = null;
try {
@@ -695,7 +717,7 @@ public class TikaConfig {
} catch (Exception e) {
throw new TikaConfigException(e.getMessage(), e);
}
-
+
// Is this a composite or decorated class? If so, support recursion
if (isComposite(loadedClass)) {
// Get the child objects for it
@@ -703,28 +725,28 @@ public class TikaConfig {
NodeList childNodes = element.getElementsByTagName(getLoaderTagName());
if (childNodes.getLength() > 0) {
for (int i = 0; i < childNodes.getLength(); i++) {
- T loadedChild = loadOne((Element)childNodes.item(i),
- mimeTypes, loader);
+ T loadedChild = loadOne((Element) childNodes.item(i),
+ mimeTypes, loader);
if (loadedChild != null) children.add(loadedChild);
}
}
-
+
// Get the list of children to exclude
Set<Class<? extends T>> excludeChildren = new HashSet<Class<? extends T>>();
- NodeList excludeChildNodes = element.getElementsByTagName(getLoaderTagName()+"-exclude");
+ NodeList excludeChildNodes = element.getElementsByTagName(getLoaderTagName() + "-exclude");
if (excludeChildNodes.getLength() > 0) {
for (int i = 0; i < excludeChildNodes.getLength(); i++) {
- Element excl = (Element)excludeChildNodes.item(i);
+ Element excl = (Element) excludeChildNodes.item(i);
String exclName = excl.getAttribute("class");
try {
excludeChildren.add(loader.getServiceClass(getLoaderClass(), exclName));
} catch (ClassNotFoundException e) {
//TIKA-3268 -- This should stop the world.
- throw new TikaConfigException("Class now found in -exclude list: " +exclName);
+ throw new TikaConfigException("Class now found in -exclude list: " + exclName);
}
}
}
-
+
// Create the Composite
loaded = createComposite(loadedClass, children, excludeChildren, params, mimeTypes, loader);
@@ -752,24 +774,24 @@ public class TikaConfig {
} catch (ClassNotFoundException e) {
if (loader.getLoadErrorHandler() == LoadErrorHandler.THROW) {
// Use a different exception signature here
- throw new TikaException(
- "Unable to find a "+getLoaderTagName()+" class: " + name, e);
+ throw new TikaConfigException(
+ "Unable to find a " + getLoaderTagName() + " class: " + name, e);
}
// Report the problem
loader.getLoadErrorHandler().handleLoadError(name, e);
return null;
} catch (IllegalAccessException e) {
throw new TikaException(
- "Unable to access a "+getLoaderTagName()+" class: " + name, e);
+ "Unable to access a " + getLoaderTagName() + " class: " + name, e);
} catch (InvocationTargetException e) {
throw new TikaException(
- "Unable to create a "+getLoaderTagName()+" class: " + name, e);
+ "Unable to create a " + getLoaderTagName() + " class: " + name, e);
} catch (InstantiationException e) {
throw new TikaException(
- "Unable to instantiate a "+getLoaderTagName()+" class: " + name, e);
+ "Unable to instantiate a " + getLoaderTagName() + " class: " + name, e);
} catch (NoSuchMethodException e) {
throw new TikaException(
- "Unable to find the right constructor for "+getLoaderTagName()+" class: " + name, e);
+ "Unable to find the right constructor for " + getLoaderTagName() + " class: " + name, e);
}
}
@@ -782,19 +804,20 @@ public class TikaConfig {
/**
* Gets parameters from a given
+ *
* @param el xml node which has {@link #PARAMS_TAG_NAME} child
* @return Map of key values read from xml
*/
- Map<String, Param> getParams(Element el) throws TikaException {
+ Map<String, Param> getParams(Element el) throws TikaException {
Map<String, Param> params = new HashMap<>();
for (Node child = el.getFirstChild(); child != null;
- child = child.getNextSibling()){
- if (PARAMS_TAG_NAME.equals(child.getNodeName())){ //found the node
+ child = child.getNextSibling()) {
+ if (PARAMS_TAG_NAME.equals(child.getNodeName())) { //found the node
if (child.hasChildNodes()) {//it has children
NodeList childNodes = child.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
Node item = childNodes.item(i);
- if (item.getNodeType() == Node.ELEMENT_NODE){
+ if (item.getNodeType() == Node.ELEMENT_NODE) {
Param<?> param = Param.load(item);
params.put(param.getName(), param);
}
@@ -807,113 +830,133 @@ public class TikaConfig {
}
}
- private static class ParserXmlLoader extends XmlLoader<CompositeParser,Parser> {
+
+ private static class ParserXmlLoader extends XmlLoader<CompositeParser, Parser> {
private final EncodingDetector encodingDetector;
- boolean supportsComposite() { return true; }
- String getParentTagName() { return "parsers"; }
- String getLoaderTagName() { return "parser"; }
+ boolean supportsComposite() {
+ return true;
+ }
+
+ String getParentTagName() {
+ return "parsers";
+ }
+
+ String getLoaderTagName() {
+ return "parser";
+ }
private ParserXmlLoader(EncodingDetector encodingDetector) {
this.encodingDetector = encodingDetector;
}
+
@Override
Class<? extends Parser> getLoaderClass() {
return Parser.class;
}
+
@Override
- Parser preLoadOne(Class<? extends Parser> loadedClass, String classname,
+ Parser preLoadOne(Class<? extends Parser> loadedClass, String classname,
MimeTypes mimeTypes) throws TikaException {
// Check for classes which can't be set in config
if (AutoDetectParser.class.isAssignableFrom(loadedClass)) {
// https://issues.apache.org/jira/browse/TIKA-866
throw new TikaException(
"AutoDetectParser not supported in a <parser>"
- + " configuration element: " + classname);
+ + " configuration element: " + classname);
}
// Continue with normal loading
return null;
}
+
@Override
boolean isComposite(Parser loaded) {
return loaded instanceof CompositeParser;
}
+
@Override
boolean isComposite(Class<? extends Parser> loadedClass) {
if (CompositeParser.class.isAssignableFrom(loadedClass) ||
- AbstractMultipleParser.class.isAssignableFrom(loadedClass) ||
- ParserDecorator.class.isAssignableFrom(loadedClass)) {
+ AbstractMultipleParser.class.isAssignableFrom(loadedClass) ||
+ ParserDecorator.class.isAssignableFrom(loadedClass)) {
return true;
}
return false;
}
+
@Override
CompositeParser createDefault(MimeTypes mimeTypes, ServiceLoader loader) {
return getDefaultParser(mimeTypes, loader, encodingDetector);
}
+
@Override
CompositeParser createComposite(List<Parser> parsers, MimeTypes mimeTypes, ServiceLoader loader) {
MediaTypeRegistry registry = mimeTypes.getMediaTypeRegistry();
return new CompositeParser(registry, parsers);
}
+
@Override
Parser createComposite(Class<? extends Parser> parserClass,
- List<Parser> childParsers, Set<Class<? extends Parser>> excludeParsers,
- Map<String, Param> params, MimeTypes mimeTypes, ServiceLoader loader)
+ List<Parser> childParsers, Set<Class<? extends Parser>> excludeParsers,
+ Map<String, Param> params, MimeTypes mimeTypes, ServiceLoader loader)
throws InvocationTargetException, IllegalAccessException, InstantiationException {
Parser parser = null;
Constructor<? extends Parser> c = null;
MediaTypeRegistry registry = mimeTypes.getMediaTypeRegistry();
-
+
// Try the possible default and composite parser constructors
if (parser == null) {
try {
c = parserClass.getConstructor(MediaTypeRegistry.class,
ServiceLoader.class, Collection.class, EncodingDetector.class);
parser = c.newInstance(registry, loader, excludeParsers, encodingDetector);
+ } catch (NoSuchMethodException me) {
}
- catch (NoSuchMethodException me) {}
}
if (parser == null) {
try {
c = parserClass.getConstructor(MediaTypeRegistry.class, ServiceLoader.class, Collection.class);
parser = c.newInstance(registry, loader, excludeParsers);
- }
- catch (NoSuchMethodException me) {}
+ } catch (NoSuchMethodException me) {
+ }
}
if (parser == null) {
try {
c = parserClass.getConstructor(MediaTypeRegistry.class, List.class, Collection.class);
parser = c.newInstance(registry, childParsers, excludeParsers);
- } catch (NoSuchMethodException me) {}
+ } catch (NoSuchMethodException me) {
+ }
}
if (parser == null) {
try {
c = parserClass.getConstructor(MediaTypeRegistry.class, Collection.class, Map.class);
parser = c.newInstance(registry, childParsers, params);
- } catch (NoSuchMethodException me) {}
+ } catch (NoSuchMethodException me) {
+ }
}
if (parser == null) {
try {
c = parserClass.getConstructor(MediaTypeRegistry.class, List.class);
parser = c.newInstance(registry, childParsers);
- } catch (NoSuchMethodException me) {}
+ } catch (NoSuchMethodException me) {
+ }
}
-
+
// Create as a Parser Decorator
if (parser == null && ParserDecorator.class.isAssignableFrom(parserClass)) {
try {
CompositeParser cp = null;
if (childParsers.size() == 1 && excludeParsers.size() == 0 &&
childParsers.get(0) instanceof CompositeParser) {
- cp = (CompositeParser)childParsers.get(0);
+ cp = (CompositeParser) childParsers.get(0);
} else {
cp = new CompositeParser(registry, childParsers, excludeParsers);
}
c = parserClass.getConstructor(Parser.class);
parser = c.newInstance(cp);
- } catch (NoSuchMethodException me) {}
+ } catch (NoSuchMethodException me) {
+ }
}
return parser;
}
@@ -931,34 +974,44 @@ public class TikaConfig {
@Override
Parser decorate(Parser created, Element element) throws IOException, TikaException {
Parser parser = created;
-
+
// Is there an explicit list of mime types for this to handle?
Set<MediaType> parserTypes = mediaTypesListFromDomElement(element, "mime");
- if (! parserTypes.isEmpty()) {
+ if (!parserTypes.isEmpty()) {
parser = ParserDecorator.withTypes(parser, parserTypes);
}
// Is there an explicit list of mime types this shouldn't handle?
Set<MediaType> parserExclTypes = mediaTypesListFromDomElement(element, "mime-exclude");
- if (! parserExclTypes.isEmpty()) {
+ if (!parserExclTypes.isEmpty()) {
parser = ParserDecorator.withoutTypes(parser, parserExclTypes);
}
-
+
// All done with decoration
return parser;
}
}
- private static class DetectorXmlLoader extends XmlLoader<CompositeDetector,Detector> {
- boolean supportsComposite() { return true; }
- String getParentTagName() { return "detectors"; }
- String getLoaderTagName() { return "detector"; }
-
+
+ private static class DetectorXmlLoader extends XmlLoader<CompositeDetector, Detector> {
+ boolean supportsComposite() {
+ return true;
+ }
+
+ String getParentTagName() {
+ return "detectors";
+ }
+
+ String getLoaderTagName() {
+ return "detector";
+ }
+
@Override
Class<? extends Detector> getLoaderClass() {
return Detector.class;
}
+
@Override
- Detector preLoadOne(Class<? extends Detector> loadedClass, String classname,
+ Detector preLoadOne(Class<? extends Detector> loadedClass, String classname,
MimeTypes mimeTypes) throws TikaException {
// If they asked for the mime types as a detector, give
// them the one we've already created. TIKA-1708
@@ -968,112 +1021,141 @@ public class TikaConfig {
// Continue with normal loading
return null;
}
+
@Override
boolean isComposite(Detector loaded) {
return loaded instanceof CompositeDetector;
}
+
@Override
boolean isComposite(Class<? extends Detector> loadedClass) {
return CompositeDetector.class.isAssignableFrom(loadedClass);
}
+
@Override
CompositeDetector createDefault(MimeTypes mimeTypes, ServiceLoader loader) {
return getDefaultDetector(mimeTypes, loader);
}
+
@Override
CompositeDetector createComposite(List<Detector> detectors, MimeTypes mimeTypes, ServiceLoader loader) {
MediaTypeRegistry registry = mimeTypes.getMediaTypeRegistry();
return new CompositeDetector(registry, detectors);
}
+
@Override
Detector createComposite(Class<? extends Detector> detectorClass,
- List<Detector> childDetectors,
- Set<Class<? extends Detector>> excludeDetectors,
- Map<String, Param> params, MimeTypes mimeTypes, ServiceLoader loader)
+ List<Detector> childDetectors,
+ Set<Class<? extends Detector>> excludeDetectors,
+ Map<String, Param> params, MimeTypes mimeTypes, ServiceLoader loader)
throws InvocationTargetException, IllegalAccessException,
InstantiationException {
Detector detector = null;
Constructor<? extends Detector> c;
MediaTypeRegistry registry = mimeTypes.getMediaTypeRegistry();
-
+
// Try the possible default and composite detector constructors
if (detector == null) {
try {
c = detectorClass.getConstructor(MimeTypes.class, ServiceLoader.class, Collection.class);
detector = c.newInstance(mimeTypes, loader, excludeDetectors);
- }
- catch (NoSuchMethodException me) {}
+ } catch (NoSuchMethodException me) {
+ }
}
if (detector == null) {
try {
c = detectorClass.getConstructor(MediaTypeRegistry.class, List.class, Collection.class);
detector = c.newInstance(registry, childDetectors, excludeDetectors);
- } catch (NoSuchMethodException me) {}
+ } catch (NoSuchMethodException me) {
+ }
}
if (detector == null) {
try {
c = detectorClass.getConstructor(MediaTypeRegistry.class, List.class);
detector = c.newInstance(registry, childDetectors);
- } catch (NoSuchMethodException me) {}
+ } catch (NoSuchMethodException me) {
+ }
}
if (detector == null) {
try {
c = detectorClass.getConstructor(List.class);
detector = c.newInstance(childDetectors);
- } catch (NoSuchMethodException me) {}
+ } catch (NoSuchMethodException me) {
+ }
}
-
+
return detector;
}
+
@Override
Detector decorate(Detector created, Element element) {
return created; // No decoration of Detectors
}
}
- private static class TranslatorXmlLoader extends XmlLoader<Translator,Translator> {
- boolean supportsComposite() { return false; }
- String getParentTagName() { return null; }
- String getLoaderTagName() { return "translator"; }
-
+
+ private static class TranslatorXmlLoader extends XmlLoader<Translator, Translator> {
+ boolean supportsComposite() {
+ return false;
+ }
+
+ String getParentTagName() {
+ return null;
+ }
+
+ String getLoaderTagName() {
+ return "translator";
+ }
+
@Override
Class<? extends Translator> getLoaderClass() {
return Translator.class;
}
+
@Override
- Translator preLoadOne(Class<? extends Translator> loadedClass, String classname,
+ Translator preLoadOne(Class<? extends Translator> loadedClass, String classname,
MimeTypes mimeTypes) throws TikaException {
// Continue with normal loading
return null;
}
+
@Override
- boolean isComposite(Translator loaded) { return false; }
+ boolean isComposite(Translator loaded) {
+ return false;
+ }
+
@Override
- boolean isComposite(Class<? extends Translator> loadedClass) { return false; }
+ boolean isComposite(Class<? extends Translator> loadedClass) {
+ return false;
+ }
+
@Override
Translator createDefault(MimeTypes mimeTypes, ServiceLoader loader) {
return getDefaultTranslator(loader);
}
+
@Override
Translator createComposite(List<Translator> loaded,
- MimeTypes mimeTypes, ServiceLoader loader) {
+ MimeTypes mimeTypes, ServiceLoader loader) {
return loaded.get(0);
}
+
@Override
Translator createComposite(Class<? extends Translator> compositeClass,
- List<Translator> children,
- Set<Class<? extends Translator>> excludeChildren,
- Map<String, Param> params, MimeTypes mimeTypes, ServiceLoader loader)
+ List<Translator> children,
+ Set<Class<? extends Translator>> excludeChildren,
+ Map<String, Param> params, MimeTypes mimeTypes, ServiceLoader loader)
throws InvocationTargetException, IllegalAccessException,
InstantiationException {
throw new InstantiationException("Only one translator supported");
}
+
@Override
Translator decorate(Translator created, Element element) {
return created; // No decoration of Translators
- }
+ }
}
-
- private static class ExecutorServiceXmlLoader extends XmlLoader<ConfigurableThreadPoolExecutor,ConfigurableThreadPoolExecutor> {
+
+ private static class ExecutorServiceXmlLoader extends XmlLoader<ConfigurableThreadPoolExecutor, ConfigurableThreadPoolExecutor> {
@Override
ConfigurableThreadPoolExecutor createComposite(
Class<? extends ConfigurableThreadPoolExecutor> compositeClass,
@@ -1084,61 +1166,69 @@ public class TikaConfig {
InstantiationException {
throw new InstantiationException("Only one executor service supported");
}
-
+
@Override
ConfigurableThreadPoolExecutor createComposite(List<ConfigurableThreadPoolExecutor> loaded,
- MimeTypes mimeTypes, ServiceLoader loader) {
+ MimeTypes mimeTypes, ServiceLoader loader) {
return loaded.get(0);
}
-
+
@Override
ConfigurableThreadPoolExecutor createDefault(MimeTypes mimeTypes, ServiceLoader loader) {
return getDefaultExecutorService();
}
-
+
@Override
ConfigurableThreadPoolExecutor decorate(ConfigurableThreadPoolExecutor created, Element element)
throws IOException, TikaException {
-
+
Element maxThreadElement = getChild(element, "max-threads");
- if(maxThreadElement != null)
- {
+ if (maxThreadElement != null) {
created.setMaximumPoolSize(Integer.parseInt(getText(maxThreadElement)));
}
-
+
Element coreThreadElement = getChild(element, "core-threads");
- if(coreThreadElement != null)
- {
+ if (coreThreadElement != null) {
created.setCorePoolSize(Integer.parseInt(getText(coreThreadElement)));
}
return created;
}
-
+
@Override
Class<? extends ConfigurableThreadPoolExecutor> getLoaderClass() {
return ConfigurableThreadPoolExecutor.class;
}
-
+
@Override
ConfigurableThreadPoolExecutor loadOne(Element element, MimeTypes mimeTypes,
- ServiceLoader loader) throws TikaException, IOException {
+ ServiceLoader loader) throws TikaException, IOException {
return super.loadOne(element, mimeTypes, loader);
}
@Override
- boolean supportsComposite() {return false;}
+ boolean supportsComposite() {
+ return false;
+ }
@Override
- String getParentTagName() {return null;}
+ String getParentTagName() {
+ return null;
+ }
@Override
- String getLoaderTagName() {return "executor-service";}
+ String getLoaderTagName() {
+ return "executor-service";
+ }
@Override
- boolean isComposite(ConfigurableThreadPoolExecutor loaded) {return false;}
+ boolean isComposite(ConfigurableThreadPoolExecutor loaded) {
+ return false;
+ }
@Override
- boolean isComposite(Class<? extends ConfigurableThreadPoolExecutor> loadedClass) {return false;}
+ boolean isComposite(Class<? extends ConfigurableThreadPoolExecutor> loadedClass) {
+ return false;
+ }
@Override
ConfigurableThreadPoolExecutor preLoadOne(
@@ -1268,7 +1358,7 @@ public class TikaConfig {
@Override
MetadataFilter preLoadOne(Class<? extends MetadataFilter> loadedClass,
- String classname, MimeTypes mimeTypes) throws TikaException {
+ String classname, MimeTypes mimeTypes) throws TikaException {
// Check for classes which can't be set in config
// Continue with normal loading
return null;
@@ -1287,9 +1377,9 @@ public class TikaConfig {
@Override
MetadataFilter createComposite(Class<? extends MetadataFilter> metadataFilterClass,
- List<MetadataFilter> childMetadataFilters,
- Set<Class<? extends MetadataFilter>> excludeFilters,
- Map<String, Param> params, MimeTypes mimeTypes, ServiceLoader loader)
+ List<MetadataFilter> childMetadataFilters,
+ Set<Class<? extends MetadataFilter>> excludeFilters,
+ Map<String, Param> params, MimeTypes mimeTypes, ServiceLoader loader)
throws InvocationTargetException, IllegalAccessException,
InstantiationException {
MetadataFilter metadataFilter = null;
@@ -1323,8 +1413,9 @@ public class TikaConfig {
}
private static class FetcherXmlLoader extends
- XmlLoader<Fetcher, Fetcher> {
+ XmlLoader<FetcherManager, Fetcher> {
+ //FetcherManager is composite
boolean supportsComposite() {
return true;
}
@@ -1345,61 +1436,42 @@ public class TikaConfig {
@Override
boolean isComposite(Fetcher loaded) {
- return loaded instanceof DefaultFetcher;
+ return false;
}
@Override
boolean isComposite(Class<? extends Fetcher> loadedClass) {
- return DefaultFetcher.class.isAssignableFrom(loadedClass);
+ return false;
}
@Override
Fetcher preLoadOne(Class<? extends Fetcher> loadedClass,
- String classname, MimeTypes mimeTypes) throws TikaException {
+ String classname, MimeTypes mimeTypes) throws TikaException {
// Check for classes which can't be set in config
// Continue with normal loading
return null;
}
@Override
- Fetcher createDefault(MimeTypes mimeTypes, ServiceLoader loader) {
- return getDefaultFetcher(loader);
+ FetcherManager createDefault(MimeTypes mimeTypes, ServiceLoader loader) {
+ return getDefaultFetcherManager(loader);
}
//this ignores the service loader
@Override
- Fetcher createComposite(List<Fetcher> loaded, MimeTypes mimeTypes, ServiceLoader loader) {
- return new DefaultFetcher(loaded);
+ FetcherManager createComposite(List<Fetcher> loaded, MimeTypes mimeTypes, ServiceLoader loader) {
+ return new FetcherManager(loaded);
}
@Override
Fetcher createComposite(Class<? extends Fetcher> fetcherClass,
- List<Fetcher> childFetchers,
- Set<Class<? extends Fetcher>> excludeFilters,
- Map<String, Param> params, MimeTypes mimeTypes, ServiceLoader loader)
+ List<Fetcher> childFetchers,
+ Set<Class<? extends Fetcher>> excludeFilters,
+ Map<String, Param> params, MimeTypes mimeTypes, ServiceLoader loader)
throws InvocationTargetException, IllegalAccessException,
InstantiationException {
- Fetcher fetcher = null;
- Constructor<? extends Fetcher> c;
+ throw new InstantiationException("Only one fetcher manager supported");
- // Try the possible default and composite detector constructors
- if (fetcher == null) {
- try {
- c = fetcherClass.getConstructor(ServiceLoader.class, Collection.class);
- fetcher = c.newInstance(loader, excludeFilters);
- } catch (NoSuchMethodException me) {
- me.printStackTrace();
- }
- }
- if (fetcher == null) {
- try {
- c = fetcherClass.getConstructor(List.class);
- fetcher = c.newInstance(childFetchers);
- } catch (NoSuchMethodException me) {
- me.printStackTrace();
- }
- }
- return fetcher;
}
@Override
@@ -1409,7 +1481,7 @@ public class TikaConfig {
}
private static class EmitterXmlLoader extends
- XmlLoader<Emitter, Emitter> {
+ XmlLoader<EmitterManager, Emitter> {
boolean supportsComposite() {
return true;
@@ -1431,12 +1503,12 @@ public class TikaConfig {
@Override
boolean isComposite(Emitter loaded) {
- return loaded instanceof DefaultEmitter;
+ return false;
}
@Override
boolean isComposite(Class<? extends Emitter> loadedClass) {
- return DefaultEmitter.class.isAssignableFrom(loadedClass);
+ return false;
}
@Override
@@ -1448,19 +1520,18 @@ public class TikaConfig {
}
@Override
- Emitter createDefault(MimeTypes mimeTypes, ServiceLoader loader) {
+ EmitterManager createDefault(MimeTypes mimeTypes, ServiceLoader loader) {
return getDefaultEmitter(loader);
}
- private Emitter getDefaultEmitter(ServiceLoader loader) {
- //TODO: should we allow service loading?
- return new DefaultEmitter(Collections.EMPTY_LIST);
+ private EmitterManager getDefaultEmitter(ServiceLoader loader) {
+ return new EmitterManager(Collections.EMPTY_LIST);
}
//this ignores the service loader
@Override
- Emitter createComposite(List<Emitter> loaded, MimeTypes mimeTypes, ServiceLoader loader) {
- return new DefaultEmitter(loaded);
+ EmitterManager createComposite(List<Emitter> loaded, MimeTypes mimeTypes, ServiceLoader loader) {
+ return new EmitterManager(loaded);
}
@Override
@@ -1504,7 +1575,7 @@ public class TikaConfig {
XmlLoader<FetchIterator, FetchIterator> {
boolean supportsComposite() {
- return true;
+ return false;
}
String getParentTagName() {
@@ -1520,7 +1591,6 @@ public class TikaConfig {
return FetchIterator.class;
}
-
@Override
boolean isComposite(FetchIterator loaded) {
return false;
@@ -1533,7 +1603,7 @@ public class TikaConfig {
@Override
FetchIterator preLoadOne(Class<? extends FetchIterator> loadedClass,
- String classname, MimeTypes mimeTypes) throws TikaException {
+ String classname, MimeTypes mimeTypes) throws TikaException {
// Check for classes which can't be set in config
// Continue with normal loading
return null;
@@ -1541,44 +1611,28 @@ public class TikaConfig {
@Override
FetchIterator createDefault(MimeTypes mimeTypes, ServiceLoader loader) {
- return new DefaultFetchIterator(Collections.EMPTY_LIST);
+ return new EmptyFetchIterator();
}
//this ignores the service loader
@Override
- FetchIterator createComposite(List<FetchIterator> loaded, MimeTypes mimeTypes, ServiceLoader loader) {
- return new DefaultFetchIterator(loaded);
+ FetchIterator createComposite(List<FetchIterator> loaded,
+ MimeTypes mimeTypes, ServiceLoader loader) {
+ if (loaded.size() > 1) {
+ throw new IllegalArgumentException(
+ "Can only specify one fetch iterator per config file");
+ }
+ return loaded.get(0);
}
@Override
FetchIterator createComposite(Class<? extends FetchIterator> fetchIteratorClass,
- List<FetchIterator> fetchIteratorChildren,
- Set<Class<? extends FetchIterator>> excludeFetchIterators,
- Map<String, Param> params, MimeTypes mimeTypes, ServiceLoader loader)
+ List<FetchIterator> fetchIteratorChildren,
+ Set<Class<? extends FetchIterator>> excludeFetchIterators,
+ Map<String, Param> params, MimeTypes mimeTypes, ServiceLoader loader)
throws InvocationTargetException, IllegalAccessException,
InstantiationException {
- FetchIterator fetchIterator = null;
- Constructor<? extends FetchIterator> c;
-
- // Try the possible default and composite detector constructors
- if (fetchIterator == null) {
- try {
- c = fetchIteratorClass.getConstructor(ServiceLoader.class, Collection.class);
- fetchIterator = c.newInstance(loader, excludeFetchIterators);
- } catch (NoSuchMethodException me) {
- me.printStackTrace();
- }
- }
- if (fetchIterator == null) {
- try {
- c = fetchIteratorClass.getConstructor(List.class);
- fetchIterator = c.newInstance(fetchIteratorChildren);
- } catch (NoSuchMethodException me) {
- me.printStackTrace();
- }
- }
-
- return fetchIterator;
+ return null;
}
@Override
@@ -1587,4 +1641,5 @@ public class TikaConfig {
}
}
+
}
diff --git a/tika-core/src/main/java/org/apache/tika/emitter/Emitter.java b/tika-core/src/main/java/org/apache/tika/emitter/Emitter.java
deleted file mode 100644
index 23021e3..0000000
--- a/tika-core/src/main/java/org/apache/tika/emitter/Emitter.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package org.apache.tika.emitter;
-
-import org.apache.tika.exception.TikaException;
-import org.apache.tika.metadata.Metadata;
-
-import java.io.IOException;
-import java.util.List;
-import java.util.Set;
-
-public interface Emitter {
-
- Set<String> getSupported();
-
- //TODO: do we need a key or can we pass that in metadatalist?
- //If we do need it, how do we populate it?
- void emit(String emitterName, List<Metadata> metadataList) throws IOException, TikaException;
- //TODO we can add this later?
- //void emit(String txt, Metadata metadata) throws IOException, TikaException;
-
-}
diff --git a/tika-core/src/main/java/org/apache/tika/emitter/TikaEmitterException.java b/tika-core/src/main/java/org/apache/tika/emitter/TikaEmitterException.java
deleted file mode 100644
index 6926b78..0000000
--- a/tika-core/src/main/java/org/apache/tika/emitter/TikaEmitterException.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package org.apache.tika.emitter;
-
-import org.apache.tika.exception.TikaException;
-
-public class TikaEmitterException extends TikaException {
- public TikaEmitterException(String msg) {
- super(msg);
- }
-}
diff --git a/tika-core/src/main/java/org/apache/tika/fetcher/DefaultFetchIterator.java b/tika-core/src/main/java/org/apache/tika/fetcher/DefaultFetchIterator.java
deleted file mode 100644
index a579314..0000000
--- a/tika-core/src/main/java/org/apache/tika/fetcher/DefaultFetchIterator.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package org.apache.tika.fetcher;
-
-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.exception.TikaConfigException;
-
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.TimeoutException;
-
-public class DefaultFetchIterator extends FetchIterator implements Initializable {
-
- private final Map<String, FetchIterator> fetchIterators = new HashMap<>();
- private String iteratorName = "";
- public DefaultFetchIterator(List<FetchIterator> fetchIterators) {
- super("default");
- for (FetchIterator fetchIterator : fetchIterators) {
- if (this.fetchIterators.containsKey(fetchIterator.getName())) {
- throw new RuntimeException(new TikaConfigException("Multiple fetchIterators cannot have the same name: "
- + fetchIterator.getName()));
- }
- this.fetchIterators.put(fetchIterator.getName(), fetchIterator);
- }
- }
-
- @Override
- protected void enqueue() throws IOException, TimeoutException {
- if (fetchIterators.size() == 0) {
- return;
- } else if (fetchIterators.size() == 1) {
- for (FetchIterator fetchIterator : fetchIterators.values()) {
- fetchIterator.enqueue();
- }
- }
- }
-
- @Field
- public void setIteratorName(String iteratorName) {
- this.iteratorName = iteratorName;
- }
-
- @Override
- public void initialize(Map<String, Param> params) throws TikaConfigException {
- //no-op
- }
-
- @Override
- public void checkInitialization(InitializableProblemHandler problemHandler) throws TikaConfigException {
- if (this.fetchIterators.size() > 1 && this.iteratorName == null) {
- throw new TikaConfigException("Must set desired iteratorName, if multiple iterators are defined");
- }
- }
-}
diff --git a/tika-core/src/main/java/org/apache/tika/fetcher/FetchIterator.java b/tika-core/src/main/java/org/apache/tika/fetcher/FetchIterator.java
deleted file mode 100644
index 84e74d3..0000000
--- a/tika-core/src/main/java/org/apache/tika/fetcher/FetchIterator.java
+++ /dev/null
@@ -1,141 +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.
- */
-package org.apache.tika.fetcher;
-
-import org.apache.tika.config.Field;
-
-import java.io.IOException;
-import java.util.Iterator;
-import java.util.concurrent.ArrayBlockingQueue;
-import java.util.concurrent.Callable;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-/**
- * Abstract class that handles the testing for timeouts/thread safety
- * issues. Concrete classes implement {@link #enqueue()}.
- *
- * This must be "called" and managed with an ExecutorService, etc.
- * for the iterable to work.
- */
-public abstract class FetchIterator implements Callable<Integer>,
- Iterable<FetchMetadataPair> {
-
- public static final long DEFAULT_MAX_WAIT_MS = 300_000;
-
- static final FetchMetadataPair POISON =
- new FetchMetadataPair(null, null);
-
- private final int queueSize = 1000;
- private long maxWaitMs = DEFAULT_MAX_WAIT_MS;
- private final ArrayBlockingQueue<FetchMetadataPair> queue = new ArrayBlockingQueue<>(queueSize);
- private String name;
-
- public FetchIterator(String name) {
- this.name = name;
- }
-
- @Field
- public void setName(String name) {
- this.name = name;
- }
-
- public String getName() {
- return name;
- }
-
- @Override
- public Integer call() throws Exception {
- enqueue();
- System.out.println("finished");
- return 1;
- }
-
- protected abstract void enqueue() throws IOException, TimeoutException;
-
- void tryToAdd(FetchMetadataPair p) throws InterruptedException, TimeoutException {
- System.out.println("trying to add: "+p + " "+ queue.size());
- boolean offered = queue.offer(p, maxWaitMs, TimeUnit.MILLISECONDS);
- System.out.println("added: "+p + " "+ queue.size());
- if (! offered) {
- throw new TimeoutException("timed out while offering");
- }
- }
-
- @Override
- public Iterator<FetchMetadataPair> iterator() {
- return new InternalIterator();
- }
-
- private class InternalIterator implements Iterator<FetchMetadataPair> {
- //Object[] is recommended by FindBugs as a lock object
- private Object[] lock = new Object[0];
- private FetchMetadataPair next = null;
- volatile boolean initialized = false;
- InternalIterator() {
-
- }
-
- @Override
- public boolean hasNext() {
- System.out.println("hasNExt");
- if (!initialized) {
- next = getNext();
- initialized = true;
- }
-
- return next != POISON;
- }
-
- /**
- *
- * @return next FetcherStringMetadataPair; if {@link #hasNext()} returns
- * false, this will return null.
- */
- @Override
- public FetchMetadataPair next() {
-
- System.out.println("in next");
-
- if (next == POISON) {
- return null;
- }
- FetchMetadataPair ret = next;
- next = getNext();
- return ret;
- }
-
- private FetchMetadataPair getNext() {
- FetchMetadataPair p = null;
- System.out.println("in get next: " + queue.size());
- try {
- //System.out.println("peek: " + queue.peek());
- p = queue.poll(maxWaitMs, TimeUnit.MILLISECONDS);
- //System.out.println("peek2: " + queue.peek() + " :: "+p);
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- if (p == null) {
- throw new RuntimeException(new TimeoutException(""));
- }
- return p;
- }
- }
-}
diff --git a/tika-core/src/main/java/org/apache/tika/fetcher/FetchPrefixKeyPair.java b/tika-core/src/main/java/org/apache/tika/fetcher/FetchPrefixKeyPair.java
deleted file mode 100644
index 2a068c5..0000000
--- a/tika-core/src/main/java/org/apache/tika/fetcher/FetchPrefixKeyPair.java
+++ /dev/null
@@ -1,53 +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.
- */
-package org.apache.tika.fetcher;
-
-public class FetchPrefixKeyPair {
- private final String prefix;
- private final String key;
-
- private FetchPrefixKeyPair(String prefix, String key) {
- this.prefix = prefix;
- this.key = key;
- }
-
- public static FetchPrefixKeyPair create(String fetcherString) throws FetcherStringException {
- int prefixIndex = fetcherString.indexOf(":");
- if (prefixIndex < 0) {
- throw new FetcherStringException("Can't find fetcher prefix, e.g. the 's3' in s3:/myfile");
- }
- String prefix = fetcherString.substring(0, prefixIndex);
- String key = fetcherString.substring(prefixIndex+1);
- return new FetchPrefixKeyPair(prefix, key);
- }
-
- public String getPrefix() {
- return prefix;
- }
-
- public String getKey() {
- return key;
- }
-
- @Override
- public String toString() {
- return "FetchPrefixKeyPair{" +
- "prefix='" + prefix + '\'' +
- ", key='" + key + '\'' +
- '}';
- }
-}
diff --git a/tika-core/src/main/java/org/apache/tika/fetcher/FileSystemFetcher.java b/tika-core/src/main/java/org/apache/tika/fetcher/FileSystemFetcher.java
deleted file mode 100644
index 63c4cba..0000000
--- a/tika-core/src/main/java/org/apache/tika/fetcher/FileSystemFetcher.java
+++ /dev/null
@@ -1,79 +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.
- */
-package org.apache.tika.fetcher;
-
-import org.apache.tika.config.Field;
-import org.apache.tika.exception.TikaException;
-import org.apache.tika.io.TikaInputStream;
-import org.apache.tika.metadata.Metadata;
-import org.apache.tika.metadata.TikaCoreProperties;
-
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.Collections;
-import java.util.Set;
-
-public class FileSystemFetcher implements Fetcher {
-
- private static String PREFIX = "fs";
- private static final Set<String> SUPPORTED = Collections.singleton(PREFIX);
- private Path basePath = null;
- @Override
- public Set<String> getSupportedPrefixes() {
- return SUPPORTED;
- }
-
- @Override
- public InputStream fetch(String fetcherString, Metadata metadata)
- throws IOException, TikaException {
- FetchPrefixKeyPair fetchPrefixKeyPair = FetchPrefixKeyPair.create(fetcherString);
- metadata.set(TikaCoreProperties.SOURCE_PATH, fetchPrefixKeyPair.getKey());
- Path p = null;
- if (basePath != null) {
- p = basePath.resolve(fetchPrefixKeyPair.getKey());
- if (!Files.isRegularFile(p)) {
- if (!Files.isDirectory(basePath)) {
- throw new IOException("BasePath is not a directory: "+basePath);
- } else {
- throw new FileNotFoundException(p.toAbsolutePath().toString());
- }
- }
- } else {
- p = Paths.get(fetchPrefixKeyPair.getKey());
- if (!Files.isRegularFile(p)) {
- throw new FileNotFoundException(p.toAbsolutePath().toString());
- }
- }
- return TikaInputStream.get(p, metadata);
- }
-
- /**
- * If clients will send in relative paths, this
- * must be set to allow this fetcher to fetch the
- * full path.
- *
- * @param basePath
- */
- @Field
- public void setBasePath(String basePath) {
- this.basePath = Paths.get(basePath);
- }
-}
diff --git a/tika-core/src/main/java/org/apache/tika/fetcher/FetcherStringException.java b/tika-core/src/main/java/org/apache/tika/pipes/emitter/AbstractEmitter.java
similarity index 72%
copy from tika-core/src/main/java/org/apache/tika/fetcher/FetcherStringException.java
copy to tika-core/src/main/java/org/apache/tika/pipes/emitter/AbstractEmitter.java
index 9f1e93b..0aa9e7f 100644
--- a/tika-core/src/main/java/org/apache/tika/fetcher/FetcherStringException.java
+++ b/tika-core/src/main/java/org/apache/tika/pipes/emitter/AbstractEmitter.java
@@ -14,16 +14,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.tika.fetcher;
+package org.apache.tika.pipes.emitter;
-import org.apache.tika.exception.TikaException;
+import org.apache.tika.config.Field;
-/**
- * If something goes wrong in parsing the fetcher string
- */
-public class FetcherStringException extends TikaException {
+public abstract class AbstractEmitter implements Emitter {
+
+ private String name;
- public FetcherStringException(String msg) {
- super(msg);
+ @Field
+ public void setName(String name) {
+ this.name = name;
+ }
+ @Override
+ public String getName() {
+ return name;
}
}
diff --git a/tika-core/src/main/java/org/apache/tika/fetcher/FetcherStringException.java b/tika-core/src/main/java/org/apache/tika/pipes/emitter/Emitter.java
similarity index 68%
copy from tika-core/src/main/java/org/apache/tika/fetcher/FetcherStringException.java
copy to tika-core/src/main/java/org/apache/tika/pipes/emitter/Emitter.java
index 9f1e93b..8f31311 100644
--- a/tika-core/src/main/java/org/apache/tika/fetcher/FetcherStringException.java
+++ b/tika-core/src/main/java/org/apache/tika/pipes/emitter/Emitter.java
@@ -14,16 +14,21 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.tika.fetcher;
+package org.apache.tika.pipes.emitter;
import org.apache.tika.exception.TikaException;
+import org.apache.tika.metadata.Metadata;
-/**
- * If something goes wrong in parsing the fetcher string
- */
-public class FetcherStringException extends TikaException {
+import java.io.IOException;
+import java.util.List;
+import java.util.Set;
+
+public interface Emitter {
+
+ String getName();
+
+ void emit(List<Metadata> metadataList) throws IOException, TikaException;
+ //TODO we can add this later?
+ //void emit(String txt, Metadata metadata) throws IOException, TikaException;
- public FetcherStringException(String msg) {
- super(msg);
- }
}
diff --git a/tika-core/src/main/java/org/apache/tika/emitter/DefaultEmitter.java b/tika-core/src/main/java/org/apache/tika/pipes/emitter/EmitterManager.java
similarity index 61%
rename from tika-core/src/main/java/org/apache/tika/emitter/DefaultEmitter.java
rename to tika-core/src/main/java/org/apache/tika/pipes/emitter/EmitterManager.java
index 80fe314..3c6ec70 100644
--- a/tika-core/src/main/java/org/apache/tika/emitter/DefaultEmitter.java
+++ b/tika-core/src/main/java/org/apache/tika/pipes/emitter/EmitterManager.java
@@ -14,16 +14,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.tika.emitter;
+package org.apache.tika.pipes.emitter;
-import org.apache.tika.config.ServiceLoader;
-import org.apache.tika.exception.TikaException;
-import org.apache.tika.fetcher.FetchPrefixKeyPair;
-import org.apache.tika.fetcher.Fetcher;
-import org.apache.tika.metadata.Metadata;
-
-import java.io.IOException;
-import java.io.InputStream;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -35,48 +27,34 @@ import java.util.concurrent.ConcurrentHashMap;
*
* This does not allow multiple fetchers supporting the same prefix.
*/
-public class DefaultEmitter implements Emitter {
+public class EmitterManager {
private final Map<String, Emitter> emitterMap = new ConcurrentHashMap<>();
- private static List<Emitter> getDefaultFilters(
- ServiceLoader loader) {
- return loader.loadStaticServiceProviders(Emitter.class);
- }
-
- public DefaultEmitter(ServiceLoader serviceLoader) {
- this(getDefaultFilters(serviceLoader));
- }
-
- public DefaultEmitter(List<Emitter> emitters) {
+ public EmitterManager(List<Emitter> emitters) {
for (Emitter emitter : emitters) {
- for (String name : emitter.getSupported()) {
- if (emitterMap.containsKey(name)) {
+ if (emitterMap.containsKey(emitter.getName())) {
throw new IllegalArgumentException(
"Multiple emitters cannot support the same name: "
- + name);
+ + emitter.getName());
}
- emitterMap.put(name, emitter);
- }
+ emitterMap.put(emitter.getName(), emitter);
+
}
}
- @Override
public Set<String> getSupported() {
return emitterMap.keySet();
}
- @Override
- public void emit(String emitterName, List<Metadata> metadata)
- throws IOException, TikaException {
-
+ public Emitter getEmitter(String emitterName) {
Emitter emitter = emitterMap.get(emitterName);
if (emitter == null) {
throw new IllegalArgumentException("Can't find emitter for prefix: "+
emitterName);
}
- emitter.emit(emitterName, metadata);
+ return emitter;
}
}
diff --git a/tika-core/src/main/java/org/apache/tika/fetcher/FetchMetadataPair.java b/tika-core/src/main/java/org/apache/tika/pipes/emitter/EmptyEmitter.java
similarity index 57%
copy from tika-core/src/main/java/org/apache/tika/fetcher/FetchMetadataPair.java
copy to tika-core/src/main/java/org/apache/tika/pipes/emitter/EmptyEmitter.java
index 9711c1f..9a1a10a 100644
--- a/tika-core/src/main/java/org/apache/tika/fetcher/FetchMetadataPair.java
+++ b/tika-core/src/main/java/org/apache/tika/pipes/emitter/EmptyEmitter.java
@@ -14,33 +14,22 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.tika.fetcher;
+package org.apache.tika.pipes.emitter;
+import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
-public class FetchMetadataPair {
+import java.io.IOException;
+import java.util.List;
- private final String fetcherString;
- private final Metadata metadata;
-
- public FetchMetadataPair(String fetcherString, Metadata metadata) {
- this.fetcherString = fetcherString;
- this.metadata = metadata;
- }
-
- public String getFetcherString() {
- return fetcherString;
- }
-
- public Metadata getMetadata() {
- return metadata;
+public class EmptyEmitter implements Emitter {
+ @Override
+ public String getName() {
+ return "empty";
}
@Override
- public String toString() {
- return "FetcherStringMetadataPair{" +
- "fetcherString='" + fetcherString + '\'' +
- ", metadata=" + metadata +
- '}';
+ public void emit(List<Metadata> metadataList) throws IOException, TikaException {
+
}
}
diff --git a/tika-core/src/main/java/org/apache/tika/fetcher/FetcherStringException.java b/tika-core/src/main/java/org/apache/tika/pipes/emitter/TikaEmitterException.java
similarity index 80%
copy from tika-core/src/main/java/org/apache/tika/fetcher/FetcherStringException.java
copy to tika-core/src/main/java/org/apache/tika/pipes/emitter/TikaEmitterException.java
index 9f1e93b..00a5197 100644
--- a/tika-core/src/main/java/org/apache/tika/fetcher/FetcherStringException.java
+++ b/tika-core/src/main/java/org/apache/tika/pipes/emitter/TikaEmitterException.java
@@ -14,16 +14,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.tika.fetcher;
+package org.apache.tika.pipes.emitter;
import org.apache.tika.exception.TikaException;
-/**
- * If something goes wrong in parsing the fetcher string
- */
-public class FetcherStringException extends TikaException {
-
- public FetcherStringException(String msg) {
+public class TikaEmitterException extends TikaException {
+ public TikaEmitterException(String msg) {
super(msg);
}
}
diff --git a/tika-core/src/main/java/org/apache/tika/fetcher/FetcherStringException.java b/tika-core/src/main/java/org/apache/tika/pipes/fetcher/AbstractFetcher.java
similarity index 65%
copy from tika-core/src/main/java/org/apache/tika/fetcher/FetcherStringException.java
copy to tika-core/src/main/java/org/apache/tika/pipes/fetcher/AbstractFetcher.java
index 9f1e93b..0b417e3 100644
--- a/tika-core/src/main/java/org/apache/tika/fetcher/FetcherStringException.java
+++ b/tika-core/src/main/java/org/apache/tika/pipes/fetcher/AbstractFetcher.java
@@ -14,16 +14,31 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.tika.fetcher;
+package org.apache.tika.pipes.fetcher;
-import org.apache.tika.exception.TikaException;
+import org.apache.tika.config.Field;
-/**
- * If something goes wrong in parsing the fetcher string
- */
-public class FetcherStringException extends TikaException {
- public FetcherStringException(String msg) {
- super(msg);
+public abstract class AbstractFetcher implements Fetcher {
+
+ private String name;
+
+ public AbstractFetcher() {
+
+ }
+
+ public AbstractFetcher(String name) {
+ this.name = name;
}
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Field
+ public void setName(String name) {
+ this.name = name;
+ }
+
}
diff --git a/tika-core/src/main/java/org/apache/tika/fetcher/FetcherStringException.java b/tika-core/src/main/java/org/apache/tika/pipes/fetcher/EmptyFetcher.java
similarity index 68%
copy from tika-core/src/main/java/org/apache/tika/fetcher/FetcherStringException.java
copy to tika-core/src/main/java/org/apache/tika/pipes/fetcher/EmptyFetcher.java
index 9f1e93b..5bc84b0 100644
--- a/tika-core/src/main/java/org/apache/tika/fetcher/FetcherStringException.java
+++ b/tika-core/src/main/java/org/apache/tika/pipes/fetcher/EmptyFetcher.java
@@ -14,16 +14,23 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.tika.fetcher;
+package org.apache.tika.pipes.fetcher;
import org.apache.tika.exception.TikaException;
+import org.apache.tika.metadata.Metadata;
-/**
- * If something goes wrong in parsing the fetcher string
- */
-public class FetcherStringException extends TikaException {
+import java.io.IOException;
+import java.io.InputStream;
+
+public class EmptyFetcher implements Fetcher {
+
+ @Override
+ public String getName() {
+ return "empty";
+ }
- public FetcherStringException(String msg) {
- super(msg);
+ @Override
+ public InputStream fetch(String fetchKey, Metadata metadata) throws TikaException, IOException {
+ return null;
}
}
diff --git a/tika-core/src/main/java/org/apache/tika/pipes/fetcher/FetchId.java b/tika-core/src/main/java/org/apache/tika/pipes/fetcher/FetchId.java
new file mode 100644
index 0000000..a327fc6
--- /dev/null
+++ b/tika-core/src/main/java/org/apache/tika/pipes/fetcher/FetchId.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tika.pipes.fetcher;
+
+/**
+ * Pair of fetcherName (which fetcher to call) and the key
+ * to send to that fetcher to retrieve a specific file.
+ */
+public class FetchId {
+ private final String fetcherName;
+ private final String fetchKey;
+
+ public FetchId(String fetcherName, String fetchKey) {
+ this.fetcherName = fetcherName;
+ this.fetchKey = fetchKey;
+ }
+
+ public String getFetcherName() {
+ return fetcherName;
+ }
+
+ public String getFetchKey() {
+ return fetchKey;
+ }
+
+ @Override
+ public String toString() {
+ return "FetcherKeyPair{" +
+ "fetcherName='" + fetcherName + '\'' +
+ ", fetchKey='" + fetchKey + '\'' +
+ '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ FetchId fetchId = (FetchId) o;
+
+ if (fetcherName != null ? !fetcherName.equals(fetchId.fetcherName) : fetchId.fetcherName != null) return false;
+ return fetchKey != null ? fetchKey.equals(fetchId.fetchKey) : fetchId.fetchKey == null;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = fetcherName != null ? fetcherName.hashCode() : 0;
+ result = 31 * result + (fetchKey != null ? fetchKey.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/tika-core/src/main/java/org/apache/tika/fetcher/FetchMetadataPair.java b/tika-core/src/main/java/org/apache/tika/pipes/fetcher/FetchIdMetadataPair.java
similarity index 53%
rename from tika-core/src/main/java/org/apache/tika/fetcher/FetchMetadataPair.java
rename to tika-core/src/main/java/org/apache/tika/pipes/fetcher/FetchIdMetadataPair.java
index 9711c1f..25d89db 100644
--- a/tika-core/src/main/java/org/apache/tika/fetcher/FetchMetadataPair.java
+++ b/tika-core/src/main/java/org/apache/tika/pipes/fetcher/FetchIdMetadataPair.java
@@ -14,33 +14,51 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.tika.fetcher;
+package org.apache.tika.pipes.fetcher;
import org.apache.tika.metadata.Metadata;
-public class FetchMetadataPair {
+public class FetchIdMetadataPair {
- private final String fetcherString;
+ private final FetchId fetchId;
private final Metadata metadata;
- public FetchMetadataPair(String fetcherString, Metadata metadata) {
- this.fetcherString = fetcherString;
+ public FetchIdMetadataPair(FetchId fetchId, Metadata metadata) {
+ this.fetchId = fetchId;
this.metadata = metadata;
}
- public String getFetcherString() {
- return fetcherString;
- }
-
public Metadata getMetadata() {
return metadata;
}
+ public FetchId getFetchId() {
+ return fetchId;
+ }
+
@Override
public String toString() {
- return "FetcherStringMetadataPair{" +
- "fetcherString='" + fetcherString + '\'' +
+ return "FetchIdMetadataPair{" +
+ "fetchId=" + fetchId +
", metadata=" + metadata +
'}';
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ FetchIdMetadataPair that = (FetchIdMetadataPair) o;
+
+ if (fetchId != null ? !fetchId.equals(that.fetchId) : that.fetchId != null) return false;
+ return metadata != null ? metadata.equals(that.metadata) : that.metadata == null;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = fetchId != null ? fetchId.hashCode() : 0;
+ result = 31 * result + (metadata != null ? metadata.hashCode() : 0);
+ return result;
+ }
}
diff --git a/tika-core/src/main/java/org/apache/tika/fetcher/Fetcher.java b/tika-core/src/main/java/org/apache/tika/pipes/fetcher/Fetcher.java
similarity index 76%
rename from tika-core/src/main/java/org/apache/tika/fetcher/Fetcher.java
rename to tika-core/src/main/java/org/apache/tika/pipes/fetcher/Fetcher.java
index 95a795c..0450737 100644
--- a/tika-core/src/main/java/org/apache/tika/fetcher/Fetcher.java
+++ b/tika-core/src/main/java/org/apache/tika/pipes/fetcher/Fetcher.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.tika.fetcher;
+package org.apache.tika.pipes.fetcher;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
@@ -30,12 +30,10 @@ import java.util.Set;
*
* Implementations of Fetcher must be thread safe.
*
- * The fetcherString must start with a prefix that can be
- * used to uniquely select the fetcher, e.g. file:my_file.pdf, s3:bucket/path/to/my_file
- *
- * Each fetcher must specify which prefixes it can handle.
*/
public interface Fetcher {
- Set<String> getSupportedPrefixes();
- InputStream fetch(String fetcherString, Metadata metadata) throws TikaException, IOException;
+
+ String getName();
+
+ InputStream fetch(String fetchKey, Metadata metadata) throws TikaException, IOException;
}
diff --git a/tika-core/src/main/java/org/apache/tika/fetcher/DefaultFetcher.java b/tika-core/src/main/java/org/apache/tika/pipes/fetcher/FetcherManager.java
similarity index 58%
rename from tika-core/src/main/java/org/apache/tika/fetcher/DefaultFetcher.java
rename to tika-core/src/main/java/org/apache/tika/pipes/fetcher/FetcherManager.java
index 085e021..1ea46fd 100644
--- a/tika-core/src/main/java/org/apache/tika/fetcher/DefaultFetcher.java
+++ b/tika-core/src/main/java/org/apache/tika/pipes/fetcher/FetcherManager.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.tika.fetcher;
+package org.apache.tika.pipes.fetcher;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
@@ -27,43 +27,41 @@ import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/**
- * Utility class that will apply the appropriate fetcher
- * to the fetcherString based on the prefix.
- *
+ * Utility class to hold multiple fetchers.
+ * <p>
* This forbids multiple fetchers supporting the same prefix.
*/
-public class DefaultFetcher implements Fetcher {
+public class FetcherManager {
private final Map<String, Fetcher> fetcherMap = new ConcurrentHashMap<>();
- public DefaultFetcher(List<Fetcher> fetchers) {
+ public FetcherManager(List<Fetcher> fetchers) {
for (Fetcher fetcher : fetchers) {
- for (String supportedPrefix : fetcher.getSupportedPrefixes()) {
- if (fetcherMap.containsKey(supportedPrefix)) {
- throw new IllegalArgumentException(
- "Multiple fetchers cannot support the same prefix: "
- + supportedPrefix);
- }
- fetcherMap.put(supportedPrefix, fetcher);
+ String name = fetcher.getName();
+ if (name == null || name.trim().length() == 0) {
+ throw new IllegalArgumentException("fetcher name must not be blank");
+ }
+ if (fetcherMap.containsKey(fetcher.getName())) {
+ throw new IllegalArgumentException(
+ "Multiple fetchers cannot support the same prefix: "
+ + fetcher.getName());
}
+ fetcherMap.put(fetcher.getName(), fetcher);
}
}
- @Override
- public Set<String> getSupportedPrefixes() {
- return fetcherMap.keySet();
- }
-
- @Override
- public InputStream fetch(String fetcherString, Metadata metadata)
+ public Fetcher getFetcher(String fetcherName)
throws IOException, TikaException {
- FetchPrefixKeyPair fetchPrefixKeyPair = FetchPrefixKeyPair.create(fetcherString);
-
- Fetcher fetcher = fetcherMap.get(fetchPrefixKeyPair.getPrefix());
+ Fetcher fetcher = fetcherMap.get(fetcherName);
if (fetcher == null) {
- throw new IllegalArgumentException("Can't find fetcher for prefix: "+
- fetchPrefixKeyPair.getPrefix());
+ throw new IllegalArgumentException("Can't find fetcher for fetcherName: " +
+ fetcherName +
+ ". I've loaded: "+fetcherMap.keySet());
}
- return fetcher.fetch(fetcherString, metadata);
+ return fetcher;
+ }
+
+ public Set<String> getSupported() {
+ return fetcherMap.keySet();
}
}
diff --git a/tika-core/src/main/java/org/apache/tika/fetcher/FetcherStringException.java b/tika-core/src/main/java/org/apache/tika/pipes/fetcher/FetcherStringException.java
similarity index 96%
copy from tika-core/src/main/java/org/apache/tika/fetcher/FetcherStringException.java
copy to tika-core/src/main/java/org/apache/tika/pipes/fetcher/FetcherStringException.java
index 9f1e93b..a07439a 100644
--- a/tika-core/src/main/java/org/apache/tika/fetcher/FetcherStringException.java
+++ b/tika-core/src/main/java/org/apache/tika/pipes/fetcher/FetcherStringException.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.tika.fetcher;
+package org.apache.tika.pipes.fetcher;
import org.apache.tika.exception.TikaException;
diff --git a/tika-core/src/main/java/org/apache/tika/pipes/fetcher/FileSystemFetcher.java b/tika-core/src/main/java/org/apache/tika/pipes/fetcher/FileSystemFetcher.java
new file mode 100644
index 0000000..7bdf56d
--- /dev/null
+++ b/tika-core/src/main/java/org/apache/tika/pipes/fetcher/FileSystemFetcher.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tika.pipes.fetcher;
+
+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.exception.TikaConfigException;
+import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
+import org.apache.tika.metadata.Metadata;
+import org.apache.tika.metadata.TikaCoreProperties;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+public class FileSystemFetcher extends AbstractFetcher implements Initializable {
+
+ private Path basePath = null;
+
+ @Override
+ public InputStream fetch(String fetchKey, Metadata metadata)
+ throws IOException, TikaException {
+ if (basePath == null) {
+ throw new IllegalStateException("must set 'basePath' before calling fetch");
+
+ }
+ if (fetchKey.contains("\u0000")) {
+ throw new IllegalArgumentException("Path must not contain \u0000. " +
+ "Please review the life decisions that led you to requesting " +
+ "a file name with this character in it.");
+ }
+ Path p = basePath.resolve(fetchKey);
+ if (!p.toRealPath().startsWith(basePath.toRealPath())) {
+ throw new IllegalArgumentException("fetchKey must resolve to be a" +
+ " descendant of the 'basePath'");
+ }
+
+ metadata.set(TikaCoreProperties.SOURCE_PATH, fetchKey);
+
+ if (!Files.isRegularFile(p)) {
+ if (!Files.isDirectory(basePath)) {
+ throw new IOException("BasePath is not a directory: " + basePath);
+ } else {
+ throw new FileNotFoundException(p.toAbsolutePath().toString());
+ }
+ }
+
+ return TikaInputStream.get(p, metadata);
+ }
+
+ /**
+ * If clients will send in relative paths, this
+ * must be set to allow this fetcher to fetch the
+ * full path.
+ *
+ * @param basePath
+ */
+ @Field
+ public void setBasePath(String basePath) {
+ this.basePath = Paths.get(basePath);
+ }
+
+ static boolean isDescendant(Path root, Path descendant) {
+ return descendant.toAbsolutePath().normalize().startsWith(
+ root.toAbsolutePath().normalize());
+ }
+
+ public Path getBasePath() {
+ return basePath;
+ }
+
+ @Override
+ public void initialize(Map<String, Param> params) throws TikaConfigException {
+ //no-op
+ }
+
+ @Override
+ public void checkInitialization(InitializableProblemHandler problemHandler) throws TikaConfigException {
+ if (basePath == null || basePath.toString().trim().length() == 0) {
+ throw new IllegalArgumentException("'basePath' must be specified");
+ }
+ if (basePath.toAbsolutePath().toString().contains("\u0000")) {
+ throw new IllegalArgumentException("base path must not contain \u0000. " +
+ "Seriously, what were you thinking?");
+ }
+ }
+}
diff --git a/tika-core/src/main/java/org/apache/tika/fetcher/SimpleUrlFetcher.java b/tika-core/src/main/java/org/apache/tika/pipes/fetcher/SimpleUrlFetcher.java
similarity index 78%
rename from tika-core/src/main/java/org/apache/tika/fetcher/SimpleUrlFetcher.java
rename to tika-core/src/main/java/org/apache/tika/pipes/fetcher/SimpleUrlFetcher.java
index a15b78c..40faadd 100644
--- a/tika-core/src/main/java/org/apache/tika/fetcher/SimpleUrlFetcher.java
+++ b/tika-core/src/main/java/org/apache/tika/pipes/fetcher/SimpleUrlFetcher.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.tika.fetcher;
+package org.apache.tika.pipes.fetcher;
import org.apache.tika.exception.TikaException;
import org.apache.tika.io.TikaInputStream;
@@ -35,21 +35,19 @@ import java.util.Set;
* This is limited to http: and https: urls. This does
* not support the file:/// protocol. See {@link FileSystemFetcher}.
*/
-public class SimpleUrlFetcher implements Fetcher {
+public class SimpleUrlFetcher extends AbstractFetcher {
- private static String PREFIX = "url";
- private static final Set<String> SUPPORTED = Collections.singleton(PREFIX);
+ private static String NAME = "url";
- @Override
- public Set<String> getSupportedPrefixes() {
- return SUPPORTED;
+ public SimpleUrlFetcher() {
+ super(NAME);
}
+
@Override
- public InputStream fetch(String fetcherString, Metadata metadata)
+ public InputStream fetch(String fetchKey, Metadata metadata)
throws IOException, TikaException {
- FetchPrefixKeyPair fetchPrefixKeyPair = FetchPrefixKeyPair.create(fetcherString);
- URL url = new URL(fetchPrefixKeyPair.getKey());
+ URL url = new URL(fetchKey);
if (! url.getProtocol().equals("http") &&
! url.getProtocol().equals("https") &&
! url.getProtocol().equals("ftp")) {
diff --git a/tika-core/src/main/java/org/apache/tika/fetcher/FetcherStringException.java b/tika-core/src/main/java/org/apache/tika/pipes/fetchiterator/EmptyFetchIterator.java
similarity index 64%
copy from tika-core/src/main/java/org/apache/tika/fetcher/FetcherStringException.java
copy to tika-core/src/main/java/org/apache/tika/pipes/fetchiterator/EmptyFetchIterator.java
index 9f1e93b..1a2d40e 100644
--- a/tika-core/src/main/java/org/apache/tika/fetcher/FetcherStringException.java
+++ b/tika-core/src/main/java/org/apache/tika/pipes/fetchiterator/EmptyFetchIterator.java
@@ -14,16 +14,22 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.tika.fetcher;
+package org.apache.tika.pipes.fetchiterator;
-import org.apache.tika.exception.TikaException;
+import org.apache.tika.config.InitializableProblemHandler;
+import org.apache.tika.config.Param;
+import org.apache.tika.exception.TikaConfigException;
-/**
- * If something goes wrong in parsing the fetcher string
- */
-public class FetcherStringException extends TikaException {
+import java.io.IOException;
+
+import java.util.Map;
+import java.util.concurrent.TimeoutException;
+
+public class EmptyFetchIterator extends FetchIterator {
+
+
+ @Override
+ protected void enqueue() throws IOException, TimeoutException, InterruptedException {
- public FetcherStringException(String msg) {
- super(msg);
}
}
diff --git a/tika-core/src/main/java/org/apache/tika/pipes/fetchiterator/FetchIterator.java b/tika-core/src/main/java/org/apache/tika/pipes/fetchiterator/FetchIterator.java
new file mode 100644
index 0000000..b11615f
--- /dev/null
+++ b/tika-core/src/main/java/org/apache/tika/pipes/fetchiterator/FetchIterator.java
@@ -0,0 +1,135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tika.pipes.fetchiterator;
+
+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.exception.TikaConfigException;
+import org.apache.tika.pipes.fetcher.FetchIdMetadataPair;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.Callable;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * Abstract class that handles the testing for timeouts/thread safety
+ * issues. Concrete classes implement the blocking {@link #enqueue()}.
+ * <p>
+ * This must be "called", obviously...
+ */
+public abstract class FetchIterator implements Callable<Integer>, Initializable {
+
+ public static final long DEFAULT_MAX_WAIT_MS = 300_000;
+ public static final int DEFAULT_QUEUE_SIZE = 1000;
+ public static final FetchIdMetadataPair COMPLETED_SEMAPHORE =
+ new FetchIdMetadataPair(null, null);
+
+ private long maxWaitMs = DEFAULT_MAX_WAIT_MS;
+ private int numConsumers = -1;
+ private ArrayBlockingQueue<FetchIdMetadataPair> queue = null;
+ private int queueSize = DEFAULT_QUEUE_SIZE;
+ private String fetcherName;
+ private int added = 0;
+ public FetchIterator() {
+
+ }
+
+ public FetchIterator(String fetcherName) {
+ this.fetcherName = fetcherName;
+ }
+
+ /**
+ * This must be called before 'calling' this object.
+ * @param numConsumers
+ */
+ public ArrayBlockingQueue<FetchIdMetadataPair> init(int numConsumers) {
+ this.queue = new ArrayBlockingQueue<>(queueSize);
+ this.numConsumers = numConsumers;
+ return queue;
+ }
+
+ @Field
+ public void setFetcherName(String fetcherName) {
+ this.fetcherName = fetcherName;
+ }
+
+ public String getFetcherName() {
+ return fetcherName;
+ }
+
+
+ @Field
+ public void setMaxWaitMs(long maxWaitMs) {
+ this.maxWaitMs = maxWaitMs;
+ }
+
+ @Field
+ public void setQueueSize(int queueSize) {
+ this.queueSize = queueSize;
+ }
+ @Override
+ public Integer call() throws Exception {
+ if (queue == null || numConsumers < 0) {
+ throw new IllegalStateException("Must call 'init' before calling this object");
+ }
+
+ enqueue();
+ for (int i = 0; i < numConsumers; i++) {
+ try {
+ tryToAdd(COMPLETED_SEMAPHORE);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ return added;
+ }
+
+ protected abstract void enqueue() throws IOException, TimeoutException, InterruptedException;
+
+ protected void tryToAdd(FetchIdMetadataPair p) throws InterruptedException, TimeoutException {
+ if (p != COMPLETED_SEMAPHORE) {
+ added++;
+ }
+ boolean offered = queue.offer(p, maxWaitMs, TimeUnit.MILLISECONDS);
+ if (!offered) {
+ throw new TimeoutException("timed out while offering");
+ }
+ }
+
+ @Override
+ public void initialize(Map<String, Param> params) throws TikaConfigException {
+ //no-op
+ }
+
+ @Override
+ public void checkInitialization(InitializableProblemHandler problemHandler) throws TikaConfigException {
+ //no-op
+ }
+
+ protected static void mustNotBeEmpty(String paramName, String paramValue) {
+ if (paramValue == null || paramValue.trim().equals("")) {
+ throw new IllegalArgumentException("parameter '"+
+ paramName + "' must be set in the config file");
+ }
+ }
+
+}
diff --git a/tika-core/src/main/java/org/apache/tika/fetcher/FileSystemFetchIterator.java b/tika-core/src/main/java/org/apache/tika/pipes/fetchiterator/FileSystemFetchIterator.java
similarity index 69%
rename from tika-core/src/main/java/org/apache/tika/fetcher/FileSystemFetchIterator.java
rename to tika-core/src/main/java/org/apache/tika/pipes/fetchiterator/FileSystemFetchIterator.java
index 5edf83d..35e2ea8 100644
--- a/tika-core/src/main/java/org/apache/tika/fetcher/FileSystemFetchIterator.java
+++ b/tika-core/src/main/java/org/apache/tika/pipes/fetchiterator/FileSystemFetchIterator.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.tika.fetcher;
+package org.apache.tika.pipes.fetchiterator;
import org.apache.tika.config.Field;
import org.apache.tika.config.Initializable;
@@ -22,6 +22,8 @@ import org.apache.tika.config.InitializableProblemHandler;
import org.apache.tika.config.Param;
import org.apache.tika.exception.TikaConfigException;
import org.apache.tika.metadata.Metadata;
+import org.apache.tika.pipes.fetcher.FetchId;
+import org.apache.tika.pipes.fetcher.FetchIdMetadataPair;
import java.io.IOException;
import java.nio.file.FileVisitResult;
@@ -30,33 +32,21 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
-import java.rmi.ServerRuntimeException;
import java.util.Map;
import java.util.concurrent.TimeoutException;
-public class FileSystemFetchIterator extends FetchIterator implements Initializable {
+public class FileSystemFetchIterator
+ extends FetchIterator implements Initializable {
- private static final String NAME = "fs";
private Path basePath;
- private String fetchPrefix;
public FileSystemFetchIterator() {
- super(NAME);
- }
- public FileSystemFetchIterator(String fetchPrefix, Path basePath) {
- super(NAME);
- this.fetchPrefix = fetchPrefix;
- this.basePath = basePath;
}
- /**
- * fetchPrefix not including the colon (:), e.g. "fs"
- * @param fetchPrefix
- */
- @Field
- public void setFetchPrefix(String fetchPrefix) {
- this.fetchPrefix = fetchPrefix;
+ public FileSystemFetchIterator(String fetcherName, Path basePath) {
+ super(fetcherName);
+ this.basePath = basePath;
}
@Field
@@ -65,10 +55,14 @@ public class FileSystemFetchIterator extends FetchIterator implements Initializa
}
@Override
- protected void enqueue() throws IOException, TimeoutException {
-
+ protected void enqueue() throws InterruptedException, IOException, TimeoutException {
+ if (! Files.isDirectory(basePath)) {
+ throw new IllegalArgumentException("\"basePath\" directory does not exist: " +
+ basePath.toAbsolutePath());
+ }
+ String fetcherName = getFetcherName();
try {
- Files.walkFileTree(basePath, new FSFileVisitor());
+ Files.walkFileTree(basePath, new FSFileVisitor(fetcherName));
} catch (IOException e) {
Throwable cause = e.getCause();
if (cause != null && cause instanceof TimeoutException) {
@@ -76,38 +70,28 @@ public class FileSystemFetchIterator extends FetchIterator implements Initializa
}
throw e;
}
- try {
- tryToAdd(POISON);
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
}
- @Override
- public void initialize(Map<String, Param> params) throws TikaConfigException {
- //no-op
- }
@Override
public void checkInitialization(InitializableProblemHandler problemHandler) throws TikaConfigException {
+
+ //ignore problem handler. These should all be fatal.
if (basePath == null) {
throw new TikaConfigException("Must specify a \"basePath\"");
}
- if (! Files.isDirectory(basePath)) {
- throw new TikaConfigException("\"root\" directory does not exist: " +
- basePath.toAbsolutePath());
- }
- if (fetchPrefix == null || fetchPrefix.trim().length() == 0) {
- throw new TikaConfigException("\"fetchPrefix\" must be specified and must be not blank");
- }
- if (fetchPrefix.contains(":")) {
- throw new TikaConfigException("\"fetchPrefix\" must not contain a colon (:)");
+ if (getFetcherName() == null || getFetcherName().trim().length() == 0) {
+ throw new TikaConfigException("\"fetcherName\" must be specified and must be not blank");
}
}
private class FSFileVisitor implements FileVisitor<Path> {
+ private final String fetcherName;
+ private FSFileVisitor(String fetcherName) {
+ this.fetcherName = fetcherName;
+ }
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
return FileVisitResult.CONTINUE;
@@ -116,10 +100,10 @@ public class FileSystemFetchIterator extends FetchIterator implements Initializa
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
String relPath = basePath.relativize(file).toString();
- String fetcherString = fetchPrefix + ":" + relPath;
try {
- tryToAdd(new FetchMetadataPair(fetcherString, new Metadata()));
+ tryToAdd(new FetchIdMetadataPair(
+ new FetchId(fetcherName, relPath), new Metadata()));
} catch (TimeoutException e) {
throw new IOException(e);
} catch (InterruptedException e) {
diff --git a/tika-core/src/test/java/org/apache/tika/config/TikaConfigTest.java b/tika-core/src/test/java/org/apache/tika/config/TikaConfigTest.java
index 5ebfdf5..f2cbf73 100644
--- a/tika-core/src/test/java/org/apache/tika/config/TikaConfigTest.java
+++ b/tika-core/src/test/java/org/apache/tika/config/TikaConfigTest.java
@@ -43,6 +43,13 @@ import org.apache.tika.parser.ErrorParser;
import org.apache.tika.parser.Parser;
import org.apache.tika.parser.ParserDecorator;
import org.apache.tika.parser.multiple.FallbackParser;
+import org.apache.tika.pipes.emitter.Emitter;
+import org.apache.tika.pipes.emitter.EmitterManager;
+import org.apache.tika.pipes.fetcher.Fetcher;
+import org.apache.tika.pipes.fetcher.FetcherManager;
+import org.apache.tika.pipes.fetcher.FileSystemFetcher;
+import org.apache.tika.pipes.fetchiterator.FetchIterator;
+import org.apache.tika.pipes.fetchiterator.FileSystemFetchIterator;
import org.apache.tika.utils.XMLReaderUtils;
import org.junit.Test;
@@ -355,4 +362,64 @@ public class TikaConfigTest extends AbstractTikaConfigTest {
}
+ @Test
+ public void testFetchers() throws Exception {
+ TikaConfig config = getConfig("fetchers-config.xml");
+ FetcherManager m = config.getFetcherManager();
+ Fetcher f1 = m.getFetcher("fs1");
+ assertEquals(Paths.get("/my/base/path1"),
+ ((FileSystemFetcher)f1).getBasePath()
+ );
+
+ Fetcher f2 = m.getFetcher("fs2");
+ assertEquals(Paths.get("/my/base/path2"),
+ ((FileSystemFetcher)f2).getBasePath()
+ );
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testDuplicateFetchers() throws Exception {
+ //can't have two fetchers with the same name
+ TikaConfig config = getConfig("fetchers-duplicate-config.xml");
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testNoNameFetchers() throws Exception {
+ //can't have two fetchers with the same name
+ TikaConfig config = getConfig("fetchers-noname-config.xml");
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testNoBasePathFetchers() throws Exception {
+ //can't have an fs fetcher with no basepath specified
+ TikaConfig config = getConfig("fetchers-nobasepath-config.xml");
+ }
+
+ @Test
+ public void testEmitters() throws Exception {
+ EmitterManager emitterManager = getConfig("emitters-config.xml").getEmitterManager();
+ Emitter em1 = emitterManager.getEmitter("em1");
+ assertNotNull(em1);
+ Emitter em2 = emitterManager.getEmitter("em2");
+ assertNotNull(em2);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testDuplicateEmitters() throws Exception {
+ getConfig("emitters-duplicate-config.xml").getEmitterManager();
+ }
+
+ @Test
+ public void testFetchIterator() throws Exception {
+ FetchIterator f = getConfig("fetch-iterator-config.xml")
+ .getFetchIterator();
+ assertEquals("fs1", f.getFetcherName());
+ }
+
+ @Test(expected = TikaConfigException.class)
+ public void testMultipleFetchIterators() throws Exception {
+ FetchIterator f = getConfig("fetch-iterator-multiple-config.xml")
+ .getFetchIterator();
+ assertEquals("fs1", f.getFetcherName());
+ }
}
\ No newline at end of file
diff --git a/tika-core/src/main/java/org/apache/tika/fetcher/FetcherStringException.java b/tika-core/src/test/java/org/apache/tika/pipes/emitter/MockEmitter.java
similarity index 75%
rename from tika-core/src/main/java/org/apache/tika/fetcher/FetcherStringException.java
rename to tika-core/src/test/java/org/apache/tika/pipes/emitter/MockEmitter.java
index 9f1e93b..f00d815 100644
--- a/tika-core/src/main/java/org/apache/tika/fetcher/FetcherStringException.java
+++ b/tika-core/src/test/java/org/apache/tika/pipes/emitter/MockEmitter.java
@@ -14,16 +14,18 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.tika.fetcher;
+package org.apache.tika.pipes.emitter;
import org.apache.tika.exception.TikaException;
+import org.apache.tika.metadata.Metadata;
-/**
- * If something goes wrong in parsing the fetcher string
- */
-public class FetcherStringException extends TikaException {
+import java.io.IOException;
+import java.util.List;
+
+public class MockEmitter extends AbstractEmitter {
+
+ @Override
+ public void emit(List<Metadata> metadataList) throws IOException, TikaException {
- public FetcherStringException(String msg) {
- super(msg);
}
}
diff --git a/tika-core/src/test/java/org/apache/tika/pipes/fetcher/FileSystemFetcherTest.java b/tika-core/src/test/java/org/apache/tika/pipes/fetcher/FileSystemFetcherTest.java
new file mode 100644
index 0000000..60e14e3
--- /dev/null
+++ b/tika-core/src/test/java/org/apache/tika/pipes/fetcher/FileSystemFetcherTest.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tika.pipes.fetcher;
+
+import org.apache.tika.config.InitializableProblemHandler;
+import org.junit.Test;
+
+
+import java.nio.file.InvalidPathException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+
+public class FileSystemFetcherTest {
+
+ @Test
+ public void testDescendant() throws Exception {
+
+ Path root = Paths.get("/ab/cd/");
+ Path descendant = root.resolve("ef/gh/ij.pdf");
+ assertTrue(FileSystemFetcher.isDescendant(root, descendant));
+
+ descendant = Paths.get("/cd/ef.pdf");
+ assertFalse(FileSystemFetcher.isDescendant(root, descendant));
+
+ descendant = root.resolve("../../ij.pdf");
+ assertFalse(FileSystemFetcher.isDescendant(root, descendant));
+ }
+
+ @Test(expected = InvalidPathException.class)
+ public void testNullByte() throws Exception {
+ FileSystemFetcher f = new FileSystemFetcher();
+ f.setBasePath("bad\u0000path");
+ f.setName("fs");
+ f.checkInitialization(InitializableProblemHandler.IGNORE);
+ }
+}
diff --git a/tika-core/src/test/java/org/apache/tika/fetcher/FileSystemFetchIteratorTest.java b/tika-core/src/test/java/org/apache/tika/pipes/fetchiterator/FileSystemFetchIteratorTest.java
similarity index 77%
rename from tika-core/src/test/java/org/apache/tika/fetcher/FileSystemFetchIteratorTest.java
rename to tika-core/src/test/java/org/apache/tika/pipes/fetchiterator/FileSystemFetchIteratorTest.java
index 5349fcb..f23489a 100644
--- a/tika-core/src/test/java/org/apache/tika/fetcher/FileSystemFetchIteratorTest.java
+++ b/tika-core/src/test/java/org/apache/tika/pipes/fetchiterator/FileSystemFetchIteratorTest.java
@@ -14,8 +14,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.tika.fetcher;
+package org.apache.tika.pipes.fetchiterator;
+import org.apache.tika.pipes.fetcher.FetchIdMetadataPair;
import org.junit.Test;
import java.io.IOException;
@@ -25,6 +26,7 @@ import java.nio.file.Paths;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@@ -37,28 +39,38 @@ import static org.junit.Assert.assertEquals;
public class FileSystemFetchIteratorTest {
- @Test
+ @Test(timeout = 30000)
public void testBasic() throws Exception {
Path root = Paths.get(".");
- String fetchPrefix = "fs";
+
+ List<Path> files = listFiles(root);
+ Set<String> truthSet = new HashSet<>();
+ for (Path p : files) {
+ String fetchString = root.relativize(p).toString();
+ truthSet.add(fetchString);
+ }
+
+ String fetcherName = "fs";
ExecutorService es = Executors.newFixedThreadPool(1);
ExecutorCompletionService cs = new ExecutorCompletionService(es);
- FetchIterator it = new FileSystemFetchIterator(fetchPrefix, root);
+ FetchIterator it = new FileSystemFetchIterator(fetcherName, root);
+ it.setQueueSize(20000);
+ ArrayBlockingQueue<FetchIdMetadataPair> q = it.init(1);
cs.submit(it);
- Set<String> iteratorSet = new HashSet<>();
- int i = 0;
- for (FetchMetadataPair p : it) {
- iteratorSet.add(p.getFetcherString());
- }
+
+
Future f = cs.take();
f.get();
- List<Path> files = listFiles(root);
- Set<String> truthSet = new HashSet<>();
- for (Path p : files) {
- String fetchString = fetchPrefix+":"+root.relativize(p);
- truthSet.add(fetchString);
+
+ Set<String> iteratorSet = new HashSet<>();
+ for (FetchIdMetadataPair p : q) {
+ if (p == FetchIterator.COMPLETED_SEMAPHORE) {
+ break;
+ }
+ iteratorSet.add(p.getFetchId().getFetchKey());
}
+
assertEquals(truthSet, iteratorSet);
}
diff --git a/tika-fetchers/tika-fetcher-s3/src/test/resources/tika-config-s3.xml b/tika-core/src/test/resources/org/apache/tika/config/emitters-config.xml
similarity index 69%
copy from tika-fetchers/tika-fetcher-s3/src/test/resources/tika-config-s3.xml
copy to tika-core/src/test/resources/org/apache/tika/config/emitters-config.xml
index 39a2ce8..73218c4 100644
--- a/tika-fetchers/tika-fetcher-s3/src/test/resources/tika-config-s3.xml
+++ b/tika-core/src/test/resources/org/apache/tika/config/emitters-config.xml
@@ -16,12 +16,16 @@
limitations under the License.
-->
<properties>
- <fetchers>
- <fetcher class="org.apache.tika.fetcher.s3.S3Fetcher">
+ <emitters>
+ <emitter class="org.apache.tika.pipes.emitter.MockEmitter">
<params>
- <param name="region" type="string">us-east-1</param>
- <param name="profile" type="string">my_profile</param>
+ <param name="name" type="string">em1</param>
</params>
- </fetcher>
- </fetchers>
-</properties>
\ No newline at end of file
+ </emitter>
+ <emitter class="org.apache.tika.pipes.emitter.MockEmitter">
+ <params>
+ <param name="name" type="string">em2</param>
+ </params>
+ </emitter>
+ </emitters>
+</properties>
diff --git a/tika-fetchers/tika-fetcher-s3/src/test/resources/tika-config-s3.xml b/tika-core/src/test/resources/org/apache/tika/config/emitters-duplicate-config.xml
similarity index 69%
copy from tika-fetchers/tika-fetcher-s3/src/test/resources/tika-config-s3.xml
copy to tika-core/src/test/resources/org/apache/tika/config/emitters-duplicate-config.xml
index 39a2ce8..25dd7ce 100644
--- a/tika-fetchers/tika-fetcher-s3/src/test/resources/tika-config-s3.xml
+++ b/tika-core/src/test/resources/org/apache/tika/config/emitters-duplicate-config.xml
@@ -16,12 +16,16 @@
limitations under the License.
-->
<properties>
- <fetchers>
- <fetcher class="org.apache.tika.fetcher.s3.S3Fetcher">
+ <emitters>
+ <emitter class="org.apache.tika.pipes.emitter.MockEmitter">
<params>
- <param name="region" type="string">us-east-1</param>
- <param name="profile" type="string">my_profile</param>
+ <param name="name" type="string">em1</param>
</params>
- </fetcher>
- </fetchers>
-</properties>
\ No newline at end of file
+ </emitter>
+ <emitter class="org.apache.tika.pipes.emitter.MockEmitter">
+ <params>
+ <param name="name" type="string">em1</param>
+ </params>
+ </emitter>
+ </emitters>
+</properties>
diff --git a/tika-fetchers/tika-fetcher-s3/src/test/resources/tika-config-s3.xml b/tika-core/src/test/resources/org/apache/tika/config/fetch-iterator-config.xml
similarity index 73%
copy from tika-fetchers/tika-fetcher-s3/src/test/resources/tika-config-s3.xml
copy to tika-core/src/test/resources/org/apache/tika/config/fetch-iterator-config.xml
index 39a2ce8..7f3dd41 100644
--- a/tika-fetchers/tika-fetcher-s3/src/test/resources/tika-config-s3.xml
+++ b/tika-core/src/test/resources/org/apache/tika/config/fetch-iterator-config.xml
@@ -16,12 +16,12 @@
limitations under the License.
-->
<properties>
- <fetchers>
- <fetcher class="org.apache.tika.fetcher.s3.S3Fetcher">
+ <fetchIterators>
+ <fetchIterator class="org.apache.tika.pipes.fetchiterator.FileSystemFetchIterator">
<params>
- <param name="region" type="string">us-east-1</param>
- <param name="profile" type="string">my_profile</param>
+ <param name="fetcherName" type="string">fs1</param>
+ <param name="basePath" type="string">/my/base/path1</param>
</params>
- </fetcher>
- </fetchers>
-</properties>
\ No newline at end of file
+ </fetchIterator>
+ </fetchIterators>
+</properties>
diff --git a/tika-fetchers/tika-fetcher-s3/src/test/resources/tika-config-s3.xml b/tika-core/src/test/resources/org/apache/tika/config/fetch-iterator-multiple-config.xml
similarity index 58%
copy from tika-fetchers/tika-fetcher-s3/src/test/resources/tika-config-s3.xml
copy to tika-core/src/test/resources/org/apache/tika/config/fetch-iterator-multiple-config.xml
index 39a2ce8..4417fbc 100644
--- a/tika-fetchers/tika-fetcher-s3/src/test/resources/tika-config-s3.xml
+++ b/tika-core/src/test/resources/org/apache/tika/config/fetch-iterator-multiple-config.xml
@@ -16,12 +16,18 @@
limitations under the License.
-->
<properties>
- <fetchers>
- <fetcher class="org.apache.tika.fetcher.s3.S3Fetcher">
+ <fetchIterators>
+ <fetchIterator class="org.apache.tika.pipes.fetchiterator.FileSystemFetchIterator">
<params>
- <param name="region" type="string">us-east-1</param>
- <param name="profile" type="string">my_profile</param>
+ <param name="fetcherName" type="string">fs1</param>
+ <param name="basePath" type="string">/my/base/path1</param>
</params>
- </fetcher>
- </fetchers>
-</properties>
\ No newline at end of file
+ </fetchIterator>
+ <fetchIterator class="org.apache.tika.pipes.fetchiterator.FileSystemFetchIterator">
+ <params>
+ <param name="fetcherName" type="string">fs2</param>
+ <param name="basePath" type="string">/my/base/path2</param>
+ </params>
+ </fetchIterator>
+ </fetchIterators>
+</properties>
diff --git a/tika-fetchers/tika-fetcher-s3/src/test/resources/tika-config-s3.xml b/tika-core/src/test/resources/org/apache/tika/config/fetchers-config.xml
similarity index 65%
copy from tika-fetchers/tika-fetcher-s3/src/test/resources/tika-config-s3.xml
copy to tika-core/src/test/resources/org/apache/tika/config/fetchers-config.xml
index 39a2ce8..647c676 100644
--- a/tika-fetchers/tika-fetcher-s3/src/test/resources/tika-config-s3.xml
+++ b/tika-core/src/test/resources/org/apache/tika/config/fetchers-config.xml
@@ -17,11 +17,17 @@
-->
<properties>
<fetchers>
- <fetcher class="org.apache.tika.fetcher.s3.S3Fetcher">
+ <fetcher class="org.apache.tika.pipes.fetcher.FileSystemFetcher">
<params>
- <param name="region" type="string">us-east-1</param>
- <param name="profile" type="string">my_profile</param>
+ <param name="name" type="string">fs1</param>
+ <param name="basePath" type="string">/my/base/path1</param>
+ </params>
+ </fetcher>
+ <fetcher class="org.apache.tika.pipes.fetcher.FileSystemFetcher">
+ <params>
+ <param name="name" type="string">fs2</param>
+ <param name="basePath" type="string">/my/base/path2</param>
</params>
</fetcher>
</fetchers>
-</properties>
\ No newline at end of file
+</properties>
diff --git a/tika-fetchers/tika-fetcher-s3/src/test/resources/tika-config-s3.xml b/tika-core/src/test/resources/org/apache/tika/config/fetchers-duplicate-config.xml
similarity index 65%
copy from tika-fetchers/tika-fetcher-s3/src/test/resources/tika-config-s3.xml
copy to tika-core/src/test/resources/org/apache/tika/config/fetchers-duplicate-config.xml
index 39a2ce8..314ed35 100644
--- a/tika-fetchers/tika-fetcher-s3/src/test/resources/tika-config-s3.xml
+++ b/tika-core/src/test/resources/org/apache/tika/config/fetchers-duplicate-config.xml
@@ -17,11 +17,17 @@
-->
<properties>
<fetchers>
- <fetcher class="org.apache.tika.fetcher.s3.S3Fetcher">
+ <fetcher class="org.apache.tika.pipes.fetcher.FileSystemFetcher">
<params>
- <param name="region" type="string">us-east-1</param>
- <param name="profile" type="string">my_profile</param>
+ <param name="name" type="string">fs1</param>
+ <param name="basePath" type="string">/my/base/path1</param>
+ </params>
+ </fetcher>
+ <fetcher class="org.apache.tika.pipes.fetcher.FileSystemFetcher">
+ <params>
+ <param name="name" type="string">fs1</param>
+ <param name="basePath" type="string">/my/base/path2</param>
</params>
</fetcher>
</fetchers>
-</properties>
\ No newline at end of file
+</properties>
diff --git a/tika-fetchers/tika-fetcher-s3/src/test/resources/tika-config-s3.xml b/tika-core/src/test/resources/org/apache/tika/config/fetchers-nobasepath-config.xml
similarity index 68%
copy from tika-fetchers/tika-fetcher-s3/src/test/resources/tika-config-s3.xml
copy to tika-core/src/test/resources/org/apache/tika/config/fetchers-nobasepath-config.xml
index 39a2ce8..de954cd 100644
--- a/tika-fetchers/tika-fetcher-s3/src/test/resources/tika-config-s3.xml
+++ b/tika-core/src/test/resources/org/apache/tika/config/fetchers-nobasepath-config.xml
@@ -17,11 +17,16 @@
-->
<properties>
<fetchers>
- <fetcher class="org.apache.tika.fetcher.s3.S3Fetcher">
+ <fetcher class="org.apache.tika.pipes.fetcher.FileSystemFetcher">
<params>
- <param name="region" type="string">us-east-1</param>
- <param name="profile" type="string">my_profile</param>
+ <param name="name" type="string">fs1</param>
+ <param name="basePath" type="string">/my/base/path1</param>
+ </params>
+ </fetcher>
+ <fetcher class="org.apache.tika.pipes.fetcher.FileSystemFetcher">
+ <params>
+ <param name="name" type="string">fs2</param>
</params>
</fetcher>
</fetchers>
-</properties>
\ No newline at end of file
+</properties>
diff --git a/tika-fetchers/tika-fetcher-s3/src/test/resources/tika-config-s3.xml b/tika-core/src/test/resources/org/apache/tika/config/fetchers-noname-config.xml
similarity index 68%
copy from tika-fetchers/tika-fetcher-s3/src/test/resources/tika-config-s3.xml
copy to tika-core/src/test/resources/org/apache/tika/config/fetchers-noname-config.xml
index 39a2ce8..bb92c42 100644
--- a/tika-fetchers/tika-fetcher-s3/src/test/resources/tika-config-s3.xml
+++ b/tika-core/src/test/resources/org/apache/tika/config/fetchers-noname-config.xml
@@ -17,11 +17,16 @@
-->
<properties>
<fetchers>
- <fetcher class="org.apache.tika.fetcher.s3.S3Fetcher">
+ <fetcher class="org.apache.tika.pipes.fetcher.FileSystemFetcher">
<params>
- <param name="region" type="string">us-east-1</param>
- <param name="profile" type="string">my_profile</param>
+ <param name="name" type="string">fs1</param>
+ <param name="basePath" type="string">/my/base/path1</param>
+ </params>
+ </fetcher>
+ <fetcher class="org.apache.tika.pipes.fetcher.FileSystemFetcher">
+ <params>
+ <param name="basePath" type="string">/my/base/path2</param>
</params>
</fetcher>
</fetchers>
-</properties>
\ No newline at end of file
+</properties>
diff --git a/tika-fetchers/tika-fetcher-jdbc/pom.xml b/tika-fetchers/tika-fetcher-jdbc/pom.xml
deleted file mode 100644
index 06f79d5..0000000
--- a/tika-fetchers/tika-fetcher-jdbc/pom.xml
+++ /dev/null
@@ -1,122 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- 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.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <parent>
- <artifactId>tika-fetchers</artifactId>
- <groupId>org.apache.tika</groupId>
- <version>2.0.0-SNAPSHOT</version>
- </parent>
- <modelVersion>4.0.0</modelVersion>
-
- <artifactId>jdbc-fetcher</artifactId>
-
- <dependencies>
- <dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>tika-core</artifactId>
- <version>${project.version}</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>com.h2database</groupId>
- <artifactId>h2</artifactId>
- <version>${h2.version}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <scope>test</scope>
- </dependency>
- </dependencies>
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-jar-plugin</artifactId>
- <configuration>
- <archive>
- <manifestEntries>
- <Automatic-Module-Name>org.apache.tika.fetcher.jdbc</Automatic-Module-Name>
- </manifestEntries>
- </archive>
- </configuration>
- <executions>
- <execution>
- <goals>
- <goal>test-jar</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <artifactId>maven-shade-plugin</artifactId>
- <version>${maven.shade.version}</version>
- <executions>
- <execution>
- <phase>package</phase>
- <goals>
- <goal>shade</goal>
- </goals>
- <configuration>
- <createDependencyReducedPom>
- false
- </createDependencyReducedPom>
- <!-- <filters> -->
- <filters>
- <filter>
- <artifact>*:*</artifact>
- <excludes>
- <exclude>META-INF/*</exclude>
- <exclude>LICENSE.txt</exclude>
- <exclude>NOTICE.txt</exclude>
- </excludes>
- </filter>
- </filters>
- <transformers>
- <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
- <mainClass>org.apache.tika.eval.app.TikaEvalCLI</mainClass>
- </transformer>
-
- <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
- <transformer implementation="org.apache.maven.plugins.shade.resource.IncludeResourceTransformer">
- <resource>META-INF/LICENSE</resource>
- <file>target/classes/META-INF/LICENSE</file>
- </transformer>
- <transformer implementation="org.apache.maven.plugins.shade.resource.IncludeResourceTransformer">
- <resource>META-INF/NOTICE</resource>
- <file>target/classes/META-INF/NOTICE</file>
- </transformer>
- <transformer implementation="org.apache.maven.plugins.shade.resource.IncludeResourceTransformer">
- <resource>META-INF/DEPENDENCIES</resource>
- <file>target/classes/META-INF/DEPENDENCIES</file>
- </transformer>
- </transformers>
- </configuration>
- </execution>
- </executions>
- </plugin>
-
- </plugins>
- </build>
-
-</project>
\ No newline at end of file
diff --git a/tika-fetchers/tika-fetcher-jdbc/src/main/java/org/apache/tika/fetcher/jdbc/JDBCFetcher.java b/tika-fetchers/tika-fetcher-jdbc/src/main/java/org/apache/tika/fetcher/jdbc/JDBCFetcher.java
deleted file mode 100644
index 25152a9..0000000
--- a/tika-fetchers/tika-fetcher-jdbc/src/main/java/org/apache/tika/fetcher/jdbc/JDBCFetcher.java
+++ /dev/null
@@ -1,100 +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.
- */
-package org.apache.tika.fetcher.jdbc;
-
-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.exception.TikaConfigException;
-import org.apache.tika.exception.TikaException;
-import org.apache.tika.fetcher.Fetcher;
-import org.apache.tika.metadata.Metadata;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-public class JDBCFetcher implements Fetcher, Initializable {
-
- private int requestPoolSize = 10;
- private String table;
- private List<String> metadataColumns = new ArrayList<>();
- private String binaryField;
- private String connectionString;
-
-
- @Override
- public void initialize(Map<String, Param> params) throws TikaConfigException {
- //TODO: init prepared
- }
-
- @Override
- public void checkInitialization(InitializableProblemHandler problemHandler) throws TikaConfigException {
- //no-op
- }
-
- @Override
- public Set<String> getSupportedPrefixes() {
- return null;
- }
-
- @Override
- public InputStream fetch(String fetcherString, Metadata metadata) throws TikaException, IOException {
- return null;
- }
-
- /**
- * The prepared inserts are pooled. The default is 10.
- * This sets how big this pool should be.
- * @param requestPoolSize
- */
- @Field
- public void setRequestPoolSize(int requestPoolSize) {
- this.requestPoolSize = requestPoolSize;
- }
-
- @Field
- public void setJDBCConnectionString(String connectionString) {
- this.connectionString = connectionString;
- }
-
- @Field
- public void setTable(String table) {
- this.table = table;
- }
-
- @Field
- public void setMetadataFields(List<String> cols) {
-
- }
-
- /**
- * If there's a blob or text field that you
- * want Tika to parse.
- *
- * This is optional.
- * @param binaryField
- */
- @Field
- public void setBinaryField(String binaryField) {
-
- }
-}
diff --git a/tika-pipes/pom.xml b/tika-pipes/pom.xml
new file mode 100644
index 0000000..b90d3c3
--- /dev/null
+++ b/tika-pipes/pom.xml
@@ -0,0 +1,41 @@
+<!--
+ 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <packaging>pom</packaging>
+
+
+ <parent>
+ <groupId>org.apache.tika</groupId>
+ <artifactId>tika-parent</artifactId>
+ <version>2.0.0-SNAPSHOT</version>
+ <relativePath>../tika-parent/pom.xml</relativePath>
+ </parent>
+
+ <artifactId>tika-pipes</artifactId>
+ <name>Apache Tika pipes</name>
+ <url>http://tika.apache.org/</url>
+
+ <modules>
+ <module>tika-httpclient-commons</module>
+ <module>tika-fetchers</module>
+ <module>tika-emitters</module>
+ <module>tika-fetch-iterators</module>
+ <module>tika-pipes-integration-tests</module>
+ </modules>
+
+</project>
diff --git a/tika-emitters/pom.xml b/tika-pipes/tika-emitters/pom.xml
similarity index 89%
copy from tika-emitters/pom.xml
copy to tika-pipes/tika-emitters/pom.xml
index 42bdf6b..bfb55c8 100644
--- a/tika-emitters/pom.xml
+++ b/tika-pipes/tika-emitters/pom.xml
@@ -22,9 +22,9 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.apache.tika</groupId>
- <artifactId>tika-parent</artifactId>
+ <artifactId>tika-pipes</artifactId>
<version>2.0.0-SNAPSHOT</version>
- <relativePath>../tika-parent/pom.xml</relativePath>
+ <relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -35,9 +35,7 @@
<modules>
<module>tika-emitter-fs</module>
- <module>tika-httpclient-commons</module>
<module>tika-emitter-solr</module>
-
</modules>
diff --git a/tika-emitters/tika-emitter-fs/pom.xml b/tika-pipes/tika-emitters/tika-emitter-fs/pom.xml
similarity index 100%
rename from tika-emitters/tika-emitter-fs/pom.xml
rename to tika-pipes/tika-emitters/tika-emitter-fs/pom.xml
diff --git a/tika-emitters/tika-emitter-fs/src/main/java/org/apache/tika/emitter/fs/FileSystemEmitter.java b/tika-pipes/tika-emitters/tika-emitter-fs/src/main/java/org/apache/tika/emitter/fs/FileSystemEmitter.java
similarity index 69%
rename from tika-emitters/tika-emitter-fs/src/main/java/org/apache/tika/emitter/fs/FileSystemEmitter.java
rename to tika-pipes/tika-emitters/tika-emitter-fs/src/main/java/org/apache/tika/emitter/fs/FileSystemEmitter.java
index 0acae53..e42b57c 100644
--- a/tika-emitters/tika-emitter-fs/src/main/java/org/apache/tika/emitter/fs/FileSystemEmitter.java
+++ b/tika-pipes/tika-emitters/tika-emitter-fs/src/main/java/org/apache/tika/emitter/fs/FileSystemEmitter.java
@@ -1,8 +1,24 @@
+/*
+ * 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.emitter.fs;
import org.apache.tika.config.Field;
-import org.apache.tika.emitter.Emitter;
-import org.apache.tika.emitter.TikaEmitterException;
+import org.apache.tika.pipes.emitter.Emitter;
+import org.apache.tika.pipes.emitter.TikaEmitterException;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.metadata.TikaCoreProperties;
@@ -25,12 +41,12 @@ public class FileSystemEmitter implements Emitter {
private String fileExtension = "json";
@Override
- public Set<String> getSupported() {
- return Collections.singleton(name);
+ public String getName() {
+ return name;
}
@Override
- public void emit(String emitterName, List<Metadata> metadataList) throws IOException, TikaException {
+ public void emit(List<Metadata> metadataList) throws IOException, TikaException {
Path output;
if (metadataList == null || metadataList.size() == 0) {
throw new TikaEmitterException("metadata list must not be null or of size 0");
diff --git a/tika-emitters/tika-emitter-solr/pom.xml b/tika-pipes/tika-emitters/tika-emitter-solr/pom.xml
similarity index 100%
copy from tika-emitters/tika-emitter-solr/pom.xml
copy to tika-pipes/tika-emitters/tika-emitter-solr/pom.xml
diff --git a/tika-emitters/tika-emitter-solr/src/main/java/org/apache/tika/emitter/solr/SolrEmitter.java b/tika-pipes/tika-emitters/tika-emitter-solr/src/main/java/org/apache/tika/emitter/solr/SolrEmitter.java
similarity index 87%
rename from tika-emitters/tika-emitter-solr/src/main/java/org/apache/tika/emitter/solr/SolrEmitter.java
rename to tika-pipes/tika-emitters/tika-emitter-solr/src/main/java/org/apache/tika/emitter/solr/SolrEmitter.java
index e77519e..df78bb7 100644
--- a/tika-emitters/tika-emitter-solr/src/main/java/org/apache/tika/emitter/solr/SolrEmitter.java
+++ b/tika-pipes/tika-emitters/tika-emitter-solr/src/main/java/org/apache/tika/emitter/solr/SolrEmitter.java
@@ -1,3 +1,19 @@
+/*
+ * 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.emitter.solr;
import com.google.gson.Gson;
@@ -8,7 +24,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.emitter.Emitter;
+import org.apache.tika.pipes.emitter.Emitter;
import org.apache.tika.exception.TikaConfigException;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
@@ -19,7 +35,6 @@ import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
-import java.util.Set;
import java.util.UUID;
public class SolrEmitter implements Emitter, Initializable {
@@ -43,7 +58,12 @@ public class SolrEmitter implements Emitter, Initializable {
private int commitWithin = 100;
@Override
- public void emit(String emitterName, List<Metadata> metadataList) throws IOException,
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public void emit(List<Metadata> metadataList) throws IOException,
TikaException {
if (metadataList == null || metadataList.size() == 0) {
LOG.warn("metadataList is null or empty");
@@ -200,7 +220,7 @@ public class SolrEmitter implements Emitter, Initializable {
@Override
public void initialize(Map<String, Param> params) throws TikaConfigException {
- //TODO: build the client here
+ //TODO: build the client here?
}
@@ -209,9 +229,4 @@ public class SolrEmitter implements Emitter, Initializable {
}
- @Override
- public Set<String> getSupported() {
- return Collections.singleton(name);
- }
-
}
diff --git a/tika-emitters/tika-emitter-solr/src/test/java/org/apache/tika/emitter/solr/TestBasic.java b/tika-pipes/tika-emitters/tika-emitter-solr/src/test/java/org/apache/tika/emitter/solr/TestBasic.java
similarity index 58%
rename from tika-emitters/tika-emitter-solr/src/test/java/org/apache/tika/emitter/solr/TestBasic.java
rename to tika-pipes/tika-emitters/tika-emitter-solr/src/test/java/org/apache/tika/emitter/solr/TestBasic.java
index b374476..3df4c4a 100644
--- a/tika-emitters/tika-emitter-solr/src/test/java/org/apache/tika/emitter/solr/TestBasic.java
+++ b/tika-pipes/tika-emitters/tika-emitter-solr/src/test/java/org/apache/tika/emitter/solr/TestBasic.java
@@ -1,25 +1,42 @@
+/*
+ * 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.emitter.solr;
import org.apache.tika.config.TikaConfig;
-import org.apache.tika.emitter.Emitter;
+import org.apache.tika.pipes.emitter.Emitter;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.metadata.TikaCoreProperties;
import org.apache.tika.metadata.filter.MetadataFilter;
import org.apache.tika.sax.AbstractRecursiveParserWrapperHandler;
+import org.junit.Ignore;
import org.junit.Test;
-import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.List;
+@Ignore("requires solr to be up and running")
public class TestBasic {
@Test
public void testBasic() throws Exception {
TikaConfig tikaConfig = new TikaConfig(
TestBasic.class.getResourceAsStream("/tika-config-simple-emitter.xml"));
- Emitter emitter = tikaConfig.getEmitter();
+ Emitter emitter = tikaConfig.getEmitterManager().getEmitter("solr1");
List<Metadata> metadataList = new ArrayList<>();
Metadata m1 = new Metadata();
m1.set("id", "1");
@@ -38,6 +55,6 @@ public class TestBasic {
metadataList.add(m1);
metadataList.add(m2);
- emitter.emit("solr1", metadataList);
+ emitter.emit(metadataList);
}
}
diff --git a/tika-emitters/tika-emitter-solr/src/test/resources/log4j.properties b/tika-pipes/tika-emitters/tika-emitter-solr/src/test/resources/log4j.properties
similarity index 100%
copy from tika-emitters/tika-emitter-solr/src/test/resources/log4j.properties
copy to tika-pipes/tika-emitters/tika-emitter-solr/src/test/resources/log4j.properties
diff --git a/tika-emitters/tika-emitter-solr/src/test/resources/tika-config-simple-emitter.xml b/tika-pipes/tika-emitters/tika-emitter-solr/src/test/resources/tika-config-simple-emitter.xml
similarity index 100%
rename from tika-emitters/tika-emitter-solr/src/test/resources/tika-config-simple-emitter.xml
rename to tika-pipes/tika-emitters/tika-emitter-solr/src/test/resources/tika-config-simple-emitter.xml
diff --git a/tika-emitters/pom.xml b/tika-pipes/tika-fetch-iterators/pom.xml
similarity index 72%
rename from tika-emitters/pom.xml
rename to tika-pipes/tika-fetch-iterators/pom.xml
index 42bdf6b..38603af 100644
--- a/tika-emitters/pom.xml
+++ b/tika-pipes/tika-fetch-iterators/pom.xml
@@ -22,23 +22,22 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.apache.tika</groupId>
- <artifactId>tika-parent</artifactId>
+ <artifactId>tika-pipes</artifactId>
<version>2.0.0-SNAPSHOT</version>
- <relativePath>../tika-parent/pom.xml</relativePath>
+ <relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
- <artifactId>tika-emitters</artifactId>
+ <artifactId>tika-fetch-iterators</artifactId>
<packaging>pom</packaging>
- <name>Apache Tika emitters</name>
+ <name>Apache Tika fetch iterators</name>
<url>http://tika.apache.org/</url>
+ <!-- see also org.apache.tika.pipes.fetchiterator.FileSystemIterator
+ in tika-core if you want a file system directory crawler -->
<modules>
- <module>tika-emitter-fs</module>
- <module>tika-httpclient-commons</module>
- <module>tika-emitter-solr</module>
-
+ <module>tika-fetch-iterator-csv</module>
+ <module>tika-fetch-iterator-jdbc</module>
+ <module>tika-fetch-iterator-s3</module>
</modules>
-
-
-</project>
\ No newline at end of file
+</project>
diff --git a/tika-emitters/tika-emitter-solr/pom.xml b/tika-pipes/tika-fetch-iterators/tika-fetch-iterator-csv/pom.xml
similarity index 79%
copy from tika-emitters/tika-emitter-solr/pom.xml
copy to tika-pipes/tika-fetch-iterators/tika-fetch-iterator-csv/pom.xml
index 6aefb89..bac6ace 100644
--- a/tika-emitters/tika-emitter-solr/pom.xml
+++ b/tika-pipes/tika-fetch-iterators/tika-fetch-iterator-csv/pom.xml
@@ -21,14 +21,18 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
- <artifactId>tika-emitters</artifactId>
<groupId>org.apache.tika</groupId>
+ <artifactId>tika-fetch-iterators</artifactId>
<version>2.0.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
- <artifactId>tika-emitter-solr</artifactId>
-
+ <artifactId>tika-fetch-iterator-csv</artifactId>
+
+ <name>Apache Tika Fetch Iterator - CSV</name>
+ <url>http://tika.apache.org/</url>
+
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
@@ -37,13 +41,9 @@
<scope>provided</scope>
</dependency>
<dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>tika-httpclient-commons</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-log4j12</artifactId>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-csv</artifactId>
+ <version>${commons.csv.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
@@ -51,5 +51,4 @@
<scope>test</scope>
</dependency>
</dependencies>
-
-</project>
\ No newline at end of file
+</project>
diff --git a/tika-pipes/tika-fetch-iterators/tika-fetch-iterator-csv/src/main/java/org/apache/tika/pipes/fetchiterator/csv/CSVFetchIterator.java b/tika-pipes/tika-fetch-iterators/tika-fetch-iterator-csv/src/main/java/org/apache/tika/pipes/fetchiterator/csv/CSVFetchIterator.java
new file mode 100644
index 0000000..e87f730
--- /dev/null
+++ b/tika-pipes/tika-fetch-iterators/tika-fetch-iterator-csv/src/main/java/org/apache/tika/pipes/fetchiterator/csv/CSVFetchIterator.java
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tika.pipes.fetchiterator.csv;
+
+import org.apache.commons.csv.CSVFormat;
+import org.apache.commons.csv.CSVRecord;
+import org.apache.tika.config.Field;
+import org.apache.tika.config.Initializable;
+import org.apache.tika.config.InitializableProblemHandler;
+import org.apache.tika.exception.TikaConfigException;
+import org.apache.tika.metadata.Metadata;
+import org.apache.tika.pipes.fetcher.FetchId;
+import org.apache.tika.pipes.fetcher.FetchIdMetadataPair;
+import org.apache.tika.pipes.fetchiterator.FetchIterator;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeoutException;
+
+public class CSVFetchIterator extends FetchIterator implements Initializable {
+
+ private Charset charset = StandardCharsets.UTF_8;
+ private Path csvPath;
+ private String fetchKeyColumn;
+
+
+ @Field
+ public void setCsvPath(String csvPath) {
+ setCsvPath(Paths.get(csvPath));
+ }
+
+ @Field
+ public void setFetchKeyColumn(String fetchKeyColumn) {
+ this.fetchKeyColumn = fetchKeyColumn;
+ }
+
+ public void setCsvPath(Path csvPath) {
+ this.csvPath = csvPath;
+ }
+
+ @Override
+ protected void enqueue() throws InterruptedException, IOException, TimeoutException {
+ String fetcherName = getFetcherName();
+ try (Reader reader = Files.newBufferedReader(csvPath, charset)) {
+ Iterable<CSVRecord> records = CSVFormat.EXCEL.parse(reader);
+ int fetchKeyIndex = -1;
+ List<String> headers = new ArrayList<>();
+ for (CSVRecord record : records) {
+ fetchKeyIndex = loadHeaders(record, headers);
+ break;
+ }
+ //check that if a user set a fetchKeyColumn, but we didn't find it
+ if (fetchKeyIndex < 0 && (fetchKeyColumn != null)) {
+ throw new IllegalArgumentException("Can't find " + fetchKeyColumn +
+ " in the csv. I see:"+
+ headers);
+ }
+ for (CSVRecord record : records) {
+ String fetchKey = "";
+ if (fetchKeyIndex > -1) {
+ fetchKey = record.get(fetchKeyIndex);
+ }
+ Metadata metadata = loadMetadata(fetchKeyIndex, headers, record);
+ tryToAdd(new FetchIdMetadataPair(new FetchId(fetcherName, fetchKey), metadata));
+ }
+ }
+ }
+
+ private Metadata loadMetadata(int fetchKeyIndex, List<String> headers, CSVRecord record) {
+ Metadata metadata = new Metadata();
+ for (int i = 0; i < record.size(); i++) {
+ if (fetchKeyIndex == i) {
+ continue;
+ }
+ metadata.set(headers.get(i), record.get(i));
+ }
+ return metadata;
+ }
+
+
+ private int loadHeaders(CSVRecord record, List<String> headers) {
+ int fetchKeyColumnIndex = -1;
+
+ for (int col = 0; col < record.size(); col++) {
+ String header = record.get(col);
+ headers.add(header);
+ if (header.equals(fetchKeyColumn)) {
+ fetchKeyColumnIndex = col;
+ }
+ }
+ return fetchKeyColumnIndex;
+ }
+
+ @Override
+ public void checkInitialization(InitializableProblemHandler problemHandler)
+ throws TikaConfigException {
+ super.checkInitialization(problemHandler);
+ mustNotBeEmpty("csvPath", this.csvPath.toString());
+ }
+}
diff --git a/tika-pipes/tika-fetch-iterators/tika-fetch-iterator-csv/src/test/java/TestCSVFetchIterator.java b/tika-pipes/tika-fetch-iterators/tika-fetch-iterator-csv/src/test/java/TestCSVFetchIterator.java
new file mode 100644
index 0000000..2a6ab52
--- /dev/null
+++ b/tika-pipes/tika-fetch-iterators/tika-fetch-iterator-csv/src/test/java/TestCSVFetchIterator.java
@@ -0,0 +1,129 @@
+/*
+ * 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.
+ */
+import org.apache.tika.metadata.Metadata;
+import org.apache.tika.pipes.fetcher.FetchId;
+import org.apache.tika.pipes.fetcher.FetchIdMetadataPair;
+import org.apache.tika.pipes.fetchiterator.FetchIterator;
+import org.apache.tika.pipes.fetchiterator.csv.CSVFetchIterator;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorCompletionService;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import static org.junit.Assert.assertEquals;
+
+public class TestCSVFetchIterator {
+
+
+ @Test
+ public void testSimple() throws Exception {
+ Path p = get("test-simple.csv");
+ CSVFetchIterator it = new CSVFetchIterator();
+ it.setFetcherName("fs");
+ it.setCsvPath(p);
+ it.setFetchKeyColumn("fetchKey");
+ int numConsumers = 2;
+ ExecutorService es = Executors.newFixedThreadPool(numConsumers+1);
+ ArrayBlockingQueue<FetchIdMetadataPair> queue = it.init(numConsumers);
+ ExecutorCompletionService c = new ExecutorCompletionService(es);
+ c.submit(it);
+ List<MockFetcher> fetchers = new ArrayList<>();
+ for (int i = 0; i < numConsumers; i++) {
+ MockFetcher f = new MockFetcher(queue);
+ fetchers.add(f);
+ c.submit(f);
+ }
+ int finished = 0;
+ int completed = 0;
+ try {
+ while (finished++ < numConsumers+1) {
+ Future<Integer> f = c.take();
+ completed += f.get();
+ }
+ } finally {
+ es.shutdownNow();
+ }
+ assertEquals(10, completed);
+ for (MockFetcher f : fetchers) {
+ for (FetchIdMetadataPair pair : f.pairs) {
+ String id = pair.getMetadata().get("id");
+ assertEquals("path/to/my/file"+id,
+ pair.getFetchId().getFetchKey());
+ assertEquals("project"+
+ (Integer.parseInt(id) % 2 == 1 ? "a" : "b"),
+ pair.getMetadata().get("project"));
+ }
+ }
+ }
+
+ @Test(expected = ExecutionException.class)
+ public void testBadFetchKeyCol() throws Exception {
+ Path p = get("test-simple.csv");
+ CSVFetchIterator it = new CSVFetchIterator();
+ it.setFetcherName("fs");
+ it.setCsvPath(p);
+ it.setFetchKeyColumn("fetchKeyDoesntExist");
+ ExecutorService es = Executors.newFixedThreadPool(2);
+ ExecutorCompletionService c = new ExecutorCompletionService(es);
+ c.submit(it);
+ c.submit(new MockFetcher(it.init(1)));
+ int finished = 0;
+ try {
+ while (finished++ < 2) {
+ Future f = c.take();
+ f.get();
+ }
+ } finally {
+ es.shutdownNow();
+ }
+
+ }
+
+ private Path get(String testFileName) throws Exception {
+ return Paths.get(TestCSVFetchIterator.class.getResource("/"+testFileName).toURI());
+ }
+
+ private static class MockFetcher implements Callable<Integer> {
+ private final ArrayBlockingQueue<FetchIdMetadataPair> queue;
+ private final List<FetchIdMetadataPair> pairs = new ArrayList<>();
+ private MockFetcher(ArrayBlockingQueue<FetchIdMetadataPair> queue) {
+ this.queue = queue;
+ }
+
+ @Override
+ public Integer call() throws Exception {
+ while (true) {
+ FetchIdMetadataPair p = queue.poll(1, TimeUnit.HOURS);
+ if (p == FetchIterator.COMPLETED_SEMAPHORE) {
+ return pairs.size();
+ }
+ pairs.add(p);
+ }
+ }
+ }
+}
diff --git a/tika-pipes/tika-fetch-iterators/tika-fetch-iterator-csv/src/test/resources/test-simple.csv b/tika-pipes/tika-fetch-iterators/tika-fetch-iterator-csv/src/test/resources/test-simple.csv
new file mode 100644
index 0000000..22630ef
--- /dev/null
+++ b/tika-pipes/tika-fetch-iterators/tika-fetch-iterator-csv/src/test/resources/test-simple.csv
@@ -0,0 +1,6 @@
+id,project,fetchKey
+1,projecta,path/to/my/file1
+2,projectb,path/to/my/file2
+3,projecta,path/to/my/file3
+4,projectb,path/to/my/file4
+5,projecta,path/to/my/file5
diff --git a/tika-emitters/tika-emitter-solr/pom.xml b/tika-pipes/tika-fetch-iterators/tika-fetch-iterator-jdbc/pom.xml
similarity index 79%
copy from tika-emitters/tika-emitter-solr/pom.xml
copy to tika-pipes/tika-fetch-iterators/tika-fetch-iterator-jdbc/pom.xml
index 6aefb89..14cd6f3 100644
--- a/tika-emitters/tika-emitter-solr/pom.xml
+++ b/tika-pipes/tika-fetch-iterators/tika-fetch-iterator-jdbc/pom.xml
@@ -21,14 +21,18 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
- <artifactId>tika-emitters</artifactId>
<groupId>org.apache.tika</groupId>
+ <artifactId>tika-fetch-iterators</artifactId>
<version>2.0.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
- <artifactId>tika-emitter-solr</artifactId>
-
+ <artifactId>tika-fetch-iterator-jdbc</artifactId>
+
+ <name>Apache Tika Fetch Iterator - jdbc</name>
+ <url>http://tika.apache.org/</url>
+
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
@@ -37,13 +41,10 @@
<scope>provided</scope>
</dependency>
<dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>tika-httpclient-commons</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-log4j12</artifactId>
+ <groupId>com.h2database</groupId>
+ <artifactId>h2</artifactId>
+ <version>${h2.version}</version>
+ <scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
@@ -51,5 +52,4 @@
<scope>test</scope>
</dependency>
</dependencies>
-
-</project>
\ No newline at end of file
+</project>
diff --git a/tika-pipes/tika-fetch-iterators/tika-fetch-iterator-jdbc/src/main/java/org/apache/tika/pipes/fetchiterator/jdbc/JDBCFetchIterator.java b/tika-pipes/tika-fetch-iterators/tika-fetch-iterator-jdbc/src/main/java/org/apache/tika/pipes/fetchiterator/jdbc/JDBCFetchIterator.java
new file mode 100644
index 0000000..9908681
--- /dev/null
+++ b/tika-pipes/tika-fetch-iterators/tika-fetch-iterator-jdbc/src/main/java/org/apache/tika/pipes/fetchiterator/jdbc/JDBCFetchIterator.java
@@ -0,0 +1,166 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tika.pipes.fetchiterator.jdbc;
+
+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.exception.TikaConfigException;
+import org.apache.tika.metadata.Metadata;
+import org.apache.tika.pipes.fetcher.FetchId;
+import org.apache.tika.pipes.fetcher.FetchIdMetadataPair;
+import org.apache.tika.pipes.fetchiterator.FetchIterator;
+import org.apache.tika.utils.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeoutException;
+
+public class JDBCFetchIterator extends FetchIterator implements Initializable {
+
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(JDBCFetchIterator.class);
+
+ private String fetchKeyColumn;
+ private String connection;
+ private String select;
+
+ private Connection db;
+
+ @Field
+ public void setFetchKeyColumn(String fetchKeyColumn) {
+ this.fetchKeyColumn = fetchKeyColumn;
+ }
+
+ @Field
+ public void setConnection(String connection) {
+ this.connection = connection;
+ }
+
+ @Field
+ public void setSelect(String select) {
+ this.select = select;
+ }
+
+ @Override
+ protected void enqueue() throws InterruptedException, IOException, TimeoutException {
+ String fetcherName = getFetcherName();
+ int fetchKeyIndex = -1;
+ List<String> headers = new ArrayList<>();
+ int rowCount = 0;
+ LOGGER.debug("select: {}", select);
+ try (Statement st = db.createStatement()) {
+ try (ResultSet rs = st.executeQuery(select)) {
+ while (rs.next()) {
+ if (headers.size() == 0) {
+ fetchKeyIndex = loadHeaders(rs.getMetaData(), headers);
+ }
+ try {
+ processRow(fetcherName, headers, fetchKeyIndex, rs);
+ } catch (SQLException e) {
+ LOGGER.warn("Failed to insert: "+rs, e);
+ }
+ rowCount++;
+ if (rowCount % 1000 == 0) {
+ LOGGER.info("added "+rowCount + " rows to the queue");
+ }
+ }
+ }
+ } catch (SQLException e) {
+ LOGGER.warn("problem initializing connection and selecting", e);
+ throw new IOException(e);
+ } finally {
+ try {
+ db.close();
+ } catch (SQLException e){
+ LOGGER.warn("failed to close connection", e);
+ }
+ }
+ }
+
+ private void processRow(String fetcherName, List<String> headers,
+ int fetchKeyIndex, ResultSet rs)
+ throws SQLException, TimeoutException, InterruptedException {
+ Metadata metadata = new Metadata();
+ String fetchKey = null;
+ for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++) {
+ if (i == fetchKeyIndex) {
+ fetchKey = getString(i, rs);
+ fetchKey = (fetchKey == null) ? "" : fetchKey;
+ continue;
+ }
+ String val = getString(i, rs);
+ if (val != null) {
+ metadata.set(headers.get(i - 1), val);
+ }
+ }
+
+ tryToAdd(new FetchIdMetadataPair(new FetchId(fetcherName, fetchKey), metadata));
+ }
+
+ private String getString(int i, ResultSet rs) throws SQLException {
+ //TODO: improve this later with special handling for numerals/dates/timestamps, etc
+ String val = rs.getString(i);
+ if (rs.wasNull()) {
+ return null;
+ }
+ return val;
+ }
+
+
+ private int loadHeaders(ResultSetMetaData metaData, List<String> headers) throws SQLException {
+ int fetchKeyIndex = -1;
+ for (int i = 1; i <= metaData.getColumnCount(); i++) {
+ if (metaData.getColumnLabel(i).equalsIgnoreCase(fetchKeyColumn)) {
+ fetchKeyIndex = i;
+ }
+ headers.add(metaData.getColumnLabel(i));
+ }
+ return fetchKeyIndex;
+ }
+
+ @Override
+ public void initialize(Map<String, Param> params) throws TikaConfigException {
+ try {
+ db = DriverManager.getConnection(connection);
+ } catch (SQLException e) {
+ throw new TikaConfigException("couldn't connect to db", e);
+ }
+ }
+
+ @Override
+ public void checkInitialization(InitializableProblemHandler problemHandler)
+ throws TikaConfigException {
+ super.checkInitialization(problemHandler);
+ mustNotBeEmpty("connection", this.connection);
+ mustNotBeEmpty("select", this.select);
+ if (StringUtils.isEmpty(fetchKeyColumn)) {
+ LOGGER.info("no fetch key column has been specified");
+ }
+ }
+}
diff --git a/tika-pipes/tika-fetch-iterators/tika-fetch-iterator-jdbc/src/test/java/org/apache/tika/pipes/fetchiterator/jdbc/TestJDBCFetchIterator.java b/tika-pipes/tika-fetch-iterators/tika-fetch-iterator-jdbc/src/test/java/org/apache/tika/pipes/fetchiterator/jdbc/TestJDBCFetchIterator.java
new file mode 100644
index 0000000..fb0277b
--- /dev/null
+++ b/tika-pipes/tika-fetch-iterators/tika-fetch-iterator-jdbc/src/test/java/org/apache/tika/pipes/fetchiterator/jdbc/TestJDBCFetchIterator.java
@@ -0,0 +1,178 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tika.pipes.fetchiterator.jdbc;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.tika.config.TikaConfig;
+import org.apache.tika.metadata.Metadata;
+import org.apache.tika.pipes.fetcher.FetchId;
+import org.apache.tika.pipes.fetcher.FetchIdMetadataPair;
+import org.apache.tika.pipes.fetchiterator.FetchIterator;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Queue;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorCompletionService;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+public class TestJDBCFetchIterator {
+
+ static final String TABLE = "fetchkeys";
+ static Connection CONNECTION;
+ static Path DB_DIR;
+ static final String db = "mydb";
+ private static final int NUM_ROWS = 1000;
+
+ @BeforeClass
+ public static void setUp() throws Exception {
+ DB_DIR = Files.createTempDirectory("tika-jdbc-fetchiterator-test-");
+
+ CONNECTION = DriverManager.getConnection("jdbc:h2:file:"+DB_DIR.toAbsolutePath()+"/"+db);
+ String sql = "create table "+TABLE +
+ " (id varchar(128), " +
+ "project varchar(128), " +
+ "fetchKey varchar(128))";
+ CONNECTION.createStatement().execute(sql);
+
+ for (int i = 0; i < NUM_ROWS; i++) {
+ sql = "insert into "+TABLE + " (id, project, fetchKey) values ('id"+i+"','project"+
+ (i%2 == 0 ? "a" : "b") +"','fk"+i+"')";
+ CONNECTION.createStatement().execute(sql);
+ }
+ sql = "select count(1) from "+ TABLE;
+ ResultSet rs = CONNECTION.createStatement().executeQuery(sql);
+ while (rs.next()) {
+ int cnt = rs.getInt(1);
+ assertEquals(NUM_ROWS, cnt);
+ }
+ }
+
+ @AfterClass
+ public static void tearDown() throws IOException {
+ FileUtils.deleteDirectory(DB_DIR.toFile());
+ }
+
+ @Test
+ public void testSimple() throws Exception {
+ TikaConfig tk = getConfig();
+ int numConsumers = 5;
+ FetchIterator fetchIterator = tk.getFetchIterator();
+ ExecutorService es = Executors.newFixedThreadPool(numConsumers+1);
+ ExecutorCompletionService<Integer> completionService = new ExecutorCompletionService<>(es);
+ ArrayBlockingQueue<FetchIdMetadataPair> queue = fetchIterator.init(numConsumers);
+ completionService.submit(fetchIterator);
+ List<MockFetcher> fetchers = new ArrayList<>();
+ for (int i = 0; i < numConsumers; i++) {
+ MockFetcher mockFetcher = new MockFetcher(queue);
+ fetchers.add(mockFetcher);
+ completionService.submit(mockFetcher);
+ }
+ int processed = 0;
+ int completed = 0;
+ while (completed < numConsumers+1) {
+ Future<Integer> f = completionService.take();
+ processed += f.get();
+ completed++;
+ }
+ //fetchiterator added + MockFetcher yields 2x
+ assertEquals(NUM_ROWS * 2, processed);
+ int cnt = 0;
+ Matcher m = Pattern.compile("fk(\\d+)").matcher("");
+ for (MockFetcher f : fetchers) {
+ for (FetchIdMetadataPair p : f.pairs) {
+ String k = p.getFetchId().getFetchKey();
+ String num = "";
+ if (m.reset(k).find()) {
+ num = m.group(1);
+ } else {
+ fail("failed to find key pattern: "+k);
+ }
+ String aOrB = Integer.parseInt(num) % 2 == 0 ? "a" : "b";
+ assertEquals("id"+num, p.getMetadata().get("MY_ID"));
+ assertEquals("project"+aOrB, p.getMetadata().get("MY_PROJECT"));
+ assertNull(p.getMetadata().get("fetchKey"));
+ assertNull(p.getMetadata().get("MY_FETCHKEY"));
+ cnt++;
+ }
+ }
+ assertEquals(NUM_ROWS, cnt);
+ }
+
+ private TikaConfig getConfig() throws Exception {
+ String config = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?><properties>\n" +
+ " <fetchIterators>\n" +
+ " <fetchIterator class=\"org.apache.tika.pipes.fetchiterator.jdbc.JDBCFetchIterator\">\n" +
+ " <params>\n" +
+ " <param name=\"fetcherName\" type=\"string\">s3</param>\n" +
+ " <param name=\"queueSize\" type=\"int\">57</param>\n" +
+ " <param name=\"fetchKeyColumn\" type=\"string\">my_fetchkey</param>\n" +
+ " <param name=\"select\" type=\"string\">" +
+ "select id as my_id, project as my_project, fetchKey as my_fetchKey from fetchkeys</param>\n" +
+ " <param name=\"connection\" type=\"string\">jdbc:h2:file:"+
+ DB_DIR.toAbsolutePath()+"/"+db +"</param>\n" +
+ " </params>\n" +
+ " </fetchIterator>\n" +
+ " </fetchIterators>\n" +
+ "</properties>";
+ return new TikaConfig(new ByteArrayInputStream(config.getBytes(StandardCharsets.UTF_8)));
+ }
+
+ private static class MockFetcher implements Callable<Integer> {
+ private final ArrayBlockingQueue<FetchIdMetadataPair> queue;
+ private final List<FetchIdMetadataPair> pairs = new ArrayList<>();
+ private MockFetcher(ArrayBlockingQueue<FetchIdMetadataPair> queue) {
+ this.queue = queue;
+ }
+
+ @Override
+ public Integer call() throws Exception {
+ while (true) {
+ FetchIdMetadataPair p = queue.poll(1, TimeUnit.HOURS);
+ if (p == FetchIterator.COMPLETED_SEMAPHORE) {
+ return pairs.size();
+ }
+ pairs.add(p);
+ }
+ }
+ }
+}
diff --git a/tika-emitters/tika-emitter-solr/src/test/resources/log4j.properties b/tika-pipes/tika-fetch-iterators/tika-fetch-iterator-jdbc/src/test/resources/log4j.properties
similarity index 91%
copy from tika-emitters/tika-emitter-solr/src/test/resources/log4j.properties
copy to tika-pipes/tika-fetch-iterators/tika-fetch-iterator-jdbc/src/test/resources/log4j.properties
index 92b6d56..1bee240 100644
--- a/tika-emitters/tika-emitter-solr/src/test/resources/log4j.properties
+++ b/tika-pipes/tika-fetch-iterators/tika-fetch-iterator-jdbc/src/test/resources/log4j.properties
@@ -14,11 +14,11 @@
# limitations under the License.
#info,debug, error,fatal ...
-log4j.rootLogger=debug,stderr
+log4j.rootLogger=info,stderr
#console
log4j.appender.stderr=org.apache.log4j.ConsoleAppender
log4j.appender.stderr.layout=org.apache.log4j.PatternLayout
log4j.appender.stderr.Target=System.err
-log4j.appender.stderr.layout.ConversionPattern= %-5p %m%n
+log4j.appender.stderr.layout.ConversionPattern=%-5p [%t]: %m%n
diff --git a/tika-emitters/tika-emitter-solr/pom.xml b/tika-pipes/tika-fetch-iterators/tika-fetch-iterator-s3/pom.xml
similarity index 53%
copy from tika-emitters/tika-emitter-solr/pom.xml
copy to tika-pipes/tika-fetch-iterators/tika-fetch-iterator-s3/pom.xml
index 6aefb89..b0cce91 100644
--- a/tika-emitters/tika-emitter-solr/pom.xml
+++ b/tika-pipes/tika-fetch-iterators/tika-fetch-iterator-s3/pom.xml
@@ -21,13 +21,17 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
- <artifactId>tika-emitters</artifactId>
<groupId>org.apache.tika</groupId>
+ <artifactId>tika-fetch-iterators</artifactId>
<version>2.0.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
- <artifactId>tika-emitter-solr</artifactId>
+ <artifactId>tika-fetch-iterator-s3</artifactId>
+
+ <name>Apache Tika Fetch Iterator - S3</name>
+ <url>http://tika.apache.org/</url>
<dependencies>
<dependency>
@@ -37,19 +41,54 @@
<scope>provided</scope>
</dependency>
<dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>tika-httpclient-commons</artifactId>
- <version>${project.version}</version>
+ <groupId>com.amazonaws</groupId>
+ <artifactId>aws-java-sdk-s3</artifactId>
+ <version>${aws.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-core</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ <version>${jackson.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ <version>${commons.logging.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
<dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>tika-core</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
-
-</project>
\ No newline at end of file
+</project>
diff --git a/tika-pipes/tika-fetch-iterators/tika-fetch-iterator-s3/src/main/java/org/apache/tika/pipes/fetchiterator/s3/S3FetchIterator.java b/tika-pipes/tika-fetch-iterators/tika-fetch-iterator-s3/src/main/java/org/apache/tika/pipes/fetchiterator/s3/S3FetchIterator.java
new file mode 100644
index 0000000..0fd88b6
--- /dev/null
+++ b/tika-pipes/tika-fetch-iterators/tika-fetch-iterator-s3/src/main/java/org/apache/tika/pipes/fetchiterator/s3/S3FetchIterator.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tika.pipes.fetchiterator.s3;
+
+import com.amazonaws.auth.profile.ProfileCredentialsProvider;
+import com.amazonaws.services.s3.AmazonS3;
+import com.amazonaws.services.s3.AmazonS3ClientBuilder;
+import com.amazonaws.services.s3.iterable.S3Objects;
+import com.amazonaws.services.s3.model.ObjectListing;
+import com.amazonaws.services.s3.model.S3ObjectSummary;
+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.exception.TikaConfigException;
+import org.apache.tika.metadata.Metadata;
+import org.apache.tika.pipes.fetcher.FetchId;
+import org.apache.tika.pipes.fetcher.FetchIdMetadataPair;
+import org.apache.tika.pipes.fetchiterator.FetchIterator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.concurrent.TimeoutException;
+
+public class S3FetchIterator extends FetchIterator implements Initializable {
+
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(S3FetchIterator.class);
+ private String s3PathPrefix = "";
+ private String region;
+ private String profile;
+ private String bucket;
+
+ private AmazonS3 s3Client;
+
+ @Field
+ public void setBucket(String bucket) {
+ this.bucket = bucket;
+ }
+
+ @Field
+ public void setRegion(String region) {
+ this.region = region;
+ }
+
+ @Field
+ public void setProfile(String profile) {
+ this.profile = profile;
+ }
+
+ @Field
+ public void setS3PathPrefix(String s3PathPrefix) {
+ this.s3PathPrefix = s3PathPrefix;
+ }
+
+ @Override
+ public void initialize(Map<String, Param> params) throws TikaConfigException {
+ //params have already been set
+ //ignore them
+
+ s3Client = AmazonS3ClientBuilder.standard()
+ .withRegion(region)
+ .withCredentials(new ProfileCredentialsProvider(profile))
+ .build();
+ }
+
+ @Override
+ public void checkInitialization(InitializableProblemHandler problemHandler)
+ throws TikaConfigException {
+ super.checkInitialization(problemHandler);
+ mustNotBeEmpty("bucket", this.bucket);
+ mustNotBeEmpty("profile", this.profile);
+ mustNotBeEmpty("region", this.region);
+ }
+
+ @Override
+ protected void enqueue() throws InterruptedException, IOException, TimeoutException {
+ String fetcherName = getFetcherName();
+ long start = System.currentTimeMillis();
+ int count = 0;
+ for (S3ObjectSummary summary : S3Objects.withPrefix(s3Client, bucket, s3PathPrefix)) {
+ long elapsed = System.currentTimeMillis() - start;
+ LOGGER.debug("adding ({}) {} in {} ms", count, bucket+"/"+summary.getKey(),
+ elapsed);
+ tryToAdd( new FetchIdMetadataPair(
+ new FetchId(fetcherName, bucket+"/"+summary.getKey()),
+ new Metadata()));
+ count++;
+ }
+ long elapsed = System.currentTimeMillis() - start;
+ LOGGER.info("finished enqueuing {} files in {} ms", count, elapsed);
+ }
+}
diff --git a/tika-pipes/tika-fetch-iterators/tika-fetch-iterator-s3/src/test/java/org/apache/tika/pipes/fetchiterator/s3/TestS3FetchIterator.java b/tika-pipes/tika-fetch-iterators/tika-fetch-iterator-s3/src/test/java/org/apache/tika/pipes/fetchiterator/s3/TestS3FetchIterator.java
new file mode 100644
index 0000000..1984577
--- /dev/null
+++ b/tika-pipes/tika-fetch-iterators/tika-fetch-iterator-s3/src/test/java/org/apache/tika/pipes/fetchiterator/s3/TestS3FetchIterator.java
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tika.pipes.fetchiterator.s3;
+import org.apache.tika.metadata.Metadata;
+import org.apache.tika.pipes.fetcher.FetchId;
+import org.apache.tika.pipes.fetcher.FetchIdMetadataPair;
+import org.apache.tika.pipes.fetchiterator.FetchIterator;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorCompletionService;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import static org.junit.Assert.assertEquals;
+
+@Ignore("turn into an actual unit test")
+public class TestS3FetchIterator {
+
+
+ @Test
+ public void testSimple() throws Exception {
+ S3FetchIterator it = new S3FetchIterator();
+ it.setFetcherName("s3");
+ it.setBucket("");//find one
+ it.setProfile("");//use one
+ it.setRegion("");//select one
+ it.initialize(Collections.EMPTY_MAP);
+ int numConsumers = 6;
+ ArrayBlockingQueue<FetchIdMetadataPair> queue = it.init(numConsumers);
+
+ ExecutorService es = Executors.newFixedThreadPool(numConsumers+1);
+ ExecutorCompletionService c = new ExecutorCompletionService(es);
+ c.submit(it);
+ List<MockFetcher> fetchers = new ArrayList<>();
+ for (int i = 0; i < numConsumers; i++) {
+ MockFetcher fetcher = new MockFetcher(queue);
+ fetchers.add(fetcher);
+ c.submit(fetcher);
+ }
+ int finished = 0;
+ int completed = 0;
+ try {
+ while (finished++ < numConsumers+1) {
+ Future<Integer> f = c.take();
+ completed += f.get();
+ }
+ } finally {
+ es.shutdownNow();
+ }
+ assertEquals(20000, completed);
+
+ }
+
+ private static class MockFetcher implements Callable<Integer> {
+ private final ArrayBlockingQueue<FetchIdMetadataPair> queue;
+ private final List<FetchIdMetadataPair> pairs = new ArrayList<>();
+ private MockFetcher(ArrayBlockingQueue<FetchIdMetadataPair> queue) {
+ this.queue = queue;
+ }
+
+ @Override
+ public Integer call() throws Exception {
+ while (true) {
+ FetchIdMetadataPair p = queue.poll(1, TimeUnit.HOURS);
+ if (p == FetchIterator.COMPLETED_SEMAPHORE) {
+ return pairs.size();
+ }
+ pairs.add(p);
+ }
+ }
+ }
+}
diff --git a/tika-emitters/tika-emitter-solr/src/test/resources/log4j.properties b/tika-pipes/tika-fetch-iterators/tika-fetch-iterator-s3/src/test/resources/log4j.properties
similarity index 91%
copy from tika-emitters/tika-emitter-solr/src/test/resources/log4j.properties
copy to tika-pipes/tika-fetch-iterators/tika-fetch-iterator-s3/src/test/resources/log4j.properties
index 92b6d56..1bee240 100644
--- a/tika-emitters/tika-emitter-solr/src/test/resources/log4j.properties
+++ b/tika-pipes/tika-fetch-iterators/tika-fetch-iterator-s3/src/test/resources/log4j.properties
@@ -14,11 +14,11 @@
# limitations under the License.
#info,debug, error,fatal ...
-log4j.rootLogger=debug,stderr
+log4j.rootLogger=info,stderr
#console
log4j.appender.stderr=org.apache.log4j.ConsoleAppender
log4j.appender.stderr.layout=org.apache.log4j.PatternLayout
log4j.appender.stderr.Target=System.err
-log4j.appender.stderr.layout.ConversionPattern= %-5p %m%n
+log4j.appender.stderr.layout.ConversionPattern=%-5p [%t]: %m%n
diff --git a/tika-fetchers/pom.xml b/tika-pipes/tika-fetchers/pom.xml
similarity index 90%
rename from tika-fetchers/pom.xml
rename to tika-pipes/tika-fetchers/pom.xml
index 833a56f..597c76b 100644
--- a/tika-fetchers/pom.xml
+++ b/tika-pipes/tika-fetchers/pom.xml
@@ -22,9 +22,9 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.apache.tika</groupId>
- <artifactId>tika-parent</artifactId>
+ <artifactId>tika-pipes</artifactId>
<version>2.0.0-SNAPSHOT</version>
- <relativePath>../tika-parent/pom.xml</relativePath>
+ <relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -34,7 +34,6 @@
<url>http://tika.apache.org/</url>
<modules>
- <module>tika-fetcher-jdbc</module>
<module>tika-fetcher-s3</module>
</modules>
diff --git a/tika-fetchers/tika-fetcher-s3/pom.xml b/tika-pipes/tika-fetchers/tika-fetcher-s3/pom.xml
similarity index 97%
rename from tika-fetchers/tika-fetcher-s3/pom.xml
rename to tika-pipes/tika-fetchers/tika-fetcher-s3/pom.xml
index 2ac83e1..1d561aa 100644
--- a/tika-fetchers/tika-fetcher-s3/pom.xml
+++ b/tika-pipes/tika-fetchers/tika-fetcher-s3/pom.xml
@@ -27,7 +27,7 @@
</parent>
<modelVersion>4.0.0</modelVersion>
- <artifactId>s3-fetcher</artifactId>
+ <artifactId>tika-fetcher-s3</artifactId>
<dependencies>
<dependency>
@@ -61,6 +61,10 @@
<version>${commons.logging.version}</version>
</dependency>
<dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ </dependency>
+ <dependency>
<groupId>${project.groupId}</groupId>
<artifactId>tika-core</artifactId>
<version>${project.version}</version>
diff --git a/tika-fetchers/tika-fetcher-s3/src/main/java/org/apache/tika/fetcher/s3/S3Fetcher.java b/tika-pipes/tika-fetchers/tika-fetcher-s3/src/main/java/org/apache/tika/pipes/fetcher/s3/S3Fetcher.java
similarity index 63%
rename from tika-fetchers/tika-fetcher-s3/src/main/java/org/apache/tika/fetcher/s3/S3Fetcher.java
rename to tika-pipes/tika-fetchers/tika-fetcher-s3/src/main/java/org/apache/tika/pipes/fetcher/s3/S3Fetcher.java
index 2757f17..126f8fa 100644
--- a/tika-fetchers/tika-fetcher-s3/src/main/java/org/apache/tika/fetcher/s3/S3Fetcher.java
+++ b/tika-pipes/tika-fetchers/tika-fetcher-s3/src/main/java/org/apache/tika/pipes/fetcher/s3/S3Fetcher.java
@@ -14,27 +14,35 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.tika.fetcher.s3;
+package org.apache.tika.pipes.fetcher.s3;
import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.GetObjectRequest;
import com.amazonaws.services.s3.model.S3Object;
+import org.apache.commons.io.IOUtils;
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.exception.TikaConfigException;
import org.apache.tika.exception.TikaException;
-import org.apache.tika.fetcher.FetchPrefixKeyPair;
-import org.apache.tika.fetcher.Fetcher;
-import org.apache.tika.fetcher.FetcherStringException;
+import org.apache.tika.io.TemporaryResources;
+import org.apache.tika.pipes.fetcher.AbstractFetcher;
+import org.apache.tika.pipes.fetcher.FetchId;
+import org.apache.tika.pipes.fetcher.Fetcher;
+import org.apache.tika.pipes.fetcher.FetcherStringException;
import org.apache.tika.io.TikaInputStream;
import org.apache.tika.metadata.Metadata;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.InputStream;
+import java.nio.file.CopyOption;
+import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
@@ -43,39 +51,35 @@ import java.util.Set;
* Fetches files from s3. Example string: s3://my_bucket/path/to/my_file.pdf
* This will parse the bucket out of that string and retrieve the path.
*/
-public class S3Fetcher implements Fetcher, Initializable {
+public class S3Fetcher extends AbstractFetcher implements Initializable {
+ private static final Logger LOGGER = LoggerFactory.getLogger(S3Fetcher.class);
private static final String PREFIX = "s3";
- private static final Set<String> SUPPORTED = Collections.singleton(PREFIX);
-
private String region;
private String profile;
private boolean extractUserMetadata = true;
private AmazonS3 s3Client;
+ private boolean spoolToTemp = true;
@Override
- public Set<String> getSupportedPrefixes() {
- return SUPPORTED;
- }
-
- @Override
- public InputStream fetch(String fetcherString, Metadata metadata)
+ public InputStream fetch(String fetchKey, Metadata metadata)
throws TikaException, IOException {
- FetchPrefixKeyPair fetchPrefixKeyPair = FetchPrefixKeyPair.create(fetcherString);
- String bucketKey = fetchPrefixKeyPair.getKey();
- if (bucketKey.startsWith("//")) {
- bucketKey = bucketKey.substring(2);
- } else if (bucketKey.startsWith("/")) {
- bucketKey = bucketKey.substring(1);
+
+ LOGGER.debug("about to fetch fetchkey={}", fetchKey);
+ final String origFetchKey = fetchKey;
+ if (fetchKey.startsWith("//")) {
+ fetchKey = fetchKey.substring(2);
+ } else if (fetchKey.startsWith("/")) {
+ fetchKey = fetchKey.substring(1);
}
- int i = bucketKey.indexOf("/");
+ int i = fetchKey.indexOf("/");
if (i < 0) {
- throw new FetcherStringException("Couldn't find bucket:" + fetchPrefixKeyPair.getKey());
+ throw new FetcherStringException("Couldn't find bucket:" +
+ origFetchKey);
}
- String bucket = bucketKey.substring(0, i);
- String key = bucketKey.substring(i + 1);
- //should we cache this to a local file so that
- //we can close the s3Object?
+ String bucket = fetchKey.substring(0, i);
+ String key = fetchKey.substring(i + 1);
+ LOGGER.debug("about to fetch bucket: ({}); key: ({})", bucket, key);
S3Object fullObject = s3Client.getObject(new GetObjectRequest(bucket, key));
if (extractUserMetadata) {
for (Map.Entry<String, String> e :
@@ -83,8 +87,23 @@ public class S3Fetcher implements Fetcher, Initializable {
metadata.add(PREFIX + ":" + e.getKey(), e.getValue());
}
}
- return TikaInputStream.get(
- fullObject.getObjectContent());
+ if (! spoolToTemp) {
+ return TikaInputStream.get(
+ fullObject.getObjectContent());
+ } else {
+ long start = System.currentTimeMillis();
+ TikaInputStream tis = TikaInputStream.get(
+ fullObject.getObjectContent());
+ tis.getPath();
+ long elapsed = System.currentTimeMillis()-start;
+ LOGGER.debug("took {} ms to copy to local tmp file", elapsed);
+ return tis;
+ }
+ }
+
+ @Field
+ public void setSpoolToTemp(boolean spoolToTemp) {
+ this.spoolToTemp = spoolToTemp;
}
@Field
diff --git a/tika-fetchers/tika-fetcher-s3/src/test/java/org/apache/tika/fetcher/s3/TestS3Fetcher.java b/tika-pipes/tika-fetchers/tika-fetcher-s3/src/test/java/org/apache/tika/pipes/fetcher/s3/TestS3Fetcher.java
similarity index 93%
rename from tika-fetchers/tika-fetcher-s3/src/test/java/org/apache/tika/fetcher/s3/TestS3Fetcher.java
rename to tika-pipes/tika-fetchers/tika-fetcher-s3/src/test/java/org/apache/tika/pipes/fetcher/s3/TestS3Fetcher.java
index 1e352f9..450d933 100644
--- a/tika-fetchers/tika-fetcher-s3/src/test/java/org/apache/tika/fetcher/s3/TestS3Fetcher.java
+++ b/tika-pipes/tika-fetchers/tika-fetcher-s3/src/test/java/org/apache/tika/pipes/fetcher/s3/TestS3Fetcher.java
@@ -14,10 +14,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.tika.fetcher.s3;
-import com.amazonaws.regions.Regions;
+package org.apache.tika.pipes.fetcher.s3;
import org.apache.tika.config.TikaConfig;
-import org.apache.tika.fetcher.Fetcher;
+import org.apache.tika.pipes.fetcher.Fetcher;
import org.apache.tika.metadata.Metadata;
import org.junit.Ignore;
import org.junit.Test;
@@ -54,7 +53,7 @@ public class TestS3Fetcher {
TikaConfig config = new TikaConfig(
this.getClass().getResourceAsStream("/tika-config-s3.xml")
);
- Fetcher fetcher = config.getFetcher();
+ Fetcher fetcher = config.getFetcherManager().getFetcher("s3");
Metadata metadata = new Metadata();
try (InputStream is = fetcher.fetch(FETCH_STRING, metadata)) {
Files.copy(is, outputFile, StandardCopyOption.REPLACE_EXISTING);
diff --git a/tika-fetchers/tika-fetcher-s3/src/test/resources/tika-config-s3.xml b/tika-pipes/tika-fetchers/tika-fetcher-s3/src/test/resources/tika-config-s3.xml
similarity index 93%
rename from tika-fetchers/tika-fetcher-s3/src/test/resources/tika-config-s3.xml
rename to tika-pipes/tika-fetchers/tika-fetcher-s3/src/test/resources/tika-config-s3.xml
index 39a2ce8..5c1de6c 100644
--- a/tika-fetchers/tika-fetcher-s3/src/test/resources/tika-config-s3.xml
+++ b/tika-pipes/tika-fetchers/tika-fetcher-s3/src/test/resources/tika-config-s3.xml
@@ -19,6 +19,7 @@
<fetchers>
<fetcher class="org.apache.tika.fetcher.s3.S3Fetcher">
<params>
+ <param name="name" type="string">s3</param>
<param name="region" type="string">us-east-1</param>
<param name="profile" type="string">my_profile</param>
</params>
diff --git a/tika-emitters/tika-httpclient-commons/pom.xml b/tika-pipes/tika-httpclient-commons/pom.xml
similarity index 94%
rename from tika-emitters/tika-httpclient-commons/pom.xml
rename to tika-pipes/tika-httpclient-commons/pom.xml
index 8a5fa89..ef7797a 100644
--- a/tika-emitters/tika-httpclient-commons/pom.xml
+++ b/tika-pipes/tika-httpclient-commons/pom.xml
@@ -21,9 +21,10 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
- <artifactId>tika-emitters</artifactId>
+ <artifactId>tika-pipes</artifactId>
<groupId>org.apache.tika</groupId>
<version>2.0.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/tika-emitters/tika-httpclient-commons/src/main/java/org/apache/tika/client/HttpClientUtil.java b/tika-pipes/tika-httpclient-commons/src/main/java/org/apache/tika/client/HttpClientUtil.java
similarity index 100%
rename from tika-emitters/tika-httpclient-commons/src/main/java/org/apache/tika/client/HttpClientUtil.java
rename to tika-pipes/tika-httpclient-commons/src/main/java/org/apache/tika/client/HttpClientUtil.java
diff --git a/tika-emitters/tika-httpclient-commons/src/main/java/org/apache/tika/client/TikaClientException.java b/tika-pipes/tika-httpclient-commons/src/main/java/org/apache/tika/client/TikaClientException.java
similarity index 100%
rename from tika-emitters/tika-httpclient-commons/src/main/java/org/apache/tika/client/TikaClientException.java
rename to tika-pipes/tika-httpclient-commons/src/main/java/org/apache/tika/client/TikaClientException.java
diff --git a/tika-emitters/tika-emitter-solr/pom.xml b/tika-pipes/tika-pipes-integration-tests/pom.xml
similarity index 69%
rename from tika-emitters/tika-emitter-solr/pom.xml
rename to tika-pipes/tika-pipes-integration-tests/pom.xml
index 6aefb89..ccb138c 100644
--- a/tika-emitters/tika-emitter-solr/pom.xml
+++ b/tika-pipes/tika-pipes-integration-tests/pom.xml
@@ -21,30 +21,39 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
- <artifactId>tika-emitters</artifactId>
+ <artifactId>tika-pipes</artifactId>
<groupId>org.apache.tika</groupId>
<version>2.0.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
- <artifactId>tika-emitter-solr</artifactId>
+ <artifactId>tika-pipes-integration-tests</artifactId>
<dependencies>
<dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>tika-core</artifactId>
- <version>${project.version}</version>
- <scope>provided</scope>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ <scope>test</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
- <artifactId>tika-httpclient-commons</artifactId>
+ <artifactId>tika-core</artifactId>
<version>${project.version}</version>
+ <scope>test</scope>
</dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-log4j12</artifactId>
- </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>tika-fetcher-s3</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>tika-fetch-iterator-s3</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
@@ -52,4 +61,4 @@
</dependency>
</dependencies>
-</project>
\ No newline at end of file
+</project>
diff --git a/tika-pipes/tika-pipes-integration-tests/src/test/java/org/apache/tika/pipes/PipeIntegrationTests.java b/tika-pipes/tika-pipes-integration-tests/src/test/java/org/apache/tika/pipes/PipeIntegrationTests.java
new file mode 100644
index 0000000..590a125
--- /dev/null
+++ b/tika-pipes/tika-pipes-integration-tests/src/test/java/org/apache/tika/pipes/PipeIntegrationTests.java
@@ -0,0 +1,162 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tika.pipes;
+
+import com.amazonaws.auth.profile.ProfileCredentialsProvider;
+import com.amazonaws.services.s3.AmazonS3;
+import com.amazonaws.services.s3.AmazonS3Client;
+import com.amazonaws.services.s3.AmazonS3ClientBuilder;
+import com.amazonaws.services.s3.iterable.S3Objects;
+import com.amazonaws.services.s3.model.S3Object;
+import com.amazonaws.services.s3.model.S3ObjectSummary;
+import org.apache.tika.config.TikaConfig;
+import org.apache.tika.exception.TikaException;
+import org.apache.tika.pipes.emitter.Emitter;
+import org.apache.tika.pipes.fetcher.FetchIdMetadataPair;
+import org.apache.tika.pipes.fetcher.Fetcher;
+import org.apache.tika.pipes.fetchiterator.FetchIterator;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorCompletionService;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicInteger;
+
+@Ignore("turn these into actual tests")
+public class PipeIntegrationTests {
+
+ private static final Path OUTDIR = Paths.get("");
+
+ @Test
+ public void testBruteForce() throws Exception {
+ String region = "";
+ String profile = "";
+ String bucket = "";
+ AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
+ .withRegion(region)
+ .withCredentials(new ProfileCredentialsProvider(profile))
+ .build();
+ s3Client.listObjects(bucket);
+ int cnt = 0;
+ long sz = 0;
+
+ for (S3ObjectSummary summary : S3Objects.withPrefix(s3Client, bucket, "")) {
+ Path targ = OUTDIR.resolve(summary.getKey());
+ if (Files.isRegularFile(targ)) {
+ continue;
+ }
+ if (! Files.isDirectory(targ.getParent())) {
+ Files.createDirectories(targ.getParent());
+ }
+ System.out.println("id: " + cnt + " :: " + summary.getKey() + " : " + summary.getSize());
+ S3Object s3Object = s3Client.getObject(bucket, summary.getKey());
+ Files.copy(s3Object.getObjectContent(), targ);
+ summary.getSize();
+ cnt++;
+ sz += summary.getSize();
+ }
+ System.out.println("iterated: "+cnt + " sz: "+sz);
+ }
+
+ @Test
+ public void testS3ToFS() throws Exception {
+ TikaConfig tikaConfig = getConfig("tika-config-s3ToFs.xml");
+ FetchIterator it = tikaConfig.getFetchIterator();
+ int numConsumers = 1;
+ ExecutorService es = Executors.newFixedThreadPool(numConsumers + 1);
+ ExecutorCompletionService<Integer> completionService = new ExecutorCompletionService<>(es);
+ ArrayBlockingQueue<FetchIdMetadataPair> queue = it.init(numConsumers);
+ completionService.submit(it);
+ for (int i = 0; i < numConsumers; i++) {
+ completionService.submit(new FetcherEmitter(
+ queue, tikaConfig.getFetcherManager().getFetcher("s3"), null));
+ }
+ int finished = 0;
+ try {
+ while (finished++ < numConsumers+1) {
+ Future<Integer> future = completionService.take();
+ future.get();
+ }
+ } finally {
+ es.shutdownNow();
+ }
+
+
+ }
+
+ private TikaConfig getConfig(String fileName) throws Exception {
+ try (InputStream is =
+ PipeIntegrationTests.class.getResourceAsStream("/"+fileName)) {
+ return new TikaConfig(is);
+ }
+ }
+
+
+ private static class FetcherEmitter implements Callable<Integer> {
+ private static final AtomicInteger counter = new AtomicInteger(0);
+
+ private final Fetcher fetcher;
+ private final Emitter emitter;
+ private final ArrayBlockingQueue<FetchIdMetadataPair> queue;
+
+ FetcherEmitter(ArrayBlockingQueue<FetchIdMetadataPair> queue, Fetcher
+ fetcher, Emitter emitter) {
+ this.queue = queue;
+ this.fetcher = fetcher;
+ this.emitter = emitter;
+ }
+
+ @Override
+ public Integer call() throws Exception {
+
+ while (true) {
+ FetchIdMetadataPair p = queue.poll(5, TimeUnit.MINUTES);
+ if (p == null) {
+ throw new TimeoutException("");
+ }
+ if (p == FetchIterator.COMPLETED_SEMAPHORE) {
+ return 1;
+ }
+ process(p);
+ }
+ }
+
+ private void process(FetchIdMetadataPair p) throws IOException, TikaException {
+ Path targ = OUTDIR.resolve(p.getFetchId().getFetchKey());
+ if (Files.isRegularFile(targ)) {
+ return;
+ }
+ try (InputStream is = fetcher.fetch(p.getFetchId().getFetchKey(), p.getMetadata())) {
+ System.out.println(counter.getAndIncrement() + " : "+p );
+ Files.createDirectories(targ.getParent());
+ Files.copy(is, targ);
+ }
+ }
+ }
+}
diff --git a/tika-emitters/tika-emitter-solr/src/test/resources/log4j.properties b/tika-pipes/tika-pipes-integration-tests/src/test/resources/log4j.properties
similarity index 91%
rename from tika-emitters/tika-emitter-solr/src/test/resources/log4j.properties
rename to tika-pipes/tika-pipes-integration-tests/src/test/resources/log4j.properties
index 92b6d56..1bee240 100644
--- a/tika-emitters/tika-emitter-solr/src/test/resources/log4j.properties
+++ b/tika-pipes/tika-pipes-integration-tests/src/test/resources/log4j.properties
@@ -14,11 +14,11 @@
# limitations under the License.
#info,debug, error,fatal ...
-log4j.rootLogger=debug,stderr
+log4j.rootLogger=info,stderr
#console
log4j.appender.stderr=org.apache.log4j.ConsoleAppender
log4j.appender.stderr.layout=org.apache.log4j.PatternLayout
log4j.appender.stderr.Target=System.err
-log4j.appender.stderr.layout.ConversionPattern= %-5p %m%n
+log4j.appender.stderr.layout.ConversionPattern=%-5p [%t]: %m%n
diff --git a/tika-pipes/tika-pipes-integration-tests/src/test/resources/tika-config-s3ToFs.xml b/tika-pipes/tika-pipes-integration-tests/src/test/resources/tika-config-s3ToFs.xml
new file mode 100644
index 0000000..3e5bbc5
--- /dev/null
+++ b/tika-pipes/tika-pipes-integration-tests/src/test/resources/tika-config-s3ToFs.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<properties>
+ <fetchers>
+ <fetcher class="org.apache.tika.pipes.fetcher.s3.S3Fetcher">
+ <params>
+ <param name="name" type="string">s3</param>
+ <param name="region" type="string">us-east-1</param>
+ <param name="profile" type="string"><!-- fill in here --></param>
+ </params>
+ </fetcher>
+ </fetchers>
+ <fetchIterators>
+ <fetchIterator class="org.apache.tika.pipes.fetchiterator.s3.S3FetchIterator">
+ <params>
+ <param name="fetcherName" type="string">s3</param>
+ <param name="bucket" type="string"><!-- fill in here --></param>
+ <param name="region" type="string">us-east-1</param>
+ <param name="profile" type="string"><!-- fill in here --></param>
+ </params>
+ </fetchIterator>
+ </fetchIterators>
+</properties>
\ No newline at end of file
diff --git a/tika-server/tika-server-classic/src/test/java/org/apache/tika/server/classic/FetcherTest.java b/tika-server/tika-server-classic/src/test/java/org/apache/tika/server/classic/FetcherTest.java
index 3e5a15f..2343d4a 100644
--- a/tika-server/tika-server-classic/src/test/java/org/apache/tika/server/classic/FetcherTest.java
+++ b/tika-server/tika-server-classic/src/test/java/org/apache/tika/server/classic/FetcherTest.java
@@ -75,7 +75,7 @@ public class FetcherTest extends CXFTestBase {
@Override
protected InputStreamFactory getInputStreamFactory(TikaConfig tikaConfig) {
- return new FetcherStreamFactory(tikaConfig.getFetcher());
+ return new FetcherStreamFactory(tikaConfig.getFetcherManager());
}
@Test
@@ -84,7 +84,8 @@ public class FetcherTest extends CXFTestBase {
.create(endPoint + META_PATH)
.accept("application/json")
.acceptEncoding("gzip")
- .header("fetcherString", "url:https://tika.apache.org").put("");
+ .header("fetcherName", "url")
+ .header("fetchKey", "https://tika.apache.org").put("");
Reader reader = new InputStreamReader(new GzipCompressorInputStream((InputStream) response.getEntity()), UTF_8);
List<Metadata> metadataList = JsonMetadataList.fromJson(reader);
diff --git a/tika-server/tika-server-classic/src/test/resources/config/tika-config-url-fetcher.xml b/tika-server/tika-server-classic/src/test/resources/config/tika-config-url-fetcher.xml
index ea4079c..d3aaff0 100644
--- a/tika-server/tika-server-classic/src/test/resources/config/tika-config-url-fetcher.xml
+++ b/tika-server/tika-server-classic/src/test/resources/config/tika-config-url-fetcher.xml
@@ -22,6 +22,10 @@
<parser class="org.apache.tika.parser.DefaultParser"/>
</parsers>
<fetchers>
- <fetcher class="org.apache.tika.fetcher.SimpleUrlFetcher"/>
+ <fetcher class="org.apache.tika.pipes.fetcher.SimpleUrlFetcher">
+ <params>
+ <param name="name" type="string">url</param>
+ </params>
+ </fetcher>
</fetchers>
</properties>
\ No newline at end of file
diff --git a/tika-server/tika-server-client/src/main/java/org/apache/tika/server/client/TikaClient.java b/tika-server/tika-server-client/src/main/java/org/apache/tika/server/client/TikaClient.java
index f535f52..d7ebcf0 100644
--- a/tika-server/tika-server-client/src/main/java/org/apache/tika/server/client/TikaClient.java
+++ b/tika-server/tika-server-client/src/main/java/org/apache/tika/server/client/TikaClient.java
@@ -16,17 +16,15 @@
*/
package org.apache.tika.server.client;
-
-
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import org.apache.tika.config.TikaConfig;
-import org.apache.tika.exception.TikaConfigException;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
+import org.apache.tika.pipes.fetcher.FetchId;
import java.io.IOException;
import java.util.ArrayList;
@@ -59,17 +57,18 @@ public class TikaClient {
}*/
- public TikaEmitterResult parse(String fetcherString, Metadata metadata, String emitter)
+ public TikaEmitterResult parse(FetchId fetchId, Metadata metadata, String emitter)
throws IOException, TikaException {
TikaHttpClient client = getHttpClient();
- String jsonRequest = jsonifyRequest(fetcherString, metadata, emitter);
+ String jsonRequest = jsonifyRequest(fetchId, metadata, emitter);
return client.postJson(jsonRequest);
}
- private String jsonifyRequest(String fetcherString, Metadata metadata, String emitter) {
+ private String jsonifyRequest(FetchId fetchId, Metadata metadata, String emitter) {
JsonObject root = new JsonObject();
- root.add("fetcherString", new JsonPrimitive(fetcherString));
+ root.add("fetcherName", new JsonPrimitive(fetchId.getFetcherName()));
+ root.add("fetchKey", new JsonPrimitive(fetchId.getFetchKey()));
root.add("emitter", new JsonPrimitive(emitter));
if (metadata.size() > 0) {
JsonObject m = new JsonObject();
diff --git a/tika-server/tika-server-client/src/main/java/org/apache/tika/server/client/TikaClientCLI.java b/tika-server/tika-server-client/src/main/java/org/apache/tika/server/client/TikaClientCLI.java
index 08489c2..2ca9f97 100644
--- a/tika-server/tika-server-client/src/main/java/org/apache/tika/server/client/TikaClientCLI.java
+++ b/tika-server/tika-server-client/src/main/java/org/apache/tika/server/client/TikaClientCLI.java
@@ -18,9 +18,9 @@ package org.apache.tika.server.client;
import org.apache.tika.config.TikaConfig;
import org.apache.tika.exception.TikaException;
-import org.apache.tika.fetcher.FetchIterator;
-import org.apache.tika.fetcher.FetchMetadataPair;
-import org.apache.tika.fetcher.FileSystemFetchIterator;
+import org.apache.tika.pipes.fetchiterator.FetchIterator;
+import org.apache.tika.pipes.fetcher.FetchIdMetadataPair;
+import org.apache.tika.pipes.fetchiterator.FileSystemFetchIterator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.SAXException;
@@ -43,9 +43,6 @@ import java.util.concurrent.TimeoutException;
public class TikaClientCLI {
- private static final FetchMetadataPair POISON =
- new FetchMetadataPair(null, null);
-
private static final Logger LOGGER = LoggerFactory.getLogger(TikaClientCLI.class);
//make these configurable
@@ -66,14 +63,13 @@ public class TikaClientCLI {
throws TikaException, IOException, SAXException {
TikaConfig config = new TikaConfig(tikaConfigPath);
- ArrayBlockingQueue<FetchMetadataPair> queue = new ArrayBlockingQueue<>(1000);
- ExecutorService executorService = Executors.newFixedThreadPool(numThreads+2);
+ ExecutorService executorService = Executors.newFixedThreadPool(numThreads+1);
ExecutorCompletionService<Integer> completionService = new ExecutorCompletionService<>(executorService);
//TODO: fix this!
- final FetchIterator fetchIterator = new FileSystemFetchIterator(
- "fs", Paths.get("."));
+ final FetchIterator fetchIterator = config.getFetchIterator();
+ ArrayBlockingQueue<FetchIdMetadataPair> queue = fetchIterator.init(numThreads);
+
completionService.submit(fetchIterator);
- completionService.submit(new Enqueuer(queue, fetchIterator, numThreads));
if (tikaServerUrls.size() == numThreads) {
logDiffSizes(tikaServerUrls.size(), numThreads);
for (int i = 0; i < numThreads; i++) {
@@ -82,12 +78,14 @@ public class TikaClientCLI {
completionService.submit(new FetchWorker(queue, client, fetcherString));
}
} else {
- TikaClient client = TikaClient.get(config,tikaServerUrls);
- completionService.submit(new FetchWorker(queue, client, fetcherString));
+ for (int i = 0; i < numThreads; i++) {
+ TikaClient client = TikaClient.get(config, tikaServerUrls);
+ completionService.submit(new FetchWorker(queue, client, fetcherString));
+ }
}
int finished = 0;
- while (finished < numThreads+2) {
+ while (finished < numThreads+1) {
Future<Integer> future = null;
try {
future = completionService.poll(maxWaitMs, TimeUnit.MILLISECONDS);
@@ -107,7 +105,6 @@ public class TikaClientCLI {
}
}
}
-
}
private void logDiffSizes(int servers, int numThreads) {
@@ -116,44 +113,11 @@ public class TikaClientCLI {
servers, numThreads);
}
- private class Enqueuer implements Callable<Integer> {
- //simple class that pulls fetchmetadata pairs from the fetchiterator
- //and enqueues them for the worker threads.
- private final ArrayBlockingQueue<FetchMetadataPair> queue;
- private final FetchIterator fetchIterator;
- private final int numThreads;
-
- public Enqueuer(ArrayBlockingQueue<FetchMetadataPair> queue, FetchIterator fetchIterator, int numThreads) {
- this.queue = queue;
- this.fetchIterator = fetchIterator;
- this.numThreads = numThreads;
- }
-
- @Override
- public Integer call() throws Exception {
- System.out.println("enqueing");
- for (FetchMetadataPair p : fetchIterator) {
- System.out.println("offering "+p);
- boolean offered = queue.offer(p, maxWaitMs, TimeUnit.MILLISECONDS);
- if (! offered) {
- throw new TimeoutException("exceeded max wait");
- }
- }
- for (int i = 0; i < numThreads; i++) {
- boolean offered = queue.offer(POISON, maxWaitMs, TimeUnit.MILLISECONDS);
- if (! offered) {
- throw new TimeoutException("exceeded max wait");
- }
- }
- return 1;
- }
- }
-
private class FetchWorker implements Callable<Integer> {
- private final ArrayBlockingQueue<FetchMetadataPair> queue;
+ private final ArrayBlockingQueue<FetchIdMetadataPair> queue;
private final TikaClient client;
private final String emitterString;
- public FetchWorker(ArrayBlockingQueue<FetchMetadataPair> queue, TikaClient client,
+ public FetchWorker(ArrayBlockingQueue<FetchIdMetadataPair> queue, TikaClient client,
String emitterString) {
this.queue = queue;
this.client = client;
@@ -164,21 +128,21 @@ public class TikaClientCLI {
public Integer call() throws Exception {
while (true) {
- System.out.println("about to work");
- FetchMetadataPair p = queue.poll(maxWaitMs, TimeUnit.MILLISECONDS);
+
+ FetchIdMetadataPair p = queue.poll(maxWaitMs, TimeUnit.MILLISECONDS);
if (p == null) {
throw new TimeoutException("exceeded maxWaitMs");
}
- if (p == POISON) {
+ if (p == FetchIterator.COMPLETED_SEMAPHORE) {
return 1;
}
try {
- System.out.println("parsing; "+p.getFetcherString());
- System.out.println(client.parse(p.getFetcherString(), p.getMetadata(), emitterString));
+ LOGGER.debug("about to parse: {}", p.getFetchId());
+ client.parse(p.getFetchId(), p.getMetadata(), emitterString);
} catch (IOException e) {
- LOGGER.warn(p.getFetcherString(), e);
+ LOGGER.warn(p.getFetchId().toString(), e);
} catch (TikaException e) {
- LOGGER.warn(p.getFetcherString(), e);
+ LOGGER.warn(p.getFetchId().toString(), e);
}
}
}
diff --git a/tika-server/tika-server-client/src/test/resources/tika-config-simple-solr-emitter.xml b/tika-server/tika-server-client/src/test/resources/tika-config-simple-solr-emitter.xml
index ae5a9b2..56be391 100644
--- a/tika-server/tika-server-client/src/test/resources/tika-config-simple-solr-emitter.xml
+++ b/tika-server/tika-server-client/src/test/resources/tika-config-simple-solr-emitter.xml
@@ -20,7 +20,7 @@
<properties>
<service-loader initializableProblemHandler="throw"/>
<fetchIterators>
- <fetchIterator class="org.apache.tika.fetcher.FileSystemFetchIterator">
+ <fetchIterator class="org.apache.tika.pipes.fetchiterator.FileSystemFetchIterator">
<params>
<param name="fetchPrefix" type="string">fs</param>
<param name="basePath" type="string">fix</param>
@@ -28,7 +28,7 @@
</fetchIterator>
</fetchIterators>
<fetchers>
- <fetcher class="org.apache.tika.fetcher.FileSystemFetcher">
+ <fetcher class="org.apache.tika.pipes.fetcher.FileSystemFetcher">
<params>
<param name="name" type="string">fs</param>
<param name="basePath" type="string">fix</param>
diff --git a/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/FetcherStreamFactory.java b/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/FetcherStreamFactory.java
index 0841004..949ab57 100644
--- a/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/FetcherStreamFactory.java
+++ b/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/FetcherStreamFactory.java
@@ -19,12 +19,12 @@ package org.apache.tika.server.core;
import javax.ws.rs.core.HttpHeaders;
import java.io.IOException;
import java.io.InputStream;
-import java.net.URL;
+import org.apache.commons.lang3.StringUtils;
import org.apache.tika.exception.TikaException;
-import org.apache.tika.fetcher.Fetcher;
-import org.apache.tika.io.TikaInputStream;
+import org.apache.tika.pipes.fetcher.Fetcher;
import org.apache.tika.metadata.Metadata;
+import org.apache.tika.pipes.fetcher.FetcherManager;
/**
* This class looks for "fileUrl" in the http header. If it is not null
@@ -44,19 +44,25 @@ import org.apache.tika.metadata.Metadata;
*/
public class FetcherStreamFactory implements InputStreamFactory {
- private final Fetcher fetcher;
+ private final FetcherManager fetcherManager;
- public FetcherStreamFactory(Fetcher fetcher) {
- this.fetcher = fetcher;
+ public FetcherStreamFactory(FetcherManager fetcherManager) {
+ this.fetcherManager = fetcherManager;
}
+
@Override
public InputStream getInputSteam(InputStream is, Metadata metadata,
HttpHeaders httpHeaders) throws IOException {
- String fetcherString = httpHeaders.getHeaderString("fetcherString");
+ String fetcherName= httpHeaders.getHeaderString("fetcherName");
+ String fetchKey = httpHeaders.getHeaderString("fetchKey");
+ if (StringUtils.isBlank(fetcherName) != StringUtils.isBlank(fetchKey)) {
+ throw new IOException("Must specify both a 'fetcherName' and a 'fetchKey'. I see: "+
+ " fetcherName:"+fetcherName+" and fetchKey:"+fetchKey);
+ }
- if(fetcherString != null && !"".equals(fetcherString)){
+ if (!StringUtils.isBlank(fetcherName)){
try {
- return fetcher.fetch(fetcherString, metadata);
+ return fetcherManager.getFetcher(fetcherName).fetch(fetchKey, metadata);
} catch (TikaException e) {
throw new IOException(e);
}
diff --git a/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/TikaServerCli.java b/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/TikaServerCli.java
index 0035efb..6680751 100644
--- a/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/TikaServerCli.java
+++ b/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/TikaServerCli.java
@@ -45,7 +45,6 @@ import org.apache.cxf.transport.common.gzip.GZIPOutInterceptor;
import org.apache.tika.Tika;
import org.apache.tika.config.ServiceLoader;
import org.apache.tika.config.TikaConfig;
-import org.apache.tika.emitter.Emitter;
import org.apache.tika.parser.DigestingParser;
import org.apache.tika.parser.digestutils.BouncyCastleDigester;
import org.apache.tika.parser.digestutils.CommonsDigester;
@@ -278,7 +277,7 @@ public class TikaServerCli {
InputStreamFactory inputStreamFactory = null;
if (line.hasOption("enableUnsecureFeatures")) {
- inputStreamFactory = new FetcherStreamFactory(tika.getFetcher());
+ inputStreamFactory = new FetcherStreamFactory(tika.getFetcherManager());
LOG.info(UNSECURE_WARNING);
} else {
inputStreamFactory = new DefaultInputStreamFactory();
@@ -376,7 +375,7 @@ public class TikaServerCli {
private static void logFetchersAndEmitters(boolean enableUnsecureFeatures, TikaConfig tika) {
if (enableUnsecureFeatures) {
StringBuilder sb = new StringBuilder();
- Set<String> supportedFetchers = tika.getFetcher().getSupportedPrefixes();
+ Set<String> supportedFetchers = tika.getFetcherManager().getSupported();
sb.append("enableSecureFeatures has been selected.\n");
if (supportedFetchers.size() == 0) {
sb.append("There are no fetchers specified in the TikaConfig");
@@ -386,7 +385,7 @@ public class TikaServerCli {
sb.append(p).append("\n");
}
}
- Set<String> emitters = tika.getEmitter().getSupported();
+ Set<String> emitters = tika.getEmitterManager().getSupported();
if (supportedFetchers.size() == 0) {
sb.append("There are no emitters specified in the TikaConfig");
} else {
@@ -397,16 +396,16 @@ public class TikaServerCli {
}
LOG.info(sb.toString());
} else {
- if (tika.getEmitter().getSupported().size() > 0) {
+ if (tika.getEmitterManager().getSupported().size() > 0) {
String warn = "-enableUnsecureFeatures has not been specified on the commandline.\n"+
- "The "+tika.getEmitter().getSupported().size() + " emitter(s) that you've\n"+
+ "The "+tika.getEmitterManager().getSupported().size() + " emitter(s) that you've\n"+
"specified in TikaConfig will not be available on the /emit endpoint\n"+
"To enable your emitters, start tika-server with the -enableUnsecureFeatures flag\n\n";
LOG.warn(warn);
}
- if (tika.getFetcher().getSupportedPrefixes().size() > 0) {
+ if (tika.getFetcherManager().getSupported().size() > 0) {
String warn = "-enableUnsecureFeatures has not been specified on the commandline.\n"+
- "The "+tika.getFetcher().getSupportedPrefixes().size() + " fetcher(s) that you've\n"+
+ "The "+tika.getFetcherManager().getSupported().size() + " fetcher(s) that you've\n"+
"specified in TikaConfig will not be available\n"+
"To enable your fetchers, start tika-server with the -enableUnsecureFeatures flag\n\n";
LOG.warn(warn);
diff --git a/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/EmitterResource.java b/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/EmitterResource.java
index 008feed..7f116fa 100644
--- a/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/EmitterResource.java
+++ b/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/EmitterResource.java
@@ -20,10 +20,11 @@ package org.apache.tika.server.core.resource;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
-import org.apache.tika.emitter.Emitter;
-import org.apache.tika.emitter.TikaEmitterException;
+import org.apache.tika.pipes.emitter.Emitter;
+import org.apache.tika.pipes.emitter.TikaEmitterException;
import org.apache.tika.exception.TikaException;
-import org.apache.tika.fetcher.Fetcher;
+import org.apache.tika.pipes.fetcher.FetchId;
+import org.apache.tika.pipes.fetcher.Fetcher;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.metadata.TikaCoreProperties;
import org.apache.tika.sax.AbstractRecursiveParserWrapperHandler;
@@ -54,7 +55,8 @@ import java.util.Map;
public class EmitterResource {
private static final String EMITTER_PARAM = "emitter";
- private static final String FETCH_STRING_ABBREV = "f";
+ private static final String FETCHER_NAME_ABBREV = "fn";
+ private static final String FETCH_KEY_ABBREV = "fk";
/**
* key that is safe to pass through http header.
@@ -69,24 +71,23 @@ public class EmitterResource {
* @param httpHeaders
* @param info
* @param emitterName
- * @param fetcherString specify the fetch string in the url's query section
+ * @param fetcherName specify the fetcherName in the url's query section
+ * @param fetchKey specify the fetch key in the url's query section
* @return
* @throws Exception
*/
@GET
@Produces("application/json")
@Path("{" + EMITTER_PARAM + " : (\\w+)?}")
- public Map<String, String> getMetadataAbbrev(InputStream is, @Context HttpHeaders httpHeaders,
+ public Map<String, String> getRmeta(InputStream is, @Context HttpHeaders httpHeaders,
@Context UriInfo info,
@PathParam(EMITTER_PARAM) String emitterName,
- @QueryParam(FETCH_STRING_ABBREV) String fetcherString) throws Exception {
+ @QueryParam(FETCHER_NAME_ABBREV) String fetcherName,
+ @QueryParam(FETCH_KEY_ABBREV) String fetchKey) throws Exception {
Metadata metadata = new Metadata();
- Fetcher fetcher = TikaResource.getConfig().getFetcher();
- System.out.println("FETCHER: " + fetcher.getClass() + " : " + fetcher.getSupportedPrefixes());
- System.out.println("emitter: " + TikaResource.getConfig().getEmitter().getClass()
- + " : " + TikaResource.getConfig().getEmitter().getSupported());
+ Fetcher fetcher = TikaResource.getConfig().getFetcherManager().getFetcher(fetcherName);
List<Metadata> metadataList;
- try (InputStream fetchedIs = fetcher.fetch(fetcherString, metadata)) {
+ try (InputStream fetchedIs = fetcher.fetch(fetchKey, metadata)) {
for (String n : metadata.names()) {
System.out.println(n + " ; "+metadata.get(n));
}
@@ -116,7 +117,7 @@ public class EmitterResource {
@PUT
@Produces("application/json")
@Path("{" + EMITTER_PARAM + " : (\\w+)?}")
- public Map<String, String> getMetadataFromInputStream(InputStream is,
+ public Map<String, String> putRmeta(InputStream is,
@Context HttpHeaders httpHeaders,
@Context UriInfo info,
@PathParam(EMITTER_PARAM) String emitterName
@@ -140,7 +141,7 @@ public class EmitterResource {
* through of metadata from the client.
* <p>
* The extracted text content is stored with the key
- * {@link org.apache.tika.sax.AbstractRecursiveParserWrapperHandler#TIKA_CONTENT}
+ * {@link AbstractRecursiveParserWrapperHandler#TIKA_CONTENT}
* <p>
* Must specify a fetcherString and an emitter in the posted json.
* @param info uri info
@@ -149,7 +150,7 @@ public class EmitterResource {
*/
@POST
@Produces("application/json")
- public Map<String, String> getMetadataFromPost(InputStream is,
+ public Map<String, String> postRmeta(InputStream is,
@Context HttpHeaders httpHeaders,
@Context UriInfo info
) throws Exception {
@@ -157,9 +158,35 @@ public class EmitterResource {
try (Reader reader = new InputStreamReader(is, StandardCharsets.UTF_8)) {
root = JsonParser.parseReader(reader);
}
- String fetcherString = root.getAsJsonObject().get("fetcherString").getAsString();
+ String fetcherName = root.getAsJsonObject().get("fetcherName").getAsString();
+ String fetchKey = root.getAsJsonObject().get("fetchKey").getAsString();
String emitterName = root.getAsJsonObject().get("emitter").getAsString();
Metadata metadata = new Metadata();
+
+
+ List<Metadata> metadataList = null;
+ try (InputStream stream =
+ TikaResource.getConfig().getFetcherManager()
+ .getFetcher(fetcherName).fetch(fetchKey, metadata)) {
+
+ metadataList = RecursiveMetadataResource.parseMetadata(
+ stream,
+ metadata,
+ httpHeaders.getRequestHeaders(), info, "text");
+ } catch (Error error) {
+ return returnError(emitterName, error);
+ }
+
+ injectUserMetadata(metadataList.get(0), root.getAsJsonObject());
+
+ for (String n : metadataList.get(0).names()) {
+ LOG.debug("post parse/pre emit metadata {}: {}",
+ n, metadataList.get(0).get(n));
+ }
+ return emit(emitterName, metadataList);
+ }
+
+ private void injectUserMetadata(Metadata metadata, JsonObject root) {
if (root.getAsJsonObject().has("metadata")) {
JsonObject meta = root.getAsJsonObject().getAsJsonObject("metadata");
for (String k : meta.keySet()) {
@@ -173,25 +200,6 @@ public class EmitterResource {
}
}
}
- for (String n : metadata.names()) {
- System.out.println(n + " ; "+metadata.get(n));
- }
- List<Metadata> metadataList = null;
- try (InputStream stream = TikaResource.getConfig().getFetcher().fetch(fetcherString, metadata)) {
- for (String n : metadata.names()) {
- System.out.println("2: " + n + " ; "+metadata.get(n));
- }
- metadataList = RecursiveMetadataResource.parseMetadata(
- stream,
- metadata,
- httpHeaders.getRequestHeaders(), info, "text");
- } catch (Error error) {
- return returnError(emitterName, error);
- }
- for (String n : metadataList.get(0).names()) {
- System.out.println("3: " + n + " ; "+metadataList.get(0).get(n));
- }
- return emit(emitterName, metadataList);
}
private Map<String, String> returnError(String emitterName, Error error) {
@@ -201,15 +209,14 @@ public class EmitterResource {
String msg = ExceptionUtils.getStackTrace(error);
statusMap.put("parse_error", msg);
return statusMap;
-
}
private Map<String, String> emit(String emitterName, List<Metadata> metadataList) throws TikaException {
- Emitter emitter = TikaResource.getConfig().getEmitter();
+ Emitter emitter = TikaResource.getConfig().getEmitterManager().getEmitter(emitterName);
String status = "ok";
String exceptionMsg = "";
try {
- emitter.emit(emitterName, metadataList);
+ emitter.emit(metadataList);
} catch (IOException|TikaEmitterException e) {
LOG.warn("problem with emitting", e);
status = "emitter_exception";
diff --git a/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/TikaEmitterTest.java b/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/TikaEmitterTest.java
index c02f078..0631eef 100644
--- a/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/TikaEmitterTest.java
+++ b/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/TikaEmitterTest.java
@@ -64,7 +64,7 @@ import static org.junit.Assert.assertNotNull;
public class TikaEmitterTest extends CXFTestBase {
private static final String EMITTER_PATH = "/emit";
- private static final String EMITTER_PATH_AND_FS = "/emit/fs";
+ private static final String EMITTER_PATH_AND_FS = "/emit/fse";
private static Path TMP_DIR;
private static Path TMP_OUTPUT_DIR;
private static Path TMP_OUTPUT_FILE;
@@ -91,8 +91,9 @@ public class TikaEmitterTest extends CXFTestBase {
TIKA_CONFIG_XML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"+
"<properties>"+
"<fetchers>"+
- "<fetcher class=\"org.apache.tika.fetcher.FileSystemFetcher\">"+
+ "<fetcher class=\"org.apache.tika.pipes.fetcher.FileSystemFetcher\">"+
"<params>"+
+ "<param name=\"name\" type=\"string\">fsf</param>"+
"<param name=\"basePath\" type=\"string\">"+inputDir.toAbsolutePath()+"</param>"+
"</params>"+
"</fetcher>"+
@@ -100,6 +101,7 @@ public class TikaEmitterTest extends CXFTestBase {
"<emitters>"+
"<emitter class=\"org.apache.tika.emitter.fs.FileSystemEmitter\">"+
"<params>"+
+ "<param name=\"name\" type=\"string\">fse</param>"+
"<param name=\"basePath\" type=\"string\">"+ TMP_OUTPUT_DIR.toAbsolutePath()+"</param>"+
"</params>"+
"</emitter>"+
@@ -141,14 +143,13 @@ public class TikaEmitterTest extends CXFTestBase {
@Override
protected InputStreamFactory getInputStreamFactory(TikaConfig tikaConfig) {
- return new FetcherStreamFactory(tikaConfig.getFetcher());
+ return new FetcherStreamFactory(tikaConfig.getFetcherManager());
}
@Test
public void testGet() throws Exception {
- String q = "?f="+
- URLEncoder.encode("fs:hello_world.xml", StandardCharsets.UTF_8.name());
+ String q = "?fn=fsf&fk=hello_world.xml";
String getUrl = endPoint+EMITTER_PATH_AND_FS+q;
Response response = WebClient
.create(getUrl)
@@ -171,8 +172,9 @@ public class TikaEmitterTest extends CXFTestBase {
public void testPost() throws Exception {
JsonObject root = new JsonObject();
- root.add("fetcherString", new JsonPrimitive("fs:hello_world.xml"));
- root.add("emitter", new JsonPrimitive("fs"));
+ root.add("fetcherName", new JsonPrimitive("fsf"));
+ root.add("fetchKey", new JsonPrimitive("hello_world.xml"));
+ root.add("emitter", new JsonPrimitive("fse"));
JsonObject userMetadata = new JsonObject();
String[] valueArray = new String[] {"my-value-1", "my-value-2", "my-value-3"};
JsonArray arr = new JsonArray();
@@ -239,8 +241,9 @@ public class TikaEmitterTest extends CXFTestBase {
public void testPostNPE() throws Exception {
JsonObject root = new JsonObject();
- root.add("fetcherString", new JsonPrimitive("fs:null_pointer.xml"));
- root.add("emitter", new JsonPrimitive("fs"));
+ root.add("fetcherName", new JsonPrimitive("fsf"));
+ root.add("fetchKey", new JsonPrimitive("null_pointer.xml"));
+ root.add("emitter", new JsonPrimitive("fse"));
JsonObject userMetadata = new JsonObject();
String[] valueArray = new String[] {"my-value-1", "my-value-2", "my-value-3"};
JsonArray arr = new JsonArray();
diff --git a/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/TikaServerEmitterIntegrationTest.java b/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/TikaServerEmitterIntegrationTest.java
index acb4657..3fa10f5 100644
--- a/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/TikaServerEmitterIntegrationTest.java
+++ b/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/TikaServerEmitterIntegrationTest.java
@@ -60,6 +60,9 @@ public class TikaServerEmitterIntegrationTest extends IntegrationTestBase {
private static Path TIKA_CONFIG;
private static Gson GSON = new GsonBuilder().create();
+ private static final String EMITTER_NAME = "fse";
+ private static final String FETCHER_NAME = "fsf";
+
private static String[] FILES = new String[] {
"hello_world.xml",
"heavy_hang_30000.xml", "real_oom.xml", "system_exit.xml"
@@ -83,8 +86,9 @@ public class TikaServerEmitterIntegrationTest extends IntegrationTestBase {
TIKA_CONFIG_XML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"+
"<properties>"+
"<fetchers>"+
- "<fetcher class=\"org.apache.tika.fetcher.FileSystemFetcher\">"+
+ "<fetcher class=\"org.apache.tika.pipes.fetcher.FileSystemFetcher\">"+
"<params>"+
+ "<param name=\"name\" type=\"string\">"+FETCHER_NAME+"</param>"+
"<param name=\"basePath\" type=\"string\">"+inputDir.toAbsolutePath()+"</param>"+
"</params>"+
"</fetcher>"+
@@ -92,6 +96,8 @@ public class TikaServerEmitterIntegrationTest extends IntegrationTestBase {
"<emitters>"+
"<emitter class=\"org.apache.tika.emitter.fs.FileSystemEmitter\">"+
"<params>"+
+ "<param name=\"name\" type=\"string\">"+EMITTER_NAME+"</param>"+
+
"<param name=\"basePath\" type=\"string\">"+ TMP_OUTPUT_DIR.toAbsolutePath()+"</param>"+
"</params>"+
"</emitter>"+
@@ -261,8 +267,9 @@ public class TikaServerEmitterIntegrationTest extends IntegrationTestBase {
private String getJsonString(String fileName) {
JsonObject root = new JsonObject();
- root.add("fetcherString", new JsonPrimitive("fs:"+fileName));
- root.add("emitter", new JsonPrimitive("fs"));
+ root.add("fetcherName", new JsonPrimitive(FETCHER_NAME));
+ root.add("fetchKey", new JsonPrimitive(fileName));
+ root.add("emitter", new JsonPrimitive(EMITTER_NAME));
return GSON.toJson(root);
}
}
diff --git a/tika-server/tika-server-core/src/test/resources/test-documents/mock/hello_world.xml b/tika-server/tika-server-core/src/test/resources/test-documents/mock/hello_world.xml
index e1cb32b..27cd62a 100644
--- a/tika-server/tika-server-core/src/test/resources/test-documents/mock/hello_world.xml
+++ b/tika-server/tika-server-core/src/test/resources/test-documents/mock/hello_world.xml
@@ -21,5 +21,6 @@
<mock>
<metadata action="add" name="author">Nikolai Lobachevsky</metadata>
<metadata action="add" name="title">你好,世界</metadata>
+ <metadata action="add" name="my-key">parsers-value</metadata>
<write element="p">hello world</write>
</mock>
\ No newline at end of file