
net.sf.nervalreports.converters.TeXToPDFConverter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of tex-pdf-converter Show documentation
Show all versions of tex-pdf-converter Show documentation
This is the TeX to PDF converter package of NervalReports (a lightweight report creation library),
used to convert a generated report from LaTeX to PDF format.
/** This file is part of nervalreports.
*
* nervalreports is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* nervalreports is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with nervalreports. If not, see . */
package net.sf.nervalreports.converters;
import java.io.File;
import java.io.FileInputStream;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.util.concurrent.TimeUnit;
import org.apache.commons.io.FileUtils;
import net.sf.nervalreports.core.ReportGenerator;
import net.sf.nervalreports.core.TextualFileConverter;
import net.sf.nervalreports.core.TextualFileConverterUtils;
/** Converter from TeX files to PDF.
*
* Note: This converter needs a 'pdflatex' executable avaiable in the default path. In other
* words, a full TeX workspace, usually TeXLive (https://www.tug.org/texlive/), although should work
* with any implementation, as long as it provides all packages needed by the TeX
* {@link ReportGenerator} used.
* @author farrer */
public class TeXToPDFConverter extends TextualFileConverter {
/** Maximun time, in seconds, to wait for each pdflatex command call to finish. */
private static final int DEFAULT_PDFTEX_TIMEOUT_SECONDS = 60;
/** The singleton instance of this class. */
private static final TeXToPDFConverter INSTANCE = new TeXToPDFConverter();
private TeXToPDFConverter() {
}
/** @return the single instance {@link TeXToPDFConverter} available. */
public static final TeXToPDFConverter getInstance() {
return INSTANCE;
}
/** {@inheritDoc} */
@Override
public byte[] doConvert(String textualFileAsString, Charset charset) throws Exception {
File tempDir = Files.createTempDirectory("nerval_reports").toFile();
/* Save the .tex file temporally, so we can compile it. */
File texFile = File.createTempFile("report", ".tex", tempDir);
FileUtils.write(texFile, textualFileAsString, charset);
/* Generate the pdflatex command. Note that '--shel-escape' is needed to 'base64 -d' execution, necessary
* to insert base64 imagens in the report. Also, '--halt-on-error' is needed to avoid waiting until timeout
* when some error on the compilation occurs (usually due to bad formed .tex file). */
ProcessBuilder procesBuilder = new ProcessBuilder().command("pdflatex", "--shell-escape", "--halt-on-error", texFile.getAbsolutePath())
.directory(tempDir);
/* Do the first compilation. */
Process execution = procesBuilder.start();
execution.waitFor(DEFAULT_PDFTEX_TIMEOUT_SECONDS, TimeUnit.SECONDS);
if (execution.exitValue() != 0) {
/* Note that the default error and warnings from pdflatex is stdout, not stderr.*/
throw new RuntimeException(TextualFileConverterUtils.getProcessOutputAsString(execution, false));
}
/* Do the second compilation, needed for number of total pages, for example (but also for other things). */
execution = procesBuilder.start();
execution.waitFor(DEFAULT_PDFTEX_TIMEOUT_SECONDS, TimeUnit.SECONDS);
if (execution.exitValue() != 0) {
throw new RuntimeException(TextualFileConverterUtils.getProcessOutputAsString(execution, false));
}
/* Load the generated pdf file. */
File pdfFile = new File(texFile.getAbsolutePath().replaceAll("tex", "pdf"));
byte fileContent[];
try (FileInputStream inputStream = new FileInputStream(pdfFile);) {
fileContent = new byte[(int) pdfFile.length()];
inputStream.read(fileContent);
}
/* Delete all created files by deleting the temporary created directory. */
FileUtils.deleteDirectory(tempDir);
return fileContent;
}
/** {@inheritDoc} */
@Override
public String getContentType() {
return "application/pdf";
}
/** {@inheritDoc} */
@Override
public String getFileExtension() {
return "pdf";
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy