gt:                 Copies c = (Copies)svc.getDefaultAttributeValue(Copies.class);
context: /*
   * Copyright 2000-2006 Sun Microsystems, Inc.  All Rights Reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.  Sun designates this
   * particular file as subject to the "Classpath" exception as provided
   * by Sun in the LICENSE file that accompanied this code.
   *
   * This code 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 General Public License
   * version 2 for more details (a copy is included in the LICENSE file that
   * accompanied this code).
   *
   * You should have received a copy of the GNU General Public License version
   * 2 along with this work; if not, write to the Free Software Foundation,
   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   *
   * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   * CA 95054 USA or visit www.sun.com if you need additional information or
   * have any questions.
   */
  
  package sun.print;
  
  import java.net.URI;
  import java.io.BufferedInputStream;
  import java.io.BufferedOutputStream;
  import java.io.File;
  import java.io.FileOutputStream;
  import java.io.InputStream;
  import java.io.OutputStream;
  import java.io.InputStream;
  import java.io.IOException;
  import java.io.FileNotFoundException;
  import java.io.Reader;
  import java.net.URL;
  import java.util.Vector;
  
  import javax.print.CancelablePrintJob;
  import javax.print.Doc;
  import javax.print.DocFlavor;
  import javax.print.DocPrintJob;
  import javax.print.PrintService;
  import javax.print.PrintException;
  import javax.print.event.PrintJobEvent;
  import javax.print.event.PrintJobListener;
  import javax.print.event.PrintJobAttributeListener;
  
  import javax.print.attribute.Attribute;
  import javax.print.attribute.AttributeSet;
  import javax.print.attribute.AttributeSetUtilities;
  import javax.print.attribute.DocAttributeSet;
  import javax.print.attribute.HashPrintJobAttributeSet;
  import javax.print.attribute.HashPrintRequestAttributeSet;
  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.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.RequestingUserName;
  import javax.print.attribute.standard.Destination;
  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 java.awt.print.*;
  
  public class Win32PrintJob implements CancelablePrintJob {
  
      transient private Vector jobListeners;
      transient private Vector attrListeners;
      transient private Vector listenedAttributeSets;
  
      private Win32PrintService service;
      private boolean fidelity;
      private boolean printing = false;
      private boolean printReturned = false;
      private PrintRequestAttributeSet reqAttrSet = null;
      private PrintJobAttributeSet jobAttrSet = null;
      private PrinterJob job;
      private Doc doc;
      private String mDestination = null;
  
      /* 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 = null;
      private Reader reader = null;
  
      /* default values overridden by those extracted from the attributes */
      private String jobName = "Java Printing";
      private int copies = 0;
      private MediaSizeName mediaName = null;
      private MediaSize     mediaSize = null;
      private OrientationRequested orient = null;
  
      /* print job handle used by native code */
      private long hPrintJob;
  
      /* buffer length for printing raw data */
      private static final int PRINTBUFFERLEN = 8192;
  
      Win32PrintJob(Win32PrintService service) {
          this.service = service;
      }
  
      public PrintService getPrintService() {
          return service;
      }
  
      public PrintJobAttributeSet getAttributes() {
          synchronized (this) {
              if (jobAttrSet == null) {
                  /* just return an empty set until the job is submitted */
                  PrintJobAttributeSet jobSet = new HashPrintJobAttributeSet();
                  return AttributeSetUtilities.unmodifiableView(jobSet);
              } else {
                return jobAttrSet;
              }
          }
      }
  
      public void addPrintJobListener(PrintJobListener listener) {
          synchronized (this) {
              if (listener == null) {
                  return;
              }
              if (jobListeners == null) {
                  jobListeners = new Vector();
              }
              jobListeners.add(listener);
          }
      }
  
      public void removePrintJobListener(PrintJobListener listener) {
          synchronized (this) {
              if (listener == null || jobListeners == null ) {
                  return;
              }
              jobListeners.remove(listener);
              if (jobListeners.isEmpty()) {
                  jobListeners = null;
              }
          }
      }
  
  
      /* Closes any stream already retrieved for the data.
       * We want to avoid unnecessarily asking the Doc to create a stream only
       * to get a reference in order to close it because the job failed.
       * If the representation class is itself a "stream", this
       * closes that stream too.
       */
      private void closeDataStreams() {
  
          if (doc == null) {
              return;
          }
  
          Object data = null;
  
          try {
              data = doc.getPrintData();
          } catch (IOException e) {
              return;
          }
  
          if (instream != null) {
              try {
                  instream.close();
              } catch (IOException e) {
              } finally {
                  instream = null;
              }
          }
          else if (reader != null) {
              try {
                  reader.close();
              } catch (IOException e) {
              } finally {
                  reader = null;
              }
          }
          else if (data instanceof InputStream) {
              try {
                  ((InputStream)data).close();
              } catch (IOException e) {
              }
          }
          else if (data instanceof Reader) {
              try {
                  ((Reader)data).close();
              } catch (IOException e) {
              }
          }
      }
  
      private void notifyEvent(int reason) {
  
          /* since this method should always get called, here's where
           * we will perform the clean up of any data stream supplied.
           */
          switch (reason) {
              case PrintJobEvent.DATA_TRANSFER_COMPLETE:
              case PrintJobEvent.JOB_CANCELED :
              case PrintJobEvent.JOB_FAILED :
              case PrintJobEvent.NO_MORE_EVENTS :
              case PrintJobEvent.JOB_COMPLETE :
                  closeDataStreams();
          }
  
          synchronized (this) {
              if (jobListeners != null) {
                  PrintJobListener listener;
                  PrintJobEvent event = new PrintJobEvent(this, reason);
                  for (int i = 0; i < jobListeners.size(); i++) {
                      listener = (PrintJobListener)(jobListeners.elementAt(i));
                      switch (reason) {
  
                          case PrintJobEvent.JOB_COMPLETE :
                              listener.printJobCompleted(event);
                              break;
  
                          case PrintJobEvent.JOB_CANCELED :
                              listener.printJobCanceled(event);
                              break;
  
                          case PrintJobEvent.JOB_FAILED :
                              listener.printJobFailed(event);
                              break;
  
                          case PrintJobEvent.DATA_TRANSFER_COMPLETE :
                              listener.printDataTransferCompleted(event);
                              break;
  
                          case PrintJobEvent.NO_MORE_EVENTS :
                              listener.printJobNoMoreEvents(event);
                              break;
  
                          default:
                              break;
                      }
                  }
              }
         }
      }
  
      public void addPrintJobAttributeListener(
                                    PrintJobAttributeListener listener,
                                    PrintJobAttributeSet attributes) {
          synchronized (this) {
              if (listener == null) {
                  return;
              }
              if (attrListeners == null) {
                  attrListeners = new Vector();
                  listenedAttributeSets = new Vector();
              }
              attrListeners.add(listener);
              if (attributes == null) {
                  attributes = new HashPrintJobAttributeSet();
              }
              listenedAttributeSets.add(attributes);
          }
      }
  
      public void removePrintJobAttributeListener(
                                          PrintJobAttributeListener listener) {
          synchronized (this) {
              if (listener == null || attrListeners == null ) {
                  return;
              }
              int index = attrListeners.indexOf(listener);
              if (index == -1) {
                  return;
              } else {
                  attrListeners.remove(index);
                  listenedAttributeSets.remove(index);
                  if (attrListeners.isEmpty()) {
                      attrListeners = null;
                      listenedAttributeSets = null;
                  }
              }
          }
      }
  
      public void print(Doc doc, PrintRequestAttributeSet attributes)
          throws PrintException {
  
          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 {
              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;
              }
  
              if (!startPrintRawData(service.getName(), jobName)) {
                  notifyEvent(PrintJobEvent.JOB_FAILED);
                  throw new PrintException("Print job failed to start.");
              }
              BufferedInputStream  bin = new BufferedInputStream(instream);
              int bread = 0;
              try {
                  byte[] buffer = new byte[PRINTBUFFERLEN];
  
                  while ((bread = bin.read(buffer, 0, PRINTBUFFERLEN)) >=0) {
                      if (!printRawData(buffer, bread)) {
                          bin.close();
                          notifyEvent(PrintJobEvent.JOB_FAILED);
                          throw new PrintException ("Problem while spooling data");
                      }
                  }
                  bin.close();
                  if (!endPrintRawData()) {
                      notifyEvent(PrintJobEvent.JOB_FAILED);
                      throw new PrintException("Print job failed to close properly.");
                  }
                  notifyEvent(PrintJobEvent.DATA_TRANSFER_COMPLETE);
              } catch (IOException e) {
                  notifyEvent(PrintJobEvent.JOB_FAILED);
                  throw new PrintException (e.toString());
              } finally {
                  notifyEvent(PrintJobEvent.NO_MORE_EVENTS);
              }
          } else {
              notifyEvent(PrintJobEvent.JOB_FAILED);
              throw new PrintException("unrecognized class: "+repClassName);
          }
          service.wakeNotifier();
      }
  
      public void printableJob(Printable printable) throws PrintException {
          try {
              synchronized(this) {
                  if (job != null) { // shouldn't happen
                      throw new PrintException("already printing");
                  } else {
                      job = new sun.awt.windows.WPrinterJob();
                  }
              }
              PrintService svc = getPrintService();
              job.setPrintService(svc);
              if (copies == 0) {
  