Fix: Verwende JAXP Transformer API statt Transform.main() oder SecurityManager
Problem: - SecurityManager ist in Java 17+ deprecated und funktioniert nicht mehr - Transform.main() ruft System.exit() auf und killt Worker - s9api nicht im Classpath verfügbar Lösung: JAXP Transformer API (javax.xml.transform) - Standard Java API, immer verfügbar - Von Saxon implementiert (registriert sich als TransformerFactory) - Ruft NIE System.exit() auf - Wirft TransformerException bei Fehlern - ErrorListener für saubere Fehlererfassung - TransformerFactory einmalig erstellt, wiederverwendet (Performance!) Dies ist die korrekte, robuste Lösung für dieses Problem. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
+65
-81
@@ -17,33 +17,20 @@ logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
# Java-Worker-Code (wird zur Laufzeit kompiliert)
|
# Java-Worker-Code (wird zur Laufzeit kompiliert)
|
||||||
SAXON_WORKER_JAVA = """
|
SAXON_WORKER_JAVA = """
|
||||||
import net.sf.saxon.Transform;
|
import javax.xml.transform.*;
|
||||||
|
import javax.xml.transform.stream.*;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public class SaxonWorker {
|
public class SaxonWorker {
|
||||||
// Custom SecurityManager to block System.exit()
|
|
||||||
static class NoExitSecurityManager extends SecurityManager {
|
|
||||||
@Override
|
|
||||||
public void checkPermission(java.security.Permission perm) {
|
|
||||||
// Allow everything
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void checkExit(int status) {
|
|
||||||
// Block System.exit() by throwing an exception
|
|
||||||
throw new SecurityException("System.exit() blocked by SaxonWorker");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
// Install SecurityManager to prevent System.exit()
|
|
||||||
System.setSecurityManager(new NoExitSecurityManager());
|
|
||||||
|
|
||||||
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
|
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
|
||||||
String line;
|
String line;
|
||||||
|
|
||||||
System.err.println("SaxonWorker started and ready (System.exit blocked)");
|
// Create TransformerFactory once and reuse
|
||||||
|
TransformerFactory factory = TransformerFactory.newInstance();
|
||||||
|
|
||||||
|
System.err.println("SaxonWorker started and ready (using JAXP Transformer API)");
|
||||||
System.err.flush();
|
System.err.flush();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -75,84 +62,81 @@ public class SaxonWorker {
|
|||||||
String xslStylesheet = parts[1];
|
String xslStylesheet = parts[1];
|
||||||
String outputFo = parts[2];
|
String outputFo = parts[2];
|
||||||
|
|
||||||
System.err.println("DEBUG: Building Saxon args...");
|
System.err.println("DEBUG: Creating transformer from stylesheet...");
|
||||||
System.err.flush();
|
System.err.flush();
|
||||||
|
|
||||||
// Build Saxon arguments
|
// Create Source and Result objects
|
||||||
List<String> saxonArgs = new ArrayList<>();
|
StreamSource xslSource = new StreamSource(new File(xslStylesheet));
|
||||||
saxonArgs.add("-s:" + sourceXml);
|
StreamSource xmlSource = new StreamSource(new File(sourceXml));
|
||||||
saxonArgs.add("-xsl:" + xslStylesheet);
|
StreamResult result = new StreamResult(new File(outputFo));
|
||||||
saxonArgs.add("-o:" + outputFo);
|
|
||||||
|
|
||||||
// Add parameters if present
|
System.err.println("DEBUG: Compiling stylesheet...");
|
||||||
|
System.err.flush();
|
||||||
|
|
||||||
|
// Create transformer from stylesheet
|
||||||
|
Transformer transformer = factory.newTransformer(xslSource);
|
||||||
|
|
||||||
|
// Set parameters if present
|
||||||
if (parts.length > 3 && !parts[3].isEmpty()) {
|
if (parts.length > 3 && !parts[3].isEmpty()) {
|
||||||
String[] params = parts[3].split("\\\\|\\\\|\\\\|");
|
String[] params = parts[3].split("\\\\|\\\\|\\\\|");
|
||||||
for (String param : params) {
|
for (String param : params) {
|
||||||
if (!param.isEmpty()) {
|
if (!param.isEmpty() && param.contains("=")) {
|
||||||
saxonArgs.add(param);
|
String[] kv = param.split("=", 2);
|
||||||
|
transformer.setParameter(kv[0], kv[1]);
|
||||||
|
System.err.println("DEBUG: Set parameter: " + kv[0] + " = " + kv[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
System.err.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
System.err.println("DEBUG: Running Saxon transformation...");
|
System.err.println("DEBUG: Running transformation...");
|
||||||
System.err.flush();
|
System.err.flush();
|
||||||
|
|
||||||
// Redirect Saxon output to stderr to avoid polluting stdout
|
// Capture errors via ErrorListener
|
||||||
PrintStream oldOut = System.out;
|
final StringBuilder errors = new StringBuilder();
|
||||||
PrintStream oldErr = System.err;
|
transformer.setErrorListener(new ErrorListener() {
|
||||||
ByteArrayOutputStream saxonOut = new ByteArrayOutputStream();
|
@Override
|
||||||
ByteArrayOutputStream saxonErr = new ByteArrayOutputStream();
|
public void warning(TransformerException e) {
|
||||||
|
errors.append("WARNING: ").append(e.getMessage()).append("\\n");
|
||||||
try {
|
|
||||||
System.setOut(new PrintStream(saxonOut));
|
|
||||||
System.setErr(new PrintStream(saxonErr));
|
|
||||||
|
|
||||||
// Run Saxon transformation
|
|
||||||
// If Saxon calls System.exit(), our SecurityManager will throw SecurityException
|
|
||||||
Transform.main(saxonArgs.toArray(new String[0]));
|
|
||||||
|
|
||||||
// Restore streams
|
|
||||||
System.setOut(oldOut);
|
|
||||||
System.setErr(oldErr);
|
|
||||||
|
|
||||||
oldErr.println("DEBUG: Saxon transformation completed");
|
|
||||||
oldErr.flush();
|
|
||||||
|
|
||||||
// Send success response
|
|
||||||
System.out.println("OK");
|
|
||||||
System.out.flush();
|
|
||||||
|
|
||||||
} catch (SecurityException e) {
|
|
||||||
// System.exit() was called by Saxon - treat as error
|
|
||||||
System.setOut(oldOut);
|
|
||||||
System.setErr(oldErr);
|
|
||||||
|
|
||||||
oldErr.println("DEBUG: Saxon tried to call System.exit() (blocked)");
|
|
||||||
oldErr.flush();
|
|
||||||
|
|
||||||
// Check Saxon's output for error details
|
|
||||||
String saxonOutput = saxonErr.toString();
|
|
||||||
String errorMsg = "Transformation failed";
|
|
||||||
if (!saxonOutput.isEmpty()) {
|
|
||||||
errorMsg = saxonOutput.trim();
|
|
||||||
// Limit error message length
|
|
||||||
if (errorMsg.length() > 200) {
|
|
||||||
errorMsg = errorMsg.substring(0, 200) + "...";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
System.out.println("ERROR: " + errorMsg);
|
@Override
|
||||||
System.out.flush();
|
public void error(TransformerException e) {
|
||||||
|
errors.append("ERROR: ").append(e.getMessage()).append("\\n");
|
||||||
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
@Override
|
||||||
System.setOut(oldOut);
|
public void fatalError(TransformerException e) throws TransformerException {
|
||||||
System.setErr(oldErr);
|
errors.append("FATAL: ").append(e.getMessage()).append("\\n");
|
||||||
oldErr.println("DEBUG: Saxon exception: " + e.getClass().getName());
|
throw e;
|
||||||
oldErr.flush();
|
}
|
||||||
e.printStackTrace(oldErr);
|
});
|
||||||
System.out.println("ERROR: " + (e.getMessage() != null ? e.getMessage() : e.getClass().getName()));
|
|
||||||
System.out.flush();
|
// Run transformation
|
||||||
|
transformer.transform(xmlSource, result);
|
||||||
|
|
||||||
|
System.err.println("DEBUG: Transformation completed");
|
||||||
|
System.err.flush();
|
||||||
|
|
||||||
|
// Check for errors
|
||||||
|
if (errors.length() > 0) {
|
||||||
|
System.out.println("ERROR: " + errors.toString().trim());
|
||||||
|
} else {
|
||||||
|
System.out.println("OK");
|
||||||
}
|
}
|
||||||
|
System.out.flush();
|
||||||
|
|
||||||
|
} catch (TransformerException e) {
|
||||||
|
System.err.println("DEBUG: Transformer exception: " + e.getClass().getName());
|
||||||
|
System.err.flush();
|
||||||
|
e.printStackTrace(System.err);
|
||||||
|
|
||||||
|
String errorMsg = e.getMessage();
|
||||||
|
if (errorMsg == null || errorMsg.isEmpty()) {
|
||||||
|
errorMsg = e.getClass().getSimpleName();
|
||||||
|
}
|
||||||
|
System.out.println("ERROR: " + errorMsg);
|
||||||
|
System.out.flush();
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
System.err.println("DEBUG: Job processing exception: " + e.getClass().getName());
|
System.err.println("DEBUG: Job processing exception: " + e.getClass().getName());
|
||||||
|
|||||||
Reference in New Issue
Block a user