1 /*
   2  * $Id$
   3  *
   4  * Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved.
   5  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   6  *
   7  * This code is free software; you can redistribute it and/or modify it
   8  * under the terms of the GNU General Public License version 2 only, as
   9  * published by the Free Software Foundation.  Oracle designates this
  10  * particular file as subject to the "Classpath" exception as provided
  11  * by Oracle in the LICENSE file that accompanied this code.
  12  *
  13  * This code is distributed in the hope that it will be useful, but WITHOUT
  14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  15  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  16  * version 2 for more details (a copy is included in the LICENSE file that
  17  * accompanied this code).
  18  *
  19  * You should have received a copy of the GNU General Public License version
  20  * 2 along with this work; if not, write to the Free Software Foundation,
  21  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  22  *
  23  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  24  * or visit www.oracle.com if you need additional information or have any
  25  * questions.
  26  */
  27 package com.sun.javatest.audit;
  28 
  29 import java.awt.BorderLayout;
  30 import java.awt.Component;
  31 import java.awt.Dimension;
  32 import java.awt.EventQueue;
  33 import java.awt.GridBagConstraints;
  34 import java.awt.GridBagLayout;
  35 import java.awt.event.ActionEvent;
  36 import java.awt.event.ActionListener;
  37 import java.awt.event.HierarchyEvent;
  38 import java.awt.event.HierarchyListener;
  39 import java.io.File;
  40 import java.util.Map;
  41 import javax.swing.BorderFactory;
  42 import javax.swing.JLabel;
  43 import javax.swing.JMenu;
  44 import javax.swing.JMenuBar;
  45 import javax.swing.JPanel;
  46 import javax.swing.JTabbedPane;
  47 import javax.swing.JTextField;
  48 import javax.swing.event.ChangeEvent;
  49 import javax.swing.event.ChangeListener;
  50 
  51 import com.sun.javatest.tool.jthelp.ContextHelpManager;
  52 import com.sun.javatest.InterviewParameters;
  53 import com.sun.javatest.TestSuite;
  54 import com.sun.javatest.WorkDirectory;
  55 import com.sun.javatest.tool.Tool;
  56 import com.sun.javatest.util.I18NResourceBundle;
  57 import javax.swing.JDialog;
  58 import javax.swing.Timer;
  59 
  60 class AuditTool extends Tool
  61 {
  62     AuditTool(AuditToolManager m) {
  63         super(m, "audit", "audit.window.csh");
  64         setI18NTitle("tool.title");
  65         setShortTitle(uif.getI18NString("tool.shortTitle"));
  66         initGUI();
  67     }
  68 
  69     public void dispose() {
  70         super.dispose();
  71 
  72         if (optionsDialog != null) {
  73             optionsDialog.setVisible(false);
  74             optionsDialog.dispose();
  75         }
  76     }
  77 
  78     public JMenuBar getMenuBar() {
  79         return menuBar;
  80     }
  81 
  82     public TestSuite[] getLoadedTestSuites() {
  83         TestSuite ts = (interviewParams == null ? null : interviewParams.getTestSuite());
  84         return (ts == null ? null : new TestSuite[] { ts });
  85     }
  86 
  87     public WorkDirectory[] getLoadedWorkDirectories() {
  88         WorkDirectory wd = (interviewParams == null ? null : interviewParams.getWorkDirectory());
  89         return (wd == null ? null : new WorkDirectory[] { wd });
  90     }
  91 
  92     public void save(Map<String, String> m) {
  93         if (interviewParams == null)
  94             return;
  95 
  96         // save test suite
  97         TestSuite ts = interviewParams.getTestSuite();
  98         m.put("testSuite", ts.getRoot().getPath());
  99 
 100         // save work directory
 101         WorkDirectory wd = interviewParams.getWorkDirectory();
 102         if (wd != null)
 103             m.put("workDir", wd.getPath());
 104 
 105         // save name of interview file
 106         File cf = interviewParams.getFile();
 107         if (cf != null)
 108             m.put("config", cf.getPath());
 109     }
 110 
 111     @Override
 112     protected void restore(Map<String, String> m) {
 113         String tsp = (String) (m.get("testSuite"));
 114         String wdp = (String) (m.get("workDir"));
 115         String cfp = (String) (m.get("config"));
 116 
 117         if (tsp == null && wdp == null && cfp == null)
 118             return;
 119 
 120         try {
 121             if (interviewParams != null) {
 122                 interviewParams.dispose();
 123             }
 124             interviewParams = InterviewParameters.open(tsp, wdp, cfp);
 125             updateGUI(null, interviewParams, uif.getI18NString("tool.restore.txt"));
 126             autoShowOptions = false;
 127         }
 128         catch (InterviewParameters.Fault e) {
 129             uif.showError("tool.cantRestore", e.getMessage());
 130         }
 131     }
 132 
 133     private void initGUI() {
 134         int dpi = uif.getDotsPerInch();
 135         setPreferredSize(new Dimension(6 * dpi, 4 * dpi));
 136         setLayout(new BorderLayout());
 137 
 138         addHierarchyListener(listener);
 139 
 140         menuBar = uif.createMenuBar("tool");
 141         String[] auditMenuEntries = {
 142             OPTIONS
 143         };
 144         JMenu auditMenu = uif.createMenu("tool.audit", auditMenuEntries, listener);
 145         menuBar.add(auditMenu);
 146 
 147         menuBar.add(uif.createHorizontalGlue("tool.pad"));
 148 
 149         JMenu helpMenu = uif.createMenu("tool.help");
 150         helpMenu.add(uif.createHelpMenuItem("tool.help.window", "audit.window.csh"));
 151         menuBar.add(helpMenu);
 152 
 153         JPanel head = uif.createPanel("head", false);
 154         head.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
 155         head.setLayout(new GridBagLayout());
 156 
 157         GridBagConstraints lc = new GridBagConstraints();
 158         lc.anchor = GridBagConstraints.EAST;
 159         lc.gridwidth = 1;
 160         lc.insets.right = 5;
 161         lc.weightx = 0;
 162 
 163         GridBagConstraints fc = new GridBagConstraints();
 164         fc.fill = GridBagConstraints.HORIZONTAL;
 165         fc.weightx = 1;
 166         fc.gridwidth = GridBagConstraints.REMAINDER;
 167 
 168         testSuiteField = initField("tool.testSuite", head, lc, fc);
 169         workDirField = initField("tool.workDir", head, lc, fc);
 170         configFileField = initField("tool.configFile", head, lc, fc);
 171 
 172         add(head, BorderLayout.NORTH);
 173 
 174         panes = new AuditPane[] {
 175             new SummaryPane(uif),
 176             new BadTestsPane(uif),
 177             new BadChecksumPane(uif),
 178             new BadTestDescriptionPane(uif),
 179             new BadTestCaseTestsPane(uif)
 180         };
 181 
 182         tabs = uif.createTabbedPane("tool.tabs", panes);
 183         tabs.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
 184         tabs.addChangeListener(new ChangeListener() {
 185             public void stateChanged(ChangeEvent e) {
 186                 Component c = tabs.getSelectedComponent();
 187                 ContextHelpManager.setHelpIDString(tabs, ContextHelpManager.getHelpIDString(c));
 188             }
 189         });
 190         ContextHelpManager.setHelpIDString(tabs, ContextHelpManager.getHelpIDString(panes[0]));
 191 
 192         add(tabs, BorderLayout.CENTER);
 193 
 194         updateGUI(null, null, uif.getI18NString("tool.initial.txt"));
 195     }
 196 
 197     private JTextField initField(String key, JPanel p,
 198                                  GridBagConstraints lc, GridBagConstraints fc) {
 199 
 200         JLabel lbl = uif.createLabel(key, true);
 201         p.add(lbl, lc);
 202         JTextField tf = uif.createOutputField(key, lbl);
 203         tf.setBorder(null);
 204         p.add(tf, fc);
 205         return tf;
 206     }
 207 
 208 
 209     private synchronized void showOptions() {
 210         if (worker != null) {
 211             uif.showError("tool.auditInProgress");
 212             return;
 213         }
 214 
 215         if (optionsDialog == null) {
 216             // should arguably worry about standard ownership problem
 217             optionsDialog = new OptionsDialog(this, listener, uif);
 218         }
 219 
 220         if (interviewParams != null)
 221             optionsDialog.setParameters(interviewParams);
 222 
 223         optionsDialog.setVisible(true);
 224     }
 225 
 226     private void setOptions() {
 227         String tsp = optionsDialog.getTestSuitePath();
 228         String wdp = optionsDialog.getWorkDirPath();
 229         String cfp = optionsDialog.getConfigFilePath();
 230 
 231         if ( isEmpty(tsp) && isEmpty(wdp) && isEmpty(cfp) ) {
 232             uif.showError("tool.noOptions");
 233             return;
 234         }
 235 
 236         try {
 237             if (interviewParams != null) {
 238                 interviewParams.dispose();
 239             }
 240             interviewParams = InterviewParameters.open(tsp, wdp, cfp);
 241         }
 242         catch (InterviewParameters.Fault e) {
 243             uif.showError("tool.badOptions", e.getMessage());
 244             return;
 245         }
 246 
 247         optionsDialog.setVisible(false);
 248 
 249         startAudit();
 250     }
 251 
 252     private synchronized void startAudit() {
 253         if (worker != null) {
 254             uif.showError("tool.auditInProgress");
 255             return;
 256         }
 257 
 258         // can't do this operation without WD
 259         if (interviewParams.getWorkDirectory() == null) {
 260             uif.showError("tool.noWd");
 261             return;
 262         }
 263 
 264         final JDialog d = uif.createWaitDialog("tool.wait", this);
 265         d.setLocationRelativeTo(this);
 266 
 267         worker = new Thread() {
 268                 public void run() {
 269                     Audit a = audit; // default to previous value
 270                     try {
 271                         a = new Audit(interviewParams);
 272                     }
 273                     finally {
 274                         synchronized (AuditTool.this) {
 275                             worker = null;
 276                         }
 277                         d.setVisible(false);
 278                         // the following may not be right if the audit
 279                         // has been interrupted and we are reverting to
 280                         // previous state. Ideally, should pull parameters
 281                         // from the audit object
 282                         updateGUI(a, interviewParams, null);
 283                     }
 284             }
 285         };
 286 
 287         ActionListener al = new ActionListener() {
 288             public void actionPerformed(ActionEvent evt){
 289                 // show dialog if still processing
 290                 if (worker != null && worker.isAlive()) {
 291                     d.setVisible(true);
 292                 }
 293             }
 294         };
 295 
 296         // show wait dialog if operation is still running after
 297         // WAIT_DIALOG_DELAY
 298         Timer timer = new Timer(WAIT_DIALOG_DELAY, al);
 299         timer.setRepeats(false);
 300         timer.start();
 301 
 302         worker.start();
 303 
 304 
 305         updateGUI(null, interviewParams, "");
 306     }
 307 
 308     private static int WAIT_DIALOG_DELAY = 2000;
 309 
 310     private void updateGUI(final Audit a, final InterviewParameters p, final String msg) {
 311         if (!EventQueue.isDispatchThread()) {
 312             EventQueue.invokeLater(new Runnable() {
 313                     public void run() {
 314                         updateGUI(a, p, msg);
 315                     }
 316                 });
 317             return;
 318         }
 319 
 320         audit = a;
 321 
 322         TestSuite ts = (p == null ? null : p.getTestSuite());
 323         String tsp = (ts == null ? "" : ts.getPath());
 324         testSuiteField.setText(tsp);
 325 
 326         WorkDirectory wd = (p == null ? null : p.getWorkDirectory());
 327         String wdp = (wd == null? "" : wd.getPath());
 328         workDirField.setText(wdp);
 329 
 330         File configFile = (p == null ? null : p.getFile());
 331         String cfp = (configFile == null ? "" : configFile.getPath());
 332         configFileField.setText(cfp);
 333 
 334         for (int i = 0; i < panes.length; i++) {
 335             AuditPane pane = panes[i];
 336             if (a != null)
 337                 pane.show(a);
 338             else if (msg != null)
 339                 pane.show(msg);
 340         }
 341     }
 342 
 343     private static boolean isEmpty(String s) {
 344         return (s == null || s.length() == 0);
 345     }
 346 
 347 
 348     private JMenuBar menuBar;
 349     private JTextField testSuiteField;
 350     private JTextField workDirField;
 351     private JTextField configFileField;
 352     private AuditPane[] panes;
 353     private JTabbedPane tabs;
 354     private OptionsDialog optionsDialog;
 355     private boolean autoShowOptions = true;;
 356     private Listener listener = new Listener();
 357 
 358     private InterviewParameters interviewParams;
 359 
 360     // access to these fields must be synchronized
 361     private Thread worker;
 362     private Audit audit;
 363 
 364     private static final String OPTIONS = "options";
 365     private static I18NResourceBundle i18n = I18NResourceBundle.getBundleForClass(AuditTool.class);
 366 
 367     private class Listener implements ActionListener, HierarchyListener {
 368         public void actionPerformed(ActionEvent e) {
 369             String cmd = e.getActionCommand();
 370             if (cmd.equals(OPTIONS)) {
 371                 showOptions();
 372             }
 373             else if (cmd.equals(OptionsDialog.OK)) {
 374                 setOptions();
 375             }
 376         }
 377 
 378         public void hierarchyChanged(HierarchyEvent e) {
 379             if (isShowing() && autoShowOptions) {
 380                 EventQueue.invokeLater(new Runnable() {
 381                         public void run() {
 382                             showOptions();
 383                         }
 384                     });
 385                 autoShowOptions = false;
 386             }
 387         }
 388     };
 389 }