Skip to content

Commit 1d7d90d

Browse files
committed
Plugins on server info page.
1 parent 0b35de6 commit 1d7d90d

3 files changed

Lines changed: 43 additions & 17 deletions

File tree

engine/src/main/java/nl/inl/blacklab/plugins/PluginsOfType.java

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@
44
import java.util.ArrayList;
55
import java.util.Collection;
66
import java.util.HashMap;
7-
import java.util.HashSet;
87
import java.util.Iterator;
8+
import java.util.LinkedHashSet;
99
import java.util.List;
1010
import java.util.Map;
1111
import java.util.Optional;
1212
import java.util.ServiceConfigurationError;
1313
import java.util.ServiceLoader;
14+
import java.util.Set;
1415
import java.util.regex.Pattern;
1516

1617
import org.apache.commons.lang3.StringUtils;
@@ -34,12 +35,21 @@ public class PluginsOfType<T extends Plugin> {
3435
*/
3536
private static final Pattern PLUGIN_ID_PATTERN = Pattern.compile("[\\p{L}\\p{N}\\-._]+");
3637

38+
/** Plugin type we're managing. */
3739
private final Class<T> pluginClass;
3840

39-
/**
40-
* Plugins by their id
41+
/** Registered plugins of this type. */
42+
private final Set<PluginData<T>> plugins = new LinkedHashSet<>();
43+
44+
/** Mapping from ids to plugins.
45+
*
46+
* Note that multiple ids may point to the same plugin,
47+
* e.g. [fully qualified] class name, script name, value returned by plugin.getId().
48+
* Usually you will use the script name for Groovy plugins and the class name for Java plugins.
49+
* plugin.getId() should only be used if you want to support a different id as well, e.g.
50+
* in the case of QueryFunctionAbs we want to refer to it as just "abs".
4151
*/
42-
private final Map<String, PluginData<T>> pluginsById = new HashMap<>();
52+
private final Map<String, PluginData<T>> idToPlugin = new HashMap<>();
4353

4454
PluginsOfType(Class<T> pluginClass, BLConfigPlugins pluginConfig, URLClassLoader cl) {
4555
this.pluginClass = pluginClass;
@@ -96,8 +106,13 @@ void register(Plugin plugin, BLConfigPlugins configs, String alternateId) {
96106

97107
private void add(String id, PluginData<T> data) {
98108
if (BlackLab.isPluginAllowed(data.getPlugin())) {
99-
synchronized (pluginsById) {
100-
pluginsById.putIfAbsent(id.toLowerCase(), data);
109+
synchronized (this) {
110+
if (!idToPlugin.containsKey(id)) {
111+
idToPlugin.put(id.toLowerCase(), data);
112+
plugins.add(data);
113+
} else if (!idToPlugin.get(id).equals(data)){
114+
logger.warn("Plugin id collision, plugin '" + id + "' was already registered.");
115+
}
101116
}
102117
} else
103118
logger.warn("Skipping plugin '" + id + "'; it's not on the plugins.allowed list)");
@@ -107,16 +122,15 @@ public Collection<T> getAll() {
107122
PluginManager.loadAllGroovyScripts();
108123
List<T> result = new ArrayList<>();
109124
Collection<PluginData<T>> pluginDatas;
110-
synchronized (pluginsById) {
111-
pluginDatas = pluginsById.values();
125+
synchronized (this) {
126+
pluginDatas = new ArrayList<>(plugins);
112127
}
113128
for (PluginData<T> data: pluginDatas) {
114129
T plugin = data.getPlugin();
115130
if (pluginClass.isInstance(plugin)) {
116131
try {
117132
data.initializePlugin();
118-
if (!result.contains(plugin))
119-
result.add(pluginClass.cast(plugin));
133+
result.add(pluginClass.cast(plugin));
120134
} catch (PluginException e) {
121135
// exception already cached in plugindata, no need to throw.
122136
logger.error("Plugin {} failed to initialize: {}", plugin.getId(), e.getMessage());
@@ -150,14 +164,14 @@ public boolean exists(String id) {
150164

151165
public Optional<T> getIfExists(String id) throws PluginException {
152166
PluginData<T> pluginData;
153-
synchronized (pluginsById) {
154-
pluginData = pluginsById.get(id.toLowerCase());
167+
synchronized (this) {
168+
pluginData = idToPlugin.get(id.toLowerCase());
155169
}
156170
if (pluginData == null) {
157171
// Maybe this is a groovy script we haven't loaded yet.
158172
PluginManager.getUnloaded(id);
159-
synchronized (pluginsById) {
160-
pluginData = pluginsById.get(id.toLowerCase());
173+
synchronized (this) {
174+
pluginData = idToPlugin.get(id.toLowerCase());
161175
}
162176
}
163177
if (pluginData == null) {
@@ -174,8 +188,8 @@ public Optional<T> getIfExists(String id) throws PluginException {
174188
*/
175189
void initializePlugins() {
176190
Collection<PluginData<T>> pluginDatas;
177-
synchronized (pluginsById) {
178-
pluginDatas = new HashSet<>(pluginsById.values());
191+
synchronized (this) {
192+
pluginDatas = new ArrayList<>(plugins);
179193
}
180194
pluginDatas.forEach(pluginData -> {
181195
try {

wslib/src/main/java/nl/inl/blacklab/server/lib/results/ResponseStreamer.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1455,6 +1455,7 @@ public void serverInfo(ResultServerInfo result) {
14551455
}
14561456

14571457
userInfo(result.getUserInfo(), result.isDebugMode());
1458+
plugins(result.getPlugins());
14581459
}
14591460
ds.endMap();
14601461
}
@@ -1882,6 +1883,11 @@ public void formatInfoResponse(ResultInputFormat result) {
18821883

18831884
public void pluginsResponse(ResultListPlugins result) {
18841885
ds.startMap();
1886+
plugins(result);
1887+
ds.endMap();
1888+
}
1889+
1890+
public void plugins(ResultListPlugins result) {
18851891
ds.startEntry("plugins").startMap();
18861892
for (Map.Entry<String, List<ResultListPlugins.PluginInfo>> typeEntry : result.getPluginsByType().entrySet()) {
18871893
ds.startEntry(typeEntry.getKey()).startList();
@@ -1904,7 +1910,6 @@ public void pluginsResponse(ResultListPlugins result) {
19041910
ds.endList().endEntry();
19051911
}
19061912
ds.endMap().endEntry();
1907-
ds.endMap();
19081913
}
19091914

19101915
public void cacheInfo(SearchCache blackLabCache, boolean includeDebugInfo) {

wslib/src/main/java/nl/inl/blacklab/server/lib/results/ResultServerInfo.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ public class ResultServerInfo {
2323

2424
private final ResultUserInfo userInfo;
2525

26+
private final ResultListPlugins plugins;
27+
2628
private final List<ResultIndexStatus> indexStatuses;
2729

2830
public ResultServerInfo(RequestServerInfo request) {
@@ -32,6 +34,7 @@ public ResultServerInfo(RequestServerInfo request) {
3234
User user = request.user();
3335
IndexManager indexManager = request.indexManager();
3436
userInfo = new ResultUserInfo(user, indexManager);
37+
plugins = new ResultListPlugins();
3538
indexStatuses = new ArrayList<>();
3639
Collection<Index> indices = indexManager.getAllAvailableCorpora(user);
3740
for (Index index: indices) {
@@ -56,6 +59,10 @@ public ResultUserInfo getUserInfo() {
5659
return userInfo;
5760
}
5861

62+
public ResultListPlugins getPlugins() {
63+
return plugins;
64+
}
65+
5966
public List<ResultIndexStatus> getIndexStatuses() {
6067
return indexStatuses;
6168
}

0 commit comments

Comments
 (0)