Skip to content

Commit b4b995f

Browse files
author
Nicholas DiPiazza
committed
TIKA-4583: Refactor ConfigStore to use PF4J plugin system
- ConfigStore now extends TikaExtension interface - ConfigStoreFactory converted to PF4J-based factory interface - Created IgniteConfigStoreFactory with @extension annotation - IgniteConfigStore now loaded via plugin discovery - Updated InMemoryConfigStore and LoggingConfigStore with getExtensionConfig() - TikaGrpcServerImpl now uses plugin manager to load ConfigStore Benefits: - Proper plugin architecture following Tika patterns - ConfigStore implementations auto-discovered via PF4J - No hard-coded class names or reflection needed - Consistent with Fetcher/Emitter factory pattern
1 parent a8c0700 commit b4b995f

File tree

7 files changed

+143
-30
lines changed

7 files changed

+143
-30
lines changed

tika-grpc/src/main/java/org/apache/tika/pipes/grpc/TikaGrpcServerImpl.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,12 @@ class TikaGrpcServerImpl extends TikaGrpc.TikaImplBase {
109109
pluginManager = new org.pf4j.DefaultPluginManager();
110110
}
111111

112-
// Create ConfigStore based on PipesConfig setting
112+
// Create ConfigStore based on PipesConfig setting using plugin system
113113
org.apache.tika.pipes.core.config.ConfigStore configStore =
114114
org.apache.tika.pipes.core.config.ConfigStoreFactory.createConfigStore(
115-
pipesConfig.getConfigStoreType());
115+
pluginManager,
116+
pipesConfig.getConfigStoreType(),
117+
null);
116118

117119
fetcherManager = FetcherManager.load(pluginManager, tikaJsonConfig, true, configStore);
118120
}

