KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > edu > rice > cs > drjava > ui > DrJavaErrorWindow


1 /*BEGIN_COPYRIGHT_BLOCK
2  *
3  * This file is part of DrJava. Download the current version of this project from http://www.drjava.org/
4  * or http://sourceforge.net/projects/drjava/
5  *
6  * DrJava Open Source License
7  *
8  * Copyright (C) 2001-2005 JavaPLT group at Rice University (javaplt@rice.edu). All rights reserved.
9  *
10  * Developed by: Java Programming Languages Team, Rice University, http://www.cs.rice.edu/~javaplt/
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
13  * documentation files (the "Software"), to deal with the Software without restriction, including without limitation
14  * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
15  * to permit persons to whom the Software is furnished to do so, subject to the following conditions:
16  *
17  * - Redistributions of source code must retain the above copyright notice, this list of conditions and the
18  * following disclaimers.
19  * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
20  * following disclaimers in the documentation and/or other materials provided with the distribution.
21  * - Neither the names of DrJava, the JavaPLT, Rice University, nor the names of its contributors may be used to
22  * endorse or promote products derived from this Software without specific prior written permission.
23  * - Products derived from this software may not be called "DrJava" nor use the term "DrJava" as part of their
24  * names without prior written permission from the JavaPLT group. For permission, write to javaplt@rice.edu.
25  *
26  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
27  * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28  * CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
29  * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
30  * WITH THE SOFTWARE.
31  *
32  *END_COPYRIGHT_BLOCK*/

33
34 package edu.rice.cs.drjava.ui;
35
36 import javax.swing.*;
37 import javax.swing.event.*;
38 import javax.swing.text.*;
39 import javax.swing.border.*;
40 import java.awt.event.*;
41 import java.awt.*;
42 import java.io.ByteArrayOutputStream JavaDoc;
43
44 import edu.rice.cs.drjava.DrJava;
45 import edu.rice.cs.util.UnexpectedException;
46 import edu.rice.cs.util.StringOps;
47 import edu.rice.cs.util.swing.BorderlessScrollPane;
48 import edu.rice.cs.drjava.platform.PlatformFactory;
49
50 /** Displays uncaught exceptions and logged conditions.
51  * This window is not automatically updated when new errors occur. In the case of errors, we want to
52  * minimize the effects on the GUI. If we want to see an updated dialog, we can click on the "DrJava Errors"
53  * button again.
54  * @version $Id: DrJavaErrorWindow.java 4059 2007-01-17 05:53:14Z mgricken $
55  */

