update pdfbox 2.0.28, bytebuddy, Ghostscript loading reworked, added dispose()
This commit is contained in:
parent
9cbc3f3d10
commit
a0d193eb7f
13 changed files with 213 additions and 241 deletions
|
@ -1,5 +1,5 @@
|
||||||
group = org.xbib.graphics
|
group = org.xbib.graphics
|
||||||
name = graphics
|
name = graphics
|
||||||
version = 4.3.3
|
version = 4.3.4
|
||||||
|
|
||||||
org.gradle.warning.mode = ALL
|
org.gradle.warning.mode = ALL
|
||||||
|
|
|
@ -7,13 +7,13 @@ dependencies {
|
||||||
|
|
||||||
test {
|
test {
|
||||||
useJUnitPlatform()
|
useJUnitPlatform()
|
||||||
failFast = false
|
failFast = true
|
||||||
environment 'TMPDIR', '/var/tmp/gs'
|
environment 'TMPDIR', '/var/tmp/gs'
|
||||||
file('/var/tmp/gs').mkdirs()
|
file('/var/tmp/gs').mkdirs()
|
||||||
systemProperty 'java.awt.headless', 'true'
|
systemProperty 'java.awt.headless', 'true'
|
||||||
systemProperty 'java.io.tmpdir', '/var/tmp/'
|
systemProperty 'java.io.tmpdir', '/var/tmp/'
|
||||||
systemProperty 'jna.tmpdir', '/var/tmp/'
|
systemProperty 'jna.tmpdir', '/var/tmp/'
|
||||||
systemProperty 'jna.debug', 'false'
|
systemProperty 'jna.debug', 'true'
|
||||||
systemProperty 'java.util.logging.config.file', 'src/test/resources/logging.properties'
|
systemProperty 'java.util.logging.config.file', 'src/test/resources/logging.properties'
|
||||||
testLogging {
|
testLogging {
|
||||||
events 'STARTED', 'PASSED', 'FAILED', 'SKIPPED'
|
events 'STARTED', 'PASSED', 'FAILED', 'SKIPPED'
|
||||||
|
|
|
@ -23,8 +23,8 @@ public class FontAnalyzer {
|
||||||
"-sFile=" + path.toAbsolutePath(),
|
"-sFile=" + path.toAbsolutePath(),
|
||||||
"-sOutputFile=%stdout",
|
"-sOutputFile=%stdout",
|
||||||
"-f", "-"};
|
"-f", "-"};
|
||||||
Ghostscript gs = Ghostscript.getInstance();
|
try (Ghostscript gs = new Ghostscript();
|
||||||
try (InputStream is = this.getClass().getClassLoader().getResourceAsStream("script/AnalyzePDFFonts.ps");
|
InputStream is = this.getClass().getClassLoader().getResourceAsStream("script/AnalyzePDFFonts.ps");
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
|
ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
|
||||||
gs.setStdIn(is);
|
gs.setStdIn(is);
|
||||||
gs.setStdOut(baos);
|
gs.setStdOut(baos);
|
||||||
|
@ -56,8 +56,6 @@ public class FontAnalyzer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
} finally {
|
|
||||||
gs.close();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,8 @@ package org.xbib.graphics.ghostscript;
|
||||||
|
|
||||||
import com.sun.jna.Pointer;
|
import com.sun.jna.Pointer;
|
||||||
import com.sun.jna.ptr.IntByReference;
|
import com.sun.jna.ptr.IntByReference;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import org.xbib.graphics.ghostscript.internal.ErrorCodes;
|
import org.xbib.graphics.ghostscript.internal.ErrorCodes;
|
||||||
import org.xbib.graphics.ghostscript.internal.GhostscriptLibrary;
|
import org.xbib.graphics.ghostscript.internal.GhostscriptLibrary;
|
||||||
import org.xbib.graphics.ghostscript.internal.GhostscriptLibraryLoader;
|
import org.xbib.graphics.ghostscript.internal.GhostscriptLibraryLoader;
|
||||||
|
@ -23,13 +25,13 @@ import java.util.logging.Logger;
|
||||||
/**
|
/**
|
||||||
* The Ghostscript native library API.
|
* The Ghostscript native library API.
|
||||||
*/
|
*/
|
||||||
public class Ghostscript {
|
public class Ghostscript implements AutoCloseable {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(Ghostscript.class.getName());
|
private static final Logger logger = Logger.getLogger(Ghostscript.class.getName());
|
||||||
|
|
||||||
public static final String ENCODING_PARAMETER = "org.xbib.graphics.ghostscript.encoding";
|
public static final String ENCODING_PARAMETER = "org.xbib.graphics.ghostscript.encoding";
|
||||||
|
|
||||||
private static Ghostscript INSTANCE;
|
private final GhostscriptLibrary libraryInstance;
|
||||||
|
|
||||||
private InputStream stdIn;
|
private InputStream stdIn;
|
||||||
|
|
||||||
|
@ -37,19 +39,16 @@ public class Ghostscript {
|
||||||
|
|
||||||
private OutputStream stdErr;
|
private OutputStream stdErr;
|
||||||
|
|
||||||
private GhostscriptLibrary libraryInstance;
|
private final AtomicBoolean closed;
|
||||||
|
|
||||||
private Ghostscript(GhostscriptLibrary libraryInstance) {
|
public Ghostscript() throws IOException {
|
||||||
this.libraryInstance = libraryInstance;
|
prepareTmp();
|
||||||
|
GhostscriptLibraryLoader libraryLoader = new GhostscriptLibraryLoader();
|
||||||
|
this.libraryInstance = libraryLoader.getGhostscriptLibrary();
|
||||||
|
Objects.requireNonNull(this.libraryInstance);
|
||||||
this.stdOut = new LoggingOutputStream(logger);
|
this.stdOut = new LoggingOutputStream(logger);
|
||||||
this.stdErr = new LoggingOutputStream(logger);
|
this.stdErr = new LoggingOutputStream(logger);
|
||||||
}
|
this.closed = new AtomicBoolean(false);
|
||||||
|
|
||||||
public synchronized static Ghostscript getInstance() {
|
|
||||||
if (INSTANCE == null) {
|
|
||||||
INSTANCE = createInstance();
|
|
||||||
}
|
|
||||||
return INSTANCE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -57,9 +56,9 @@ public class Ghostscript {
|
||||||
*
|
*
|
||||||
* @return the Ghostscript revision data.
|
* @return the Ghostscript revision data.
|
||||||
*/
|
*/
|
||||||
public synchronized static GhostscriptRevision getRevision() {
|
public synchronized GhostscriptRevision getRevision() {
|
||||||
GhostscriptLibrary.gsapi_revision_s revision = new GhostscriptLibrary.gsapi_revision_s();
|
GhostscriptLibrary.gsapi_revision_s revision = new GhostscriptLibrary.gsapi_revision_s();
|
||||||
INSTANCE.libraryInstance.gsapi_revision(revision, revision.size());
|
libraryInstance.gsapi_revision(revision, revision.size());
|
||||||
GhostscriptRevision result = new GhostscriptRevision();
|
GhostscriptRevision result = new GhostscriptRevision();
|
||||||
result.setProduct(revision.product);
|
result.setProduct(revision.product);
|
||||||
result.setCopyright(revision.copyright);
|
result.setCopyright(revision.copyright);
|
||||||
|
@ -257,7 +256,9 @@ public class Ghostscript {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public synchronized void close() throws IOException {
|
public synchronized void close() throws IOException {
|
||||||
|
if (closed.compareAndSet(false, true)) {
|
||||||
if (stdIn != null) {
|
if (stdIn != null) {
|
||||||
stdIn.close();
|
stdIn.close();
|
||||||
stdIn = null;
|
stdIn = null;
|
||||||
|
@ -270,20 +271,14 @@ public class Ghostscript {
|
||||||
stdErr.close();
|
stdErr.close();
|
||||||
stdErr = null;
|
stdErr = null;
|
||||||
}
|
}
|
||||||
libraryInstance = null;
|
if (libraryInstance != null) {
|
||||||
INSTANCE = null;
|
libraryInstance.dispose();
|
||||||
System.gc();
|
System.gc();
|
||||||
logger.log(Level.INFO, "ghostscript instance closed and gc'ed()");
|
logger.log(Level.INFO, "ghostscript library instance disposed and gc'ed()");
|
||||||
|
} else {
|
||||||
|
logger.log(Level.WARNING, "ghostscript library instance is null");
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
private static void prepareTmp() throws IOException {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package org.xbib.graphics.ghostscript;
|
package org.xbib.graphics.ghostscript;
|
||||||
|
|
||||||
|
import java.security.SecureRandom;
|
||||||
import org.xbib.graphics.ghostscript.internal.LoggingOutputStream;
|
import org.xbib.graphics.ghostscript.internal.LoggingOutputStream;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -20,6 +21,8 @@ public class PDFConverter {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(PDFConverter.class.getName());
|
private static final Logger logger = Logger.getLogger(PDFConverter.class.getName());
|
||||||
|
|
||||||
|
private static final SecureRandom random = new SecureRandom();
|
||||||
|
|
||||||
public static final int OPTION_AUTOROTATEPAGES_NONE = 0;
|
public static final int OPTION_AUTOROTATEPAGES_NONE = 0;
|
||||||
public static final int OPTION_AUTOROTATEPAGES_ALL = 1;
|
public static final int OPTION_AUTOROTATEPAGES_ALL = 1;
|
||||||
public static final int OPTION_AUTOROTATEPAGES_PAGEBYPAGE = 2;
|
public static final int OPTION_AUTOROTATEPAGES_PAGEBYPAGE = 2;
|
||||||
|
@ -72,8 +75,6 @@ public class PDFConverter {
|
||||||
*/
|
*/
|
||||||
private final PaperSize paperSize;
|
private final PaperSize paperSize;
|
||||||
|
|
||||||
private final Path tmpPath;
|
|
||||||
|
|
||||||
public PDFConverter() {
|
public PDFConverter() {
|
||||||
this(OPTION_AUTOROTATEPAGES_OFF, OPTION_PROCESSCOLORMODEL_RGB,
|
this(OPTION_AUTOROTATEPAGES_OFF, OPTION_PROCESSCOLORMODEL_RGB,
|
||||||
OPTION_PDFSETTINGS_PRINTER, "1.4", false, PaperSize.A4);
|
OPTION_PDFSETTINGS_PRINTER, "1.4", false, PaperSize.A4);
|
||||||
|
@ -91,7 +92,6 @@ public class PDFConverter {
|
||||||
this.compatibilityLevel = compatibilityLevel;
|
this.compatibilityLevel = compatibilityLevel;
|
||||||
this.pdfx = pdfx;
|
this.pdfx = pdfx;
|
||||||
this.paperSize = paperSize;
|
this.paperSize = paperSize;
|
||||||
this.tmpPath = Paths.get(System.getProperty("java.io.tmpdir", "/var/tmp")).resolve(toString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -106,56 +106,32 @@ public class PDFConverter {
|
||||||
if (outputStream == null) {
|
if (outputStream == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Ghostscript gs = Ghostscript.getInstance();
|
Path tmpPath = createTmpPath();
|
||||||
try {
|
try (Ghostscript gs = new Ghostscript()) {
|
||||||
prepare(tmpPath);
|
|
||||||
Path output = Files.createTempFile(tmpPath, "pdf", "pdf");
|
Path output = Files.createTempFile(tmpPath, "pdf", "pdf");
|
||||||
List<String> gsArgs = new LinkedList<>();
|
List<String> gsArgs = new LinkedList<>();
|
||||||
gsArgs.add("-ps2pdf");
|
gsArgs.add("-ps2pdf");
|
||||||
gsArgs.add("-dNOPAUSE");
|
gsArgs.add("-dNOPAUSE");
|
||||||
//gsArgs.add("-dQUIET");
|
|
||||||
gsArgs.add("-dBATCH");
|
gsArgs.add("-dBATCH");
|
||||||
gsArgs.add("-dSAFER");
|
gsArgs.add("-dSAFER");
|
||||||
switch (autoRotatePages) {
|
switch (autoRotatePages) {
|
||||||
case OPTION_AUTOROTATEPAGES_NONE:
|
case OPTION_AUTOROTATEPAGES_NONE -> gsArgs.add("-dAutoRotatePages=/None");
|
||||||
gsArgs.add("-dAutoRotatePages=/None");
|
case OPTION_AUTOROTATEPAGES_ALL -> gsArgs.add("-dAutoRotatePages=/All");
|
||||||
break;
|
case OPTION_AUTOROTATEPAGES_PAGEBYPAGE -> gsArgs.add("-dAutoRotatePages=/PageByPage");
|
||||||
case OPTION_AUTOROTATEPAGES_ALL:
|
default -> {
|
||||||
gsArgs.add("-dAutoRotatePages=/All");
|
}
|
||||||
break;
|
|
||||||
case OPTION_AUTOROTATEPAGES_PAGEBYPAGE:
|
|
||||||
gsArgs.add("-dAutoRotatePages=/PageByPage");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
switch (processColorModel) {
|
switch (processColorModel) {
|
||||||
case OPTION_PROCESSCOLORMODEL_CMYK:
|
case OPTION_PROCESSCOLORMODEL_CMYK -> gsArgs.add("-dProcessColorModel=/DeviceCMYK");
|
||||||
gsArgs.add("-dProcessColorModel=/DeviceCMYK");
|
case OPTION_PROCESSCOLORMODEL_GRAY -> gsArgs.add("-dProcessColorModel=/DeviceGray");
|
||||||
break;
|
default -> gsArgs.add("-dProcessColorModel=/DeviceRGB");
|
||||||
case OPTION_PROCESSCOLORMODEL_GRAY:
|
|
||||||
gsArgs.add("-dProcessColorModel=/DeviceGray");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
gsArgs.add("-dProcessColorModel=/DeviceRGB");
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
switch (pdfsettings) {
|
switch (pdfsettings) {
|
||||||
case OPTION_PDFSETTINGS_EBOOK:
|
case OPTION_PDFSETTINGS_EBOOK -> gsArgs.add("-dPDFSETTINGS=/ebook");
|
||||||
gsArgs.add("-dPDFSETTINGS=/ebook");
|
case OPTION_PDFSETTINGS_SCREEN -> gsArgs.add("-dPDFSETTINGS=/screen");
|
||||||
break;
|
case OPTION_PDFSETTINGS_PRINTER -> gsArgs.add("-dPDFSETTINGS=/printer");
|
||||||
case OPTION_PDFSETTINGS_SCREEN:
|
case OPTION_PDFSETTINGS_PREPRESS -> gsArgs.add("-dPDFSETTINGS=/prepress");
|
||||||
gsArgs.add("-dPDFSETTINGS=/screen");
|
default -> gsArgs.add("-dPDFSETTINGS=/default");
|
||||||
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("-dCompatibilityLevel=" + compatibilityLevel);
|
||||||
gsArgs.add("-dPDFX=" + pdfx);
|
gsArgs.add("-dPDFX=" + pdfx);
|
||||||
|
@ -163,28 +139,19 @@ public class PDFConverter {
|
||||||
gsArgs.add("-dDEVICEHEIGHTPOINTS=" + paperSize.getHeight());
|
gsArgs.add("-dDEVICEHEIGHTPOINTS=" + paperSize.getHeight());
|
||||||
gsArgs.add("-sDEVICE=pdfwrite");
|
gsArgs.add("-sDEVICE=pdfwrite");
|
||||||
gsArgs.add("-sOutputFile=" + output.toAbsolutePath().toString());
|
gsArgs.add("-sOutputFile=" + output.toAbsolutePath().toString());
|
||||||
//gsArgs.add("-q");
|
|
||||||
gsArgs.add("-f");
|
gsArgs.add("-f");
|
||||||
gsArgs.add("-");
|
gsArgs.add("-");
|
||||||
try {
|
|
||||||
gs.setStdIn(inputStream);
|
gs.setStdIn(inputStream);
|
||||||
gs.setStdOut(new LoggingOutputStream(logger));
|
gs.setStdOut(new LoggingOutputStream(logger));
|
||||||
gs.setStdErr(new LoggingOutputStream(logger));
|
gs.setStdErr(new LoggingOutputStream(logger));
|
||||||
gs.run(gsArgs.toArray(new String[gsArgs.size()]));
|
gs.run(gsArgs.toArray(new String[0]));
|
||||||
Files.copy(output.toAbsolutePath(), outputStream);
|
Files.copy(output.toAbsolutePath(), outputStream);
|
||||||
} finally {
|
} finally {
|
||||||
delete(tmpPath);
|
deleteTmpPath(tmpPath);
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
gs.close();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void prepare(Path path) throws IOException {
|
private static void deleteTmpPath(Path path) throws IOException {
|
||||||
Files.createDirectories(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void delete(Path path) throws IOException {
|
|
||||||
if (path == null) {
|
if (path == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -211,4 +178,12 @@ public class PDFConverter {
|
||||||
Files.deleteIfExists(path);
|
Files.deleteIfExists(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Path createTmpPath() throws IOException {
|
||||||
|
int integer = random.nextInt();
|
||||||
|
Path tmpPath = Paths.get(System.getProperty("java.io.tmpdir", "/var/tmp"))
|
||||||
|
.resolve("gs" + Math.abs(integer));
|
||||||
|
Files.createDirectories(tmpPath);
|
||||||
|
return tmpPath;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package org.xbib.graphics.ghostscript;
|
package org.xbib.graphics.ghostscript;
|
||||||
|
|
||||||
|
import java.security.SecureRandom;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
|
@ -45,6 +46,8 @@ public class PDFRasterizer {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(PDFRasterizer.class.getName());
|
private static final Logger logger = Logger.getLogger(PDFRasterizer.class.getName());
|
||||||
|
|
||||||
|
private static final SecureRandom random = new SecureRandom();
|
||||||
|
|
||||||
private static final int MAX_IMAGE_SIZE_BYTES = 128 * 1024 * 1024;
|
private static final int MAX_IMAGE_SIZE_BYTES = 128 * 1024 * 1024;
|
||||||
|
|
||||||
private String creator;
|
private String creator;
|
||||||
|
@ -53,10 +56,7 @@ public class PDFRasterizer {
|
||||||
|
|
||||||
private String subject;
|
private String subject;
|
||||||
|
|
||||||
private final Path tmpPath;
|
|
||||||
|
|
||||||
public PDFRasterizer() {
|
public PDFRasterizer() {
|
||||||
this.tmpPath = Paths.get(System.getProperty("java.io.tmpdir", "/var/tmp")).resolve(toString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCreator(String creator) {
|
public void setCreator(String creator) {
|
||||||
|
@ -82,51 +82,54 @@ public class PDFRasterizer {
|
||||||
if (Files.size(source) == 0) {
|
if (Files.size(source) == 0) {
|
||||||
throw new IOException("empty file at " + source);
|
throw new IOException("empty file at " + source);
|
||||||
}
|
}
|
||||||
prepare(tmpPath);
|
Path tmpPath = createTmpPath();
|
||||||
Path tmp = Files.createTempDirectory(tmpPath, "pdf-rasterize");
|
|
||||||
if (!Files.isWritable(tmp)) {
|
|
||||||
throw new IOException("unable to write to " + tmp);
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
pdfToImage(source, tmp, "pdf", null);
|
Path path = Files.createTempDirectory(tmpPath, "pdf-rasterize");
|
||||||
Path tmpTarget = tmp.resolve(target.getFileName());
|
pdfToImage(source, path, "pdf", null);
|
||||||
mergeImagesToPDF(tmp, tmpTarget);
|
Path tmpTarget = path.resolve(target.getFileName());
|
||||||
|
mergeImagesToPDF(path, tmpTarget);
|
||||||
scalePDF(tmpTarget, target);
|
scalePDF(tmpTarget, target);
|
||||||
logger.info("convert source=" + source + " done");
|
logger.info("convert source=" + source + " done");
|
||||||
} finally {
|
} finally {
|
||||||
delete(tmpPath);
|
deleteTmpPath(tmpPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void screenConvert(Path source, Path target) throws IOException {
|
public synchronized void screenConvert(Path source, Path target) throws IOException {
|
||||||
logger.info("convert source=" + source.toAbsolutePath() + " target=" + target);
|
logger.info("screen convert source=" + source.toAbsolutePath() + " target=" + target);
|
||||||
if (!Files.exists(source.toAbsolutePath())) {
|
if (!Files.exists(source.toAbsolutePath())) {
|
||||||
throw new FileNotFoundException(source.toString());
|
throw new FileNotFoundException(source.toString());
|
||||||
}
|
}
|
||||||
if (!Files.isReadable(source.toAbsolutePath())) {
|
if (!Files.isReadable(source.toAbsolutePath())) {
|
||||||
throw new IOException("unable to read " + source.toString());
|
throw new IOException("unable to read " + source.toString());
|
||||||
}
|
}
|
||||||
prepare(tmpPath);
|
if (Files.size(source) == 0) {
|
||||||
Path tmp = Files.createTempDirectory(tmpPath, "pdf-rasterize");
|
throw new IOException("empty file at " + source);
|
||||||
|
}
|
||||||
|
Path tmpPath = createTmpPath();
|
||||||
try {
|
try {
|
||||||
pdfToGrayScreenImage(source.toAbsolutePath(), tmp);
|
Path path = Files.createTempDirectory(tmpPath, "pdf-rasterize");
|
||||||
Path tmpTarget = tmp.resolve(target.getFileName());
|
pdfToGrayScreenImage(source.toAbsolutePath(), path);
|
||||||
mergeImagesToPDF(tmp, tmpTarget);
|
Path tmpTarget = path.resolve(target.getFileName());
|
||||||
|
mergeImagesToPDF(path, tmpTarget);
|
||||||
//toPDFA(tmpTarget, target);
|
//toPDFA(tmpTarget, target);
|
||||||
scalePDF(tmpTarget, target);
|
scalePDF(tmpTarget, target);
|
||||||
logger.info("convert source=" + source.toAbsolutePath() + " done");
|
logger.info("screen convert source=" + source.toAbsolutePath() + " done");
|
||||||
} finally {
|
} finally {
|
||||||
delete(tmpPath);
|
deleteTmpPath(tmpPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void pdfToGrayScreenImage(Path source, Path target) throws IOException {
|
public synchronized void pdfToGrayScreenImage(Path source, Path target) throws IOException {
|
||||||
logger.info("pdfToGrayScreenImage source=" + source + " target=" + target);
|
logger.info("pdfToGrayScreenImage source=" + source + " target=" + target);
|
||||||
if (!Files.exists(source.toAbsolutePath())) {
|
if (!Files.exists(source.toAbsolutePath())) {
|
||||||
throw new FileNotFoundException(source.toString());
|
throw new FileNotFoundException("not found: " + source);
|
||||||
}
|
}
|
||||||
if (!Files.isReadable(source.toAbsolutePath())) {
|
if (!Files.isReadable(source.toAbsolutePath())) {
|
||||||
throw new IOException("unable to read " + source.toString());
|
throw new IOException("unable to read " + source);
|
||||||
|
}
|
||||||
|
if (Files.size(source) == 0) {
|
||||||
|
throw new IOException("empty file at " + source);
|
||||||
}
|
}
|
||||||
List<String> gsArgs = new LinkedList<>();
|
List<String> gsArgs = new LinkedList<>();
|
||||||
gsArgs.add("-dNOPAUSE");
|
gsArgs.add("-dNOPAUSE");
|
||||||
|
@ -141,16 +144,12 @@ public class PDFRasterizer {
|
||||||
gsArgs.add("-f");
|
gsArgs.add("-f");
|
||||||
gsArgs.add(source.toString());
|
gsArgs.add(source.toString());
|
||||||
logger.info("pdfToImage args=" + gsArgs);
|
logger.info("pdfToImage args=" + gsArgs);
|
||||||
// reset stdin
|
try (Ghostscript gs = new Ghostscript()) {
|
||||||
Ghostscript gs = Ghostscript.getInstance();
|
|
||||||
try {
|
|
||||||
gs.setStdIn(null);
|
gs.setStdIn(null);
|
||||||
gs.setStdOut(new LoggingOutputStream(logger));
|
gs.setStdOut(new LoggingOutputStream(logger));
|
||||||
gs.setStdErr(new LoggingOutputStream(logger));
|
gs.setStdErr(new LoggingOutputStream(logger));
|
||||||
gs.run(gsArgs.toArray(new String[gsArgs.size()]));
|
gs.run(gsArgs.toArray(new String[0]));
|
||||||
logger.info("pdfToImage done");
|
logger.info("pdfToImage done");
|
||||||
} finally {
|
|
||||||
gs.close();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,16 +181,13 @@ public class PDFRasterizer {
|
||||||
gsArgs.add("-f");
|
gsArgs.add("-f");
|
||||||
gsArgs.add(sourceFile.toString());
|
gsArgs.add(sourceFile.toString());
|
||||||
logger.info("pdfToImage args=" + gsArgs);
|
logger.info("pdfToImage args=" + gsArgs);
|
||||||
Ghostscript gs = Ghostscript.getInstance();
|
try (Ghostscript gs = new Ghostscript()) {
|
||||||
try {
|
|
||||||
// reset stdin
|
// reset stdin
|
||||||
gs.setStdIn(null);
|
gs.setStdIn(null);
|
||||||
gs.setStdOut(new LoggingOutputStream(logger));
|
gs.setStdOut(new LoggingOutputStream(logger));
|
||||||
gs.setStdErr(new LoggingOutputStream(logger));
|
gs.setStdErr(new LoggingOutputStream(logger));
|
||||||
gs.run(gsArgs.toArray(new String[gsArgs.size()]));
|
gs.run(gsArgs.toArray(new String[0]));
|
||||||
logger.info("pdfToImage done");
|
logger.info("pdfToImage done");
|
||||||
} finally {
|
|
||||||
gs.close();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,19 +290,17 @@ public class PDFRasterizer {
|
||||||
gsArgs.add("-sPAPERSIZE=a4");
|
gsArgs.add("-sPAPERSIZE=a4");
|
||||||
gsArgs.add("-sOutputFile=" + targetFile.toString());
|
gsArgs.add("-sOutputFile=" + targetFile.toString());
|
||||||
gsArgs.add(sourceFile.toString());
|
gsArgs.add(sourceFile.toString());
|
||||||
Ghostscript gs = Ghostscript.getInstance();
|
try (Ghostscript gs = new Ghostscript()) {
|
||||||
try {
|
|
||||||
gs.setStdIn(null);
|
gs.setStdIn(null);
|
||||||
logger.info(gsArgs.toString());
|
logger.info(gsArgs.toString());
|
||||||
gs.run(gsArgs.toArray(new String[gsArgs.size()]));
|
gs.run(gsArgs.toArray(new String[0]));
|
||||||
logger.info("scalePDF: source = " + sourceFile + " target = " + targetFile + " done");
|
logger.info("scalePDF: source = " + sourceFile + " target = " + targetFile + " done");
|
||||||
} finally {
|
|
||||||
gs.close();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void toPDFA(Path source, Path target) throws IOException {
|
public void toPDFA(Path source, Path target) throws IOException {
|
||||||
prepare(tmpPath);
|
Path tmpPath = createTmpPath();
|
||||||
|
try (Ghostscript gs = new Ghostscript()) {
|
||||||
Path iccPath = Files.createTempFile(tmpPath, "srgb", ".icc");
|
Path iccPath = Files.createTempFile(tmpPath, "srgb", ".icc");
|
||||||
Path pdfapsPathTmp = Files.createTempFile(tmpPath, "PDFA_def", ".tmp");
|
Path pdfapsPathTmp = Files.createTempFile(tmpPath, "PDFA_def", ".tmp");
|
||||||
Path pdfapsPath = Files.createTempFile(tmpPath, "PDFA_def", ".ps");
|
Path pdfapsPath = Files.createTempFile(tmpPath, "PDFA_def", ".ps");
|
||||||
|
@ -338,15 +332,10 @@ public class PDFRasterizer {
|
||||||
gsArgs.add("-sOutputFile=" + target.toString());
|
gsArgs.add("-sOutputFile=" + target.toString());
|
||||||
gsArgs.add(pdfapsPath.toAbsolutePath().toString());
|
gsArgs.add(pdfapsPath.toAbsolutePath().toString());
|
||||||
gsArgs.add(source.toString());
|
gsArgs.add(source.toString());
|
||||||
Ghostscript gs = Ghostscript.getInstance();
|
|
||||||
try {
|
|
||||||
gs.setStdIn(null);
|
gs.setStdIn(null);
|
||||||
gs.run(gsArgs.toArray(new String[gsArgs.size()]));
|
gs.run(gsArgs.toArray(new String[0]));
|
||||||
} finally {
|
} finally {
|
||||||
delete(pdfapsPathTmp);
|
deleteTmpPath(tmpPath);
|
||||||
delete(pdfapsPath);
|
|
||||||
delete(iccPath);
|
|
||||||
gs.close();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -420,11 +409,7 @@ public class PDFRasterizer {
|
||||||
return pos >= 0 ? filename.substring(pos + 1).toLowerCase(Locale.ROOT) : null;
|
return pos >= 0 ? filename.substring(pos + 1).toLowerCase(Locale.ROOT) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void prepare(Path path) throws IOException {
|
private static void deleteTmpPath(Path path) throws IOException {
|
||||||
Files.createDirectories(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void delete(Path path) throws IOException {
|
|
||||||
if (path == null) {
|
if (path == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -451,4 +436,15 @@ public class PDFRasterizer {
|
||||||
Files.deleteIfExists(path);
|
Files.deleteIfExists(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Path createTmpPath() throws IOException {
|
||||||
|
int integer = random.nextInt();
|
||||||
|
Path tmpPath = Paths.get(System.getProperty("java.io.tmpdir", "/var/tmp"))
|
||||||
|
.resolve("gs" + Math.abs(integer));
|
||||||
|
Files.createDirectories(tmpPath);
|
||||||
|
if (!Files.isWritable(tmpPath)) {
|
||||||
|
throw new IOException("unable to write to " + tmpPath);
|
||||||
|
}
|
||||||
|
return tmpPath;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,11 @@ import java.util.List;
|
||||||
*/
|
*/
|
||||||
public interface GhostscriptLibrary extends Library {
|
public interface GhostscriptLibrary extends Library {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A default method to call JNA's dispose().
|
||||||
|
*/
|
||||||
|
void dispose();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function returns the revision numbers and strings of the Ghostscript
|
* This function returns the revision numbers and strings of the Ghostscript
|
||||||
* interpreter library. You should call it before any other interpreter
|
* interpreter library. You should call it before any other interpreter
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
package org.xbib.graphics.ghostscript.internal;
|
package org.xbib.graphics.ghostscript.internal;
|
||||||
|
|
||||||
import static com.sun.jna.Platform.LINUX;
|
|
||||||
import static com.sun.jna.Platform.MAC;
|
import static com.sun.jna.Platform.MAC;
|
||||||
import com.sun.jna.Function;
|
import com.sun.jna.Function;
|
||||||
|
import com.sun.jna.InvocationMapper;
|
||||||
import com.sun.jna.Library;
|
import com.sun.jna.Library;
|
||||||
import com.sun.jna.Native;
|
import com.sun.jna.Native;
|
||||||
import com.sun.jna.Platform;
|
import com.sun.jna.Platform;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.Arrays;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
@ -28,29 +28,39 @@ public class GhostscriptLibraryLoader {
|
||||||
"libgs.9.25",
|
"libgs.9.25",
|
||||||
"gs.9.25",
|
"gs.9.25",
|
||||||
"libgs.dylib",
|
"libgs.dylib",
|
||||||
"libgs",
|
|
||||||
"gs",
|
"gs",
|
||||||
};
|
};
|
||||||
|
|
||||||
public static GhostscriptLibrary loadLibrary() {
|
private GhostscriptLibrary ghostscriptLibrary;
|
||||||
Map<String, Object> options = new HashMap<>();
|
|
||||||
options.put(Library.OPTION_CALLING_CONVENTION, Function.C_CONVENTION);
|
public GhostscriptLibraryLoader() {
|
||||||
String[] LIBNAMES = {};
|
Map<String, Object> options = Map.of(Library.OPTION_CALLING_CONVENTION, Function.C_CONVENTION,
|
||||||
switch (Platform.getOSType()) {
|
Library.OPTION_INVOCATION_MAPPER, (InvocationMapper) (lib, m) -> {
|
||||||
case LINUX:
|
if (m.getName().equals("dispose")) {
|
||||||
LIBNAMES = LINUX_LIBNAMES;
|
return (proxy, method, args) -> {
|
||||||
break;
|
lib.dispose();
|
||||||
case MAC:
|
return null;
|
||||||
LIBNAMES = MAC_LIBNAMES;
|
};
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
for (String libname : LIBNAMES) {
|
return null;
|
||||||
|
});
|
||||||
|
String[] libnames = LINUX_LIBNAMES;
|
||||||
|
if (Platform.getOSType() == MAC) {
|
||||||
|
libnames = MAC_LIBNAMES;
|
||||||
|
}
|
||||||
|
for (String libname : libnames) {
|
||||||
try {
|
try {
|
||||||
return Native.load(libname, GhostscriptLibrary.class, options);
|
this.ghostscriptLibrary = Native.load(libname, GhostscriptLibrary.class, options);
|
||||||
} catch (Error e) {
|
} catch (Error e) {
|
||||||
logger.log(Level.WARNING, "library " + libname + " not found", e);
|
logger.log(Level.WARNING, "library " + libname + " not found", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
if (this.ghostscriptLibrary == null) {
|
||||||
|
throw new IllegalStateException("library not found in libs: " + Arrays.asList(libnames));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public GhostscriptLibrary getGhostscriptLibrary() {
|
||||||
|
return ghostscriptLibrary;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,8 @@ public class GhostScriptLibraryTester {
|
||||||
private final GhostscriptLibrary ghostscriptLibrary;
|
private final GhostscriptLibrary ghostscriptLibrary;
|
||||||
|
|
||||||
public GhostScriptLibraryTester() {
|
public GhostScriptLibraryTester() {
|
||||||
ghostscriptLibrary = GhostscriptLibraryLoader.loadLibrary();
|
GhostscriptLibraryLoader loader = new GhostscriptLibraryLoader();
|
||||||
|
this.ghostscriptLibrary = loader.getGhostscriptLibrary();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getRevisionProduct() {
|
public String getRevisionProduct() {
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package org.xbib.graphics.ghostscript.test;
|
package org.xbib.graphics.ghostscript.test;
|
||||||
|
|
||||||
import java.io.IOException;
|
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.Disabled;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.xbib.graphics.ghostscript.Ghostscript;
|
import org.xbib.graphics.ghostscript.Ghostscript;
|
||||||
|
@ -23,21 +21,10 @@ public class GhostscriptTest {
|
||||||
|
|
||||||
private static final String dir = "src/test/resources/org/xbib/graphics/ghostscript/test/";
|
private static final String dir = "src/test/resources/org/xbib/graphics/ghostscript/test/";
|
||||||
|
|
||||||
static Ghostscript gs;
|
|
||||||
|
|
||||||
@BeforeAll
|
|
||||||
public static void init() {
|
|
||||||
gs = Ghostscript.getInstance();
|
|
||||||
}
|
|
||||||
|
|
||||||
@AfterAll
|
|
||||||
public static void shutdown() throws IOException {
|
|
||||||
gs.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetRevision() {
|
public void testGetRevision() throws IOException {
|
||||||
GhostscriptRevision revision = Ghostscript.getRevision();
|
try (Ghostscript gs = new Ghostscript()) {
|
||||||
|
GhostscriptRevision revision = gs.getRevision();
|
||||||
logger.log(Level.INFO, "product = " + revision.getProduct());
|
logger.log(Level.INFO, "product = " + revision.getProduct());
|
||||||
assertNotNull(revision.getProduct());
|
assertNotNull(revision.getProduct());
|
||||||
logger.log(Level.INFO, "copyright = " + revision.getCopyright());
|
logger.log(Level.INFO, "copyright = " + revision.getCopyright());
|
||||||
|
@ -47,20 +34,22 @@ public class GhostscriptTest {
|
||||||
logger.log(Level.INFO, "number = " + revision.getNumber());
|
logger.log(Level.INFO, "number = " + revision.getNumber());
|
||||||
assertNotNull(revision.getNumber());
|
assertNotNull(revision.getNumber());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExit() {
|
public void testExit() {
|
||||||
try {
|
try (Ghostscript gs = new Ghostscript()) {
|
||||||
String[] args = {"-dNODISPLAY", "-dQUIET"};
|
String[] args = {"-dNODISPLAY", "-dQUIET"};
|
||||||
gs.run(args);
|
gs.run(args);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
logger.log(Level.SEVERE, e.getMessage(), e);
|
||||||
fail(e.getMessage());
|
fail(e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRunString() {
|
public void testRunString() {
|
||||||
try {
|
try (Ghostscript gs = new Ghostscript()) {
|
||||||
String[] args = {"-dNODISPLAY", "-dQUIET"};
|
String[] args = {"-dNODISPLAY", "-dQUIET"};
|
||||||
gs.run(args, "devicenames ==", null);
|
gs.run(args, "devicenames ==", null);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -73,7 +62,7 @@ public class GhostscriptTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRunFile() {
|
public void testRunFile() {
|
||||||
try {
|
try (Ghostscript gs = new Ghostscript()) {
|
||||||
String[] args = {"-dNODISPLAY", "-dQUIET", "-dNOPAUSE", "-dBATCH", "-dSAFER"};
|
String[] args = {"-dNODISPLAY", "-dQUIET", "-dNOPAUSE", "-dBATCH", "-dSAFER"};
|
||||||
gs.run(args, null, dir + "input.ps");
|
gs.run(args, null, dir + "input.ps");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -90,7 +79,8 @@ public class GhostscriptTest {
|
||||||
@Disabled("core dump")
|
@Disabled("core dump")
|
||||||
@Test
|
@Test
|
||||||
public void testStdIn() {
|
public void testStdIn() {
|
||||||
try (InputStream is = new FileInputStream(dir + "input.ps")) {
|
try (Ghostscript gs = new Ghostscript();
|
||||||
|
InputStream is = new FileInputStream(dir + "input.ps")) {
|
||||||
gs.setStdIn(is);
|
gs.setStdIn(is);
|
||||||
String[] args = {"-dNODISPLAY", "-dQUIET", "-dNOPAUSE", "-dBATCH", "-sOutputFile=%stdout", "-f", "-"};
|
String[] args = {"-dNODISPLAY", "-dQUIET", "-dNOPAUSE", "-dBATCH", "-sOutputFile=%stdout", "-f", "-"};
|
||||||
gs.run(args);
|
gs.run(args);
|
||||||
|
@ -101,7 +91,8 @@ public class GhostscriptTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testStdOut() {
|
public void testStdOut() {
|
||||||
try (InputStream is = new ByteArrayInputStream("devicenames ==\n".getBytes())) {
|
try (Ghostscript gs = new Ghostscript();
|
||||||
|
InputStream is = new ByteArrayInputStream("devicenames ==\n".getBytes())) {
|
||||||
gs.setStdIn(is);
|
gs.setStdIn(is);
|
||||||
String[] args = { "-dNODISPLAY", "-sOutputFile=%stdout", "-f", "-" };
|
String[] args = { "-dNODISPLAY", "-sOutputFile=%stdout", "-f", "-" };
|
||||||
gs.run(args);
|
gs.run(args);
|
||||||
|
@ -112,7 +103,8 @@ public class GhostscriptTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testStdErr() {
|
public void testStdErr() {
|
||||||
try (InputStream is = new ByteArrayInputStream("stupid\n".getBytes())) {
|
try (Ghostscript gs = new Ghostscript();
|
||||||
|
InputStream is = new ByteArrayInputStream("stupid\n".getBytes())) {
|
||||||
gs.setStdIn(is);
|
gs.setStdIn(is);
|
||||||
String[] args = { "-dNODISPLAY", "-sOutputFile=%stdout", "-f", "-" };
|
String[] args = { "-dNODISPLAY", "-sOutputFile=%stdout", "-f", "-" };
|
||||||
gs.run(args);
|
gs.run(args);
|
||||||
|
|
|
@ -45,17 +45,17 @@ public class PDFRasterizerTest {
|
||||||
public void testPDFUnpackRasterAndScale() throws IOException {
|
public void testPDFUnpackRasterAndScale() throws IOException {
|
||||||
Path source = Paths.get("src/test/resources/org/xbib/graphics/ghostscript/test/20200024360.pdf");
|
Path source = Paths.get("src/test/resources/org/xbib/graphics/ghostscript/test/20200024360.pdf");
|
||||||
Path target = Paths.get("build/20200024360-new.pdf");
|
Path target = Paths.get("build/20200024360-new.pdf");
|
||||||
Path tmp = Files.createTempDirectory("graphics-test");
|
Path path = Files.createTempDirectory("graphics-test");
|
||||||
int pagecount = 0;
|
int pagecount = 0;
|
||||||
try {
|
try {
|
||||||
PDFRasterizer pdfRasterizer = new PDFRasterizer();
|
PDFRasterizer pdfRasterizer = new PDFRasterizer();
|
||||||
pdfRasterizer.pdfToImage(source, tmp, null, null);
|
pdfRasterizer.pdfToImage(source, path, null, null);
|
||||||
Path tmpTarget = tmp.resolve(target.getFileName());
|
Path tmpTarget = path.resolve(target.getFileName());
|
||||||
pagecount = pdfRasterizer.mergeImagesToPDF(tmp, tmpTarget);
|
pagecount = pdfRasterizer.mergeImagesToPDF(path, tmpTarget);
|
||||||
logger.info("pagecount = " + pagecount);
|
logger.info("pagecount = " + pagecount);
|
||||||
pdfRasterizer.scalePDF(tmpTarget, target);
|
pdfRasterizer.scalePDF(tmpTarget, target);
|
||||||
} finally {
|
} finally {
|
||||||
delete(tmp);
|
delete(path);
|
||||||
}
|
}
|
||||||
assertEquals(28, pagecount);
|
assertEquals(28, pagecount);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,6 @@ dependencies {
|
||||||
testImplementation libs.groovy.templates
|
testImplementation libs.groovy.templates
|
||||||
testImplementation libs.groovy.test
|
testImplementation libs.groovy.test
|
||||||
testImplementation libs.spock
|
testImplementation libs.spock
|
||||||
testImplementation libs.cglib
|
testImplementation libs.bytebuddy
|
||||||
testImplementation libs.objenesis
|
testImplementation libs.objenesis
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,10 +36,10 @@ dependencyResolutionManagement {
|
||||||
library('groovy-templates', 'org.apache.groovy', 'groovy-templates').versionRef('groovy')
|
library('groovy-templates', 'org.apache.groovy', 'groovy-templates').versionRef('groovy')
|
||||||
library('groovy-test', 'org.apache.groovy', 'groovy-test').versionRef('groovy')
|
library('groovy-test', 'org.apache.groovy', 'groovy-test').versionRef('groovy')
|
||||||
library('spock', 'org.spockframework', 'spock-core').versionRef('spock')
|
library('spock', 'org.spockframework', 'spock-core').versionRef('spock')
|
||||||
library('cglib', 'cglib', 'cglib-nodep').version('3.3.0')
|
library('bytebuddy', 'net.bytebuddy', 'byte-buddy').version('1.14.4')
|
||||||
library('objenesis', 'org.objenesis', 'objenesis').version('2.6')
|
library('objenesis', 'org.objenesis', 'objenesis').version('2.6')
|
||||||
library('jna', 'net.java.dev.jna', 'jna').version('5.12.1')
|
library('jna', 'net.java.dev.jna', 'jna').version('5.13.0')
|
||||||
library('pdfbox', 'org.apache.pdfbox', 'pdfbox').version('2.0.27')
|
library('pdfbox', 'org.apache.pdfbox', 'pdfbox').version('2.0.28')
|
||||||
library('zxing', 'com.google.zxing', 'javase').version('3.4.1')
|
library('zxing', 'com.google.zxing', 'javase').version('3.4.1')
|
||||||
library('reflections', 'org.reflections', 'reflections').version('0.9.11')
|
library('reflections', 'org.reflections', 'reflections').version('0.9.11')
|
||||||
library('jfreechart', 'org.jfree', 'jfreechart').version('1.5.2')
|
library('jfreechart', 'org.jfree', 'jfreechart').version('1.5.2')
|
||||||
|
|
Loading…
Reference in a new issue