From 3a79e6a87f5853fd5a7b2932182529af708fcd63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Prante?= Date: Tue, 17 Jan 2023 19:17:43 +0100 Subject: [PATCH] add close() method to Ghostscript --- gradle.properties | 2 +- .../graphics/ghostscript/FontAnalyzer.java | 4 +- .../graphics/ghostscript/Ghostscript.java | 79 +++++++---- .../graphics/ghostscript/PDFConverter.java | 132 +++++++++--------- .../graphics/ghostscript/PDFRasterizer.java | 45 +++--- .../test}/GhostScriptLibraryTester.java | 2 +- .../test/GhostscriptLibraryTest.java | 1 - .../ghostscript/test/GhostscriptTest.java | 15 +- 8 files changed, 166 insertions(+), 114 deletions(-) rename graphics-ghostscript/src/{main/java/org/xbib/graphics/ghostscript => test/java/org/xbib/graphics/ghostscript/test}/GhostScriptLibraryTester.java (99%) diff --git a/gradle.properties b/gradle.properties index f972855..55b8d93 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ group = org.xbib.graphics name = graphics -version = 4.3.2 +version = 4.3.3 org.gradle.warning.mode = ALL diff --git a/graphics-ghostscript/src/main/java/org/xbib/graphics/ghostscript/FontAnalyzer.java b/graphics-ghostscript/src/main/java/org/xbib/graphics/ghostscript/FontAnalyzer.java index 0bcdb2c..b7f5ee0 100644 --- a/graphics-ghostscript/src/main/java/org/xbib/graphics/ghostscript/FontAnalyzer.java +++ b/graphics-ghostscript/src/main/java/org/xbib/graphics/ghostscript/FontAnalyzer.java @@ -23,9 +23,9 @@ public class FontAnalyzer { "-sFile=" + path.toAbsolutePath(), "-sOutputFile=%stdout", "-f", "-"}; + Ghostscript gs = Ghostscript.getInstance(); try (InputStream is = this.getClass().getClassLoader().getResourceAsStream("script/AnalyzePDFFonts.ps"); ByteArrayOutputStream baos = new ByteArrayOutputStream()) { - Ghostscript gs = Ghostscript.getInstance(); gs.setStdIn(is); gs.setStdOut(baos); gs.run(gsArgs); @@ -56,6 +56,8 @@ public class FontAnalyzer { } } return result; + } finally { + gs.close(); } } } diff --git a/graphics-ghostscript/src/main/java/org/xbib/graphics/ghostscript/Ghostscript.java b/graphics-ghostscript/src/main/java/org/xbib/graphics/ghostscript/Ghostscript.java index 86c6bec..ef07044 100644 --- a/graphics-ghostscript/src/main/java/org/xbib/graphics/ghostscript/Ghostscript.java +++ b/graphics-ghostscript/src/main/java/org/xbib/graphics/ghostscript/Ghostscript.java @@ -31,32 +31,24 @@ public class Ghostscript { private static Ghostscript INSTANCE; - private static InputStream stdIn; + private InputStream stdIn; - private static OutputStream stdOut; + private OutputStream stdOut; - private static OutputStream stdErr; + private OutputStream stdErr; - static { - try { - prepareTmp(); - INSTANCE = new Ghostscript(); - stdOut = new LoggingOutputStream(logger); - stdErr = new LoggingOutputStream(logger); - INSTANCE.setStdOut(stdOut); - INSTANCE.setStdErr(stdErr); - } catch (Exception e) { - logger.log(Level.SEVERE, e.getMessage(), e); + private GhostscriptLibrary libraryInstance; + + private Ghostscript(GhostscriptLibrary libraryInstance) { + this.libraryInstance = libraryInstance; + this.stdOut = new LoggingOutputStream(logger); + this.stdErr = new LoggingOutputStream(logger); + } + + public synchronized static Ghostscript getInstance() { + if (INSTANCE == null) { + INSTANCE = createInstance(); } - } - - private final GhostscriptLibrary libraryInstance; - - private Ghostscript() { - libraryInstance = GhostscriptLibraryLoader.loadLibrary(); - } - - public static Ghostscript getInstance() { return INSTANCE; } @@ -65,7 +57,7 @@ public class Ghostscript { * * @return the Ghostscript revision data. */ - public static GhostscriptRevision getRevision() { + public synchronized static GhostscriptRevision getRevision() { GhostscriptLibrary.gsapi_revision_s revision = new GhostscriptLibrary.gsapi_revision_s(); INSTANCE.libraryInstance.gsapi_revision(revision, revision.size()); GhostscriptRevision result = new GhostscriptRevision(); @@ -83,7 +75,7 @@ public class Ghostscript { * * @return The OutputStream or null */ - public synchronized OutputStream getStdErr() { + public OutputStream getStdErr() { return stdErr; } @@ -92,7 +84,7 @@ public class Ghostscript { * * @param outputStream OutputStream object */ - public synchronized void setStdErr(OutputStream outputStream) { + public void setStdErr(OutputStream outputStream) { stdErr = outputStream; } @@ -101,7 +93,7 @@ public class Ghostscript { * * @return The OutputStream or null */ - public synchronized OutputStream getStdOut() { + public OutputStream getStdOut() { return stdOut; } @@ -110,7 +102,7 @@ public class Ghostscript { * * @param outputStream OutputStream object */ - public synchronized void setStdOut(OutputStream outputStream) { + public void setStdOut(OutputStream outputStream) { stdOut = outputStream; } @@ -119,7 +111,7 @@ public class Ghostscript { * * @return The InputStream or null */ - public synchronized InputStream getStdIn() { + public InputStream getStdIn() { return stdIn; } @@ -128,7 +120,7 @@ public class Ghostscript { * * @param inputStream InputStream object */ - public synchronized void setStdIn(InputStream inputStream) { + public void setStdIn(InputStream inputStream) { stdIn = inputStream; } @@ -265,6 +257,35 @@ public class Ghostscript { } } + public synchronized void close() throws IOException { + if (stdIn != null) { + stdIn.close(); + stdIn = null; + } + if (stdOut != null) { + stdOut.close(); + stdOut = null; + } + if (stdErr != null) { + stdErr.close(); + stdErr = null; + } + libraryInstance = null; + INSTANCE = null; + System.gc(); + logger.log(Level.INFO, "ghostscript instance closed and gc'ed()"); + } + + private static Ghostscript createInstance() { + try { + prepareTmp(); + return new Ghostscript(GhostscriptLibraryLoader.loadLibrary()); + } catch (Exception e) { + logger.log(Level.SEVERE, e.getMessage(), e); + } + return null; + } + private static void prepareTmp() throws IOException { String tmp = System.getenv("TMPDIR"); // the variable that ghostscript uses if (tmp == null) { diff --git a/graphics-ghostscript/src/main/java/org/xbib/graphics/ghostscript/PDFConverter.java b/graphics-ghostscript/src/main/java/org/xbib/graphics/ghostscript/PDFConverter.java index 9e5daf1..8ac2cb1 100644 --- a/graphics-ghostscript/src/main/java/org/xbib/graphics/ghostscript/PDFConverter.java +++ b/graphics-ghostscript/src/main/java/org/xbib/graphics/ghostscript/PDFConverter.java @@ -106,73 +106,77 @@ public class PDFConverter { if (outputStream == null) { return; } - prepare(tmpPath); - Path output = Files.createTempFile(tmpPath, "pdf", "pdf"); Ghostscript gs = Ghostscript.getInstance(); - List gsArgs = new LinkedList<>(); - gsArgs.add("-ps2pdf"); - gsArgs.add("-dNOPAUSE"); - //gsArgs.add("-dQUIET"); - gsArgs.add("-dBATCH"); - gsArgs.add("-dSAFER"); - switch (autoRotatePages) { - case OPTION_AUTOROTATEPAGES_NONE: - gsArgs.add("-dAutoRotatePages=/None"); - break; - case OPTION_AUTOROTATEPAGES_ALL: - gsArgs.add("-dAutoRotatePages=/All"); - break; - case OPTION_AUTOROTATEPAGES_PAGEBYPAGE: - gsArgs.add("-dAutoRotatePages=/PageByPage"); - break; - default: - break; - } - switch (processColorModel) { - case OPTION_PROCESSCOLORMODEL_CMYK: - gsArgs.add("-dProcessColorModel=/DeviceCMYK"); - break; - case OPTION_PROCESSCOLORMODEL_GRAY: - gsArgs.add("-dProcessColorModel=/DeviceGray"); - break; - default: - gsArgs.add("-dProcessColorModel=/DeviceRGB"); - break; - } - switch (pdfsettings) { - case OPTION_PDFSETTINGS_EBOOK: - gsArgs.add("-dPDFSETTINGS=/ebook"); - break; - case OPTION_PDFSETTINGS_SCREEN: - gsArgs.add("-dPDFSETTINGS=/screen"); - break; - case OPTION_PDFSETTINGS_PRINTER: - gsArgs.add("-dPDFSETTINGS=/printer"); - break; - case OPTION_PDFSETTINGS_PREPRESS: - gsArgs.add("-dPDFSETTINGS=/prepress"); - break; - default: - gsArgs.add("-dPDFSETTINGS=/default"); - break; - } - gsArgs.add("-dCompatibilityLevel=" + compatibilityLevel); - gsArgs.add("-dPDFX=" + pdfx); - gsArgs.add("-dDEVICEWIDTHPOINTS=" + paperSize.getWidth()); - gsArgs.add("-dDEVICEHEIGHTPOINTS=" + paperSize.getHeight()); - gsArgs.add("-sDEVICE=pdfwrite"); - gsArgs.add("-sOutputFile=" + output.toAbsolutePath().toString()); - //gsArgs.add("-q"); - gsArgs.add("-f"); - gsArgs.add("-"); try { - gs.setStdIn(inputStream); - gs.setStdOut(new LoggingOutputStream(logger)); - gs.setStdErr(new LoggingOutputStream(logger)); - gs.run(gsArgs.toArray(new String[gsArgs.size()])); - Files.copy(output.toAbsolutePath(), outputStream); + prepare(tmpPath); + Path output = Files.createTempFile(tmpPath, "pdf", "pdf"); + List gsArgs = new LinkedList<>(); + gsArgs.add("-ps2pdf"); + gsArgs.add("-dNOPAUSE"); + //gsArgs.add("-dQUIET"); + gsArgs.add("-dBATCH"); + gsArgs.add("-dSAFER"); + switch (autoRotatePages) { + case OPTION_AUTOROTATEPAGES_NONE: + gsArgs.add("-dAutoRotatePages=/None"); + break; + case OPTION_AUTOROTATEPAGES_ALL: + gsArgs.add("-dAutoRotatePages=/All"); + break; + case OPTION_AUTOROTATEPAGES_PAGEBYPAGE: + gsArgs.add("-dAutoRotatePages=/PageByPage"); + break; + default: + break; + } + switch (processColorModel) { + case OPTION_PROCESSCOLORMODEL_CMYK: + gsArgs.add("-dProcessColorModel=/DeviceCMYK"); + break; + case OPTION_PROCESSCOLORMODEL_GRAY: + gsArgs.add("-dProcessColorModel=/DeviceGray"); + break; + default: + gsArgs.add("-dProcessColorModel=/DeviceRGB"); + break; + } + switch (pdfsettings) { + case OPTION_PDFSETTINGS_EBOOK: + gsArgs.add("-dPDFSETTINGS=/ebook"); + break; + case OPTION_PDFSETTINGS_SCREEN: + gsArgs.add("-dPDFSETTINGS=/screen"); + break; + case OPTION_PDFSETTINGS_PRINTER: + gsArgs.add("-dPDFSETTINGS=/printer"); + break; + case OPTION_PDFSETTINGS_PREPRESS: + gsArgs.add("-dPDFSETTINGS=/prepress"); + break; + default: + gsArgs.add("-dPDFSETTINGS=/default"); + break; + } + gsArgs.add("-dCompatibilityLevel=" + compatibilityLevel); + gsArgs.add("-dPDFX=" + pdfx); + gsArgs.add("-dDEVICEWIDTHPOINTS=" + paperSize.getWidth()); + gsArgs.add("-dDEVICEHEIGHTPOINTS=" + paperSize.getHeight()); + gsArgs.add("-sDEVICE=pdfwrite"); + gsArgs.add("-sOutputFile=" + output.toAbsolutePath().toString()); + //gsArgs.add("-q"); + gsArgs.add("-f"); + gsArgs.add("-"); + try { + gs.setStdIn(inputStream); + gs.setStdOut(new LoggingOutputStream(logger)); + gs.setStdErr(new LoggingOutputStream(logger)); + gs.run(gsArgs.toArray(new String[gsArgs.size()])); + Files.copy(output.toAbsolutePath(), outputStream); + } finally { + delete(tmpPath); + } } finally { - delete(tmpPath); + gs.close(); } } diff --git a/graphics-ghostscript/src/main/java/org/xbib/graphics/ghostscript/PDFRasterizer.java b/graphics-ghostscript/src/main/java/org/xbib/graphics/ghostscript/PDFRasterizer.java index 891162e..75de4e6 100644 --- a/graphics-ghostscript/src/main/java/org/xbib/graphics/ghostscript/PDFRasterizer.java +++ b/graphics-ghostscript/src/main/java/org/xbib/graphics/ghostscript/PDFRasterizer.java @@ -143,11 +143,15 @@ public class PDFRasterizer { logger.info("pdfToImage args=" + gsArgs); // reset stdin Ghostscript gs = Ghostscript.getInstance(); - gs.setStdIn(null); - gs.setStdOut(new LoggingOutputStream(logger)); - gs.setStdErr(new LoggingOutputStream(logger)); - gs.run(gsArgs.toArray(new String[gsArgs.size()])); - logger.info("pdfToImage done"); + try { + gs.setStdIn(null); + gs.setStdOut(new LoggingOutputStream(logger)); + gs.setStdErr(new LoggingOutputStream(logger)); + gs.run(gsArgs.toArray(new String[gsArgs.size()])); + logger.info("pdfToImage done"); + } finally { + gs.close(); + } } public synchronized void pdfToImage(Path sourceFile, @@ -179,12 +183,16 @@ public class PDFRasterizer { gsArgs.add(sourceFile.toString()); logger.info("pdfToImage args=" + gsArgs); Ghostscript gs = Ghostscript.getInstance(); - // reset stdin - gs.setStdIn(null); - gs.setStdOut(new LoggingOutputStream(logger)); - gs.setStdErr(new LoggingOutputStream(logger)); - gs.run(gsArgs.toArray(new String[gsArgs.size()])); - logger.info("pdfToImage done"); + try { + // reset stdin + gs.setStdIn(null); + gs.setStdOut(new LoggingOutputStream(logger)); + gs.setStdErr(new LoggingOutputStream(logger)); + gs.run(gsArgs.toArray(new String[gsArgs.size()])); + logger.info("pdfToImage done"); + } finally { + gs.close(); + } } public int mergeImagesToPDF(Path sourceDir, Path targetFile) throws IOException { @@ -287,10 +295,14 @@ public class PDFRasterizer { gsArgs.add("-sOutputFile=" + targetFile.toString()); gsArgs.add(sourceFile.toString()); Ghostscript gs = Ghostscript.getInstance(); - gs.setStdIn(null); - logger.info(gsArgs.toString()); - gs.run(gsArgs.toArray(new String[gsArgs.size()])); - logger.info("scalePDF: source = " + sourceFile + " target = " + targetFile + " done"); + try { + gs.setStdIn(null); + logger.info(gsArgs.toString()); + gs.run(gsArgs.toArray(new String[gsArgs.size()])); + logger.info("scalePDF: source = " + sourceFile + " target = " + targetFile + " done"); + } finally { + gs.close(); + } } public void toPDFA(Path source, Path target) throws IOException { @@ -326,14 +338,15 @@ public class PDFRasterizer { gsArgs.add("-sOutputFile=" + target.toString()); gsArgs.add(pdfapsPath.toAbsolutePath().toString()); gsArgs.add(source.toString()); + Ghostscript gs = Ghostscript.getInstance(); try { - Ghostscript gs = Ghostscript.getInstance(); gs.setStdIn(null); gs.run(gsArgs.toArray(new String[gsArgs.size()])); } finally { delete(pdfapsPathTmp); delete(pdfapsPath); delete(iccPath); + gs.close(); } } diff --git a/graphics-ghostscript/src/main/java/org/xbib/graphics/ghostscript/GhostScriptLibraryTester.java b/graphics-ghostscript/src/test/java/org/xbib/graphics/ghostscript/test/GhostScriptLibraryTester.java similarity index 99% rename from graphics-ghostscript/src/main/java/org/xbib/graphics/ghostscript/GhostScriptLibraryTester.java rename to graphics-ghostscript/src/test/java/org/xbib/graphics/ghostscript/test/GhostScriptLibraryTester.java index c39000f..8a41cc8 100644 --- a/graphics-ghostscript/src/main/java/org/xbib/graphics/ghostscript/GhostScriptLibraryTester.java +++ b/graphics-ghostscript/src/test/java/org/xbib/graphics/ghostscript/test/GhostScriptLibraryTester.java @@ -1,4 +1,4 @@ -package org.xbib.graphics.ghostscript; +package org.xbib.graphics.ghostscript.test; import com.sun.jna.ptr.IntByReference; import org.xbib.graphics.ghostscript.internal.GhostscriptLibrary; diff --git a/graphics-ghostscript/src/test/java/org/xbib/graphics/ghostscript/test/GhostscriptLibraryTest.java b/graphics-ghostscript/src/test/java/org/xbib/graphics/ghostscript/test/GhostscriptLibraryTest.java index 12b7fe0..cb0c06b 100644 --- a/graphics-ghostscript/src/test/java/org/xbib/graphics/ghostscript/test/GhostscriptLibraryTest.java +++ b/graphics-ghostscript/src/test/java/org/xbib/graphics/ghostscript/test/GhostscriptLibraryTest.java @@ -3,7 +3,6 @@ package org.xbib.graphics.ghostscript.test; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; -import org.xbib.graphics.ghostscript.GhostScriptLibraryTester; import java.io.File; import java.util.logging.Logger; diff --git a/graphics-ghostscript/src/test/java/org/xbib/graphics/ghostscript/test/GhostscriptTest.java b/graphics-ghostscript/src/test/java/org/xbib/graphics/ghostscript/test/GhostscriptTest.java index a7f478f..05223a0 100644 --- a/graphics-ghostscript/src/test/java/org/xbib/graphics/ghostscript/test/GhostscriptTest.java +++ b/graphics-ghostscript/src/test/java/org/xbib/graphics/ghostscript/test/GhostscriptTest.java @@ -1,5 +1,8 @@ package org.xbib.graphics.ghostscript.test; +import java.io.IOException; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.xbib.graphics.ghostscript.Ghostscript; @@ -20,7 +23,17 @@ public class GhostscriptTest { private static final String dir = "src/test/resources/org/xbib/graphics/ghostscript/test/"; - private static final Ghostscript gs = Ghostscript.getInstance(); + static Ghostscript gs; + + @BeforeAll + public static void init() { + gs = Ghostscript.getInstance(); + } + + @AfterAll + public static void shutdown() throws IOException { + gs.close(); + } @Test public void testGetRevision() {