KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > csdl > jblanket > app > ExcludeIndividualMethodApp


1 package csdl.jblanket.app;
2
3 import csdl.jblanket.JBlanketException;
4 import csdl.jblanket.app.tree.NodeContentHandler;
5 import csdl.jblanket.app.tree.NodeErrorHandler;
6 import csdl.jblanket.app.tree.MethodNode;
7 import csdl.jblanket.app.tree.Node;
8 import csdl.jblanket.app.tree.TreeWriter;
9 import csdl.jblanket.util.MethodCategories;
10
11 import java.awt.BorderLayout JavaDoc;
12 import java.awt.Color JavaDoc;
13 import java.awt.Container JavaDoc;
14 import java.awt.Dimension JavaDoc;
15 import java.awt.FlowLayout JavaDoc;
16 import java.awt.GridBagConstraints JavaDoc;
17 import java.awt.GridBagLayout JavaDoc;
18 import java.awt.GridLayout JavaDoc;
19 import java.awt.event.ActionEvent JavaDoc;
20 import java.awt.event.ActionListener JavaDoc;
21 import java.awt.event.WindowAdapter JavaDoc;
22 import java.awt.event.WindowEvent JavaDoc;
23 import java.io.File JavaDoc;
24 import java.io.FileInputStream JavaDoc;
25 import java.io.FileOutputStream JavaDoc;
26 import java.io.IOException JavaDoc;
27 import java.util.ArrayList JavaDoc;
28 import java.util.Enumeration JavaDoc;
29 import java.util.Iterator JavaDoc;
30 import java.util.List JavaDoc;
31
32 import javax.swing.JButton JavaDoc;
33 import javax.swing.JOptionPane JavaDoc;
34 import javax.swing.JPanel JavaDoc;
35 import javax.swing.JScrollPane JavaDoc;
36 import javax.swing.JFrame JavaDoc;
37 import javax.swing.JTextPane JavaDoc;
38 import javax.swing.JTree JavaDoc;
39 import javax.swing.UIManager JavaDoc;
40 import javax.swing.text.BadLocationException JavaDoc;
41 import javax.swing.text.Document JavaDoc;
42 import javax.swing.text.Style JavaDoc;
43 import javax.swing.text.StyleConstants JavaDoc;
44 import javax.swing.text.StyleContext JavaDoc;
45 import javax.swing.tree.DefaultMutableTreeNode JavaDoc;
46 import javax.swing.tree.DefaultTreeModel JavaDoc;
47 import javax.swing.tree.TreePath JavaDoc;
48 import javax.swing.tree.TreeSelectionModel JavaDoc;
49 //import javax.xml.parsers.SAXParserFactory;
50