56 public class DrJavaErrorWindow extends JDialog {
57   /** Sourceforge add bug URL */
58   public static final String JavaDoc SF_ADD_BUG_URL = "http://sourceforge.net/tracker/?func=add&group_id=44253&atid=438935/";
59
60   /** Sourceforge URL */
61   public static final String JavaDoc SF_LINK_NAME = "http://sourceforge.net/projects/drjava";
62   
63   /** information about the error */
64   private volatile JEditorPane _errorInfo;
65   /** contains the stack trace */
66   private final JTextArea _stackTrace;
67   /** label with index */
68   private final JLabel _indexLabel;
69   /** scroll pane for _stackTrace */
70   private final JScrollPane _stackTraceScroll;
71   /** compresses the buttonPanel into the east */
72   private final JPanel _bottomPanel;
73   /** contains the butons */
74   private final JPanel _buttonPanel;
75   /** the button that copies the stack trace to the clipboard */
76   private final JButton _copyButton;
77   /** the button that closes this window */
78   private final JButton _okButton;
79   /** the button that moves to the next error */
80   private final JButton _nextButton;
81   /** the button that moves to the previous error */
82   private final JButton _prevButton;
83   /** the button that clears all errors and closes the window */
84   private final JButton _dismissButton;
85   /** the number of errors that had occurred */
86   private volatile int _errorCount;
87   /** the currently selected error */
88   private volatile Throwable JavaDoc _error;
89   /** the currently selected error index */
90   private volatile int _errorIndex;
91   /** the parent frame */
92   private static volatile JFrame _parentFrame = new JFrame();
93   /** true if parent changed since last singleton() call */
94   private static volatile boolean _parentChanged = true;
95   
96   /** Sets the parent frame. */
97   public static void setFrame(JFrame f) { _parentFrame = f; _parentChanged = true; }
98   
99   /** Gets the parent frame. */
100   public static JFrame getFrame() { return _parentFrame; }
101   
102   /** The singleton instance of this dialog. */
103   private static volatile DrJavaErrorWindow _singletonInstance;
104   
105   /** Returns the singleton instance. Recreates it if necessary. */
106   public static DrJavaErrorWindow singleton() {
107     if (_parentChanged) {
108       synchronized(DrJavaErrorWindow.class) {
109         if (_parentChanged) {
110           _singletonInstance = new DrJavaErrorWindow();
111           _parentChanged = false;
112         }
113       }
114     }
115     return _singletonInstance;
116   }
117   
118   /** Creates a window to graphically display the errors that have occurred in the code of DrJava. */
119   private DrJavaErrorWindow() {
120     super(_parentFrame, "DrJava Errors");
121
122     this.setSize(600,400);
123
124     // If we set this pane to be of type text/rtf, it wraps based on words
125
// as opposed to based on characters.
126
_stackTrace = new JTextArea();
127     _stackTrace.setEditable(false);
128
129     _prevButton = new JButton(_prevAction);
130     _nextButton = new JButton(_nextAction);
131     _copyButton = new JButton(_copyAction);
132     _dismissButton = new JButton(_dismissAction);
133     _okButton = new JButton(_okAction);
134
135     _bottomPanel = new JPanel(new BorderLayout());
136     _buttonPanel = new JPanel();
137     _buttonPanel.add(_prevButton);
138     _buttonPanel.add(_nextButton);
139     _buttonPanel.add(_copyButton);
140     _buttonPanel.add(_dismissButton);
141     _buttonPanel.add(_okButton);
142     _indexLabel = new JLabel();
143     _bottomPanel.add(_indexLabel, BorderLayout.CENTER);
144     _bottomPanel.add(_buttonPanel, BorderLayout.EAST);
145
146     _stackTraceScroll = new BorderlessScrollPane(_stackTrace,
147                                                  JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
148                                                  JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
149     _errorInfo = _errorInfo = new JEditorPane("text/html", HEADER_HTML+NO_ERRORS_HTML);
150     _errorInfo.setEditable(false);
151     _errorInfo.setBackground(getContentPane().getBackground());
152     final JPanel cp = new JPanel(new BorderLayout(5,5));
153     cp.setBorder(new EmptyBorder(5,5,5,5));
154     setContentPane(cp);
155     cp.add(_errorInfo, BorderLayout.NORTH);
156     cp.add(_stackTraceScroll, BorderLayout.CENTER);
157     cp.add(_bottomPanel, BorderLayout.SOUTH);
158     getRootPane().setDefaultButton(_okButton);
159     init();
160   }
161   
162   /** Initialize the dialog when setting to visible. */
163   public void setVisible(boolean b) {
164     if (b) {
165       init();
166     }
167     super.setVisible(b);
168   }
169   
170   /** Initialize the dialog. */
171   private void init() {
172     _errorCount = DrJavaErrorHandler.getErrorCount();
173     if (_errorCount>0) {
174       _error = DrJavaErrorHandler.getError(0);
175       _errorIndex = 0;
176     }
177     else {
178       _error = null;
179       _errorIndex = -1;
180     }
181     _prevAction.setEnabled(false);
182     _nextAction.setEnabled(_errorCount>1);
183     _dismissAction.setEnabled(_errorCount>0);
184     _copyAction.setEnabled(_errorCount>0);
185     updateErrorInfo();
186   }
187
188   /** Update the buttons and text area after next or previous. */
189   private void updateErrorInfo() {
190     getContentPane().remove(_errorInfo);
191     if (_error!=null) {
192       final StringBuilder JavaDoc b = new StringBuilder JavaDoc();
193       if (_error instanceof DrJavaErrorHandler.LoggedCondition) {
194         b.append("Logged condition: ");
195         b.append(_error.getMessage());
196         b.append('\n');
197         boolean first = true;
198         for (StackTraceElement JavaDoc ste: _error.getStackTrace()) {
199           if (first) { first = false; continue; /* skip first frame, that's the log method itself */ }
200           b.append("\tat ");
201           b.append(ste);
202           b.append('\n');
203         }
204       }
205       else {
206         b.append(StringOps.getStackTrace(_error));
207         if (_error instanceof UnexpectedException) {
208           Throwable JavaDoc t = ((UnexpectedException)_error).getCause();
209           b.append("\nCaused by:\n");
210           b.append(StringOps.getStackTrace(t));
211         }
212       }
213       
214       b.append("\n\n");
215       b.append(getSystemAndDrJavaInfo());
216
217       _stackTrace.setText(b.toString());
218       _stackTrace.setCaretPosition(0);
219       
220       final StringBuilder JavaDoc b2 = new StringBuilder JavaDoc();
221       b2.append(HEADER_HTML);
222       b2.append(_errorCount);
223       b2.append(" error");
224       b2.append(((_errorCount>1)?"s":""));
225       b2.append(" occured!<br>");
226       b2.append(ERRORS_FOOTER_HTML);
227       _errorInfo = new JEditorPane("text/html", b2.toString());
228       _errorInfo.addHyperlinkListener(new HyperlinkListener() {
229         public void hyperlinkUpdate(HyperlinkEvent e) {
230           if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
231             try {
232               PlatformFactory.ONLY.openURL(e.getURL());
233             } catch(Exception JavaDoc ex) { /* ignore, just not open web page */ }
234           }
235         }
236       });
237       _errorInfo.setEditable(false);
238       _errorInfo.setBackground(getContentPane().getBackground());
239       _indexLabel.setText("Error "+(_errorIndex+1)+" of "+(_errorCount));
240     }
241     else {
242       _errorInfo = new JEditorPane("text/html", HEADER_HTML+NO_ERRORS_HTML);
243       _errorInfo.addHyperlinkListener(new HyperlinkListener() {
244         public void hyperlinkUpdate(HyperlinkEvent e) {
245           if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
246             try {
247               PlatformFactory.ONLY.openURL(e.getURL());
248             } catch(Exception JavaDoc ex) { /* ignore, just not open web page */ }
249           }
250         }
251       });
252       _errorInfo.setEditable(false);
253       _errorInfo.setBackground(getContentPane().getBackground());
254       _stackTrace.setText("");
255       _indexLabel.setText("");
256     }
257     getContentPane().add(_errorInfo, BorderLayout.NORTH);
258     validate();
259   }
260   
261   /** Return a string with the system properties, the DrJava configuration file contents, and
262     * information about memory. The data is anonymized.
263     * @return information string */

