net.sf.jasperreports.engine.export.JRPrintServiceExporter Maven / Gradle / Ivy
The newest version!
/*
* JasperReports - Free Java Reporting Library.
* Copyright (C) 2001 - 2023 Cloud Software Group, Inc. All rights reserved.
* http://www.jaspersoft.com
*
* Unless you have purchased a commercial license agreement from Jaspersoft,
* the following license terms apply:
*
* This program is part of JasperReports.
*
* JasperReports 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.
*
* JasperReports 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 JasperReports. If not, see .
*/
package net.sf.jasperreports.engine.export;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.print.PageFormat;
import java.awt.print.Paper;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.util.ArrayList;
import java.util.List;
import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import javax.print.attribute.Attribute;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.HashPrintServiceAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.PrintServiceAttributeSet;
import javax.print.attribute.standard.MediaPrintableArea;
import javax.print.attribute.standard.OrientationRequested;
import javax.print.attribute.standard.PageRanges;
import javax.print.attribute.standard.PrinterIsAcceptingJobs;
import net.sf.jasperreports.engine.DefaultJasperReportsContext;
import net.sf.jasperreports.engine.JRAbstractExporter;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRPropertiesUtil;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReportsContext;
import net.sf.jasperreports.engine.print.JRPrinterAWT;
import net.sf.jasperreports.export.ExporterInputItem;
import net.sf.jasperreports.export.ExporterOutput;
import net.sf.jasperreports.export.PrintServiceExporterConfiguration;
import net.sf.jasperreports.export.PrintServiceReportConfiguration;
import net.sf.jasperreports.export.SimpleExporterInput;
import net.sf.jasperreports.export.SimpleGraphics2DExporterOutput;
import net.sf.jasperreports.export.SimpleGraphics2DReportConfiguration;
/**
* Prints a JasperReports document using the Java Print Service API.
*
* There are four ways of using the Java Print Service with the Java 2D API:
*
* - Printing 2D graphics using
java.awt.print.PrinterJob
* - Streaming 2D graphics using
java.awt.print.PrinterJob
* - Printing 2D graphics using
javax.print.DocPrintJob
and a service-formatted javax.print.DocFlavor
* - Streaming 2D graphics using
javax.print.DocPrintJob
and a service-formatted javax.print.DocFlavor
*
*
* The {@link net.sf.jasperreports.engine.export.JRPrintServiceExporter}
* implementation takes the first approach and uses some of the methods added to the
* java.awt.print.PrinterJob
class:
*
* - Static convenience methods to look up print services that can image 2D graphics,
* which are returned as an array of
PrintService
or
* StreamPrintServiceFactory
objects depending on the method
* - Methods to set and get a
PrintService
on a PrinterJob
* - A
pageDialog()
method that takes a PrintRequestAttributeSet
parameter
* - A
printDialog()()
method that takes a PrintRequestAttributeSet
parameter
* - A print method that takes a
PrintRequestAttributeSet
parameter
*
* Looking Up a Printing Service
* This exporter tries to find a print service that supports the necessary attributes. The set of
* attributes can be supplied to the exporter in the form of a
* javax.print.attribute.PrintServiceAttributeSet
object that is passed as the
* value for the special
* {@link net.sf.jasperreports.export.PrintServiceExporterConfiguration#getPrintServiceAttributeSet() getPrintServiceAttributeSet()}
* exporter configuration setting. For more
* details about the attributes that can be part of such an attribute set, check the Java Print
* Service API documentation.
*
* The lookup procedure might return one or more print services able to handle the
* specified print service attributes. If so, the exporter uses the first one in the list. If no
* suitable print service is found, then the exporter throws an exception. As an alternative, a
* javax.print.PrintService
instance can be passed in using the
* {@link net.sf.jasperreports.export.PrintServiceExporterConfiguration#getPrintService() getPrintService()}
* exporter configuration setting when users do not want the Java Print Service to search for an
* available print service.
* Configuring the Printer Job
* Once a print service has been located, it is associated with a PrinterJob
instance.
* Further customization is made by passing a
* javax.print.attribute.PrintRequestAttributeSet
instance when calling the
* print()
method on the PrinterJob
object to start the printing process.
*
* To supply the javax.print.attribute.PrintRequestAttributeSet
object
* containing the desired javax.print.attribute.PrintRequestAttribute
values to
* the exporter, set the special
* {@link net.sf.jasperreports.export.PrintServiceExporterConfiguration#getPrintRequestAttributeSet() getPrintRequestAttributeSet()}
* exporter configuration setting.
* Displaying Print Dialogs
* If this exporter is invoked by a desktop or client-side Java application, you can offer the
* end user a final chance to customize the printer job before the printing process actually
* starts. The exporter has two other predefined configuration settings:
* {@link net.sf.jasperreports.export.PrintServiceExporterConfiguration#isDisplayPageDialog() isDisplayPageDialog()}
* and
* {@link net.sf.jasperreports.export.PrintServiceExporterConfiguration#isDisplayPrintDialog() isDisplayPrintDialog()},
* both receiving java.lang.Boolean
values, which show or
* suppress the page dialog and/or the print dialog associated with the PrinterJob
* instance.
*
* The two dialogs are cross-platform. They enable users to alter the print service attributes
* and the print request attributes that are already set for the current print service and printer
* job. They also allow canceling the current printing procedure altogether. When batch
* printing a set of documents, if
* {@link net.sf.jasperreports.export.PrintServiceExporterConfiguration#isDisplayPageDialog() isDisplayPageDialog()} or
* {@link net.sf.jasperreports.export.PrintServiceExporterConfiguration#isDisplayPrintDialog() isDisplayPrintDialog()} are
* set to true, a dialog window will pop up each time a document in the list is to be
* printed. This is very useful if you intend to set different printing options for each
* document. However, setting the same page/printing options each time would quickly
* become cumbersome. If same settings are intended for all documents in the list, the
* exporter provides two additional predefined export configuration settings:
* {@link net.sf.jasperreports.export.PrintServiceExporterConfiguration#isDisplayPageDialogOnlyOnce() isDisplayPageDialogOnlyOnce()} and
* {@link net.sf.jasperreports.export.PrintServiceExporterConfiguration#isDisplayPrintDialogOnlyOnce() isDisplayPrintDialogOnlyOnce()}. These
* are only effective if the corresponding
* {@link net.sf.jasperreports.export.PrintServiceExporterConfiguration#isDisplayPageDialog() isDisplayPageDialog()} or
* {@link net.sf.jasperreports.export.PrintServiceExporterConfiguration#isDisplayPrintDialog() isDisplayPrintDialog()} are
* set to true.
*
* If {@link net.sf.jasperreports.export.PrintServiceExporterConfiguration#isDisplayPageDialogOnlyOnce() isDisplayPageDialogOnlyOnce()}
* is true, then the page dialog will open only
* once, and the export options set within will be preserved for all documents in the list.
* The same thing happens when
* {@link net.sf.jasperreports.export.PrintServiceExporterConfiguration#isDisplayPrintDialogOnlyOnce() isDisplayPrintDialogOnlyOnce()}
* is set to true - the print dialog will open only once.
*
* Below is an example of configuring the print service exporter taken from the supplied
* /demo/ samples/printservice
sample:
*
* public void print() throws JRException
* {
* PrintRequestAttributeSet printRequestAttributeSet = new HashPrintRequestAttributeSet();
* printRequestAttributeSet.add(MediaSizeName.ISO_A4);
*
* PrintServiceAttributeSet printServiceAttributeSet = new HashPrintServiceAttributeSet();
* //printServiceAttributeSet.add(new PrinterName("Epson Stylus 820 ESC/P 2", null));
* //printServiceAttributeSet.add(new PrinterName("hp LaserJet 1320 PCL 6", null));
* //printServiceAttributeSet.add(new PrinterName("PDFCreator", null));
*
* JRPrintServiceExporter exporter = new JRPrintServiceExporter();
*
* exporter.setExporterInput(new SimpleExporterInput("build/reports/PrintServiceReport.jrprint"));
* SimplePrintServiceExporterConfiguration configuration = new SimplePrintServiceExporterConfiguration();
* configuration.setPrintRequestAttributeSet(printRequestAttributeSet);
* configuration.setPrintServiceAttributeSet(printServiceAttributeSet);
* configuration.setDisplayPageDialog(false);
* configuration.setDisplayPrintDialog(true);
* exporter.setConfiguration(configuration);
* exporter.exportReport();
* System.err.println("Printing time : " + (System.currentTimeMillis() - start));
* }
*
* @see net.sf.jasperreports.export.PrintServiceExporterConfiguration
* @author Teodor Danciu ([email protected])
*/
public class JRPrintServiceExporter extends JRAbstractExporter implements Printable
{
protected static final String PRINT_SERVICE_EXPORTER_PROPERTIES_PREFIX = JRPropertiesUtil.PROPERTY_PREFIX + "export.print.service.";
public static final String EXCEPTION_MESSAGE_KEY_PRINT_SERVICE_NOT_FOUND = "export.print.service.not.found";
/**
*
*/
protected JRGraphics2DExporter exporter;
protected SimpleGraphics2DReportConfiguration grxConfiguration;
protected int reportIndex;
private PrintService printService;
private Boolean[] printStatus;
protected class ExporterContext extends BaseExporterContext
{
}
/**
* @see #JRPrintServiceExporter(JasperReportsContext)
*/
public JRPrintServiceExporter()
{
this(DefaultJasperReportsContext.getInstance());
}
/**
*
*/
public JRPrintServiceExporter(JasperReportsContext jasperReportsContext)
{
super(jasperReportsContext);
exporterContext = new ExporterContext();
}
@Override
protected Class getConfigurationInterface()
{
return PrintServiceExporterConfiguration.class;
}
@Override
protected Class getItemConfigurationInterface()
{
return PrintServiceReportConfiguration.class;
}
@Override
protected void ensureOutput()
{
//nothing to do
}
@Override
public void exportReport() throws JRException
{
/* */
ensureJasperReportsContext();
ensureInput();
initExport();
ensureOutput();
try
{
PrintServiceExporterConfiguration configuration = getCurrentConfiguration();
PrintServiceAttributeSet printServiceAttributeSet = configuration.getPrintServiceAttributeSet();
if (printServiceAttributeSet == null)
{
printServiceAttributeSet = new HashPrintServiceAttributeSet();
}
boolean displayPageDialog = false;
boolean displayPageDialogOnlyOnce = false;
boolean displayPrintDialog = false;
boolean displayPrintDialogOnlyOnce = false;
Boolean pageDialog = configuration.isDisplayPageDialog();
if (pageDialog != null)
{
displayPageDialog = pageDialog;
}
Boolean pageDialogOnlyOnce = configuration.isDisplayPageDialogOnlyOnce();
if (displayPageDialog && pageDialogOnlyOnce != null)
{
// it can be (eventually) set to true only if displayPageDialog is true
displayPageDialogOnlyOnce = pageDialogOnlyOnce;
}
Boolean printDialog = configuration.isDisplayPrintDialog();
if (printDialog != null)
{
displayPrintDialog = printDialog;
}
Boolean printDialogOnlyOnce = configuration.isDisplayPrintDialogOnlyOnce();
if (displayPrintDialog && printDialogOnlyOnce != null)
{
// it can be (eventually) set to true only if displayPrintDialog is true
displayPrintDialogOnlyOnce = printDialogOnlyOnce;
}
PrinterJob printerJob = PrinterJob.getPrinterJob();
JRPrinterAWT.initPrinterJobFields(printerJob);
printerJob.setPrintable(this);
printStatus = null;
// determining the print service only once
printService = configuration.getPrintService();
if (printService == null) {
PrintService[] services = PrintServiceLookup.lookupPrintServices(null, printServiceAttributeSet);
if (services.length > 0)
{
printService = services[0];
}
}
if (printService == null)
{
throw
new JRException(
EXCEPTION_MESSAGE_KEY_PRINT_SERVICE_NOT_FOUND,
(Object[])null
);
}
try
{
printerJob.setPrintService(printService);
}
catch (PrinterException e)
{
throw new JRException(e);
}
List items = exporterInput.getItems();
PrintRequestAttributeSet printRequestAttributeSet = null;
if(displayPrintDialogOnlyOnce || displayPageDialogOnlyOnce)
{
printRequestAttributeSet = new HashPrintRequestAttributeSet();
setDefaultPrintRequestAttributeSet(printRequestAttributeSet);
setOrientation(items.get(0).getJasperPrint(), printRequestAttributeSet);
if(displayPageDialogOnlyOnce)
{
if(printerJob.pageDialog(printRequestAttributeSet) == null)
{
return;
}
else
{
displayPageDialog = false;
}
}
if(displayPrintDialogOnlyOnce)
{
if(!printerJob.printDialog(printRequestAttributeSet))
{
printStatus = new Boolean[]{Boolean.FALSE};
return;
}
else
{
displayPrintDialog = false;
}
}
}
List status = new ArrayList<>();
// fix for bug ID artf1455 from jasperforge.org bug database
for(reportIndex = 0; reportIndex < items.size(); reportIndex++)
{
ExporterInputItem item = items.get(reportIndex);
setCurrentExporterInputItem(item);
PrintServiceReportConfiguration lcItemConfiguration = getCurrentItemConfiguration();
exporter = new JRGraphics2DExporter(jasperReportsContext);
exporter.setExporterInput(new SimpleExporterInput(jasperPrint));
grxConfiguration = new SimpleGraphics2DReportConfiguration();
grxConfiguration.setProgressMonitor(lcItemConfiguration.getProgressMonitor());
grxConfiguration.setOffsetX(lcItemConfiguration.getOffsetX());
grxConfiguration.setOffsetY(lcItemConfiguration.getOffsetY());
grxConfiguration.setZoomRatio(lcItemConfiguration.getZoomRatio());
// exporter.setParameter(JRExporterParameter.CLASS_LOADER, classLoader);
// exporter.setParameter(JRExporterParameter.URL_HANDLER_FACTORY, urlHandlerFactory);
// exporter.setParameter(JRExporterParameter.FILE_RESOLVER, fileResolver);
grxConfiguration.setExporterFilter(filter);
grxConfiguration.setMinimizePrinterJobSize(lcItemConfiguration.isMinimizePrinterJobSize());
if(displayPrintDialog || displayPageDialog ||
(!displayPrintDialogOnlyOnce && !displayPageDialogOnlyOnce))
{
printRequestAttributeSet = new HashPrintRequestAttributeSet();
setDefaultPrintRequestAttributeSet(printRequestAttributeSet);
setOrientation(jasperPrint, printRequestAttributeSet);
}
try
{
PageRange pageRange = getPageRange();
int startPageIndex = (pageRange == null || pageRange.getStartPageIndex() == null) ? 0 : pageRange.getStartPageIndex();
int endPageIndex = (pageRange == null || pageRange.getEndPageIndex() == null) ? (jasperPrint.getPages().size() - 1) : pageRange.getEndPageIndex();
if (items.size() == 1)
{
printRequestAttributeSet.add(new PageRanges(startPageIndex + 1, endPageIndex + 1));
}
printerJob.setJobName("JasperReports - " + jasperPrint.getName());
if (displayPageDialog)
{
printerJob.pageDialog(printRequestAttributeSet);
}
if (displayPrintDialog)
{
if (printerJob.printDialog(printRequestAttributeSet))
{
status.add(Boolean.TRUE);
printerJob.print(printRequestAttributeSet);
}
else
{
status.add(Boolean.FALSE);
}
}
else
{
PageFormat pageFormat = printerJob.defaultPage();
Paper paper = pageFormat.getPaper();
switch (jasperPrint.getOrientationValue())
{
case LANDSCAPE :
{
pageFormat.setOrientation(PageFormat.LANDSCAPE);
paper.setSize(jasperPrint.getPageHeight(), jasperPrint.getPageWidth());
paper.setImageableArea(
0,
0,
jasperPrint.getPageHeight(),
jasperPrint.getPageWidth()
);
break;
}
case PORTRAIT :
default :
{
pageFormat.setOrientation(PageFormat.PORTRAIT);
paper.setSize(jasperPrint.getPageWidth(), jasperPrint.getPageHeight());
paper.setImageableArea(
0,
0,
jasperPrint.getPageWidth(),
jasperPrint.getPageHeight()
);
}
}
// setting the paper object back as getPaper() returns a clone
pageFormat.setPaper(paper);
printerJob.setPrintable(this, pageFormat);
printerJob.print(printRequestAttributeSet);
}
}
catch (PrinterException e)
{
throw new JRException(e);
}
}
printStatus = status.toArray(new Boolean[status.size()]);
printService = printerJob.getPrintService();
}
finally
{
resetExportContext();
}
}
@Override
protected void initExport()
{
super.initExport();
}
@Override
protected void initReport()
{
super.initReport();
}
@Override
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException
{
if (Thread.interrupted())
{
throw new PrinterException("Current thread interrupted.");
}
if ( pageIndex < 0 || pageIndex >= jasperPrint.getPages().size() )
{
return Printable.NO_SUCH_PAGE;
}
SimpleGraphics2DExporterOutput output = new SimpleGraphics2DExporterOutput();
output.setGraphics2D((Graphics2D)graphics);
exporter.setExporterOutput(output);
grxConfiguration.setPageIndex(pageIndex);
exporter.setConfiguration(grxConfiguration);
try
{
exporter.exportReport();
}
catch (JRException e)
{
throw new PrinterException(e.getMessage()); //NOPMD
}
return Printable.PAGE_EXISTS;
}
private void setOrientation(JasperPrint jPrint,PrintRequestAttributeSet printRequestAttributeSet)
{
if (!printRequestAttributeSet.containsKey(MediaPrintableArea.class))
{
int printableWidth;
int printableHeight;
switch (jPrint.getOrientationValue())
{
case LANDSCAPE:
printableWidth = jPrint.getPageHeight();
printableHeight = jPrint.getPageWidth();
break;
default:
printableWidth = jPrint.getPageWidth();
printableHeight = jPrint.getPageHeight();
break;
}
printRequestAttributeSet.add(
new MediaPrintableArea(
0f,
0f,
printableWidth / 72f,
printableHeight / 72f,
MediaPrintableArea.INCH
)
);
}
if (!printRequestAttributeSet.containsKey(OrientationRequested.class))
{
OrientationRequested orientation;
switch (jPrint.getOrientationValue())
{
case LANDSCAPE:
orientation = OrientationRequested.LANDSCAPE;
break;
default:
orientation = OrientationRequested.PORTRAIT;
break;
}
printRequestAttributeSet.add(orientation);
}
}
private void setDefaultPrintRequestAttributeSet(PrintRequestAttributeSet printRequestAttributeSet)
{
PrintRequestAttributeSet configPrintRequestAttributeSet = getCurrentConfiguration().getPrintRequestAttributeSet();
if (configPrintRequestAttributeSet != null)
{
printRequestAttributeSet.addAll(configPrintRequestAttributeSet);
}
}
// artf1936
public static boolean checkAvailablePrinters()
{
PrintService[] ss = java.awt.print.PrinterJob.lookupPrintServices();
for (int i=0;ijava.lang.Boolean values, one for each appearance of the print dialog during the last export operation.
* A Boolean.TRUE value in this array means that for that particular occurrence of the print dialog, the OK button was hit.
* A Boolean.FALSE value means the respective print dialog was canceled.
*/
public Boolean[] getPrintStatus()
{
return printStatus;
}
/**
* Returns the {@link PrintService} instance used by the exporter last time the exportReport() method was run.
*/
public PrintService getPrintService()
{
return printService;
}
@Override
public String getExporterKey()
{
return null;
}
@Override
public String getExporterPropertiesPrefix()
{
return PRINT_SERVICE_EXPORTER_PROPERTIES_PREFIX;
}
}