/* * FindBugs - Find bugs in Java programs * Copyright (C) 2003,2004 University of Maryland * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * RunAnalysisDialog.java * * Created on April 1, 2003, 3:22 PM */ package edu.umd.cs.findbugs.gui; import java.awt.event.WindowEvent; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; import edu.umd.cs.findbugs.FindBugsProgress; import edu.umd.cs.findbugs.L10N; /** * A modal dialog to run the actual FindBugs analysis on a project. * The analysis is done in a separate thread, so that the GUI can * still stay current while the analysis is running. We provide support * for reporting the progress of the analysis, and for asynchronously * cancelling the analysis before it completes. * * @author David Hovemeyer */ public class RunAnalysisDialog extends javax.swing.JDialog { private static final long serialVersionUID = 1L; private class RunAnalysisProgress implements FindBugsProgress { private int goal, count; private synchronized int getGoal() { return goal; } private synchronized int getCount() { return count; } public void reportNumberOfArchives(final int numArchives) { beginStage(L10N.getLocalString("msg.scanningarchives_txt", "Scanning archives"), numArchives); } public void finishArchive() { step(); } public void startAnalysis(int numClasses) { beginStage(L10N.getLocalString("msg.analysingclasses_txt", "Analyzing classes"), numClasses); } public void finishClass() { step(); } public void finishPerClassAnalysis() { SwingUtilities.invokeLater(new Runnable() { public void run() { stageNameLabel.setText(L10N.getLocalString("msg.finishedanalysis_txt", "Finishing analysis")); } }); } private void beginStage(final String stageName, final int goal) { synchronized (this) { this.count = 0; this.goal = goal; } SwingUtilities.invokeLater(new Runnable() { public void run() { int goal = getGoal(); stageNameLabel.setText(stageName); countValueLabel.setText("0/" + goal); progressBar.setMaximum(goal); progressBar.setValue(0); } }); } private void step() { synchronized (this) { count++; } SwingUtilities.invokeLater(new Runnable() { public void run() { int count = getCount(); int goal = getGoal(); countValueLabel.setText(count + "/" + goal); progressBar.setValue(count); } }); } public void predictPassCount(int[] classesPerPass) { // noop } public void startArchive(String name) { // noop } } private final AnalysisRun analysisRun; private Thread analysisThread; private boolean completed; private Exception fatalException; private int analysisPriority; /** * Creates new form RunAnalysisDialog */ public RunAnalysisDialog(java.awt.Frame parent, AnalysisRun analysisRun_, int analysisPriority) { super(parent, true); initComponents(); this.analysisRun = analysisRun_; this.completed = false; this.analysisPriority = analysisPriority; // Create a progress callback to give the user feedback // about how far along we are. final FindBugsProgress progress = new RunAnalysisProgress(); // This is the thread that will actually run the analysis. this.analysisThread = new Thread() { @Override public void run() { try { analysisRun.execute(progress); setCompleted(true); } catch (java.io.IOException e) { setException(e); } catch (InterruptedException e) { // We don't need to do anything here. // The completed flag is not set, so the frame // will know that the analysis did not complete. } catch (Exception e) { setException(e); } // Send a message to the dialog that it should close // That way, it goes away without any need for user intervention SwingUtilities.invokeLater(new Runnable() { public void run() { closeDialog(new WindowEvent(RunAnalysisDialog.this, WindowEvent.WINDOW_CLOSING)); } }); } }; } public synchronized void setCompleted(boolean completed) { this.completed = completed; } /** * The creator of the dialog may call this method to find out whether * or not the analysis completed normally. */ public synchronized boolean isCompleted() { return completed; } public synchronized void setException(Exception e) { fatalException = e; } /** * Determine whether or not a fatal exception occurred * during analysis. */ public synchronized boolean exceptionOccurred() { return fatalException != null; } /** * Get the exception that abnormally terminated the analysis. */ public synchronized Exception getException() { return fatalException; } /** * This method is called from within the constructor to * initialize the form. * WARNING: Do NOT modify this code. The content of this method is * always regenerated by the Form Editor. */ private void initComponents() {//GEN-BEGIN:initComponents java.awt.GridBagConstraints gridBagConstraints; findBugsLabel = new javax.swing.JLabel(); countLabel = new javax.swing.JLabel(); progressLabel = new javax.swing.JLabel(); progressBar = new javax.swing.JProgressBar(); cancelButton = new javax.swing.JButton(); jSeparator1 = new javax.swing.JSeparator(); stageLabel = new javax.swing.JLabel(); stageNameLabel = new javax.swing.JLabel(); topVerticalFiller = new javax.swing.JLabel(); bottomVerticalFiller = new javax.swing.JLabel(); countValueLabel = new javax.swing.JLabel(); getContentPane().setLayout(new java.awt.GridBagLayout()); setTitle("Run Analysis"); this.setTitle(L10N.getLocalString("dlg.runanalysis_ttl", "Run Analysis")); addWindowListener(new java.awt.event.WindowAdapter() { @Override public void windowClosing(java.awt.event.WindowEvent evt) { closeDialog(evt); } @Override public void windowOpened(java.awt.event.WindowEvent evt) { formWindowOpened(evt); } }); findBugsLabel.setBackground(new java.awt.Color(0, 0, 204)); findBugsLabel.setFont(new java.awt.Font("Dialog", 1, 24)); findBugsLabel.setForeground(new java.awt.Color(255, 255, 255)); findBugsLabel.setText("Find Bugs!"); findBugsLabel.setOpaque(true); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridwidth = 2; gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH; gridBagConstraints.weightx = 1.0; gridBagConstraints.insets = new java.awt.Insets(0, 0, 3, 0); getContentPane().add(findBugsLabel, gridBagConstraints); countLabel.setFont(new java.awt.Font("Dialog", 0, 12)); countLabel.setText("Count:"); countLabel.setText(L10N.getLocalString("dlg.count_lbl", "Count:")); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 3; gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST; gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3); getContentPane().add(countLabel, gridBagConstraints); progressLabel.setFont(new java.awt.Font("Dialog", 0, 12)); progressLabel.setText("Progress:"); progressLabel.setText(L10N.getLocalString("dlg.progress_lbl", "Progress:")); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 5; gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST; gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3); getContentPane().add(progressLabel, gridBagConstraints); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 5; gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 3); getContentPane().add(progressBar, gridBagConstraints); cancelButton.setFont(new java.awt.Font("Dialog", 0, 12)); cancelButton.setText("Cancel"); cancelButton.setText(L10N.getLocalString("dlg.cancel_btn", "Cancel")); cancelButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { cancelButtonActionPerformed(evt); } }); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 8; gridBagConstraints.gridwidth = 2; gridBagConstraints.insets = new java.awt.Insets(3, 0, 3, 0); getContentPane().add(cancelButton, gridBagConstraints); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 7; gridBagConstraints.gridwidth = 2; gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; getContentPane().add(jSeparator1, gridBagConstraints); stageLabel.setFont(new java.awt.Font("Dialog", 0, 12)); stageLabel.setText("Stage:"); stageLabel.setText(L10N.getLocalString("dlg.stage_lbl", "Stage:")); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 2; gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST; gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3); getContentPane().add(stageLabel, gridBagConstraints); stageNameLabel.setFont(new java.awt.Font("Dialog", 0, 12)); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 2; gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; getContentPane().add(stageNameLabel, gridBagConstraints); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 6; gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL; gridBagConstraints.weighty = 0.5; getContentPane().add(topVerticalFiller, gridBagConstraints); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 1; gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL; gridBagConstraints.weighty = 0.5; getContentPane().add(bottomVerticalFiller, gridBagConstraints); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 3; gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 0); getContentPane().add(countValueLabel, gridBagConstraints); pack(); }//GEN-END:initComponents private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed int option = JOptionPane.showConfirmDialog(this, L10N.getLocalString("msg.cancelanalysis_txt", "Cancel analysis?"), L10N.getLocalString("msg.analyze_txt", "Analysis"), JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); if (option == JOptionPane.YES_OPTION) { // All we need to do to cancel the analysis is to interrupt // the analysis thread. analysisThread.interrupt(); } }//GEN-LAST:event_cancelButtonActionPerformed private void formWindowOpened(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowOpened // Here is where we actually kick off the analysis thread. // Lower the priority of the analysis thread to leave more // CPU for interactive tasks. analysisThread.setPriority(analysisPriority); analysisThread.start(); }//GEN-LAST:event_formWindowOpened /** * Closes the dialog */ private void closeDialog(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_closeDialog setVisible(false); dispose(); }//GEN-LAST:event_closeDialog // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JLabel bottomVerticalFiller; private javax.swing.JButton cancelButton; private javax.swing.JLabel countLabel; private javax.swing.JLabel countValueLabel; private javax.swing.JLabel findBugsLabel; private javax.swing.JSeparator jSeparator1; private javax.swing.JProgressBar progressBar; private javax.swing.JLabel progressLabel; private javax.swing.JLabel stageLabel; private javax.swing.JLabel stageNameLabel; private javax.swing.JLabel topVerticalFiller; // End of variables declaration//GEN-END:variables }