13.5 Advanced Printing with Java 1.4
The Java 1.4 Printing API is substantially more complex than the Java
1.1 and Java 1.2 APIs. It is a command-line utility that can:
List available printers capable of handling specific printing
requests (color printing, collation, stapling, etc.) Query the status of a particular named printer Spool text or image files directly to a printer Convert GIF, JPEG, and PNG image files to PostScript files
Example 13-5 demonstrates some of these advanced
features. The example does not create a GUI, and, unlike the other
examples in this chapter, it prints without using a
Graphics object. The code is well-commented and
straightforward; the example is long only because it demonstrates
several different features of the Java 1.4 API.
Example 13-5. Print.java
package je3.print;
import javax.print.*;
import javax.print.event.*;
import javax.print.attribute.*;
import javax.print.attribute.standard.*;
import java.io.*;
/**
* This utility program demonstrates the javax.print API and allows you to
* list available printers, query a named printer, print text and image files
* to a printer, and print to PostScript files.
*
* Usage:
* java Print -i inputfile [-q] [-p printer] [-ps outputfile] [attributes]
**/
public class Print {
public static void main(String[ ] args) throws IOException {
// These are values we'll set from the command-line arguments
boolean query = false;
String printerName = null;
String inputFileName = null;
String outputFileName = null;
String outputFileType = null;
PrintRequestAttributeSet attributes =
new HashPrintRequestAttributeSet( );
// Loop through the arguments
for(int i = 0; i < args.length; i++) {
if (args[i].equals("-q")) query = true; // Is this a query?
else if (args[i].equals("-p")) // Specific printer name
printerName = args[++i];
else if (args[i].equals("-i")) // The file to print
inputFileName = args[++i];
else if (args[i].equals("-ps")) { // Print it to this file
// Sun's Java 1.4 implementation only supports PostScript
// output. Other implementations might offer PDF, for example.
outputFileName = args[++i];
outputFileType = "application/postscript";
}
// The rest of the arguments represent common printing attributes
else if (args[i].equals("-color")) // Request a color printer
attributes.add(Chromaticity.COLOR);
else if (args[i].equals("-landscape")) // Request landscape mode
attributes.add(OrientationRequested.LANDSCAPE);
else if (args[i].equals("-letter")) // US Letter-size paper
attributes.add(MediaSizeName.NA_LETTER);
else if (args[i].equals("-a4")) // European A4 paper
attributes.add(MediaSizeName.ISO_A4);
else if (args[i].equals("-staple")) // Request stapling
attributes.add(Finishings.STAPLE);
else if (args[i].equals("-collate")) // Collate multiple copies
attributes.add(SheetCollate.COLLATED);
else if (args[i].equals("-duplex")) // Request 2-sided
attributes.add(Sides.DUPLEX);
else if (args[i].equals("-2")) // 2 pages to a sheet
attributes.add(new NumberUp(2));
else if (args[i].equals("-copies")) // how many copies
attributes.add(new Copies(Integer.parseInt(args[++i])));
else {
System.out.println("Unknown argument: " + args[i]);
System.exit(1);
}
}
if (query) {
// If the -q argument was specified, but no printer was named,
// then list all available printers that can support the attributes
if (printerName == null) queryServices(attributes);
// Otherwise, look for a named printer that can support the
// attributes and print its status
else queryPrinter(printerName, attributes);
}
else if (outputFileName != null)
// If this is not a query and we have a filename, print to a file
printToFile(outputFileName, outputFileType,
inputFileName, attributes);
else
// Otherwise, print to the named printer, or to the default
// printer otherwise.
print(printerName, inputFileName, attributes);
// The main( ) method ends here, but there may be a printing thread
// operating in the background. So the program may not terminate
// until printing completes.
}
// List names of all PrintServices that can support the attributes
public static void queryServices(PrintRequestAttributeSet attributes) {
// Find all services that can support the specified attributes
PrintService[ ] services =
PrintServiceLookup.lookupPrintServices(null, attributes);
// Loop through available services
for(int i = 0; i < services.length; i++) {
// Print service name
System.out.print(services[i].getName( ));
// Then query and print the document types it can print
DocFlavor[ ] flavors = services[i].getSupportedDocFlavors( );
for(int j = 0; j < flavors.length; j++) {
// Filter out DocFlavors that have a representation class other
// than java.io.InputStream.
String repclass = flavors[j].getRepresentationClassName( );
if (!repclass.equals("java.io.InputStream"))continue;
System.out.println("\t" + flavors[j].getMimeType( ));
}
}
}
// List details about the named printer
public static void queryPrinter(String printerName,
PrintRequestAttributeSet attributes)
{
// Find the named printer
PrintService service = getNamedPrinter(printerName, attributes);
if (service == null) {
System.out.println(printerName + ": no such printer capable of " +
"handling the specified attributes");
return;
}
// Print status and other information about the printer
System.out.println(printerName + " status:");
Attribute[ ] attrs = service.getAttributes( ).toArray( );
for(int i = 0; i < attrs.length; i++)
System.out.println("\t" + attrs[i].getName( ) + ": " + attrs[i]);
}
// Print the contents of the named file to the named printer (or to a
// default printer if printerName is null) requesting the specified
// attributes.
public static void print(String printerName, String filename,
PrintRequestAttributeSet attributes)
throws IOException
{
// Look for a printer that can support the attributes
PrintService service = getNamedPrinter(printerName, attributes);
if (service == null) {
System.out.println("Can't find a printer " +
"with specified attributes");
return;
}
// Print the file to that printer. See method definition below
printToService(service, filename, attributes);
// Let the user know where to pick up their printout
System.out.println("Printed " + filename + " to " + service.getName( ));
}
// Print to an output file instead of a printer
public static void printToFile(String outputFileName,
String outputFileType,
String inputFileName,
PrintRequestAttributeSet attributes)
throws IOException
{
// Determine whether the system can print to the specified type, and
// get a factory object if so.
// The name of this static method is way too long!
StreamPrintServiceFactory[ ] factories = StreamPrintServiceFactory.
lookupStreamPrintServiceFactories(null, outputFileType);
// Error message if we can't print to the specified output type
if (factories.length == 0) {
System.out.println("Unable to print files of type: " +
outputFileType);
return;
}
// Open the output file
FileOutputStream out = new FileOutputStream(outputFileName);
// Get a PrintService object to print to that file
StreamPrintService service = factories[0].getPrintService(out);
// Print using the method below
printToService(service, inputFileName, attributes);
// And remember to close the output file
out.close( );
}
// Print the contents of the named file to the specified PrintService,
// requesting the specified attributes.
// This is shared code used by print( ) and printToFile( ) above.
public static void printToService(PrintService service, String filename,
PrintRequestAttributeSet attributes)
throws IOException
{
// Figure out what type of file we're printing
DocFlavor flavor = getFlavorFromFilename(filename);
// Open the file
InputStream in = new FileInputStream(filename);
// Create a Doc object to print from the file and flavor.
Doc doc = new SimpleDoc(in, flavor, null);
// Create a print job from the service
DocPrintJob job = service.createPrintJob( );
// Monitor the print job with a listener
job.addPrintJobListener(new PrintJobAdapter( ) {
public void printJobCompleted(PrintJobEvent e) {
System.out.println("Print job complete");
System.exit(0);
}
public void printDataTransferCompleted(PrintJobEvent e) {
System.out.println("Document transfered to printer");
}
public void printJobRequiresAttention(PrintJobEvent e) {
System.out.println("Print job requires attention");
System.out.println("Check printer: out of paper?");
}
public void printJobFailed(PrintJobEvent e) {
System.out.println("Print job failed");
System.exit(1);
}
});
// Now print the document, catching errors
try {
job.print(doc, attributes);
}
catch(PrintException e) {
System.out.println(e);
System.exit(1);
}
}
// A utility method to look up printers that can support the specified
// attributes and return the one that matches the specified name.
public static PrintService getNamedPrinter(String name,
PrintRequestAttributeSet attrs)
{
PrintService[ ] services =
PrintServiceLookup.lookupPrintServices(null, attrs);
if (services.length > 0) {
if (name == null) return services[0];
else {
for(int i = 0; i < services.length; i++) {
if (services[i].getName( ).equals(name)) return services[i];
}
}
}
return null;
}
// A utility method to return a DocFlavor object matching the
// extension of the filename.
public static DocFlavor getFlavorFromFilename(String filename) {
String extension = filename.substring(filename.lastIndexOf('.')+1);
extension = extension.toLowerCase( );
if (extension.equals("gif"))
return DocFlavor.INPUT_STREAM.GIF;
else if (extension.equals("jpeg"))
return DocFlavor.INPUT_STREAM.JPEG;
else if (extension.equals("jpg"))
return DocFlavor.INPUT_STREAM.JPEG;
else if (extension.equals("png"))
return DocFlavor.INPUT_STREAM.PNG;
else if (extension.equals("ps"))
return DocFlavor.INPUT_STREAM.POSTSCRIPT;
else if (extension.equals("txt"))
return DocFlavor.INPUT_STREAM.TEXT_PLAIN_HOST;
// Fallback: try to determine flavor from file content
else return DocFlavor.INPUT_STREAM.AUTOSENSE;
}
}
|