51 import org.apache.xerces.parsers.SAXParser;
52 import org.xml.sax.InputSource JavaDoc;
53 import org.xml.sax.XMLReader JavaDoc;
54 import org.xml.sax.SAXException JavaDoc;
55
56 /**
57  * Provides the application used to exclude individual methods from the coverage measurement. It
58  * displays a mapping of a system's package structure to facilitate selection of individual methods
59  * and deciding what to do with them.
60  * <p>
61  * This is an optional step in JBlanket that adds to the power of Extreme Coverage.
62  * <p>
63  * The above mentioned funcitonality is achieved by invoking the <code>main</code> method.
64  * Arguments to pass to the main method include:
65  * <p>
66  * <b>Required</b> command line arguments:
67  * <ul>
68  * <p>
69  * 'total.testedFile' - file containing all the tested methods before any optional exclusions,
70  * e.g., one-line methods, etc., are removed<br>
71  * <i>For example</i>: -total.testedFile
72  * <p>
73  * 'total.untestedFile' - file containing all the untested methods before any optional exclusions,
74  * e.g., one-line methods, etc., are removed<br>
75  * <i>For example</i>: -total.untestedFile
76  * </ul>
77  * <p>
78  * <b>Optional</b> command line arguments:
79  * <ul>
80  * <p>
81  * 'verbose' - describes if application should execute in verbose mode<br>
82  * <i>For example</i>: -verbose true
83  * <p>
84  * 'excludeOneLineMethods' - describes if one-line methods should be distinguished<br>
85  * <i>For example</i>: -excludeOneLineMethods false
86  * <p>
87  * 'excludeConstructors' - describes if constructors should be distinguished<br>
88  * <i>For example</i>: -excludeConstructors false
89  * <p>
90  * <p>
91  * 'onelineFile' - name of the file containing all one-line methods<br>
92  * <i>For example</i>: -onelineFile oneLineMethods.xml
93  * <p>
94  * 'constructorFile' - name of the file containing all constructors<br>
95  * <i>For example</i>: -constructorFile constructorMethods.xml
96  * <p>
97  * 'excludedIndividualFile' - name of the file containing all indiviually excluded methods</br>
98  * <i>For example</i>: -excludedIndividualFile excludedIndividualMethods.xml
99  * </ul>
100  * <p>
101  * An example of the most basic command line is:<br>
102  * <pre>
103  * jblanket&gt;java -D"jblanket.dir"=.\build\jblanket
104  * -classpath .;.\lib\ant\jblanket.jar;.\lib\ant\jdom.jar;.\lib\ant\xerces.jar
105  * csdl.jblanket.app.ExcludeIndividualMethodApp
106  * -total.testedFile -total.untestedFile
107  * </pre>
108  * <p>
109  * Another one that excludes one-line methods in a file myOneLineMethods.xml is:<br>
110  * <pre>
111  * jblanket&gt;java -D"jblanket.dir"=.\build\jblanket
112  * -classpath .;.\lib\ant\jblanket.jar;.\lib\ant\jdom.jar;.\lib\ant\xerces.jar
113  * csdl.jblanket.app.ExcludeIndividualMethodApp
114  * -total.testedFile -total.untestedFile -excludeOneLineMethods true
115  * -oneLineFile myOneLineMethods.xml
116  * </pre>
117  *
118  * @author Joy M. Agustin
119  * @version $Id: ExcludeIndividualMethodApp.java,v 1.1 2004/11/07 00:32:41 timshadel Exp $
120  */

