import java.io.*; import java.nio.file.*; import java.util.concurrent.TimeUnit; public class PDFPrinter { // Default values private static final String DEFAULT_PRINTER = "null_printer"; private static final String DEFAULT_FILE_PATH = "/usr/local/tomee/output/SystemtestScott.pdf"; public static void main(String[] args) { String filePath = DEFAULT_FILE_PATH; String printerName = DEFAULT_PRINTER; System.out.println("=== PDF Printing Utility ==="); // Parse command line arguments for (int i = 0; i < args.length; i++) { if (args[i].equals("-d") && i + 1 < args.length) { // -d option: specify printer printerName = args[i + 1]; i++; // Skip next argument since we used it } else if (args[i].equals("-h") || args[i].equals("--help")) { // Help option printHelp(); System.exit(0); } else if (args[i].equals("-l") || args[i].equals("--list")) { // List printers option try { listAvailablePrinters(); } catch (Exception e) { System.err.println("ERROR: Failed to list printers: " + e.getMessage()); } System.exit(0); } else if (!args[i].startsWith("-")) { // Positional argument: treat as file path filePath = args[i]; } else { System.err.println("ERROR: Unknown option: " + args[i]); printHelp(); System.exit(1); } } // Display selected options System.out.println("Target file: " + filePath); System.out.println("Printer: " + printerName); try { boolean success = printPDF(filePath, printerName); if (success) { System.out.println("SUCCESS: Print job submitted successfully!"); System.exit(0); } else { System.out.println("FAILURE: Print job failed"); System.exit(1); } } catch (Exception e) { System.err.println("ERROR: " + e.getMessage()); System.exit(1); } } /** * Display help message */ private static void printHelp() { System.out.println("Usage: java PDFPrinter [options] [file-path]"); System.out.println(); System.out.println("Options:"); System.out.println(" -d Specify printer name (default: null_printer)"); System.out.println(" -l, --list List available printers"); System.out.println(" -h, --help Display this help message"); System.out.println(); System.out.println("Examples:"); System.out.println(" java PDFPrinter"); System.out.println(" Prints default file to null_printer printer"); System.out.println(); System.out.println(" java PDFPrinter -d HP-LaserJet"); System.out.println(" Prints default file to HP-LaserJet printer"); System.out.println(); System.out.println(" java PDFPrinter /path/to/file.pdf"); System.out.println(" Prints specified file to null_printer printer"); System.out.println(); System.out.println(" java PDFPrinter /path/to/file.pdf -d Office-Printer"); System.out.println(" Prints specified file to Office-Printer"); System.out.println(); System.out.println("Default values:"); System.out.println(" File: " + DEFAULT_FILE_PATH); System.out.println(" Printer: " + DEFAULT_PRINTER); } /** * Prints a PDF file using the Linux 'lp' command * * @param filePath Path to the PDF file * @param printerName Printer name (cannot be null, default is "null_printer") * @return true if print job submitted successfully * @throws IOException if file not found or command fails * @throws InterruptedException if process interrupted */ public static boolean printPDF(String filePath, String printerName) throws IOException, InterruptedException { // Validate printer name is not null or empty if (printerName == null || printerName.trim().isEmpty()) { printerName = DEFAULT_PRINTER; } // 1. Validate the file exists and is readable System.out.println("Validating PDF file..."); Path pdfPath = Paths.get(filePath); if (!Files.exists(pdfPath)) { throw new IOException("File does not exist: " + filePath); } if (!Files.isReadable(pdfPath)) { throw new IOException("File is not readable: " + filePath); } if (!filePath.toLowerCase().endsWith(".pdf")) { System.out.println("Warning: File does not have .pdf extension"); } long fileSize = Files.size(pdfPath); System.out.println("File validation passed"); System.out.println("File size: " + fileSize + " bytes"); // 2. Build the lp command - ALWAYS use -d option with printerName ProcessBuilder pb; System.out.println("Using printer: " + printerName); pb = new ProcessBuilder("lp", "-d", printerName, filePath); // 3. Configure ProcessBuilder pb.redirectErrorStream(true); // Combine stdout and stderr // 4. Execute the command System.out.println("Executing: " + String.join(" ", pb.command())); Process process; try { process = pb.start(); } catch (IOException e) { throw new IOException("Failed to start lp command. Is CUPS/lp installed? " + "Install with: sudo apt-get install cups-client", e); } // 5. Capture and display output StringBuilder output = new StringBuilder(); try (BufferedReader reader = new BufferedReader( new InputStreamReader(process.getInputStream()))) { String line; while ((line = reader.readLine()) != null) { output.append(line).append("\n"); System.out.println("lp output: " + line); } } // 6. Wait for completion with timeout (60 seconds) System.out.println("Waiting for print job submission..."); boolean completed = process.waitFor(60, TimeUnit.SECONDS); if (!completed) { process.destroyForcibly(); throw new IOException("Print command timed out after 60 seconds"); } // 7. Check exit code int exitCode = process.exitValue(); if (exitCode == 0) { // Success - extract job ID if available String response = output.toString(); if (response.contains("request id is")) { String jobId = extractJobId(response); System.out.println("Print job ID: " + jobId); } return true; } else { // Failure - provide helpful error messages String errorMsg = output.toString().trim(); if (errorMsg.contains("No such file or directory")) { throw new IOException("lp command not found. Install CUPS: sudo apt-get install cups-client"); } else if (errorMsg.contains("Unable to open")) { throw new IOException("Printer error: " + errorMsg); } else if (errorMsg.contains("invalid destination")) { throw new IOException("Invalid printer name: " + printerName + ". Use -l option to list available printers."); } else if (errorMsg.contains("Unsupported format")) { throw new IOException("PDF format not supported by printer"); } else if (!errorMsg.isEmpty()) { throw new IOException("Print failed: " + errorMsg); } else { throw new IOException("Print failed with exit code: " + exitCode); } } } /** * Extracts print job ID from lp output */ private static String extractJobId(String response) { // Example: "request id is HP-LaserJet-123 (1 file(s))" if (response.contains("request id is")) { String[] parts = response.split("request id is"); if (parts.length > 1) { String jobPart = parts[1].trim(); int endIndex = jobPart.indexOf(" ("); if (endIndex > 0) { return jobPart.substring(0, endIndex); } return jobPart; } } return "Unknown"; } /** * Utility method to check available printers */ public static void listAvailablePrinters() throws IOException, InterruptedException { System.out.println("\n=== Available Printers ==="); System.out.println("Looking for printers..."); ProcessBuilder pb = new ProcessBuilder("lpstat", "-p"); pb.redirectErrorStream(true); Process process = pb.start(); try (BufferedReader reader = new BufferedReader( new InputStreamReader(process.getInputStream()))) { boolean hasPrinters = false; String line; while ((line = reader.readLine()) != null) { if (line.startsWith("printer ")) { hasPrinters = true; String printerName = line.split("\\s+")[1]; String status = line.contains("enabled") ? "[ENABLED]" : "[DISABLED]"; System.out.println(status + " " + printerName); } } if (!hasPrinters) { System.out.println("No printers found via lpstat."); System.out.println("\nTroubleshooting steps:"); System.out.println("1. Check if CUPS is running: sudo systemctl status cups"); System.out.println("2. Check all print services: lpstat -v"); System.out.println("3. Install CUPS if needed: sudo apt-get install cups cups-client"); } else { System.out.println("\nNote: Default printer is 'null_printer'"); } } process.waitFor(); } }