diff options
author | smallsql <smallsql> | 2009-11-01 15:03:01 +0300 |
---|---|---|
committer | smallsql <smallsql> | 2009-11-01 15:03:01 +0300 |
commit | f65cead627f2afb37b256af177bec08c40023865 (patch) | |
tree | dadfbc9538238b32c59355413b6acc1e9a4f3bcc /openjdk/sun/print | |
parent | 8877fb077d825bc0f09b4c7966975299b73faeee (diff) |
Printing API next step
Diffstat (limited to 'openjdk/sun/print')
-rw-r--r-- | openjdk/sun/print/Win32PrintJob.java | 377 | ||||
-rw-r--r-- | openjdk/sun/print/Win32PrintService.java | 223 | ||||
-rw-r--r-- | openjdk/sun/print/Win32PrintServiceLookup.java | 6 |
3 files changed, 573 insertions, 33 deletions
diff --git a/openjdk/sun/print/Win32PrintJob.java b/openjdk/sun/print/Win32PrintJob.java index 1b6b68aa..5d315d06 100644 --- a/openjdk/sun/print/Win32PrintJob.java +++ b/openjdk/sun/print/Win32PrintJob.java @@ -23,13 +23,26 @@ */ package sun.print; +import java.awt.Graphics; +import java.awt.image.BufferedImage; +import java.awt.print.PageFormat; +import java.awt.print.Pageable; +import java.awt.print.Printable; +import java.awt.print.PrinterException; import java.awt.print.PrinterJob; +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStream; +import java.net.URI; import java.net.URL; import java.util.ArrayList; import javax.print.CancelablePrintJob; import javax.print.Doc; +import javax.print.DocFlavor; import javax.print.PrintException; import javax.print.PrintService; import javax.print.attribute.Attribute; @@ -41,14 +54,30 @@ import javax.print.attribute.PrintJobAttribute; import javax.print.attribute.PrintJobAttributeSet; import javax.print.attribute.PrintRequestAttribute; import javax.print.attribute.PrintRequestAttributeSet; +import javax.print.attribute.standard.Copies; +import javax.print.attribute.standard.Destination; import javax.print.attribute.standard.DocumentName; +import javax.print.attribute.standard.Fidelity; import javax.print.attribute.standard.JobName; import javax.print.attribute.standard.JobOriginatingUserName; +import javax.print.attribute.standard.Media; +import javax.print.attribute.standard.MediaSize; +import javax.print.attribute.standard.MediaSizeName; +import javax.print.attribute.standard.OrientationRequested; +import javax.print.attribute.standard.PrinterIsAcceptingJobs; +import javax.print.attribute.standard.PrinterState; +import javax.print.attribute.standard.PrinterStateReason; +import javax.print.attribute.standard.PrinterStateReasons; import javax.print.attribute.standard.RequestingUserName; +import javax.print.attribute.standard.SheetCollate; import javax.print.event.PrintJobAttributeListener; import javax.print.event.PrintJobEvent; import javax.print.event.PrintJobListener; +import sun.awt.windows.WPrinterJob; + +import cli.System.Drawing.Printing.*; + /** * @author Volker Berlin */ @@ -62,6 +91,7 @@ public class Win32PrintJob implements CancelablePrintJob{ private final Win32PrintService service; + private boolean fidelity; private boolean printing; private boolean printReturned; @@ -71,10 +101,28 @@ public class Win32PrintJob implements CancelablePrintJob{ private PrintJobAttributeSet jobAttrSet; private PrinterJob job; + private Doc doc; + private String mDestination; - - Win32PrintJob(Win32PrintService service){ + /* these variables used globally to store reference to the print + * data retrieved as a stream. On completion these are always closed + * if non-null. + */ + private InputStream instream; + + /* default values overridden by those extracted from the attributes */ + private String jobName = "Java Printing"; + private int copies; + private MediaSizeName mediaName; + private MediaSize mediaSize; + private OrientationRequested orient; + + private final PrintPeer peer; + private PrinterException printerException; + + Win32PrintJob(Win32PrintService service, PrintPeer peer){ this.service = service; + this.peer = peer; } @@ -228,15 +276,209 @@ public class Win32PrintJob implements CancelablePrintJob{ @Override public void print(Doc doc, PrintRequestAttributeSet attributes) throws PrintException{ - // TODO Auto-generated method stub + + synchronized(this){ + if(printing){ + throw new PrintException("already printing"); + }else{ + printing = true; + } + } + + PrinterState prnState = (PrinterState)service.getAttribute(PrinterState.class); + if(prnState == PrinterState.STOPPED){ + PrinterStateReasons prnStateReasons = (PrinterStateReasons)service.getAttribute(PrinterStateReasons.class); + if((prnStateReasons != null) && (prnStateReasons.containsKey(PrinterStateReason.SHUTDOWN))){ + throw new PrintException("PrintService is no longer available."); + } + } + + if((PrinterIsAcceptingJobs)(service.getAttribute(PrinterIsAcceptingJobs.class)) == PrinterIsAcceptingJobs.NOT_ACCEPTING_JOBS){ + throw new PrintException("Printer is not accepting job."); + } + + this.doc = doc; + /* check if the parameters are valid before doing much processing */ + DocFlavor flavor = doc.getDocFlavor(); + Object data; + try{ - initializeAttributeSets(doc, attributes); - System.err.println("Win32PrintJob.print:" + attributes); - }finally{ + data = doc.getPrintData(); + }catch(IOException e){ + notifyEvent(PrintJobEvent.JOB_FAILED); + throw new PrintException("can't get print data: " + e.toString()); + } + + if(flavor == null || (!service.isDocFlavorSupported(flavor))){ + notifyEvent(PrintJobEvent.JOB_FAILED); + throw new PrintJobFlavorException("invalid flavor", flavor); + } + + initializeAttributeSets(doc, attributes); + + getAttributeValues(flavor); + + String repClassName = flavor.getRepresentationClassName(); + + if(flavor.equals(DocFlavor.INPUT_STREAM.GIF) || flavor.equals(DocFlavor.INPUT_STREAM.JPEG) + || flavor.equals(DocFlavor.INPUT_STREAM.PNG) || flavor.equals(DocFlavor.BYTE_ARRAY.GIF) + || flavor.equals(DocFlavor.BYTE_ARRAY.JPEG) || flavor.equals(DocFlavor.BYTE_ARRAY.PNG)){ + try{ + instream = doc.getStreamForBytes(); + if(instream == null){ + notifyEvent(PrintJobEvent.JOB_FAILED); + throw new PrintException("No stream for data"); + } + printableJob(new ImagePrinter(instream)); + service.wakeNotifier(); + return; + }catch(ClassCastException cce){ + notifyEvent(PrintJobEvent.JOB_FAILED); + throw new PrintException(cce); + }catch(IOException ioe){ + notifyEvent(PrintJobEvent.JOB_FAILED); + throw new PrintException(ioe); + } + }else if(flavor.equals(DocFlavor.URL.GIF) || flavor.equals(DocFlavor.URL.JPEG) + || flavor.equals(DocFlavor.URL.PNG)){ + try{ + printableJob(new ImagePrinter((URL)data)); + service.wakeNotifier(); + return; + }catch(ClassCastException cce){ + notifyEvent(PrintJobEvent.JOB_FAILED); + throw new PrintException(cce); + } + }else if(repClassName.equals("java.awt.print.Pageable")){ + try{ + pageableJob((Pageable)doc.getPrintData()); + service.wakeNotifier(); + return; + }catch(ClassCastException cce){ + notifyEvent(PrintJobEvent.JOB_FAILED); + throw new PrintException(cce); + }catch(IOException ioe){ + notifyEvent(PrintJobEvent.JOB_FAILED); + throw new PrintException(ioe); + } + }else if(repClassName.equals("java.awt.print.Printable")){ + try{ + printableJob((Printable)doc.getPrintData()); + service.wakeNotifier(); + return; + }catch(ClassCastException cce){ + notifyEvent(PrintJobEvent.JOB_FAILED); + throw new PrintException(cce); + }catch(IOException ioe){ + notifyEvent(PrintJobEvent.JOB_FAILED); + throw new PrintException(ioe); + } + }else if(repClassName.equals("[B") || repClassName.equals("java.io.InputStream") + || repClassName.equals("java.net.URL")){ + + if(repClassName.equals("java.net.URL")){ + URL url = (URL)data; + try{ + instream = url.openStream(); + }catch(IOException e){ + notifyEvent(PrintJobEvent.JOB_FAILED); + throw new PrintException(e.toString()); + } + }else{ + try{ + instream = doc.getStreamForBytes(); + }catch(IOException ioe){ + notifyEvent(PrintJobEvent.JOB_FAILED); + throw new PrintException(ioe.toString()); + } + } + + if(instream == null){ + notifyEvent(PrintJobEvent.JOB_FAILED); + throw new PrintException("No stream for data"); + } + + if(mDestination != null){ // if destination attribute is set + try{ + FileOutputStream fos = new FileOutputStream(mDestination); + byte[] buffer = new byte[1024]; + int cread; + + while((cread = instream.read(buffer, 0, buffer.length)) >= 0){ + fos.write(buffer, 0, cread); + } + fos.flush(); + fos.close(); + }catch(FileNotFoundException fnfe){ + notifyEvent(PrintJobEvent.JOB_FAILED); + throw new PrintException(fnfe.toString()); + }catch(IOException ioe){ + notifyEvent(PrintJobEvent.JOB_FAILED); + throw new PrintException(ioe.toString()); + } + notifyEvent(PrintJobEvent.DATA_TRANSFER_COMPLETE); + notifyEvent(PrintJobEvent.JOB_COMPLETE); + service.wakeNotifier(); + return; + } + + notifyEvent(PrintJobEvent.JOB_FAILED); + throw new PrintException("Print job failed. IKVM does not support raw data currently."); + }else{ + notifyEvent(PrintJobEvent.JOB_FAILED); + throw new PrintException("unrecognized class: " + repClassName); + } + } + + + public void printableJob(Printable printable) throws PrintException { + throw new PrintException("Win32PrintJob.printableJob() not implemented:"); + } + + public void pageableJob(Pageable pageable) throws PrintException { + try { + System.err.println("pageableJob"); + PrintDocument printDocument = createPrintDocument(); + + //TODO Attribute set in printDocument + printDocument.add_PrintPage(new PrintPageEventHandler(new PrintPage(pageable))); + System.err.println("Print"); + printDocument.Print(); + if(printerException != null){ + throw printerException; + } + System.err.println("after Print"); + //TODO throw exception on Cancel + notifyEvent(PrintJobEvent.DATA_TRANSFER_COMPLETE); + return; + } catch (PrinterException pe) { + notifyEvent(PrintJobEvent.JOB_FAILED); + throw new PrintException(pe); + } finally { printReturned = true; + notifyEvent(PrintJobEvent.NO_MORE_EVENTS); } } + + + private PrintDocument createPrintDocument(){ + PrintDocument printDocument = new PrintDocument(); + PrinterSettings settings = printDocument.get_PrinterSettings(); + + Attribute destination = reqAttrSet.get(Destination.class); + if(destination instanceof Destination){ + settings.set_PrintFileName(((Destination)destination).getURI().toString()); + } + settings.set_Copies((short)copies); + if(copies > 1){ + Attribute collate = reqAttrSet.get(SheetCollate.class); + settings.set_Collate(collate == SheetCollate.COLLATED); + } + + return printDocument; + } + /* * There's some inefficiency here as the job set is created even though it may never be requested. @@ -314,6 +556,73 @@ public class Win32PrintJob implements CancelablePrintJob{ jobAttrSet = AttributeSetUtilities.unmodifiableView(jobAttrSet); } + private void getAttributeValues(DocFlavor flavor) throws PrintException { + + if (reqAttrSet.get(Fidelity.class) == Fidelity.FIDELITY_TRUE) { + fidelity = true; + } else { + fidelity = false; + } + + Class category; + Attribute [] attrs = reqAttrSet.toArray(); + for (int i=0; i<attrs.length; i++) { + Attribute attr = attrs[i]; + category = attr.getCategory(); + if (fidelity == true) { + if (!service.isAttributeCategorySupported(category)) { + notifyEvent(PrintJobEvent.JOB_FAILED); + throw new PrintJobAttributeException( + "unsupported category: " + category, category, null); + } else if + (!service.isAttributeValueSupported(attr, flavor, null)) { + notifyEvent(PrintJobEvent.JOB_FAILED); + throw new PrintJobAttributeException( + "unsupported attribute: " + attr, null, attr); + } + } + if (category == Destination.class) { + URI uri = ((Destination)attr).getURI(); + if (!"file".equals(uri.getScheme())) { + notifyEvent(PrintJobEvent.JOB_FAILED); + throw new PrintException("Not a file: URI"); + } else { + try { + mDestination = (new File(uri)).getPath(); + } catch (Exception e) { + throw new PrintException(e); + } + // check write access + SecurityManager security = System.getSecurityManager(); + if (security != null) { + try { + security.checkWrite(mDestination); + } catch (SecurityException se) { + notifyEvent(PrintJobEvent.JOB_FAILED); + throw new PrintException(se); + } + } + } + } else if (category == JobName.class) { + jobName = ((JobName)attr).getValue(); + } else if (category == Copies.class) { + copies = ((Copies)attr).getValue(); + } else if (category == Media.class) { + if (attr instanceof MediaSizeName) { + mediaName = (MediaSizeName)attr; + // If requested MediaSizeName is not supported, + // get the corresponding media size - this will + // be used to create a new PageFormat. + if (!service.isAttributeValueSupported(attr, null, null)) { + mediaSize = MediaSize.getMediaSizeForName(mediaName); + } + } + } else if (category == OrientationRequested.class) { + orient = (OrientationRequested)attr; + } + } + } + @Override public void cancel() throws PrintException{ @@ -330,4 +639,60 @@ public class Win32PrintJob implements CancelablePrintJob{ } } + + private class PrintPage implements PrintPageEventHandler.Method{ + + private final Pageable pageable; + private int pageIndex; + + + PrintPage(Pageable pageable){ + this.pageable = pageable; + //TODO firstPage + //TODO lastPage + //TODO PageRange + //TODO Num Copies + //TODO collatedCopies + } + + + @Override + public void Invoke(Object paramObject, PrintPageEventArgs ev){ + + try{ + System.err.println("Invoke:"+paramObject); + Printable printable = pageable.getPrintable(pageIndex); + PageFormat pageFormat = pageable.getPageFormat(pageIndex); + + BufferedImage pBand = new BufferedImage(1, 1, BufferedImage.TYPE_3BYTE_BGR); + PeekGraphics peekGraphics = new PeekGraphics(pBand.createGraphics(), job); + + /* + * Because Sun is calling first with a PeekGraphics that we do it else for compatibility + */ + if(pageIndex == 0){ + int pageResult = printable.print(peekGraphics, pageFormat, pageIndex); + if(pageResult != Printable.PAGE_EXISTS){ + ev.set_HasMorePages(false); + ev.set_Cancel(true); + return; + } + } + Graphics printGraphics = peer.createGraphics(ev.get_Graphics()); + printable.print(printGraphics, pageFormat, pageIndex++); + + printable = pageable.getPrintable(pageIndex); + pageFormat = pageable.getPageFormat(pageIndex); + int pageResult = printable.print(peekGraphics, pageFormat, pageIndex); + ev.set_HasMorePages(pageResult == Printable.PAGE_EXISTS); + }catch(PrinterException ex){ + printerException = ex; + ex.printStackTrace(); + ev.set_HasMorePages(false); + } + + } + + } + } diff --git a/openjdk/sun/print/Win32PrintService.java b/openjdk/sun/print/Win32PrintService.java index 2bd1c931..d028d4b0 100644 --- a/openjdk/sun/print/Win32PrintService.java +++ b/openjdk/sun/print/Win32PrintService.java @@ -23,53 +23,206 @@ */ package sun.print; +import java.util.ArrayList; + import javax.print.DocFlavor; import javax.print.DocPrintJob; import javax.print.PrintService; import javax.print.ServiceUIFactory; import javax.print.attribute.Attribute; import javax.print.attribute.AttributeSet; +import javax.print.attribute.AttributeSetUtilities; +import javax.print.attribute.HashPrintServiceAttributeSet; import javax.print.attribute.PrintServiceAttribute; import javax.print.attribute.PrintServiceAttributeSet; +import javax.print.attribute.standard.Chromaticity; +import javax.print.attribute.standard.ColorSupported; +import javax.print.attribute.standard.Copies; +import javax.print.attribute.standard.Destination; +import javax.print.attribute.standard.Fidelity; +import javax.print.attribute.standard.JobName; +import javax.print.attribute.standard.Media; +import javax.print.attribute.standard.MediaPrintableArea; +import javax.print.attribute.standard.OrientationRequested; +import javax.print.attribute.standard.PageRanges; +import javax.print.attribute.standard.PrintQuality; +import javax.print.attribute.standard.PrinterIsAcceptingJobs; +import javax.print.attribute.standard.PrinterName; +import javax.print.attribute.standard.PrinterResolution; +import javax.print.attribute.standard.PrinterState; +import javax.print.attribute.standard.PrinterStateReasons; +import javax.print.attribute.standard.QueuedJobCount; +import javax.print.attribute.standard.RequestingUserName; +import javax.print.attribute.standard.SheetCollate; +import javax.print.attribute.standard.Sides; import javax.print.event.PrintServiceAttributeListener; - +import cli.System.Drawing.Printing.PrinterSettings; /** * @author Volker Berlin */ public class Win32PrintService implements PrintService{ - public Win32PrintService(String string){ - // TODO Auto-generated constructor stub + private static final DocFlavor[] supportedFlavors = { + DocFlavor.SERVICE_FORMATTED.PAGEABLE, + DocFlavor.SERVICE_FORMATTED.PRINTABLE, + }; + + /* it turns out to be inconvenient to store the other categories + * separately because many attributes are in multiple categories. + */ + private static Class[] otherAttrCats = { + JobName.class, + RequestingUserName.class, + Copies.class, + Destination.class, + OrientationRequested.class, + PageRanges.class, + Media.class, + MediaPrintableArea.class, + Fidelity.class, + // We support collation on 2D printer jobs, even if the driver can't. + SheetCollate.class, + SunAlternateMedia.class, + Chromaticity.class + }; + + private final PrintPeer peer; + + private final String printer; + private final PrinterSettings settings; + private PrinterName name; + + transient private ServiceNotifier notifier = null; + + public Win32PrintService(String name, PrintPeer peer){ + if(name == null){ + throw new IllegalArgumentException("null printer name"); + } + this.peer = peer; + printer = name; + settings = new PrinterSettings(); + settings.set_PrinterName(printer); + } + + + @Override + public String getName(){ + return printer; + } + + + private PrinterName getPrinterName(){ + if(name == null){ + name = new PrinterName(printer, null); + } + return name; } + public void wakeNotifier() { + synchronized (this) { + if (notifier != null) { + notifier.wake(); + } + } + } + + @Override public void addPrintServiceAttributeListener(PrintServiceAttributeListener listener){ - // TODO Auto-generated method stub + synchronized (this) { + if (listener == null) { + return; + } + if (notifier == null) { + notifier = new ServiceNotifier(this); + } + notifier.addListener(listener); + } + } + + @Override + public void removePrintServiceAttributeListener(PrintServiceAttributeListener listener){ + synchronized (this) { + if (listener == null || notifier == null ) { + return; + } + notifier.removeListener(listener); + if (notifier.isEmpty()) { + notifier.stopNotifier(); + notifier = null; + } + } } @Override public DocPrintJob createPrintJob(){ - // TODO Auto-generated method stub - return null; + SecurityManager security = System.getSecurityManager(); + if(security != null){ + security.checkPrintJobAccess(); + } + return new Win32PrintJob(this, peer); } @Override public <T extends PrintServiceAttribute>T getAttribute(Class<T> category){ - // TODO Auto-generated method stub - return null; + if(category == null){ + throw new NullPointerException("category"); + } + if(!(PrintServiceAttribute.class.isAssignableFrom(category))){ + throw new IllegalArgumentException("Not a PrintServiceAttribute"); + } + if(category == ColorSupported.class){ + if(settings.get_SupportsColor()){ + return (T)ColorSupported.SUPPORTED; + }else{ + return (T)ColorSupported.NOT_SUPPORTED; + } + }else if(category == PrinterName.class){ + return (T)getPrinterName(); + }else if(category == PrinterState.class){ + return (T)PrinterState.UNKNOWN; // TODO + }else if(category == PrinterStateReasons.class){ + return null; // TODO + }else{ + // QueuedJobCount and PrinterIsAcceptingJobs + return (T)peer.getPrinterStatus(printer, category); + } } @Override public PrintServiceAttributeSet getAttributes(){ - // TODO Auto-generated method stub - return null; + PrintServiceAttributeSet attrs = new HashPrintServiceAttributeSet(); + attrs.add(getPrinterName()); + PrinterIsAcceptingJobs acptJobs = getAttribute(PrinterIsAcceptingJobs.class); + if(acptJobs != null){ + attrs.add(acptJobs); + } + PrinterState prnState = getAttribute(PrinterState.class); + if(prnState != null){ + attrs.add(prnState); + } + PrinterStateReasons prnStateReasons = getAttribute(PrinterStateReasons.class); + if(prnStateReasons != null){ + attrs.add(prnStateReasons); + } + QueuedJobCount jobCount = getAttribute(QueuedJobCount.class); + if(jobCount != null){ + attrs.add(jobCount); + } + if(settings.get_SupportsColor()){ + attrs.add(ColorSupported.SUPPORTED); + }else{ + attrs.add(ColorSupported.NOT_SUPPORTED); + } + + return AttributeSetUtilities.unmodifiableView(attrs); } @@ -81,13 +234,6 @@ public class Win32PrintService implements PrintService{ @Override - public String getName(){ - // TODO Auto-generated method stub - return null; - } - - - @Override public ServiceUIFactory getServiceUIFactory(){ // TODO Auto-generated method stub return null; @@ -96,8 +242,20 @@ public class Win32PrintService implements PrintService{ @Override public Class<?>[] getSupportedAttributeCategories(){ - // TODO Auto-generated method stub - return null; + ArrayList<Class> categList = new ArrayList<Class>(otherAttrCats.length+3); + for (int i=0; i < otherAttrCats.length; i++) { + categList.add(otherAttrCats[i]); + } + + if (settings.get_CanDuplex()) { + categList.add(Sides.class); + } + + if (settings.get_PrinterResolutions().get_Count() > 0) { + categList.add(PrinterResolution.class); + } + + return categList.toArray(new Class[categList.size()]); } @@ -111,8 +269,10 @@ public class Win32PrintService implements PrintService{ @Override public DocFlavor[] getSupportedDocFlavors(){ - // TODO Auto-generated method stub - return null; + int len = supportedFlavors.length; + DocFlavor[] result = new DocFlavor[len]; + System.arraycopy(supportedFlavors, 0, result, 0, len); + return result; } @@ -139,15 +299,30 @@ public class Win32PrintService implements PrintService{ @Override public boolean isDocFlavorSupported(DocFlavor flavor){ - // TODO Auto-generated method stub + for (int f=0; f<supportedFlavors.length; f++) { + if (flavor.equals(supportedFlavors[f])) { + return true; + } + } return false; } @Override - public void removePrintServiceAttributeListener(PrintServiceAttributeListener listener){ - // TODO Auto-generated method stub + public String toString(){ + return "Win32 Printer : " + getName(); + } + + @Override + public boolean equals(Object obj){ + return (obj == this || (obj instanceof Win32PrintService && ((Win32PrintService)obj).getName() + .equals(getName()))); } + + @Override + public int hashCode(){ + return this.getClass().hashCode() + getName().hashCode(); + } } diff --git a/openjdk/sun/print/Win32PrintServiceLookup.java b/openjdk/sun/print/Win32PrintServiceLookup.java index f5eb2f41..bb87b5ec 100644 --- a/openjdk/sun/print/Win32PrintServiceLookup.java +++ b/openjdk/sun/print/Win32PrintServiceLookup.java @@ -92,7 +92,7 @@ public class Win32PrintServiceLookup extends PrintServiceLookup { newServices[p] = defService; } else { if (printServices == null) { - newServices[p] = new Win32PrintService(printers[p]); + newServices[p] = new Win32PrintService(printers[p], peer); } else { int j; for (j = 0; j < printServices.length; j++) { @@ -104,7 +104,7 @@ public class Win32PrintServiceLookup extends PrintServiceLookup { } } if (j == printServices.length) { - newServices[p] = new Win32PrintService(printers[p]); + newServices[p] = new Win32PrintService(printers[p], peer); } } } @@ -257,7 +257,7 @@ public class Win32PrintServiceLookup extends PrintServiceLookup { } if (defaultPrintService == null) { - defaultPrintService = new Win32PrintService(defaultPrinter); + defaultPrintService = new Win32PrintService(defaultPrinter, peer); } return defaultPrintService; } |