/*
* Copyright (c) 1997-2024 IDRsolutions (https://www.idrsolutions.com)
*/
package org.jpedal.examples;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
/**
* Helper class for converting Office documents to PDF using LibreOffice.
*/
public final class DocumentToPDFConverter {
private static final String TEMP_DIR;
static {
String tempDir = System.getProperty("java.io.tmpdir");
if (!tempDir.endsWith("/") && !tempDir.endsWith("\\")) {
tempDir += System.getProperty("file.separator");
}
TEMP_DIR = tempDir;
}
private DocumentToPDFConverter() {
}
/**
* Uses LibreOffice to convert an office document to PDF using the provided LibreOffice executable path.
* <p>
* Creates a file with the same name (with .pdf extension) in the same directory as the source file.
* <p>
* If the output file already exists, it will not be overwritten and an IOException will be thrown.
*
* @param document Office document to convert to PDF
* @param libreOfficeExecutablePath Absolute path for the LibreOffice executable to use to convert the document
* @param allowOverwrite Boolean flag on whether the output file can be overwritten
* @return The exit code of the LibreOffice process (usually 0 regardless of success or failure)
* @throws IOException If the LibreOffice executable was not found, the document does not exist, the document does
* not have a valid file extension, or the output file already exists (and allowOverwrite
* is set to false)
* @throws InterruptedException If the conversion process gets interrupted
*/
public static int convert(final File document, final String libreOfficeExecutablePath, final boolean allowOverwrite) throws IOException, InterruptedException {
if (!document.exists()) {
throw new FileNotFoundException(document.getAbsolutePath());
}
final int idx = document.getAbsolutePath().lastIndexOf('.');
if (idx < 1) {
throw new IOException("Document does not have a valid file extension: " + document.getAbsolutePath());
}
final String outputDocumentPath = document.getAbsolutePath().substring(0, idx) + ".pdf";
final File outputDocument = new File(outputDocumentPath);
if (outputDocument.exists()) {
if (allowOverwrite) {
outputDocument.delete();
} else {
throw new IOException("Output file already exists: " + outputDocumentPath);
}
}
// Use a unique profile directory to allow multiple conversions simultaneously
final String uniqueLOProfile = (TEMP_DIR + "LO-" + UUID.randomUUID()).replace('\\', '/'); // Requires a url (not a path)
final ProcessBuilder pb = new ProcessBuilder(libreOfficeExecutablePath,
"-env:UserInstallation=file:///" + uniqueLOProfile,
"--headless", "--convert-to", "pdf", document.getName());
pb.directory(document.getParentFile());
try {
return pb.start().waitFor();
} finally {
deleteFolder(new File(uniqueLOProfile));
}
}
/**
* Uses LibreOffice to convert an office document to PDF using the provided LibreOffice executable path.
* <p>
* Creates a file with the same name (with .pdf extension) in the same directory as the source file.
* <p>
* If the output file already exists, it will not be overwritten and an IOException will be thrown.
*
* @param document Office document to convert to PDF
* @param libreOfficeExecutablePath Absolute path for the LibreOffice executable to use to convert the document
* @return The exit code of the LibreOffice process (usually 0 regardless of success or failure)
* @throws IOException If the LibreOffice executable was not found, the document does not exist, the document does
* not have a valid file extension, or the output file already exists (will not overwrite)
* @throws InterruptedException If the conversion process gets interrupted
*/
public static int convert(final File document, final String libreOfficeExecutablePath) throws IOException, InterruptedException {
return convert(document, libreOfficeExecutablePath, false);
}
private static final String[] FILE_TYPES = {
"ODT", "FODT", "ODS", "FODS", "ODP", "FODP", "ODB", "ODG", "FODG", "ODF", // LibreOffice
"SXW", "STW", "SXC", "STC", "SXI", "STI", "SXD", "STD", "SXM", // OpenOffice
"DOCX", "XLSX", "PPTX",
"DOC", "DOT",
"PPT", "PPS", "POT",
"XLS", "XLW", "XLT"
};
private static final Set<String> FILE_TYPES_LIST = new HashSet<>(Arrays.asList(FILE_TYPES));
/**
* Returns whether the provided file has a convertible file type
*
* @param file file to check
* @return whether provided file is convertible
*/
public static boolean hasConvertibleFileType(final File file) {
final int idx = file.getAbsolutePath().lastIndexOf('.');
return idx > 0 && FILE_TYPES_LIST.contains(file.getAbsolutePath().substring(idx + 1).toUpperCase());
}
private static void deleteFolder(final File dirPath) {
final File[] files = dirPath.listFiles();
if (files != null) {
for (final File file : files) {
if (file.isDirectory()) {
deleteFolder(file);
}
file.delete();
}
}
dirPath.delete();
}
}
|