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

tallison pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tika.git


The following commit(s) were added to refs/heads/main by this push:
     new d8ee89b143 TIKA-4647 - use an argfile to launch PipesServer (#2579)
d8ee89b143 is described below

commit d8ee89b143e0d7277cf2fa50cd1d26ed54871a5d
Author: Tim Allison <[email protected]>
AuthorDate: Tue Feb 3 08:00:25 2026 -0500

    TIKA-4647 - use an argfile to launch PipesServer (#2579)
    
    * TIKA-4647 - use an argfile to launch PipesServer
---
 .../org/apache/tika/pipes/core/PipesClient.java    | 36 ++++++++++++++++++++--
 1 file changed, 33 insertions(+), 3 deletions(-)

diff --git 
a/tika-pipes/tika-pipes-core/src/main/java/org/apache/tika/pipes/core/PipesClient.java
 
b/tika-pipes/tika-pipes-core/src/main/java/org/apache/tika/pipes/core/PipesClient.java
index 5c175208ab..82e37cb31d 100644
--- 
a/tika-pipes/tika-pipes-core/src/main/java/org/apache/tika/pipes/core/PipesClient.java
+++ 
b/tika-pipes/tika-pipes-core/src/main/java/org/apache/tika/pipes/core/PipesClient.java
@@ -533,7 +533,7 @@ public class PipesClient implements Closeable {
         }
     }
 
-    private String[] getCommandline(int port, Path tmpDir) {
+    private String[] getCommandline(int port, Path tmpDir) throws IOException {
         List<String> configArgs = pipesConfig.getForkedJvmArgs();
         boolean hasClassPath = false;
         boolean hasHeadless = false;
@@ -568,10 +568,14 @@ public class PipesClient implements Closeable {
         List<String> commandLine = new ArrayList<>();
         String javaPath = pipesConfig.getJavaPath();
         commandLine.add(ProcessUtils.escapeCommandLine(javaPath));
+
+        // Use @argfile to avoid Windows command line length limits (~8191 
chars)
+        // when the classpath is very long (e.g., with Ignite3 dependencies)
         if (!hasClassPath) {
-            commandLine.add("-cp");
-            commandLine.add(System.getProperty("java.class.path"));
+            Path argFile = writeArgFile(tmpDir);
+            commandLine.add("@" + argFile.toAbsolutePath());
         }
+
         if (!hasHeadless) {
             commandLine.add("-Djava.awt.headless=true");
         }
@@ -593,6 +597,32 @@ public class PipesClient implements Closeable {
         return commandLine.toArray(new String[0]);
     }
 
+    /**
+     * Writes an argfile containing the classpath for the forked JVM process.
+     * This avoids Windows command line length limits (~8191 chars) which can
+     * be exceeded when using dependencies with many transitive jars (e.g., 
Ignite3).
+     * <p>
+     * Security: The argfile is created in a temp directory with owner-only 
permissions (700).
+     * This is more secure than the alternative of passing the classpath on 
the command line,
+     * which would be visible to all users via 'ps' or /proc.
+     *
+     * @param tmpDir the temporary directory where the argfile will be created
+     * @return the path to the created argfile
+     * @throws IOException if the argfile cannot be written
+     */
+    private Path writeArgFile(Path tmpDir) throws IOException {
+        Path argFile = tmpDir.resolve("jvm-args.txt");
+        String classpath = System.getProperty("java.class.path");
+        //convert to forward for Windows compatibility
+        String normalizedClasspath = classpath.replace("\\", "/");
+        // Argfile format: each argument on its own line, with proper quoting 
for paths with spaces
+        String content = "-cp\n\"" + normalizedClasspath + "\"\n";
+        Files.writeString(argFile, content, StandardCharsets.UTF_8);
+        LOG.debug("pipesClientId={}: wrote argfile with classpath ({} chars) 
to {}",
+                pipesClientId, classpath.length(), argFile);
+        return argFile;
+    }
+
     private record ServerTuple(Process process, ServerSocket serverSocket, 
Socket socket,
                                DataInputStream input, DataOutputStream output, 
Path tmpDir) {
 

Reply via email to