4343import nl .inl .blacklab .indexers .config .process .ProcessingInstructionStrip ;
4444import nl .inl .blacklab .indexers .config .process .ProcessingInstructionUnique ;
4545import nl .inl .blacklab .search .BlackLab ;
46+ import nl .inl .blacklab .search .extensions .QueryExtensions ;
4647import nl .inl .blacklab .search .extensions .QueryFunctionAbs ;
4748import nl .inl .blacklab .search .extensions .QueryFunctionEnd ;
4849import nl .inl .blacklab .search .extensions .QueryFunctionFixedSpan ;
@@ -109,6 +110,12 @@ public class PluginManager {
109110
110111 private static final Set <Class <? extends Plugin >> safePluginClasses = new HashSet <>();
111112
113+ /** Groovy plugin script we've found but not loaded yet. We don't yet know its plugin type. */
114+ record UnloadedGroovyPlugin (File scriptFile , BLConfigPlugins pluginConfig ) {}
115+
116+ /** Groovy plugin scripts we've found but not loaded yet. We don't yet know their plugin type. */
117+ private static final Map <String , UnloadedGroovyPlugin > unloadedGroovyScripts = new LinkedHashMap <>();
118+
112119 static {
113120 addWebSafePlugins (List .of (
114121 // FileConverter
@@ -162,6 +169,7 @@ public class PluginManager {
162169 QueryFunctionSymbol .class ,
163170 QueryFunctionUnion .class
164171 ));
172+ QueryExtensions .registerAll (); // register e.g. rspan(), debug functions, etc.
165173 }
166174
167175 public static synchronized void addWebSafePlugins (List <Class <? extends Plugin >> pluginClasses ) {
@@ -173,17 +181,6 @@ public static synchronized <T extends Plugin> boolean isAllowed(Plugin plugin) {
173181 return safePluginClasses .contains (plugin .getClass ());
174182 }
175183
176- private static synchronized void ensureInitialized () {
177- if (!isInitialized )
178- initialize (BlackLab .config ().getPlugins (), BlackLab .configDir ());
179- }
180-
181- /** Groovy plugin script we've found but not loaded yet. We don't yet know its plugin type. */
182- record UnloadedGroovyPlugin (File scriptFile , BLConfigPlugins pluginConfig ) {}
183-
184- /** Groovy plugin scripts we've found but not loaded yet. We don't yet know their plugin type. */
185- private static final Map <String , UnloadedGroovyPlugin > unloadedGroovyScripts = new LinkedHashMap <>();
186-
187184 // Nothing to do; initialization happens when the blacklab config is loaded.
188185 // The blacklab Config is automatically loaded when the first BlackLabIndex is
189186 // opened, or earlier by a user library.
@@ -198,23 +195,23 @@ public static File getPluginsDir() {
198195 }
199196
200197 public static synchronized void addPluginType (Class <? extends Plugin > pluginType ) {
201- if (isInitialized )
202- throw new IllegalStateException ("Cannot add plugin type after initialization" );
203198 pluginTypes .add (pluginType );
199+ URLClassLoader cl = getPluginsDirClassLoader (PluginManager .class .getClassLoader ());
200+ pluginsByType .put (pluginType , new PluginsOfType <>(pluginType , BlackLab .config ().getPlugins (), cl ));
204201 }
205202
206203 /**
207204 * Attempts to load and initialize all plugin classes and scripts in the plugin
208205 * directory (and classes on the classpath), passing the values in the config
209206 * to the matching plugin.
210- *
211- * @param pluginConfig configurations per plugin id
212- * @param configDir directory where plugins and their configs can be found
213207 */
214- public static synchronized void initialize ( BLConfigPlugins pluginConfig , File configDir ) {
208+ public static synchronized void ensureInitialized ( ) {
215209 if (isInitialized )
216- throw new IllegalStateException ( "PluginManager already initialized" );
210+ return ; // only do this once
217211 isInitialized = true ;
212+
213+ BLConfigPlugins pluginConfig = BlackLab .config ().getPlugins ();
214+ File configDir = BlackLab .configDir ();
218215 PluginManager .pluginsDir = new File (configDir , PLUGINS_DIR_NAME );
219216
220217 logger .debug ("Initializing plugin system..." );
@@ -325,7 +322,7 @@ static synchronized <T extends Plugin> void getUnloaded(String scriptName) {
325322 }
326323 }
327324
328- private static void register (Plugin plugin , BLConfigPlugins pluginConfig , String scriptFileName , boolean registerClassName ) {
325+ private static synchronized void register (Plugin plugin , BLConfigPlugins pluginConfig , String scriptFileName , boolean registerClassName ) {
329326 ensureInitialized ();
330327 for (Class <? extends Plugin > pluginClass : pluginTypes ) {
331328 if (pluginClass .isInstance (plugin )) {
@@ -345,7 +342,7 @@ public static <T extends Plugin> PluginsOfType<T> type(Class<T> pluginType) {
345342 }
346343
347344 /** Get all registered plugin types. */
348- public static List <Class <? extends Plugin >> getPluginTypes () {
345+ public static synchronized List <Class <? extends Plugin >> getPluginTypes () {
349346 ensureInitialized ();
350347 return List .copyOf (pluginTypes );
351348 }
0 commit comments