264   public static String JavaDoc getSystemAndDrJavaInfo() {
265     final StringBuilder JavaDoc b = new StringBuilder JavaDoc();
266     b.append("System Properties:\n");
267     b.append("DrJava Version ");
268     b.append(edu.rice.cs.drjava.Version.getBuildTimeString());
269     b.append('\n');
270     java.util.Properties JavaDoc props = System.getProperties();
271     int size = props.size();
272     java.util.Iterator JavaDoc entries = props.entrySet().iterator();
273     while(entries.hasNext()) {
274       java.util.Map.Entry entry = (java.util.Map.Entry)entries.next();
275       b.append(entry.getKey());
276       b.append(" = ");
277       if (entry.getKey().equals("line.separator")) {
278         b.append("\"");
279         String JavaDoc ls = (String JavaDoc)entry.getValue();
280         for(int i=0; i<ls.length(); ++i) {
281           int ch = ls.charAt(i);
282           b.append("\\u");
283           String JavaDoc hexString = "0000" + Integer.toHexString(ch);
284           b.append(hexString.substring(hexString.length()-4));
285         }
286         b.append("\"");
287       }
288       else {
289         b.append(entry.getValue());
290       }
291       b.append('\n');
292     }
293     b.append('\n');
294     ByteArrayOutputStream JavaDoc baos = new ByteArrayOutputStream JavaDoc();
295     try {
296       DrJava.getConfig().saveConfiguration(baos, "DrJava configuration file");
297       b.append(baos.toString());
298     }
299     catch(java.io.IOException JavaDoc ioe) {
300       b.append("IOException when trying to print DrJava configuration file");
301     }
302     
303     b.append("\n\nUsed memory: about ");
304     b.append(StringOps.memSizeToString(Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory()));
305     b.append("\nFree memory: about ");
306     b.append(StringOps.memSizeToString(Runtime.getRuntime().freeMemory()));
307     b.append("\nTotal memory: about ");
308     b.append(StringOps.memSizeToString(Runtime.getRuntime().totalMemory()));
309     b.append("\nTotal memory can expand to: about ");
310     b.append(StringOps.memSizeToString(Runtime.getRuntime().maxMemory()));
311     b.append("\n\n");
312     
313     // filter out user.dir, user.home and user.name
314
String JavaDoc infoText = b.toString();
315     
316     String JavaDoc userHome = System.getProperty("user.home");
317     String JavaDoc anonUserHome = "<anonymized user.home>";
318     infoText = replaceString(infoText, userHome, anonUserHome);
319     
320     String JavaDoc userDir = System.getProperty("user.dir");
321     String JavaDoc anonUserDir = "<anonymized user.dir>";
322     infoText = replaceString(infoText, userDir, anonUserDir);
323     
324     String JavaDoc userName = System.getProperty("user.name");
325     String JavaDoc anonUserName = "<anonymized user.name>";
326     infoText = replaceString(infoText, userName, anonUserName);
327     
328     return infoText;
329   }
330   
331   /* Close the window. */
332   private final Action _okAction = new AbstractAction("OK") {
333     public void actionPerformed(ActionEvent e) {
334       DrJavaErrorWindow.this.dispose();
335     }
336   };
337   
338   /* Go to the previous error. */
339   private final Action _prevAction = new AbstractAction("Previous") {
340     public void actionPerformed(ActionEvent e) {
341       if (_errorIndex>0) {
342         --_errorIndex;
343         _error = DrJavaErrorHandler.getError(_errorIndex);
344         if (_errorIndex==0) { setEnabled(false); }
345         if (_errorCount>1) { _nextAction.setEnabled(true); }
346         updateErrorInfo();
347       }
348     }
349   };
350   
351   /** Replaces all occurrences of orig in text with repl. */
352   private static String JavaDoc replaceString(String JavaDoc text, String JavaDoc orig, String JavaDoc repl) {
353     int pos = 0;
354     while((pos=text.indexOf(orig,pos))>=0) {
355       // found occurrence at pos
356
text = text.substring(0,pos) + repl + text.substring(pos+orig.length(), text.length());
357     }
358     return text;
359   }
360   
361   /** Go to the next error. */
362   private final Action _nextAction = new AbstractAction("Next") {
363     public void actionPerformed(ActionEvent e) {
364       if (_errorIndex<_errorCount-1) {
365         ++_errorIndex;
366         _error = DrJavaErrorHandler.getError(_errorIndex);
367         if (_errorIndex==_errorCount-1) { setEnabled(false); }
368         if (_errorCount>1) { _prevAction.setEnabled(true); }
369         updateErrorInfo();
370       }
371     }
372   };
373   
374   /** Dismiss all errors and close the window. */
375   private Action _dismissAction = new AbstractAction("Dismiss") {
376     public void actionPerformed(ActionEvent e) {
377       DrJavaErrorHandler.clearErrors();
378       _errorCount = 0;
379       _error = null;
380       _errorIndex = -1;
381       setEnabled(false);
382       _prevAction.setEnabled(false);
383       _nextAction.setEnabled(false);
384       _copyAction.setEnabled(false);
385       updateErrorInfo();
386       JButton errorsButton = DrJavaErrorHandler.getButton();
387       if (errorsButton!=null) { errorsButton.setVisible(false); }
388       _okAction.actionPerformed(e);
389     }
390   };
391
392   /** Copy currently selected error to clip board. */
393   private Action _copyAction = new AbstractAction("Copy This Error") {
394     public void actionPerformed(ActionEvent e) {
395       _stackTrace.grabFocus();
396       _stackTrace.getActionMap().get(DefaultEditorKit.selectAllAction).actionPerformed(e);
397       _stackTrace.getActionMap().get(DefaultEditorKit.copyAction).actionPerformed(e);
398     }
399   };
400
401   /**
402    * Canned message for the user.
403    */

404   private final String JavaDoc HEADER_HTML =
405     "<html><font size=\"-1\" face=\"sans-serif, Arial, Helvetica, Geneva\"><b>";
406   private final String JavaDoc ERRORS_FOOTER_HTML =
407     "Please submit a bug report containing the information below " +
408     "and an account of the actions that caused the bug (if known) to " +
409     "<a HREF=\"" + SF_ADD_BUG_URL + "\"><b>" + SF_LINK_NAME + "</b></a>.<br>" +
410     "You may wish to save all your work and restart DrJava.<br>" +
411     "Thanks for your help in making DrJava better!</b></font></p></html>";
412   private final String JavaDoc NO_ERRORS_HTML =
413     "No errors occurred!<br>" +
414     "Thanks for using DrJava!</b></font></p></html>";
415 }
Popular Tags