8066139: Null return from PrintJob.getGraphics() running closed/java/awt/PrintJob/HighResTest/HighResTest.java
authorpsadhukhan
Wed, 16 Mar 2016 15:00:57 +0530
changeset 36886 c56d9d689225
parent 36885 75de89bc3d0d
child 36887 b05841864f56
8066139: Null return from PrintJob.getGraphics() running closed/java/awt/PrintJob/HighResTest/HighResTest.java Reviewed-by: prr, jdv Contributed-by: philip.race@oracle.com, prasanta.sadhukhan@oracle.com
jdk/src/java.desktop/share/classes/sun/print/PrintJob2D.java
jdk/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java
jdk/test/java/awt/PrintJob/HighResTest.java
--- a/jdk/src/java.desktop/share/classes/sun/print/PrintJob2D.java	Tue Mar 15 22:40:38 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/sun/print/PrintJob2D.java	Wed Mar 16 15:00:57 2016 +0530
@@ -995,6 +995,7 @@
     public void run() {
 
         try {
+            attributes.remove(PageRanges.class);
             printerJob.print(attributes);
         } catch (PrinterException e) {
             //REMIND: need to store this away and not rethrow it.
--- a/jdk/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java	Tue Mar 15 22:40:38 2016 -0700
+++ b/jdk/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java	Wed Mar 16 15:00:57 2016 +0530
@@ -1212,6 +1212,7 @@
         pageRangesAttr =  (PageRanges)attributes.get(PageRanges.class);
         if (!isSupportedValue(pageRangesAttr, attributes)) {
             pageRangesAttr = null;
+            setPageRange(-1, -1);
         } else {
             if ((SunPageSelection)attributes.get(SunPageSelection.class)
                      == SunPageSelection.RANGE) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/PrintJob/HighResTest.java	Wed Mar 16 15:00:57 2016 +0530
@@ -0,0 +1,412 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. 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.
+ *
+ * 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+  @test
+  @bug 4227128 8066139
+  @summary  Test printing at resolutions > 72dpi
+  @author dpm: area=awt.print
+  @run main/manual HighResTest
+ */
+import java.awt.Button;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.awt.JobAttributes;
+import java.awt.PageAttributes;
+import java.awt.PrintJob;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.JobAttributes.DialogType;
+import java.awt.JobAttributes.SidesType;
+import java.awt.PageAttributes.OrientationRequestedType;
+import java.awt.PageAttributes.OriginType;
+import java.awt.Dialog;
+import java.awt.Panel;
+import java.awt.TextArea;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+public class HighResTest {
+    static Frame f = new Frame();
+
+    private static void init() {
+        String[] instructions = {
+            "To be able to run this test it is required to have a default",
+         "printer configured in your user environment.",
+         "If no default printer exists, then test passes.",
+         " ",
+         "There will be 2 print dialogs.  The first dialog should show",
+         "portrait as the selected orientation.  The 2nd dialog should show",
+         "landscape as the selected orientation.",
+         " ",
+         "Visual inspection of the printed pages is needed. A passing",
+         "test will print 2 pages in portrait and 2 pages in landscape.",
+         "The pages have on the center of the page the text \"Center\"",
+         "2 rectangles will appear above and below it, the one below is",
+         "filled."
+        };
+        Sysout.createDialog();
+        Sysout.printInstructions(instructions);
+
+        PrintJob job = null;
+        Dimension dim = null;
+        JobAttributes jobAttributes = new JobAttributes();
+        PageAttributes pageAttributes = new PageAttributes();
+        String center = "Center";
+        Font font = new Font("SansSerif", Font.PLAIN, 200);
+        FontMetrics metrics = null;
+        int width = 0;
+        Graphics g = null;
+
+        jobAttributes.setDialog(DialogType.NATIVE);
+        pageAttributes.setOrigin(OriginType.PRINTABLE);
+        pageAttributes.setPrinterResolution(new int[]{1200, 1200, 3});
+        pageAttributes.setOrientationRequested(
+                OrientationRequestedType.PORTRAIT);
+        jobAttributes.setSides(SidesType.TWO_SIDED_LONG_EDGE);
+
+        job = f.getToolkit().getPrintJob(f, "Portrait Test", jobAttributes,
+                                          pageAttributes);
+        if (job != null) {
+            dim = job.getPageDimension();
+            for (int i = 0; i < 2; i++) {
+                g = job.getGraphics();
+
+                g.drawLine(0, 0, dim.width, 0);
+                g.drawLine(dim.width, 0, dim.width, dim.height);
+                g.drawLine(dim.width, dim.height, 0, dim.height);
+                g.drawLine(0, dim.height, 0, 0);
+
+                g.drawRect(dim.width / 2 - 200, dim.height / 3 - 300, 400, 600);
+                g.fillRect(dim.width / 2 - 200, 2 * dim.height / 3 - 300, 400, 600);
+
+                g.setFont(font);
+                metrics = g.getFontMetrics();
+                width = metrics.stringWidth(center);
+                g.setColor(Color.black);
+                g.drawString(center, (dim.width / 2) - (width / 2), dim.height / 2);
+
+                g.dispose();
+            }
+            job.end();
+            job = null;
+        }
+
+        pageAttributes.setOrientationRequested(
+                OrientationRequestedType.LANDSCAPE);
+
+        job = f.getToolkit().getPrintJob(f, "Landscape Test", jobAttributes,
+                                             pageAttributes);
+        if (job != null) {
+            dim = job.getPageDimension();
+            for (int i = 0; i < 2; i++) {
+                g = job.getGraphics();
+                g.drawLine(0, 0, dim.width, 0);
+                g.drawLine(dim.width, 0, dim.width, dim.height);
+                g.drawLine(dim.width, dim.height, 0, dim.height);
+                g.drawLine(0, dim.height, 0, 0);
+
+                g.drawRect(dim.width / 2 - 200, dim.height / 3 - 300, 400, 600);
+                g.fillRect(dim.width / 2 - 200, 2 * dim.height / 3 - 300, 400, 600);
+
+                g.setFont(font);
+                metrics = g.getFontMetrics();
+                width = metrics.stringWidth(center);
+                g.setColor(Color.black);
+                g.drawString(center, (dim.width / 2) - (width / 2), dim.height / 2);
+
+                g.dispose();
+            }
+            job.end();
+            job = null;
+        }
+        System.out.println("done");
+    }
+
+
+
+    /**
+     * ***************************************************
+     * Standard Test Machinery Section      DO NOT modify anything in this section -- it's a
+      standard chunk of code which has all of the
+      synchronisation necessary for the test harness.
+      By keeping it the same in all tests, it is easier
+      to read and understand someone else's test, as
+      well as insuring that all tests behave correctly
+      with the test harness.
+     There is a section following this for test-defined
+      classes
+    *****************************************************
+     */
+    private static boolean theTestPassed = false;
+    private static boolean testGeneratedInterrupt = false;
+    private static String failureMessage = "";
+
+    private static Thread mainThread = null;
+
+    private static int sleepTime = 300000;
+
+    public static void main(String args[]) throws InterruptedException    {
+        mainThread = Thread.currentThread();
+        try {
+            init();
+        } catch (TestPassedException e) {
+            //The test passed, so just return from main and harness will
+            // interepret this return as a pass
+            return;
+        }
+        //At this point, neither test passed nor test failed has been
+        // called -- either would have thrown an exception and ended the
+        // test, so we know we have multiple threads.
+
+        //Test involves other threads, so sleep and wait for them to
+        // called pass() or fail()
+        try {
+            Thread.sleep(sleepTime);
+            //Timed out, so fail the test
+            throw new RuntimeException("Timed out after " + sleepTime / 1000 + " seconds");
+        } catch (InterruptedException e) {
+            if (!testGeneratedInterrupt) {
+                throw e;
+            }
+
+            //reset flag in case hit this code more than once for some reason (just safety)
+            testGeneratedInterrupt = false;
+            if (theTestPassed == false) {
+                throw new RuntimeException(failureMessage);
+            }
+        }
+
+    }//main
+
+    public static synchronized void setTimeoutTo(int seconds)    {
+        sleepTime = seconds * 1000;
+    }
+
+    public static synchronized void pass()    {
+        Sysout.println("The test passed.");
+        //first check if this is executing in main thread
+        if (mainThread == Thread.currentThread()) {
+            //Still in the main thread, so set the flag just for kicks,
+            // and throw a test passed exception which will be caught
+            // and end the test.
+            theTestPassed = true;
+            throw new TestPassedException();
+        }
+        //pass was called from a different thread, so set the flag and interrupt
+        // the main thead.
+        theTestPassed = true;
+        testGeneratedInterrupt = true;
+        mainThread.interrupt();
+        Sysout.dispose();
+    }//pass()
+
+    public static synchronized void fail()    {
+        //test writer didn't specify why test failed, so give generic
+        fail("it just plain failed! :-)");
+    }
+
+    public static synchronized void fail(String whyFailed)    {
+        Sysout.println("The test failed: " + whyFailed);
+        //check if this called from main thread
+        if (mainThread == Thread.currentThread()) {
+            //If main thread, fail now 'cause not sleeping
+            throw new RuntimeException(whyFailed);
+        }
+        theTestPassed = false;
+        testGeneratedInterrupt = true;
+        failureMessage = whyFailed;
+        mainThread.interrupt();
+        Sysout.dispose();
+    }//fail()
+
+ }// class HighResTest
+
+//This exception is used to exit from any level of call nesting
+// when it's determined that the test has passed, and immediately
+// end the test.
+class TestPassedException extends RuntimeException
+ {
+ }
+
+//*********** End Standard Test Machinery Section **********
+
+//************** End classes defined for the test *******************
+
+
+
+
+/****************************************************
+ Standard Test Machinery
+ DO NOT modify anything below -- it's a standard
+  chunk of code whose purpose is to make user
+  interaction uniform, and thereby make it simpler
+  to read and understand someone else's test.
+ ****************************************************/
+
+/**
+ This is part of the standard test machinery.
+ It creates a dialog (with the instructions), and is the interface
+  for sending text messages to the user.
+ To print the instructions, send an array of strings to Sysout.createDialog
+  WithInstructions method.  Put one line of instructions per array entry.
+ To display a message for the tester to see, simply call Sysout.println
+  with the string to be displayed.
+ This mimics System.out.println but works within the test harness as well
+  as standalone.
+ */
+
+class Sysout {
+    private static TestDialog dialog;
+
+    public static void createDialogWithInstructions(String[] instructions)    {
+        dialog = new TestDialog(new Frame(), "Instructions");
+        dialog.printInstructions(instructions);
+        println("Any messages for the tester will display here.");
+    }
+
+    public static void createDialog() {
+        dialog = new TestDialog(new Frame(), "Instructions");
+        String[] defInstr = {"Instructions will appear here. ", ""};
+        dialog.printInstructions(defInstr);
+        println("Any messages for the tester will display here.");
+    }
+
+
+    public static void printInstructions(String[] instructions)    {
+        dialog.printInstructions(instructions);
+    }
+
+
+    public static void println(String messageIn)    {
+        dialog.displayMessage(messageIn);
+    }
+
+    public static void dispose() {
+        Sysout.println("Shutting down the Java process..");
+        HighResTest.f.dispose();
+        dialog.dispose();
+    }
+ }// Sysout  class
+
+/**
+  This is part of the standard test machinery.  It provides a place for the
+   test instructions to be displayed, and a place for interactive messages
+   to the user to be displayed.
+  To have the test instructions displayed, see Sysout.
+  To have a message to the user be displayed, see Sysout.
+  Do not call anything in this dialog directly.
+  */
+class TestDialog extends Dialog implements ActionListener
+{
+
+    TextArea instructionsText;
+    TextArea messageText;
+    int maxStringLength = 80;
+    Panel buttonP = new Panel();
+    Button passB = new Button("pass");
+    Button failB = new Button("fail");
+
+    //DO NOT call this directly, go through Sysout
+    public TestDialog(Frame frame, String name)    {
+        super(frame, name);
+        int scrollBoth = TextArea.SCROLLBARS_BOTH;
+        instructionsText = new TextArea("", 15, maxStringLength, scrollBoth);
+        add("North", instructionsText);
+
+        messageText = new TextArea("", 5, maxStringLength, scrollBoth);
+        add("Center", messageText);
+
+        passB = new Button("pass");
+        passB.setActionCommand("pass");
+        passB.addActionListener(this);
+        buttonP.add("East", passB);
+
+        failB = new Button("fail");
+        failB.setActionCommand("fail");
+        failB.addActionListener(this);
+        buttonP.add("West", failB);
+
+        add("South", buttonP);
+        pack();
+
+        show();
+    }// TestDialog()
+
+    //DO NOT call this directly, go through Sysout
+    public void printInstructions(String[] instructions)    {
+        //Clear out any current instructions
+        instructionsText.setText("");
+
+        //Go down array of instruction strings
+
+        String printStr, remainingStr;
+        for (int i = 0; i < instructions.length; i++) {
+            //chop up each into pieces maxSringLength long
+            remainingStr = instructions[i];
+            while (remainingStr.length() > 0) {
+                //if longer than max then chop off first max chars to print
+                if (remainingStr.length() >= maxStringLength) {
+                    //Try to chop on a word boundary
+                    int posOfSpace = remainingStr.
+                            lastIndexOf(' ', maxStringLength - 1);
+
+                    if (posOfSpace <= 0) {
+                        posOfSpace = maxStringLength - 1;
+                    }
+
+                    printStr = remainingStr.substring(0, posOfSpace + 1);
+                    remainingStr = remainingStr.substring(posOfSpace + 1);
+                } //else just print
+                else {
+                    printStr = remainingStr;
+                    remainingStr = "";
+                }
+
+                instructionsText.append(printStr + "\n");
+
+            }// while
+
+        }// for
+
+    }//printInstructions()
+
+    //DO NOT call this directly, go through Sysout
+    public void displayMessage(String messageIn)    {
+        messageText.append(messageIn + "\n");
+    }
+
+    //catch presses of the passed and failed buttons.
+    //simply call the standard pass() or fail() static methods of
+    //HighResTest
+    public void actionPerformed(ActionEvent e)    {
+        if (e.getActionCommand() == "pass") {
+            HighResTest.pass();
+        } else {
+            HighResTest.fail();
+        }
+    }
+}// TestDialog  class