1 19 20 package org.netbeans.core; 21 22 import java.awt.BorderLayout ; 23 import java.awt.Component ; 24 import java.awt.Dialog ; 25 import java.awt.Dimension ; 26 import java.awt.Font ; 27 import java.awt.GraphicsEnvironment ; 28 import java.awt.Rectangle ; 29 import java.awt.Window ; 30 import java.awt.event.ActionListener ; 31 import java.io.PrintWriter ; 32 import java.io.StringWriter ; 33 import java.lang.reflect.ParameterizedType ; 34 import java.lang.reflect.Type ; 35 import java.util.ArrayList ; 36 import java.util.ResourceBundle ; 37 import java.util.concurrent.Callable ; 38 import java.util.logging.Handler ; 39 import java.util.logging.Level ; 40 import java.util.logging.Logger ; 41 import javax.swing.Icon ; 42 import javax.swing.ImageIcon ; 43 import javax.swing.JButton ; 44 import javax.swing.JDialog ; 45 import javax.swing.JPanel ; 46 import javax.swing.JScrollPane ; 47 import javax.swing.JTextPane ; 48 import javax.swing.SwingUtilities ; 49 import javax.swing.UIManager ; 50 import org.netbeans.core.startup.CLIOptions; 51 import org.openide.DialogDescriptor; 52 import org.openide.DialogDisplayer; 53 import org.openide.NotifyDescriptor; 54 import org.openide.awt.Mnemonics; 55 import org.openide.util.Exceptions; 56 import org.openide.util.NbBundle; 57 import org.openide.util.Utilities; 58 import org.openide.windows.WindowManager; 59 60 68 public final class NotifyExcPanel extends JPanel implements ActionListener { 69 static final long serialVersionUID =3680397500573480127L; 70 71 72 73 private static NotifyExcPanel INSTANCE = null; 74 75 private static final int SIZE_PREFERRED_WIDTH=550; 76 77 private static final int SIZE_PREFERRED_HEIGHT=250; 78 79 80 private static ArrayListPos exceptions; 81 82 private NbErrorManager.Exc current; 83 84 85 private DialogDescriptor descriptor; 86 87 java.awt.Dialog dialog; 88 89 private JButton next; 90 91 private JButton previous; 92 93 private JButton details; 94 95 private JTextPane output; 96 97 98 private static boolean showDetails; 99 100 101 private static Rectangle lastBounds; 102 103 105 private NotifyExcPanel () { 106 setPreferredSize(new Dimension (SIZE_PREFERRED_WIDTH,SIZE_PREFERRED_HEIGHT)); 107 108 java.util.ResourceBundle bundle = org.openide.util.NbBundle.getBundle(NotifyExcPanel.class); 109 next = new JButton (); 110 Mnemonics.setLocalizedText(next, bundle.getString("CTL_NextException")); 111 next.setDefaultCapable (false); 113 previous = new JButton (); 114 Mnemonics.setLocalizedText(previous, bundle.getString("CTL_PreviousException")); 115 previous.setDefaultCapable (false); 116 details = new JButton (); 117 details.setDefaultCapable (false); 118 119 output = new JTextPane () { 120 public boolean getScrollableTracksViewportWidth() { 121 return false; 122 } 123 }; 124 output.setEditable(false); 125 output.setFont(new Font ("Monospaced", Font.PLAIN, output.getFont().getSize() + 1)); output.setForeground(UIManager.getColor("Label.foreground")); output.setBackground(UIManager.getColor("Label.background")); 129 setLayout( new BorderLayout () ); 130 add(new JScrollPane (output)); 131 setBorder( new javax.swing.border.BevelBorder (javax.swing.border.BevelBorder.LOWERED)); 132 133 next.getAccessibleContext().setAccessibleDescription(bundle.getString("ACSD_NextException")); 134 previous.getAccessibleContext().setAccessibleDescription(bundle.getString("ACSD_PreviousException")); 135 output.getAccessibleContext().setAccessibleName(bundle.getString("ACSN_ExceptionStackTrace")); 136 output.getAccessibleContext().setAccessibleDescription(bundle.getString("ACSD_ExceptionStackTrace")); 137 getAccessibleContext().setAccessibleDescription(bundle.getString("ACSD_NotifyExceptionPanel")); 138 139 descriptor = new DialogDescriptor ("", ""); 141 descriptor.setMessageType (DialogDescriptor.ERROR_MESSAGE); 142 descriptor.setOptions (computeOptions(previous, next)); 143 descriptor.setAdditionalOptions (new Object [] { 144 details 145 }); 146 descriptor.setClosingOptions (new Object [0]); 147 descriptor.setButtonListener (this); 148 149 descriptor.setModal( isModalDialogPresent() 155 && WindowManager.getDefault().getMainWindow().isVisible() ); 156 157 dialog = DialogDisplayer.getDefault().createDialog(descriptor); 158 if( null != lastBounds ) 159 dialog.setBounds( lastBounds ); 160 161 dialog.getAccessibleContext().setAccessibleName(bundle.getString("ACN_NotifyExcPanel_Dialog")); dialog.getAccessibleContext().setAccessibleDescription(bundle.getString("ACD_NotifyExcPanel_Dialog")); } 164 165 static Object [] computeOptions(Object previous, Object next) { 166 ArrayList <Object > arr = new ArrayList <java.lang.Object >(); 167 arr.add(previous); 168 arr.add(next); 169 170 for (Handler h : Logger.getLogger("").getHandlers()) { 171 if (h instanceof Callable <?>) { 172 boolean foundCallableForJButton = false; 173 for (Type t : h.getClass().getGenericInterfaces()) { 174 if (t instanceof ParameterizedType ) { 175 ParameterizedType p = (ParameterizedType )t; 176 Type [] params = p.getActualTypeArguments(); 177 if (params.length == 1 && params[0] == JButton .class) { 178 foundCallableForJButton = true; 179 break; 180 } 181 } 182 } 183 if (!foundCallableForJButton) { 184 continue; 185 } 186 187 188 try { 189 Object o = ((Callable <?>)h).call(); 190 assert o instanceof JButton ; 191 arr.add(o); 192 } catch (Exception ex) { 193 Exceptions.printStackTrace(ex); 194 } 195 } 196 } 197 198 arr.add(DialogDescriptor.OK_OPTION); 199 return arr.toArray(); 200 } 201 202 private static boolean isModalDialogPresent() { 203 return hasModalDialog(WindowManager.getDefault().getMainWindow()) 204 || hasModalDialog(new JDialog ().getOwner()); 206 } 207 208 private static boolean hasModalDialog(Window w) { 209 if (w == null) { return false; 211 } 212 Window [] ws = w.getOwnedWindows(); 213 for(int i = 0; i < ws.length; i++) { 214 if(ws[i] instanceof Dialog && ((Dialog )ws[i]).isModal() && ws[i].isVisible()) { 215 return true; 216 } else if(hasModalDialog(ws[i])) { 217 return true; 218 } 219 } 220 221 return false; 222 } 223 224 227 static void cleanInstance() { 228 INSTANCE = null; 229 } 230 231 232 234 public static void notify ( 235 final NbErrorManager.Exc t 236 ) { 237 if (!shallNotify(t.getSeverity(), false)) { 238 return; 239 } 240 241 if ("java.awt.HeadlessException".equals(t.getClassName()) && GraphicsEnvironment.isHeadless()) { 243 t.printStackTrace(System.err); 244 return; 245 } 246 247 SwingUtilities.invokeLater (new Runnable () { 248 public void run() { 249 String glm = t.getLocalizedMessage(); 250 Level gs = t.getSeverity(); 251 boolean loc = t.isLocalized(); 252 253 if (loc) { 254 if (gs == Level.WARNING) { 255 DialogDisplayer.getDefault().notify( 256 new NotifyDescriptor.Message(glm, NotifyDescriptor.WARNING_MESSAGE) 257 ); 258 return; 259 } 260 261 if (gs.intValue() == 1973) { 262 DialogDisplayer.getDefault().notify( 263 new NotifyDescriptor.Message(glm, NotifyDescriptor.INFORMATION_MESSAGE) 264 ); 265 return; 266 } 267 268 if (gs == Level.SEVERE) { 269 DialogDisplayer.getDefault().notify( 270 new NotifyDescriptor.Message(glm, NotifyDescriptor.ERROR_MESSAGE) 271 ); 272 return; 273 } 274 } 275 276 277 if( null == exceptions ) 278 exceptions = new ArrayListPos(); 279 exceptions.add(t); 280 exceptions.position = exceptions.size()-1; 281 282 if(shallNotify(t.getSeverity(), true)) { 283 if( INSTANCE == null ) { 285 INSTANCE = new NotifyExcPanel(); 286 } 287 INSTANCE.updateState(t); 288 } else { 289 if( null != flasher && null == INSTANCE ) { 291 flasher.setToolTipText( getExceptionSummary( t ) ); 293 flasher.startFlashing(); 294 } else { 295 if( INSTANCE == null ) { 298 INSTANCE = new NotifyExcPanel(); 299 } 300 INSTANCE.updateState(t); 301 } 302 } 303 } 304 }); 305 } 306 307 311 private static String getExceptionSummary( final NbErrorManager.Exc t ) { 312 String plainmsg; 313 String glm = t.getLocalizedMessage(); 314 if (glm != null) { 315 plainmsg = glm; 316 } else if (t.getMessage() != null) { 317 plainmsg = t.getMessage(); 318 } else { 319 plainmsg = t.getClassName(); 320 } 321 assert plainmsg != null; 322 return plainmsg; 323 } 324 325 326 329 private void updateState (NbErrorManager.Exc t) { 330 if (!exceptions.existsNextElement()) { 331 342 current = t; 344 update (); 345 } else { 346 next.setVisible (true); 348 } 349 try { 350 ensurePreferredSize(); 355 dialog.setVisible(true); 356 } catch (Exception e) { 358 exceptions.add(new NbErrorManager().createExc( 359 e, Level.SEVERE, null)); 360 next.setVisible(true); 361 } 362 } 363 364 private void ensurePreferredSize() { 365 if( null != lastBounds ) 366 return; Dimension sz = dialog.getSize(); 368 Dimension pref = dialog.getPreferredSize(); 369 if (pref.height == 0) pref.height = SIZE_PREFERRED_HEIGHT; 370 if (pref.width == 0) pref.width = SIZE_PREFERRED_WIDTH; 371 if (!sz.equals(pref)) { 372 dialog.setSize(pref.width, pref.height); 373 dialog.validate(); 374 dialog.repaint(); 375 } 376 } 377 378 379 381 private void update () { 382 boolean isLocalized = current.isLocalized(); 384 385 next.setVisible (exceptions.existsNextElement()); 386 previous.setVisible (exceptions.existsPreviousElement()); 387 388 if (showDetails) { 389 Mnemonics.setLocalizedText(details, org.openide.util.NbBundle.getBundle(NotifyExcPanel.class).getString("CTL_Exception_Hide_Details")); 390 details.getAccessibleContext().setAccessibleDescription( 391 org.openide.util.NbBundle.getBundle(NotifyExcPanel.class).getString("ACSD_Exception_Hide_Details")); 392 } else { 393 Mnemonics.setLocalizedText(details, org.openide.util.NbBundle.getBundle(NotifyExcPanel.class).getString("CTL_Exception_Show_Details")); 394 details.getAccessibleContext().setAccessibleDescription( 395 org.openide.util.NbBundle.getBundle(NotifyExcPanel.class).getString("ACSD_Exception_Show_Details")); 396 } 397 398 String title = org.openide.util.NbBundle.getBundle(NotifyExcPanel.class).getString("CTL_Title_Exception"); 400 401 if (showDetails) { 402 descriptor.setMessage (this); 403 404 SwingUtilities.invokeLater(new Runnable () { 405 public void run() { 406 StringWriter wr = new StringWriter (); 408 current.printStackTrace(new PrintWriter (wr, true)); 409 output.setText(wr.toString()); 410 output.getCaret().setDot(0); 411 output.requestFocus (); 412 } 413 }); 414 } else { 415 if (isLocalized) { 416 String msg = current.getLocalizedMessage (); 417 if (msg != null) { 418 descriptor.setMessage (msg); 419 } 420 } else { 421 ResourceBundle curBundle = NbBundle.getBundle (NotifyExcPanel.class); 422 if (current.getSeverity() == Level.WARNING) { 423 descriptor.setMessage ( 425 java.text.MessageFormat.format( 426 curBundle.getString("NTF_ExceptionWarning"), 427 new Object [] { 428 current.getClassName () 429 } 430 ) 431 ); 432 title = curBundle.getString("NTF_ExceptionWarningTitle"); } else { 434 descriptor.setMessage ( 437 java.text.MessageFormat.format( 438 curBundle.getString("NTF_ExceptionalException"), 439 new Object [] { 440 current.getClassName (), 441 CLIOptions.getLogDir () 442 } 443 ) 444 ); 445 446 title = curBundle.getString("NTF_ExceptionalExceptionTitle"); } 448 } 449 } 450 451 descriptor.setTitle (title); 452 453 } 454 455 459 public void actionPerformed(final java.awt.event.ActionEvent ev) { 460 if (ev.getSource () == next && exceptions.setNextElement() || ev.getSource () == previous && exceptions.setPreviousElement()) { 461 current = exceptions.get(); 462 update (); 463 return; 466 } 467 468 if (ev.getSource () == details) { 469 showDetails = !showDetails; 470 lastBounds = null; 471 try { 472 update (); 473 ensurePreferredSize(); 474 } catch (Exception e) { 476 exceptions.add(new NbErrorManager().createExc(e, Level.SEVERE, null)); 480 next.setVisible(true); 481 } 482 return; 483 } 484 485 if (ev.getSource () == DialogDescriptor.OK_OPTION || ev.getSource () == DialogDescriptor.CLOSED_OPTION) { 487 try { 488 exceptions.removeAll(); 489 lastBounds = dialog.getBounds(); 496 dialog.dispose(); 497 exceptions = null; 498 INSTANCE = null; 499 } catch (RuntimeException e) { 501 exceptions = null; 504 INSTANCE = null; 505 throw e; 506 } finally { 507 exceptions = null; 508 INSTANCE = null; 509 } 510 } 511 } 512 513 514 518 private static boolean shallNotify(Level level, boolean dialog) { 519 int minAlert = Integer.getInteger("netbeans.exception.alert.min.level", 900); boolean assertionsOn = false; 521 assert assertionsOn = true; 522 int defReport = assertionsOn ? 900 : 1001; 523 int minReport = Integer.getInteger("netbeans.exception.report.min.level", defReport); 525 if (dialog) { 526 return level.intValue() >= minReport; 527 } else { 528 return level.intValue() >= minAlert || level.intValue() >= minReport; 529 } 530 } 531 532 533 537 static FlashingIcon flasher = null; 538 539 547 public static Component getNotificationVisualizer() { 548 if( null == flasher ) { 550 ImageIcon img1 = new ImageIcon ( Utilities.loadImage("org/netbeans/core/resources/exception.gif", true) ); 551 flasher = new ExceptionFlasher( img1 ); 552 } 553 return flasher; 554 } 555 556 private static class ExceptionFlasher extends FlashingIcon { 557 public ExceptionFlasher( Icon img1 ) { 558 super( img1 ); 559 } 560 561 564 protected void onMouseClick() { 565 if (null != exceptions && exceptions.size() > 0) { 566 if (INSTANCE == null) { 567 INSTANCE = new NotifyExcPanel(); 568 } 569 INSTANCE.updateState(exceptions.get(exceptions.size() - 1)); 570 } 571 } 572 573 577 protected void timeout() { 578 SwingUtilities.invokeLater( new Runnable () { 579 public void run() { 580 if( null != INSTANCE ) 581 return; 582 if( null != exceptions ) 583 exceptions.clear(); 584 exceptions = null; 585 } 586 }); 587 } 588 } 589 590 protected static class ArrayListPos extends ArrayList <NbErrorManager.Exc> { 591 protected int position; 592 593 protected ArrayListPos () { 594 super(); 595 position=0; 596 } 597 598 protected boolean existsElement () { 599 return size()>0; 600 } 601 602 protected boolean existsNextElement () { 603 return position+1<size(); 604 } 605 606 protected boolean existsPreviousElement () { 607 return position>0&&size()>0; 608 } 609 610 protected boolean setNextElement () { 611 if(!existsNextElement()) 612 return false; 613 position++; 614 return true; 615 } 616 617 protected boolean setPreviousElement () { 618 if(!existsPreviousElement()) 619 return false; 620 position--; 621 return true; 622 } 623 624 protected NbErrorManager.Exc get () { 625 return existsElement()?get(position):null; 626 } 627 628 protected void removeAll () { 629 clear(); 630 position=0; 631 } 632 } 633 } 634 | Popular Tags |