This is an automated email from the ASF dual-hosted git repository.

ndipiazza pushed a commit to branch pf4j-development-mode
in repository https://gitbox.apache.org/repos/asf/tika.git

commit ce7de1d90b423d1d4a4495fa1b9b30de40a1cbca
Author: Nicholas DiPiazza <[email protected]>
AuthorDate: Sun Dec 21 18:34:41 2025 -0600

    TIKA-4587: Add pf4j development mode support to TikaPluginManager
    
    Enables plugin development without packaging as ZIP files by supporting
    pf4j's DEVELOPMENT runtime mode. This allows developers to point
    plugin-roots directly at unpackaged plugin directories (e.g., 
target/classes)
    for faster iteration during development.
    
    Features:
    - Configure via system property: -Dtika.plugin.dev.mode=true
    - Configure via environment variable: TIKA_PLUGIN_DEV_MODE=true
    - Skips ZIP extraction when in development mode
    - Logs mode on startup for visibility
    - Defaults to DEPLOYMENT mode for backward compatibility
    
    This aligns with pf4j best practices documented at:
    https://pf4j.org/doc/development-mode.html
    
    JIRA: https://issues.apache.org/jira/browse/TIKA-4587
---
 .../org/apache/tika/plugins/TikaPluginManager.java | 33 ++++++++++++-
 .../apache/tika/plugins/TikaPluginManagerTest.java | 57 ++++++++++++++++++++++
 2 files changed, 88 insertions(+), 2 deletions(-)

diff --git 
a/tika-plugins-core/src/main/java/org/apache/tika/plugins/TikaPluginManager.java
 
b/tika-plugins-core/src/main/java/org/apache/tika/plugins/TikaPluginManager.java
index cd6296755..0cd635660 100644
--- 
a/tika-plugins-core/src/main/java/org/apache/tika/plugins/TikaPluginManager.java
+++ 
b/tika-plugins-core/src/main/java/org/apache/tika/plugins/TikaPluginManager.java
@@ -29,6 +29,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
 import org.pf4j.DefaultExtensionFinder;
 import org.pf4j.DefaultPluginManager;
 import org.pf4j.ExtensionFinder;
+import org.pf4j.RuntimeMode;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -44,6 +45,9 @@ import org.apache.tika.exception.TikaConfigException;
 public class TikaPluginManager extends DefaultPluginManager {
 
     private static final Logger LOG = 
LoggerFactory.getLogger(TikaPluginManager.class);
+    
+    private static final String DEV_MODE_PROPERTY = "tika.plugin.dev.mode";
+    private static final String DEV_MODE_ENV = "TIKA_PLUGIN_DEV_MODE";
 
     //we're only using this to convert a single path or a list of paths to a 
list
     //we don't need all the functionality of the polymorphic objectmapper in 
tika-serialization
@@ -142,8 +146,29 @@ public class TikaPluginManager extends 
DefaultPluginManager {
 
     public TikaPluginManager(List<Path> pluginRoots) throws IOException {
         super(pluginRoots);
+        configureRuntimeMode();
         init();
     }
+    
+    private void configureRuntimeMode() {
+        RuntimeMode mode = isDevelopmentMode() ? RuntimeMode.DEVELOPMENT : 
RuntimeMode.DEPLOYMENT;
+        this.runtimeMode = mode;
+        if (mode == RuntimeMode.DEVELOPMENT) {
+            LOG.info("TikaPluginManager running in DEVELOPMENT mode");
+        }
+    }
+    
+    private static boolean isDevelopmentMode() {
+        String sysProp = System.getProperty(DEV_MODE_PROPERTY);
+        if (sysProp != null) {
+            return Boolean.parseBoolean(sysProp);
+        }
+        String envVar = System.getenv(DEV_MODE_ENV);
+        if (envVar != null) {
+            return Boolean.parseBoolean(envVar);
+        }
+        return false;
+    }
 
     /**
      * Override to disable classpath scanning for extensions.
@@ -163,8 +188,12 @@ public class TikaPluginManager extends 
DefaultPluginManager {
     }
 
     private void init() throws IOException {
-        for (Path root : pluginsRoots) {
-            unzip(root);
+        if (getRuntimeMode() == RuntimeMode.DEPLOYMENT) {
+            for (Path root : pluginsRoots) {
+                unzip(root);
+            }
+        } else {
+            LOG.debug("Skipping ZIP extraction in DEVELOPMENT mode");
         }
     }
 
diff --git 
a/tika-plugins-core/src/test/java/org/apache/tika/plugins/TikaPluginManagerTest.java
 
b/tika-plugins-core/src/test/java/org/apache/tika/plugins/TikaPluginManagerTest.java
new file mode 100644
index 000000000..ca492d055
--- /dev/null
+++ 
b/tika-plugins-core/src/test/java/org/apache/tika/plugins/TikaPluginManagerTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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.plugins;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.nio.file.Path;
+import java.util.Collections;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+import org.pf4j.RuntimeMode;
+
+public class TikaPluginManagerTest {
+
+    @Test
+    public void testDefaultRuntimeModeIsDeployment(@TempDir Path tmpDir) 
throws Exception {
+        TikaPluginManager manager = new 
TikaPluginManager(Collections.singletonList(tmpDir));
+        assertEquals(RuntimeMode.DEPLOYMENT, manager.getRuntimeMode());
+    }
+
+    @Test
+    public void testDevelopmentModeViaSystemProperty(@TempDir Path tmpDir) 
throws Exception {
+        System.setProperty("tika.plugin.dev.mode", "true");
+        try {
+            TikaPluginManager manager = new 
TikaPluginManager(Collections.singletonList(tmpDir));
+            assertEquals(RuntimeMode.DEVELOPMENT, manager.getRuntimeMode());
+        } finally {
+            System.clearProperty("tika.plugin.dev.mode");
+        }
+    }
+
+    @Test
+    public void testDeploymentModeWhenPropertyIsFalse(@TempDir Path tmpDir) 
throws Exception {
+        System.setProperty("tika.plugin.dev.mode", "false");
+        try {
+            TikaPluginManager manager = new 
TikaPluginManager(Collections.singletonList(tmpDir));
+            assertEquals(RuntimeMode.DEPLOYMENT, manager.getRuntimeMode());
+        } finally {
+            System.clearProperty("tika.plugin.dev.mode");
+        }
+    }
+}

Reply via email to