tika-pipes/tika-ignite-config-store/src/main/java/org/apache/tika/pipes/ignite/IgniteConfigStore.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ public class IgniteConfigStore implements ConfigStore {
5656
private CacheMode cacheMode = CacheMode.REPLICATED;
5757
private String igniteInstanceName = DEFAULT_INSTANCE_NAME;
5858
private boolean autoClose = true;
59+
private ExtensionConfig extensionConfig;
5960

6061
/**
6162
* Default constructor.
@@ -64,6 +65,17 @@ public class IgniteConfigStore implements ConfigStore {
6465
public IgniteConfigStore() {
6566
}
6667

68+
/**
69+
* Constructor with ExtensionConfig (used by factory).
70+
*
71+
* @param extensionConfig the extension configuration
72+
*/
73+
public IgniteConfigStore(ExtensionConfig extensionConfig) {
74+
this.extensionConfig = extensionConfig;
75+
// TODO: Parse configuration from extensionConfig.json() if needed
76+
// For now, using defaults
77+
}
78+
6779
/**
6880
* Constructor with custom cache name.
6981
*
@@ -73,6 +85,11 @@ public IgniteConfigStore(String cacheName) {
7385
this.cacheName = cacheName;
7486
}
7587

88+
@Override
89+
public ExtensionConfig getExtensionConfig() {
90+
return extensionConfig;
91+
}
92+
7693
@Override
7794
public void init() throws Exception {
7895
if (ignite != null) {
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.tika.pipes.ignite;
18+
19+
import java.io.IOException;
20+
21+
import org.pf4j.Extension;
22+
23+
import org.apache.tika.exception.TikaConfigException;
24+
import org.apache.tika.pipes.core.config.ConfigStore;
25+
import org.apache.tika.pipes.core.config.ConfigStoreFactory;
26+
import org.apache.tika.plugins.ExtensionConfig;
27+
28+
/**
29+
* Factory for creating Ignite-based ConfigStore instances.
30+
*/
31+
@Extension
32+
public class IgniteConfigStoreFactory implements ConfigStoreFactory {
33+
34+
private static final String NAME = "ignite";
35+
36+
@Override
37+
public String getName() {
38+
return NAME;
39+
}
40+
41+
@Override
42+
public ConfigStore buildExtension(ExtensionConfig extensionConfig)
43+
throws IOException, TikaConfigException {
44+
return new IgniteConfigStore(extensionConfig);
45+
}
46+
}

tika-pipes/tika-pipes-core/src/main/java/org/apache/tika/pipes/core/config/ConfigStore.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.util.Set;
2020

2121
import org.apache.tika.plugins.ExtensionConfig;
22+
import org.apache.tika.plugins.TikaExtension;
2223

2324
/**
2425
* Interface for storing and retrieving component configurations.
@@ -32,7 +33,7 @@
3233
* <b>Performance considerations:</b> The {@link #keySet()} method should be an inexpensive operation
3334
* as it may be called in error message generation and other scenarios where performance matters.
3435
*/
35-
public interface ConfigStore {
36+
public interface ConfigStore extends TikaExtension {
3637

3738
/**
3839
* Initializes the configuration store.

tika-pipes/tika-pipes-core/src/main/java/org/apache/tika/pipes/core/config/ConfigStoreFactory.java

Lines changed: 58 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -16,56 +16,87 @@
1616
*/
1717
package org.apache.tika.pipes.core.config;
1818

19+
import java.io.IOException;
20+
import java.util.HashMap;
21+
import java.util.List;
22+
import java.util.Map;
23+
24+
import org.pf4j.PluginManager;
1925
import org.slf4j.Logger;
2026
import org.slf4j.LoggerFactory;
2127

28+
import org.apache.tika.exception.TikaConfigException;
29+
import org.apache.tika.plugins.ExtensionConfig;
30+
import org.apache.tika.plugins.TikaExtensionFactory;
31+
2232
/**
23-
* Factory for creating ConfigStore instances based on configuration.
33+
* Factory interface for creating ConfigStore instances.
34+
* Implementations should be annotated with @Extension to be discovered by PF4J.
2435
*/
25-
public class ConfigStoreFactory {
26-
27-
private static final Logger LOG = LoggerFactory.getLogger(ConfigStoreFactory.class);
36+
public interface ConfigStoreFactory extends TikaExtensionFactory<ConfigStore> {
2837

38+
Logger LOG = LoggerFactory.getLogger(ConfigStoreFactory.class);
39+
2940
/**
30-
* Creates a ConfigStore instance based on the specified type.
41+
* Creates a ConfigStore instance based on configuration.
3142
*
32-
* @param type the type of ConfigStore to create ("memory", "ignite", or a fully qualified class name)
43+
* @param pluginManager the plugin manager
44+
* @param configStoreType the type of ConfigStore to create
45+
* @param extensionConfig optional configuration for the store
3346
* @return a ConfigStore instance
34-
* @throws RuntimeException if the store type is invalid or cannot be instantiated
47+
* @throws TikaConfigException if the store cannot be created
3548
*/
36-
public static ConfigStore createConfigStore(String type) {
37-
if (type == null || type.isEmpty() || "memory".equalsIgnoreCase(type)) {
49+
static ConfigStore createConfigStore(PluginManager pluginManager, String configStoreType,
50+
ExtensionConfig extensionConfig)
51+
throws TikaConfigException {
52+
if (configStoreType == null || configStoreType.isEmpty() || "memory".equalsIgnoreCase(configStoreType)) {
3853
LOG.info("Creating InMemoryConfigStore");
39-
return new InMemoryConfigStore();
54+
InMemoryConfigStore store = new InMemoryConfigStore();
55+
if (extensionConfig != null) {
56+
store.setExtensionConfig(extensionConfig);
57+
}
58+
return store;
59+
}
60+
61+
// Load all ConfigStoreFactory extensions
62+
List<ConfigStoreFactory> factories = pluginManager.getExtensions(ConfigStoreFactory.class);
63+
Map<String, ConfigStoreFactory> factoryMap = new HashMap<>();
64+
for (ConfigStoreFactory factory : factories) {
65+
factoryMap.put(factory.getName(), factory);
4066
}
4167

42-
if ("ignite".equalsIgnoreCase(type)) {
68+
// Try to find factory by name
69+
ConfigStoreFactory factory = factoryMap.get(configStoreType);
70+
if (factory != null) {
71+
LOG.info("Creating ConfigStore using factory: {}", factory.getName());
4372
try {
44-
LOG.info("Creating IgniteConfigStore");
45-
Class<?> igniteClass = Class.forName("org.apache.tika.pipes.ignite.IgniteConfigStore");
46-
return (ConfigStore) igniteClass.getDeclaredConstructor().newInstance();
47-
} catch (ClassNotFoundException e) {
48-
throw new RuntimeException(
49-
"IgniteConfigStore not found. Add tika-ignite-config-store dependency to use Ignite store.", e);
50-
} catch (Exception e) {
51-
throw new RuntimeException("Failed to instantiate IgniteConfigStore", e);
73+
ExtensionConfig config = extensionConfig != null ? extensionConfig :
74+
new ExtensionConfig(configStoreType, configStoreType, "{}");
75+
return factory.buildExtension(config);
76+
} catch (IOException e) {
77+
throw new TikaConfigException("Failed to create ConfigStore: " + configStoreType, e);
5278
}
5379
}
5480

5581
// Try to load as a fully qualified class name
5682
try {
57-
LOG.info("Creating ConfigStore from class: {}", type);
58-
Class<?> storeClass = Class.forName(type);
83+
LOG.info("Creating ConfigStore from class: {}", configStoreType);
84+
Class<?> storeClass = Class.forName(configStoreType);
5985
if (!ConfigStore.class.isAssignableFrom(storeClass)) {
60-
throw new RuntimeException(
61-
"Class " + type + " does not implement ConfigStore interface");
86+
throw new TikaConfigException(
87+
"Class " + configStoreType + " does not implement ConfigStore interface");
88+
}
89+
ConfigStore store = (ConfigStore) storeClass.getDeclaredConstructor().newInstance();
90+
if (extensionConfig != null) {
91+
((InMemoryConfigStore) store).setExtensionConfig(extensionConfig);
6292
}
63-
return (ConfigStore) storeClass.getDeclaredConstructor().newInstance();
93+
return store;
6494
} catch (ClassNotFoundException e) {
65-
throw new RuntimeException(
66-
"Unknown ConfigStore type: " + type + ". Use 'memory', 'ignite', or a fully qualified class name.", e);
95+
throw new TikaConfigException(
96+
"Unknown ConfigStore type: " + configStoreType +
97+
". Available types: memory, " + String.join(", ", factoryMap.keySet()), e);
6798
} catch (Exception e) {
68-
throw new RuntimeException("Failed to instantiate ConfigStore: " + type, e);
99+
throw new TikaConfigException("Failed to instantiate ConfigStore: " + configStoreType, e);
69100
}
70101
}
71102
}

tika-pipes/tika-pipes-core/src/main/java/org/apache/tika/pipes/core/config/InMemoryConfigStore.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,16 @@
2828
public class InMemoryConfigStore implements ConfigStore {
2929

3030
private final ConcurrentHashMap<String, ExtensionConfig> store = new ConcurrentHashMap<>();
31+
private ExtensionConfig extensionConfig;
32+
33+
@Override
34+
public ExtensionConfig getExtensionConfig() {
35+
return extensionConfig;
36+
}
37+
38+
public void setExtensionConfig(ExtensionConfig extensionConfig) {
39+
this.extensionConfig = extensionConfig;
40+
}
3141

3242
@Override
3343
public void put(String id, ExtensionConfig config) {

tika-pipes/tika-pipes-core/src/test/java/org/apache/tika/pipes/core/config/LoggingConfigStore.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ public class LoggingConfigStore implements ConfigStore {
3535

3636
private static final Logger LOG = LoggerFactory.getLogger(LoggingConfigStore.class);
3737
private final Map<String, ExtensionConfig> store = new HashMap<>();
38+
private ExtensionConfig extensionConfig;
39+
40+
@Override
41+
public ExtensionConfig getExtensionConfig() {
42+
return extensionConfig;
43+
}
3844

3945
@Override
4046
public void put(String id, ExtensionConfig config) {

0 commit comments

Comments
 (0)