< prev index next >

test/jdk/java/awt/print/RemotePrinterStatusRefresh/RemotePrinterStatusRefresh.java

Print this page


   1 /*
   2  * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /**
  25  * @test
  26  * @bug 8153732 8212202
  27  * @requires (os.family == "Windows")
  28  * @summary Windows remote printer changes do not reflect in lookupPrintServices()
  29  * @ignore Requires a new network printer installation\removal
  30  * @run main/manual RemotePrinterStatusRefresh
  31  */
  32 
  33 import java.awt.GridBagConstraints;
  34 import java.awt.GridBagLayout;


  35 import java.awt.event.ActionEvent;
  36 import java.awt.print.PageFormat;
  37 import java.awt.print.Paper;
  38 import java.awt.print.PrinterException;


  39 import java.util.concurrent.CountDownLatch;
  40 import java.util.concurrent.TimeUnit;


  41 import javax.swing.BorderFactory;
  42 import javax.swing.Box;



  43 import javax.swing.JButton;
  44 import javax.swing.JFrame;
  45 import javax.swing.JLabel;

  46 import javax.swing.JPanel;

  47 import javax.swing.JTextArea;

  48 import javax.swing.SwingUtilities;
  49 import java.awt.print.PrinterJob;
  50 import javax.print.PrintService;
  51 
  52 public class RemotePrinterStatusRefresh
  53 {
  54     private static TestUI test = null;
  55     public static void main(String args[]) throws Exception {
  56         final CountDownLatch latch = new CountDownLatch(1);
  57 
  58         // Test UI creation
  59         test = new TestUI(latch);
  60 
  61         SwingUtilities.invokeAndWait(new Runnable() {
  62             @Override
  63             public void run() {
  64                 try {
  65                     test.createUI();
  66                 } catch (Exception e) {
  67                     throw new RuntimeException(e);
  68                 }
  69             }
  70         });
  71 
  72         // RemotePrinterStatusRefresh creation
  73         RemotePrinterStatusRefresh RemotePrinterStatusRefresh = new RemotePrinterStatusRefresh();
  74         SwingUtilities.invokeAndWait(() -> {
  75             collectPrintersList(test.resultsTextArea, true);
  76         });
  77 
  78         // 8 min = 480000 msec
  79         if(waitForFlag(480000)) {
  80             SwingUtilities.invokeAndWait(() -> {
  81                 collectPrintersList(test.resultsTextArea, false);
  82             });
  83         } else {
  84             dispose();
  85             throw new RuntimeException("No new network printer got added/removed!! Test timed out!!");
  86         }
  87 
  88         boolean status = latch.await(1, TimeUnit.MINUTES);
  89         if (!status) {
  90             dispose();
  91             throw new RuntimeException("Test timed out.");





















  92         }
  93 
  94         if (test.testResult == false) {
  95             dispose();
  96             throw new RuntimeException("Test Failed.");



  97         }
  98 
  99         dispose();


 100     }
 101 
 102     public static void dispose() throws Exception {
 103         SwingUtilities.invokeAndWait(() -> {
 104             test.disposeUI();
 105         });
 106     }
 107 
 108     public static boolean waitForFlag (long maxTimeoutInMsec) throws Exception {
 109         while(!test.isAdded && maxTimeoutInMsec > 0) {
 110             maxTimeoutInMsec -= 100;
 111             Thread.sleep(100);
 112         }
 113 
 114         if(maxTimeoutInMsec <= 0) {
 115             return false;
 116         } else {
 117             return true;

 118         }




 119     }
 120 
 121     private static void collectPrintersList(JTextArea textArea, boolean before) {
 122         if(before) {
 123             System.out.println("List of printers(before): ");
 124             textArea.setText("List of printers(before): \n");
 125             for (PrintService printServiceBefore : PrinterJob.lookupPrintServices()) {
 126                 System.out.println(printServiceBefore);
 127                 textArea.append(printServiceBefore.toString());
 128                 textArea.append("\n");
 129             }
 130         } else {
 131             textArea.append("\n");
 132             System.out.println("List of printers(after): ");
 133             textArea.append("List of printers(after): \n");
 134             for (PrintService printServiceAfter : PrinterJob.lookupPrintServices()) {
 135                 System.out.println(printServiceAfter);
 136                 textArea.append(printServiceAfter.toString());
 137                 textArea.append("\n");
 138             }



 139         }
 140     }
 141 }
 142 
 143 class TestUI {
 144     private static JFrame mainFrame;
 145     private static JPanel mainControlPanel;

































































































































































































































 146 
 147     private static JTextArea instructionTextArea;


 148 
 149     private static JPanel resultButtonPanel;
 150     private static JButton passButton;
 151     private static JButton failButton;
 152     private static JButton addedButton;
 153 
 154     private static JPanel testPanel;
 155     private static JButton testButton;
 156     private static JLabel buttonPressCountLabel;






 157 
 158     private static GridBagLayout layout;
 159     private final CountDownLatch latch;
 160     public boolean testResult = false;
 161     public volatile Boolean isAdded = false;
 162     public static JTextArea resultsTextArea;



 163 
 164     public TestUI(CountDownLatch latch) throws Exception {
 165         this.latch = latch;




 166     }
 167 
 168     public final void createUI() {
 169         mainFrame = new JFrame("RemotePrinterStatusRefresh");
 170         layout = new GridBagLayout();
 171         mainControlPanel = new JPanel(layout);
 172         resultButtonPanel = new JPanel(layout);
 173         testPanel = new JPanel(layout);
 174         GridBagConstraints gbc = new GridBagConstraints();
 175 
 176         // Create Test instructions
 177         String instructions
 178                 = "This test displays the current list of printers(before) attached to \n"
 179                 + "this computer in the results panel.\n\n"
 180                 + "Please follow the below steps for this manual test\n"
 181                 + "--------------------------------------------------------------------\n"
 182                 + "Step 1: Add/Remove a new network printer and Wait for 4 minutes after adding/removing\n"
 183                 + "Step 2: Then click on 'Printer Added/Removed' button\n"
 184                 + "Step 2: Once the new network printer is added/removed, see if it is \n"
 185                 + "        the same as displayed/not displayed in the results panel.\n"
 186                 + "Step 3: If displayed/not displayed, then click 'Pass' else click on 'Fail' button";
 187 
 188         instructionTextArea = new JTextArea();
 189         instructionTextArea.setText(instructions);
 190         instructionTextArea.setEditable(false);
 191         instructionTextArea.setBorder(BorderFactory.
 192                 createTitledBorder("Test Instructions"));




 193 
 194         gbc.gridx = 0;
 195         gbc.gridy = 0;
 196         gbc.fill = GridBagConstraints.HORIZONTAL;
 197         mainControlPanel.add(instructionTextArea, gbc);



 198 
 199         gbc.gridx = 0;
 200         gbc.gridy = 1;
 201         testPanel.add(Box.createVerticalStrut(50));
 202         mainControlPanel.add(testPanel);

 203 
 204         addedButton = new JButton("Printer Added/Removed");
 205         addedButton.setActionCommand("Added");
 206         addedButton.addActionListener((ActionEvent e) -> {
 207             System.out.println("Added Button pressed!");
 208             isAdded = true;
 209         });
 210 
 211         // Create resultButtonPanel with Pass, Fail buttons
 212         passButton = new JButton("Pass");
 213         passButton.setActionCommand("Pass");
 214         passButton.addActionListener((ActionEvent e) -> {
 215             System.out.println("Pass Button pressed!");








 216             testResult = true;
 217             latch.countDown();
 218             disposeUI();
 219         });
 220 
 221         failButton = new JButton("Fail");
 222         failButton.setActionCommand("Fail");
 223         failButton.addActionListener((ActionEvent e) -> {
 224             System.out.println("Fail Button pressed!");
 225             testResult = false;
 226             latch.countDown();
 227             disposeUI();
 228         });
 229 
 230         gbc.gridx = 0;
 231         gbc.gridy = 0;
 232         resultButtonPanel.add(addedButton, gbc);
 233 
 234         gbc.gridx = 1;
 235         gbc.gridy = 0;
 236         resultButtonPanel.add(passButton, gbc);
 237 
 238         gbc.gridx = 2;
 239         gbc.gridy = 0;
 240         resultButtonPanel.add(failButton, gbc);
 241 
 242         resultsTextArea = new JTextArea();
 243         resultsTextArea.setEditable(false);
 244         resultsTextArea.setBorder(BorderFactory.
 245                 createTitledBorder("Results"));
 246 
 247         gbc.gridx = 0;
 248         gbc.gridy = 1;
 249         gbc.fill = GridBagConstraints.HORIZONTAL;
 250         mainControlPanel.add(resultsTextArea, gbc);
 251 
 252         gbc.gridx = 0;
 253         gbc.gridy = 2;
 254         mainControlPanel.add(resultButtonPanel, gbc);
 255 
 256         mainFrame.add(mainControlPanel);
 257         mainFrame.pack();
 258         mainFrame.setVisible(true);







 259     }
 260 
 261     public void disposeUI() {
 262         mainFrame.dispose();

 263     }

 264 }
   1 /*
   2  * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25  * @test
  26  * @bug 8153732 8212202 8221263 8221412
  27  * @requires (os.family == "Windows")
  28  * @summary Windows remote printer changes do not reflect in lookupPrintServices()
  29  * @ignore Requires a new network printer installation\removal
  30  * @run main/manual RemotePrinterStatusRefresh
  31  */
  32 
  33 import java.awt.BorderLayout;
  34 import java.awt.Color;
  35 import java.awt.Component;
  36 import java.awt.GridLayout;
  37 import java.awt.event.ActionEvent;
  38 import java.awt.event.WindowAdapter;
  39 import java.awt.event.WindowEvent;
  40 import java.util.ArrayList;
  41 import java.util.Collections;
  42 import java.util.List;
  43 import java.util.concurrent.CountDownLatch;
  44 import javax.print.PrintService;
  45 import javax.print.PrintServiceLookup;
  46 import javax.swing.AbstractListModel;
  47 import javax.swing.BorderFactory;
  48 import javax.swing.Box;
  49 import javax.swing.BoxLayout;
  50 import javax.swing.DefaultListCellRenderer;
  51 import javax.swing.GroupLayout;
  52 import javax.swing.JButton;
  53 import javax.swing.JFrame;
  54 import javax.swing.JLabel;
  55 import javax.swing.JList;
  56 import javax.swing.JPanel;
  57 import javax.swing.JScrollPane;
  58 import javax.swing.JTextArea;
  59 import javax.swing.JTextField;
  60 import javax.swing.SwingUtilities;
  61 import javax.swing.Timer;

  62 
  63 import static javax.swing.BorderFactory.createTitledBorder;




  64 
  65 public class RemotePrinterStatusRefresh extends WindowAdapter {

  66 
  67     private static final long refreshTime = getRefreshTime();









  68 
  69     private static final long TIMEOUT = refreshTime * 4 + 60;




  70 









  71 
  72     private static final CountDownLatch latch = new CountDownLatch(1);
  73     private static volatile RemotePrinterStatusRefresh test;
  74 
  75     private volatile boolean testResult;
  76     private volatile boolean testTimedOut;
  77 
  78     private final JFrame frame;
  79 
  80     private JButton refreshButton;
  81     private JButton passButton;
  82     private JButton failButton;
  83 
  84     private final ServiceItemListModel beforeList;
  85     private final ServiceItemListModel afterList;
  86 
  87     private JTextField nextRefresh;
  88     private JTextField timeLeft;
  89 
  90     private final Timer timer;
  91     private final long startTime;
  92 
  93 
  94     private static class ServiceItem {
  95         private enum State {
  96             REMOVED, UNCHANGED, ADDED
  97         }
  98 
  99         final String name;
 100         State state;
 101 
 102         private ServiceItem(final String name) {
 103             this.name = name;
 104             state = State.UNCHANGED;
 105         }
 106 
 107         @Override
 108         public String toString() {
 109             return name;
 110         }
 111 
 112         @Override
 113         public boolean equals(Object obj) {
 114             return (obj instanceof ServiceItem)
 115                     && ((ServiceItem) obj).name.equals(name);
 116         }
 117 
 118         @Override
 119         public int hashCode() {
 120             return name.hashCode();
 121         }
 122     }
 123 
 124     private static class ServiceItemListModel extends AbstractListModel<ServiceItem> {
 125         private final List<ServiceItem> list;
 126 
 127         private ServiceItemListModel(List<ServiceItem> list) {
 128             this.list = list;
 129         }
 130 
 131         @Override
 132         public int getSize() {
 133             return list.size();
 134         }
 135 
 136         @Override
 137         public ServiceItem getElementAt(int index) {
 138             return list.get(index);





 139         }
 140 
 141         private void refreshList(List<ServiceItem> newList) {
 142             list.clear();
 143             list.addAll(newList);
 144             fireChanged();



 145         }
 146 
 147         private void fireChanged() {
 148             fireContentsChanged(this, 0, list.size() - 1);
 149         }
 150     }

 151 
 152     private static class ServiceItemListRenderer extends DefaultListCellRenderer {
 153         @Override
 154         public Component getListCellRendererComponent(JList<?> list,
 155                                                       Object value,
 156                                                       int index,
 157                                                       boolean isSelected,
 158                                                       boolean cellHasFocus) {
 159             Component component =
 160                     super.getListCellRendererComponent(list, value, index,
 161                                                        isSelected, cellHasFocus);
 162             switch (((ServiceItem) value).state) {
 163                 case REMOVED:
 164                     component.setBackground(Color.RED);
 165                     component.setForeground(Color.WHITE);
 166                     break;
 167                 case ADDED:
 168                     component.setBackground(Color.GREEN);
 169                     component.setForeground(Color.BLACK);
 170                     break;
 171                 case UNCHANGED:
 172                 default:
 173                     break;
 174             }
 175             return component;
 176         }
 177     }
 178 
 179     private static final String INSTRUCTIONS_TEXT =
 180             "Please follow the steps for this manual test:\n"
 181                     + "Step 0: \"Before\" list is populated with currently "
 182                     +          "configured printers.\n"
 183                     + "Step 1: Add or Remove a network printer using "
 184                     +          "Windows Control Panel.\n"
 185                     + "Step 2: Wait for 4 minutes after adding or removing.\n"
 186                     + "             \"Next printer refresh in\" gives you a "
 187                     +          "rough estimation on when update will happen.\n"
 188                     + "Step 3: Click Refresh."
 189                     +          "\"After\" list is populated with updated list "
 190                     +          "of printers.\n"
 191                     + "Step 4: Compare the list of printers in \"Before\" and "
 192                     +          "\"After\" lists.\n"
 193                     + "              Added printers are highlighted with "
 194                     +               "green color, removed ones \u2014 with "
 195                     +               "red color.\n"
 196                     + "Step 5: Click Pass if the list of printers is correctly "
 197                     +          "updated.\n"
 198                     + "Step 6: If the list is not updated, wait for another "
 199                     +          "4 minutes, and then click Refresh again.\n"
 200                     + "Step 7: If the list does not update, click Fail.\n"
 201                     + "\n"
 202                     + "You have to click Refresh to enable Pass and Fail buttons. "
 203                     + "If no button is pressed,\n"
 204                     + "the test will time out. "
 205                     + "Closing the window also fails the test.";
 206 
 207     public static void main(String[] args) throws Exception {
 208         SwingUtilities.invokeAndWait(RemotePrinterStatusRefresh::createUI);
 209 
 210         latch.await();
 211         if (!test.testResult) {
 212             throw new RuntimeException("Test failed"
 213                 + (test.testTimedOut ? " because of time out" : ""));
 214         }
 215     }
 216 
 217     private static long getRefreshTime() {
 218         String refreshTime =
 219                 System.getProperty("sun.java2d.print.minRefreshTime", "240");
 220         try {
 221             long value = Long.parseLong(refreshTime);
 222             return value < 240L ? 240L : value;
 223         } catch (NumberFormatException e) {
 224             return 240L;
 225         }
 226     }
 227 
 228     private static void createUI() {
 229         test = new RemotePrinterStatusRefresh();
 230     }
 231 
 232     private RemotePrinterStatusRefresh() {
 233         frame = new JFrame("RemotePrinterStatusRefresh");
 234         frame.addWindowListener(this);
 235 
 236 
 237         JPanel northPanel = new JPanel(new BorderLayout());
 238         northPanel.add(createInfoPanel(), BorderLayout.NORTH);
 239         northPanel.add(createInstructionsPanel(), BorderLayout.SOUTH);
 240 
 241 
 242         beforeList = new ServiceItemListModel(
 243                 Collections.unmodifiableList(collectPrinterList()));
 244         afterList = new ServiceItemListModel(new ArrayList<>());
 245         logList("Before:", beforeList.list);
 246 
 247         JPanel listPanel = new JPanel(new GridLayout(1, 2));
 248         listPanel.setBorder(createTitledBorder("Print Services"));
 249         listPanel.add(createListPanel(beforeList, "Before:", 'b'));
 250         listPanel.add(createListPanel(afterList, "After:", 'a'));
 251 
 252 
 253         JPanel mainPanel = new JPanel(new BorderLayout());
 254         mainPanel.add(northPanel, BorderLayout.NORTH);
 255         mainPanel.add(listPanel, BorderLayout.CENTER);
 256         mainPanel.add(createButtonPanel(), BorderLayout.SOUTH);
 257 
 258 
 259         frame.add(mainPanel);
 260         frame.pack();
 261         refreshButton.requestFocusInWindow();
 262         frame.setVisible(true);
 263 
 264 
 265         timer = new Timer(1000, this::updateTimeLeft);
 266         timer.start();
 267         startTime = System.currentTimeMillis();
 268         updateTimeLeft(null);
 269     }
 270 
 271     private JPanel createInfoPanel() {
 272         JLabel javaLabel = new JLabel("Java version:");
 273         JTextField javaVersion =
 274                 new JTextField(System.getProperty("java.runtime.version"));
 275         javaVersion.setEditable(false);
 276         javaLabel.setLabelFor(javaVersion);
 277 
 278         JLabel refreshTimeLabel = new JLabel("Refresh interval:");
 279         long minutes = refreshTime / 60;
 280         long seconds = refreshTime % 60;
 281         String interval = String.format("%1$d seconds%2$s",
 282                 refreshTime,
 283                 minutes > 0
 284                     ? String.format(" (%1$d %2$s%3$s)",
 285                         minutes,
 286                         minutes > 1 ? "minutes" : "minute",
 287                         seconds > 0
 288                             ? String.format(" %1$d %2$s",
 289                                 seconds,
 290                                 seconds > 1 ? "seconds" : "second")
 291                             : "")
 292                     : ""
 293         );
 294         JTextField refreshInterval = new JTextField(interval);
 295         refreshInterval.setEditable(false);
 296         refreshTimeLabel.setLabelFor(refreshInterval);
 297 
 298         JLabel nextRefreshLabel = new JLabel("Next printer refresh in:");
 299         nextRefresh = new JTextField();
 300         nextRefresh.setEditable(false);
 301         nextRefreshLabel.setLabelFor(nextRefresh);
 302 
 303         JLabel timeoutLabel = new JLabel("Time left:");
 304         timeLeft = new JTextField();
 305         timeLeft.setEditable(false);
 306         timeoutLabel.setLabelFor(timeLeft);
 307 
 308         JPanel infoPanel = new JPanel();
 309         GroupLayout layout = new GroupLayout(infoPanel);
 310         infoPanel.setLayout(layout);
 311         infoPanel.setBorder(BorderFactory.createTitledBorder("Info"));
 312         layout.setAutoCreateGaps(true);
 313         layout.setHorizontalGroup(
 314             layout.createSequentialGroup()
 315                 .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
 316                     .addComponent(javaLabel)
 317                     .addComponent(refreshTimeLabel)
 318                     .addComponent(nextRefreshLabel)
 319                     .addComponent(timeoutLabel)
 320                 )
 321                 .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING, true)
 322                     .addComponent(javaVersion)
 323                     .addComponent(refreshInterval)
 324                     .addComponent(nextRefresh)
 325                     .addComponent(timeLeft)
 326                 )
 327         );
 328         layout.setVerticalGroup(
 329             layout.createSequentialGroup()
 330                 .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
 331                     .addComponent(javaLabel)
 332                     .addComponent(javaVersion)
 333                 )
 334                 .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
 335                     .addComponent(refreshTimeLabel)
 336                     .addComponent(refreshInterval))
 337                 .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
 338                     .addComponent(nextRefreshLabel)
 339                     .addComponent(nextRefresh))
 340                 .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
 341                     .addComponent(timeoutLabel)
 342                     .addComponent(timeLeft))
 343         );
 344         return infoPanel;
 345     }
 346 
 347     private JPanel createInstructionsPanel() {
 348         JPanel instructionsPanel = new JPanel(new BorderLayout());
 349         JTextArea instructionText = new JTextArea(INSTRUCTIONS_TEXT);
 350         instructionText.setEditable(false);
 351         instructionsPanel.setBorder(createTitledBorder("Test Instructions"));
 352         instructionsPanel.add(new JScrollPane(instructionText));
 353         return  instructionsPanel;
 354     }
 355 
 356     private JPanel createListPanel(final ServiceItemListModel model,
 357                                    final String title,
 358                                    final char mnemonic) {
 359         JPanel panel = new JPanel();
 360         panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
 361         JList<ServiceItem> list = new JList<>(model);
 362         list.setCellRenderer(new ServiceItemListRenderer());
 363 
 364         JLabel label = new JLabel(title);
 365         label.setLabelFor(list);
 366         label.setDisplayedMnemonic(mnemonic);
 367         JPanel labelPanel = new JPanel();
 368         labelPanel.setLayout(new BoxLayout(labelPanel, BoxLayout.X_AXIS));
 369         labelPanel.add(label, BorderLayout.EAST);
 370         labelPanel.add(Box.createHorizontalGlue());
 371 
 372         panel.add(labelPanel);
 373         panel.add(new JScrollPane(list));
 374         return panel;
 375     }
 376 
 377     private JPanel createButtonPanel() {
 378         refreshButton = new JButton("Refresh");
 379         refreshButton.addActionListener(this::refresh);
 380 
 381         passButton = new JButton("Pass");
 382         passButton.addActionListener(this::pass);
 383         passButton.setEnabled(false);
 384 
 385         failButton = new JButton("Fail");
 386         failButton.addActionListener(this::fail);
 387         failButton.setEnabled(false);

 388 
 389         JPanel buttonPanel = new JPanel();
 390         buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS));
 391         buttonPanel.add(Box.createHorizontalGlue());
 392         buttonPanel.add(refreshButton);
 393         buttonPanel.add(passButton);
 394         buttonPanel.add(failButton);
 395         buttonPanel.add(Box.createHorizontalGlue());
 396         return buttonPanel;
 397     }
 398 
 399     private static List<ServiceItem> collectPrinterList() {
 400         PrintService[] printServices = PrintServiceLookup.lookupPrintServices(null, null);
 401         List<ServiceItem> list = new ArrayList<>(printServices.length);
 402         for (PrintService service : printServices) {
 403             list.add(new ServiceItem(service.getName()));
 404         }
 405         return list;
 406     }
 407 
 408     private static void logList(final String title, final List<ServiceItem> list) {
 409         System.out.println(title);
 410         for (ServiceItem item : list) {
 411             System.out.println(item.name);
 412         }
 413         System.out.println();
 414     }
 415 
 416     private static void compareLists(final ServiceItemListModel before, final ServiceItemListModel after) {
 417         boolean beforeUpdated = false;
 418         boolean afterUpdated = false;




 419 
 420         for (ServiceItem item : before.list) {
 421             if (!after.list.contains(item)) {
 422                 item.state = ServiceItem.State.REMOVED;
 423                 beforeUpdated = true;
 424             } else if (item.state != ServiceItem.State.UNCHANGED) {
 425                 item.state = ServiceItem.State.UNCHANGED;
 426                 beforeUpdated = true;
 427             }
 428         }


 429 
 430         for (ServiceItem item : after.list) {
 431             if (!before.list.contains(item)) {
 432                 item.state = ServiceItem.State.ADDED;
 433                 afterUpdated = true;
 434             } else if (item.state != ServiceItem.State.UNCHANGED) {
 435                 item.state = ServiceItem.State.UNCHANGED;
 436                 afterUpdated = true;
 437             }
 438         }
 439 
 440         if (beforeUpdated) {
 441             before.fireChanged();
 442         }
 443         if (afterUpdated) {
 444             after.fireChanged();
 445         }
 446     }
 447 
 448     @Override
 449     public void windowClosing(WindowEvent e) {
 450         System.out.println("The window closed");
 451         disposeUI();
 452     }
 453 
 454     private void disposeUI() {
 455         timer.stop();
 456         latch.countDown();
 457         frame.dispose();
 458     }

 459 
 460     @SuppressWarnings("unused")
 461     private void refresh(ActionEvent e) {
 462         System.out.println("Refresh button pressed");
 463         afterList.refreshList(collectPrinterList());
 464         compareLists(beforeList, afterList);
 465         passButton.setEnabled(true);
 466         failButton.setEnabled(true);
 467         logList("After:", afterList.list);
 468     }
 469 
 470     @SuppressWarnings("unused")
 471     private void pass(ActionEvent e) {
 472         System.out.println("Pass button pressed");
 473         testResult = true;

 474         disposeUI();
 475     }
 476 
 477     @SuppressWarnings("unused")
 478     private void fail(ActionEvent e) {
 479         System.out.println("Fail button pressed");

 480         testResult = false;

 481         disposeUI();
 482     }


























 483 
 484     @SuppressWarnings("unused")
 485     private void updateTimeLeft(ActionEvent e) {
 486         long elapsed = (System.currentTimeMillis() - startTime) / 1000;
 487         long left = TIMEOUT - elapsed;
 488         if (left < 0) {
 489             testTimedOut = true;
 490             disposeUI();
 491         }
 492         timeLeft.setText(formatTime(left));
 493         nextRefresh.setText(formatTime(refreshTime - (elapsed % refreshTime)));
 494     }
 495 
 496     private static String formatTime(final long seconds) {
 497         long minutes = seconds / 60;
 498         return String.format("%d:%02d", minutes, seconds - minutes * 60);
 499     }
 500 
 501 }
< prev index next >