121 public class ExcludeIndividualMethodApp extends JPanel JavaDoc {
122   
123   /** Optionally play with line styles. Possible values are
124       "Angled", "Horizontal", and "None" (the default). */

125   private boolean playWithLineStyle = false;
126   private String JavaDoc lineStyle = "Angled";
127   
128   /** Tree holding all data */
129   private DefaultTreeModel JavaDoc treeModel;
130   /** Tree displayed in application */
131   private final JTree JavaDoc tree;
132   /** Frame containing this application */
133   private JFrame JavaDoc frame;
134   
135   /** Method categories to use */
136   private MethodCategories categories;
137   /** Describes if one-line methods should be excluded from the coverage measurement */
138   protected boolean excludeOneLineMethods;
139   /** Describes if constructors should be excluded from the coverage measurement */
140   protected boolean excludeConstructors;
141   
142   /**
143    * Creates a new ExcludeIndividualMethodApp.
144    *
145    * @param verbose describes if JBlanket should execute in verbose mode.
146    * @param excludeOneLineMethods describes if one-line methods should be excluded.
147    * @param excludeConstructors describes if constructors should be excluded.
148    * @param frame the frame to place this JPanel.
149    * @throws JBlanketException if unable to create a tree.
150    */

151   public ExcludeIndividualMethodApp(boolean verbose, boolean excludeOneLineMethods,
152                                      boolean excludeConstructors, JFrame JavaDoc frame)
153         throws JBlanketException {
154     
155     this.categories = MethodCategories.getInstance();
156     
157     this.excludeOneLineMethods = excludeOneLineMethods;
158     this.excludeConstructors = excludeConstructors;
159     
160     //Create the nodes and tree.
161
DefaultMutableTreeNode JavaDoc top = new DefaultMutableTreeNode JavaDoc(new Node("System"));
162     treeModel = new DefaultTreeModel JavaDoc(top);
163     createTree();
164
165     //Create a tree that allows multiple selections at a time.
166
this.tree = new JTree JavaDoc(treeModel);
167     this.tree.getSelectionModel()
168                .setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
169     this.tree.setCellRenderer(new AppRenderer());
170
171     setLayout(new BorderLayout JavaDoc());
172     setPreferredSize(new Dimension JavaDoc(600, 500));
173     
174     //Create the scroll pane and add the tree to it.
175
JScrollPane JavaDoc treeView = new JScrollPane JavaDoc(tree);
176     add(treeView, BorderLayout.CENTER);
177     
178     JPanel JavaDoc bottomPanel = new JPanel JavaDoc(new GridLayout JavaDoc(0, 1));
179     bottomPanel.add(createButtonPanel());
180     add(bottomPanel, BorderLayout.EAST);
181
182     this.frame = frame;
183   }
184   
185   /**
186    * Creates the tree structure from the files stored in <code>categories</code>.
187    *
188    * @throws JBlanketException if unable to parse an XML file.
189    */

190   private void createTree() throws JBlanketException {
191     // check if corresponding files were added
192
if (this.excludeOneLineMethods) {
193       this.categories.getFileName("oneLineFile");
194     }
195     if (this.excludeConstructors) {
196       this.categories.getFileName("constructorFile");
197     }
198     // automatically excluded
199
this.categories.getFileName("excludedIndividualFile");
200     
201     Iterator JavaDoc i = this.categories.getCategories().iterator();
202     while (i.hasNext()) {
203       String JavaDoc key = (String JavaDoc) i.next();
204       File JavaDoc nextFile = new File JavaDoc((String JavaDoc) this.categories.getFileName(key));
205       if (!(key.equals("excludedIndividualFile") && !nextFile.exists())) {
206         parseXmlFile(nextFile, key);
207       }
208     }
209
210   }
211   
212   /**
213    * Parses <code>fileName</code> and aggregates its contained methods into a common repository.
214    *
215    * @param file the XML file to parse.
216    * @param methodCategory the category of methods in <code>fileName</code>.
217    * @throws JBlanketException if unable to open, read, or parse <code>fileName</code>.
218    */

219   private void parseXmlFile(File JavaDoc file, String JavaDoc methodCategory) throws JBlanketException {
220     // create instances needed for parsing
221
XMLReader JavaDoc reader = new SAXParser();
222     /* Attempt at replacing Xerces with Java 1.4 Standard Library
223     XMLReader reader = null;
224     try {
225       // throws SAXException, ParserConfigurationException
226       reader = SAXParserFactory.newInstance().newSAXParser().getXMLReader();
227     }
228     catch (Exception e) {
229        throw new JBlanketException("", e);
230     }
231     */

232     // register content handler
233
reader.setContentHandler(new NodeContentHandler(this.treeModel, methodCategory));
234     // register error handler
235
reader.setErrorHandler(new NodeErrorHandler());
236     // parse
237
InputSource JavaDoc inputSource = null;
238     
239     try {
240       inputSource = new InputSource JavaDoc(new FileInputStream JavaDoc(file));
241     }
242     catch (IOException JavaDoc e) {
243       throw new JBlanketException("Unable to open file " + file);
244     }
245     
246     inputSource.setSystemId(file.getAbsolutePath());
247     
248     try {
249       reader.parse(inputSource);
250     }
251     catch (SAXException JavaDoc e) {
252       throw new JBlanketException("Unable to parse file " + file, e);
253     }
254     catch (IOException JavaDoc e) {
255       throw new JBlanketException("Unable to read file " + file, e);
256     }
257   }
258
259   /**
260    * Creates the legend at the top of the application
261    *
262    * @return filled out JPanel, ready to add to a component.
263    */

264   private JPanel JavaDoc createLegend() {
265     
266     // crate list for legend
267
List JavaDoc legendList = new ArrayList JavaDoc();
268     legendList.add("plain -- tested\n");
269     legendList.add("BOLD");
270     legendList.add(" -- untested\n");
271     legendList.add("black -- included\n");
272     
273 // if (this.excludeConstructors) {
274
legendList.add("blue");
275       legendList.add(" -- constructor\n");
276 // }
277

278 // if (this.excludeOneLineMethods) {
279
legendList.add("purple");
280       legendList.add(" -- one-line\n");
281 // }
282

283     legendList.add("red");
284     legendList.add(" -- user excluded\n");
285     
286     // create list of styles
287
List JavaDoc stylesList = new ArrayList JavaDoc();
288     stylesList.add("regular");
289     stylesList.add("bold");
290     stylesList.add("regular");
291     stylesList.add("black");
292     
293 // if (this.excludeConstructors) {
294
stylesList.add("blue");
295       stylesList.add("regular");
296 // }
297

298 // if (this.excludeOneLineMethods) {
299
stylesList.add("purple");
300       stylesList.add("regular");
301 // }
302
stylesList.add("red");
303     stylesList.add("regular");
304
305     JTextPane JavaDoc legendPane = new JTextPane JavaDoc();
306     legendPane.setEditable(false);
307     //background color of com.sun.java.swing.plaf.motif.MotifLookAndFeel
308
legendPane.setBackground(new Color JavaDoc(175, 180, 199));
309     //background color of com.sun.java.swing.plaf.windows.WindowsLookAndFeel
310
// legendPane.setBackground(new Color(209, 205, 197));
311

312     initStylesForTextPane(legendPane);
313     Document JavaDoc doc = legendPane.getDocument();
314     try {
315
316       String JavaDoc[] legend = (String JavaDoc[]) legendList.toArray(new String JavaDoc[legendList.size()]);
317       String JavaDoc[] styles = (String JavaDoc[]) legendList.toArray(new String JavaDoc[legendList.size()]);
318       for (int i = 0; i < styles.length; i++) {
319         doc.insertString(doc.getLength(), legend[i], legendPane.getStyle(styles[i]));
320       }
321     }
322     catch (BadLocationException JavaDoc e) {
323        System.out.println("Unable to display legend properly");
324     }
325     
326     JPanel JavaDoc legendPanel = new JPanel JavaDoc(new FlowLayout JavaDoc());
327     legendPanel.add(legendPane);
328     return legendPanel;
329   }
330
331   /**
332    * Initailizes the styles used in the legend.
333    *
334    * @param textPane the panel to be affected.
335    */

336   protected void initStylesForTextPane(JTextPane JavaDoc textPane) {
337
338     Style JavaDoc def = StyleContext.getDefaultStyleContext().getStyle(StyleContext.DEFAULT_STYLE);
339
340     Style JavaDoc regular = textPane.addStyle("regular", def);
341     StyleConstants.setFontFamily(def, "SansSerif");
342
343     Style JavaDoc s = textPane.addStyle("bold", regular);
344     StyleConstants.setBold(s, true);
345
346     s = textPane.addStyle("black", regular);
347     StyleConstants.setForeground(s, Color.black);
348
349     s = textPane.addStyle("green", regular);
350     StyleConstants.setForeground(s, Color.green);
351
352     s = textPane.addStyle("red", regular);
353     StyleConstants.setForeground(s, Color.red);
354
355     s = textPane.addStyle("yellow", regular);
356     StyleConstants.setForeground(s, Color.yellow);
357
358     s = textPane.addStyle("orange", regular);
359     StyleConstants.setForeground(s, Color.orange);
360
361     s = textPane.addStyle("blue", regular);
362     StyleConstants.setForeground(s, Color.blue);
363
364     s = textPane.addStyle("purple", regular);
365     StyleConstants.setForeground(s, new Color JavaDoc(122, 22, 160));
366   }
367
368   /**
369    * Creates a panel holding all buttons and initializes the buttons with ActionListeners.
370    *
371    * @return a panel ready to add to a component.
372    */

373   private JPanel JavaDoc createButtonPanel() {
374
375     JPanel JavaDoc buttonPanel = new JPanel JavaDoc();
376
377     JButton JavaDoc excludeButton = new JButton JavaDoc("Exclude");
378     excludeButton.addActionListener(new ActionListener JavaDoc() {
379       public void actionPerformed(ActionEvent JavaDoc e) {
380         TreePath JavaDoc[] selectedPaths = tree.getSelectionPaths();
381         if (selectedPaths == null) {
382           // nothing was selected when button was pushed
383
return;
384         }
385         for (int i = 0; i < selectedPaths.length; i++) {
386           // process the current selected node(s)
387
DefaultMutableTreeNode JavaDoc selectedNode =
388               (DefaultMutableTreeNode JavaDoc) selectedPaths[i].getLastPathComponent();
389           processExcludeButton(selectedNode);
390           paint(getGraphics());
391         }
392       }
393     });
394     
395     JButton JavaDoc includeButton = new JButton JavaDoc("Include");
396     includeButton.addActionListener(new ActionListener JavaDoc() {
397       public void actionPerformed(ActionEvent JavaDoc e) {
398         TreePath JavaDoc[] selectedPaths = tree.getSelectionPaths();
399         if (selectedPaths == null) {
400           // nothing was selected when button was pushed
401
return;
402         }
403         for (int i = 0; i < selectedPaths.length; i++) {
404           // process every child node of the current selected node(s)
405
DefaultMutableTreeNode JavaDoc selectedNode =
406               (DefaultMutableTreeNode JavaDoc) selectedPaths[i].getLastPathComponent();
407           processIncludeButton(selectedNode);
408           paint(getGraphics());
409         }
410       }
411     });
412
413     JButton JavaDoc saveButton = new JButton JavaDoc("Save");
414     saveButton.addActionListener(new ActionListener JavaDoc() {
415       public void actionPerformed(ActionEvent JavaDoc e) {
416         processSaveButton();
417       }
418     });
419     
420     GridBagLayout JavaDoc gridbag = new GridBagLayout JavaDoc();
421     GridBagConstraints JavaDoc c = new GridBagConstraints JavaDoc();
422     
423     c.fill = GridBagConstraints.BOTH;
424     c.weightx = 1.0;
425
426     buttonPanel.setLayout(new BorderLayout JavaDoc());
427
428     c.gridwidth = GridBagConstraints.REMAINDER;
429     
430     JPanel JavaDoc topPanel = new JPanel JavaDoc(gridbag);
431     gridbag.setConstraints(excludeButton, c);
432     topPanel.add(excludeButton);
433     gridbag.setConstraints(includeButton, c);
434     topPanel.add(includeButton);
435     buttonPanel.add(topPanel, BorderLayout.NORTH);
436     
437     JPanel JavaDoc legendPanel = createLegend();
438     gridbag.setConstraints(legendPanel, c);
439     buttonPanel.add(legendPanel, BorderLayout.CENTER);
440
441     JPanel JavaDoc bottomPanel = new JPanel JavaDoc(gridbag);
442     gridbag.setConstraints(saveButton, c);
443     bottomPanel.add(saveButton);
444     buttonPanel.add(bottomPanel, BorderLayout.SOUTH);
445
446     return buttonPanel;
447   }
448
449   /**
450    * Processes the clicking of the "Exclude" button. This method is recursive.
451    *
452    * @param treeNode the tree affected by the buton.
453    */

454   private void processExcludeButton(DefaultMutableTreeNode JavaDoc treeNode) {
455     
456     if (!treeNode.isLeaf()) {
457       Enumeration JavaDoc children = treeNode.children();
458       while (children.hasMoreElements()) {
459         DefaultMutableTreeNode JavaDoc nextChild = (DefaultMutableTreeNode JavaDoc) children.nextElement();
460         processExcludeButton(nextChild);
461       }
462     }
463     else {
464       MethodNode nextMethod = (MethodNode) treeNode.getUserObject();
465       nextMethod.setNewColor(MethodCategoryColor.EXCLUDED_INDIVIDUAL.getColor());
466     }
467   }
468
469   /**
470    * Processes the clicking of the "Include" button. This method is recursive.
471    *
472    * @param treeNode the tree affected by the buton.
473    */

474   private void processIncludeButton(DefaultMutableTreeNode JavaDoc treeNode) {
475     
476     if (!treeNode.isLeaf()) {
477       Enumeration JavaDoc children = treeNode.children();
478       while (children.hasMoreElements()) {
479         DefaultMutableTreeNode JavaDoc nextChild = (DefaultMutableTreeNode JavaDoc) children.nextElement();
480         processIncludeButton(nextChild);
481       }
482     }
483     else {
484       MethodNode nextMethod = (MethodNode) treeNode.getUserObject();
485       // if node is an excluded individual method, then its color should toggle between
486
// excluded individual method and untested
487
if ((nextMethod.getOrigColor().equals(MethodCategoryColor.EXCLUDED_INDIVIDUAL.getColor())) &&
488           (nextMethod.getNewColor().equals(MethodCategoryColor.EXCLUDED_INDIVIDUAL.getColor()))) {
489           nextMethod.setNewColor(MethodCategoryColor.UNTESTED.getColor());
490       }
491       else {
492         // else revert to the previous category
493
nextMethod.setNewColor(nextMethod.getOrigColor());
494       }
495     }
496   }
497
498   /**
499    * Processes the clicking of the "Save" button.
500    */

501   private void processSaveButton() {
502     // writes out current configuration to XML files
503
String JavaDoc fileName = categories.getFileName("excludedIndividualFile");
504     
505     try {
506       (new TreeWriter(treeModel)).store(new FileOutputStream JavaDoc(new File JavaDoc(fileName)));
507     }
508     catch (IOException JavaDoc e) {
509       System.out.println("Unable to store individually excluded methods to " + fileName);
510     }
511     
512     JOptionPane.showMessageDialog(frame, "Excluded methods saved to\n" + fileName,
513                                  "JBlanket Notification", JOptionPane.PLAIN_MESSAGE);
514   }
515   
516   /**
517    * Provides the command line interface.
518    *
519    * @param args the command line arguments.
520    * @throws JBlanketException if cannot read the date from files.
521    */

522   public static void main(String JavaDoc args[]) throws JBlanketException {
523     main(java.util.Arrays.asList(args));
524   }
525
526   /**
527    * Launches the application for excluding individual methods.
528    *
529    * @param args the command line arguments.
530    * @throws JBlanketException if errors occur.
531    */

532   public static void main(List JavaDoc args) throws JBlanketException {
533     
534     // Verbose mode
535
boolean verbose = false;
536     // format of final HTML report
537
String JavaDoc reportFormat = "frames";
538
539     // Exclude one-line methods
540
boolean excludeOneLineMethods = false;
541     // Exclude constructors
542
boolean excludeConstructors = false;
543
544     MethodCategories categories = MethodCategories.getInstance();
545
546     // index of current command line arguments.
547
int i;
548     // Parses args into corresponsing variables.
549
for (i = 0; i < args.size(); ++i) {
550       
551       String JavaDoc argument = (String JavaDoc) args.get(i);
552       
553       if (argument.equals("-verbose")) {
554         verbose = (new Boolean JavaDoc((String JavaDoc) args.get(++i))).booleanValue();
555       }
556       else if (argument.equals("-excludeOneLineMethods")) {
557         excludeOneLineMethods = (new Boolean JavaDoc((String JavaDoc) args.get(++i))).booleanValue();
558       }
559       else if (argument.equals("-excludeConstructors")) {
560         excludeConstructors = (new Boolean JavaDoc((String JavaDoc) args.get(++i))).booleanValue();
561       }
562       else if (argument.equals("-oneLineFile")) {
563         categories.addCategory("oneLineFile", (String JavaDoc) args.get(++i));
564       }
565       else if (argument.equals("-constructorFile")) {
566         categories.addCategory("constructorFile", (String JavaDoc) args.get(++i));
567       }
568       else if (argument.equals("-excludedIndividualFile")) {
569         categories.addCategory("excludedIndividualFile", (String JavaDoc) args.get(++i));
570       }
571       else if (argument.equals("-total.testedFile")) {
572         categories.addCategory("total.testedFile");
573       }
574       else if (argument.equals("-total.untestedFile")) {
575         categories.addCategory("total.untestedFile");
576       }
577       else {
578         System.out.println("Incorrect usage: " + argument);
579         System.exit(1);
580       }
581     }
582  
583     try {
584 // UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
585
// UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
586
// UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
587
UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel");
588     }
589     catch (Exception JavaDoc e) {
590       // do nothing
591
}
592     
593     JFrame JavaDoc frame = new JFrame JavaDoc("JBlanket - Exclude Individual Methods");
594
595     Container JavaDoc contentPane = frame.getContentPane();
596     contentPane.setLayout(new GridLayout JavaDoc(0, 1));
597     contentPane.add(new ExcludeIndividualMethodApp(verbose, excludeOneLineMethods,
598                                                    excludeConstructors, frame));
599   
600     frame.addWindowListener(new WindowAdapter JavaDoc() {
601       public void windowClosing(WindowEvent JavaDoc e) {
602         System.exit(0);
603       }
604     });
605     frame.pack();
606     frame.setVisible(true);
607   }
608 }
Popular Tags