Coverage Report - org.seasar.uruma.ui.dialogs.UrumaErrorDialog
 
Classes in this File Line Coverage Branch Coverage Complexity
UrumaErrorDialog
0%
0/129
0%
0/42
0
UrumaErrorDialog$1
0%
0/5
N/A
0
UrumaErrorDialog$2
0%
0/8
0%
0/2
0
UrumaErrorDialog$3
0%
0/3
N/A
0
UrumaErrorDialog$DetailLabelProvider
0%
0/15
0%
0/6
0
UrumaErrorDialog$DetailsContentProvider
0%
0/17
0%
0/12
0
 
 1  
 /*
 2  
  * Copyright 2004-2008 the Seasar Foundation and the Others.
 3  
  *
 4  
  * Licensed under the Apache License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  *     http://www.apache.org/licenses/LICENSE-2.0
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
 13  
  * either express or implied. See the License for the specific language
 14  
  * governing permissions and limitations under the License.
 15  
  */
 16  
 package org.seasar.uruma.ui.dialogs;
 17  
 
 18  
 import java.io.InputStream;
 19  
 import java.util.ArrayList;
 20  
 import java.util.List;
 21  
 
 22  
 import org.eclipse.jface.dialogs.IDialogConstants;
 23  
 import org.eclipse.jface.dialogs.IconAndMessageDialog;
 24  
 import org.eclipse.jface.viewers.ILabelProvider;
 25  
 import org.eclipse.jface.viewers.ILabelProviderListener;
 26  
 import org.eclipse.jface.viewers.ITreeContentProvider;
 27  
 import org.eclipse.jface.viewers.StructuredSelection;
 28  
 import org.eclipse.jface.viewers.TreeViewer;
 29  
 import org.eclipse.jface.viewers.Viewer;
 30  
 import org.eclipse.swt.SWT;
 31  
 import org.eclipse.swt.dnd.Clipboard;
 32  
 import org.eclipse.swt.dnd.TextTransfer;
 33  
 import org.eclipse.swt.dnd.Transfer;
 34  
 import org.eclipse.swt.events.SelectionEvent;
 35  
 import org.eclipse.swt.events.SelectionListener;
 36  
 import org.eclipse.swt.graphics.Image;
 37  
 import org.eclipse.swt.graphics.Point;
 38  
 import org.eclipse.swt.layout.GridData;
 39  
 import org.eclipse.swt.layout.GridLayout;
 40  
 import org.eclipse.swt.widgets.Button;
 41  
 import org.eclipse.swt.widgets.Composite;
 42  
 import org.eclipse.swt.widgets.Control;
 43  
 import org.eclipse.swt.widgets.Display;
 44  
 import org.eclipse.swt.widgets.Menu;
 45  
 import org.eclipse.swt.widgets.MenuItem;
 46  
 import org.eclipse.swt.widgets.Shell;
 47  
 import org.eclipse.swt.widgets.Tree;
 48  
 import org.seasar.uruma.core.UrumaConstants;
 49  
 import org.seasar.uruma.util.MessageUtil;
 50  
 
 51  
 /**
 52  
  * 例外スタックトレースを表示するためのダイアログです。<br />
 53  
  * 
 54  
  * @author y-komori
 55  
  */
 56  0
 public class UrumaErrorDialog extends IconAndMessageDialog implements
 57  
         UrumaConstants {
 58  
     protected static final int DETAILS_ITEM_COUNT = 10;
 59  
 
 60  
     protected static final String NESTING_INDENT = "  ";
 61  
 
 62  
     protected String title;
 63  
 
 64  
     protected Button detailsButton;
 65  
 
 66  
     protected TreeViewer detailTreeViewer;
 67  
 
 68  
     protected boolean detailsCreated;
 69  
 
 70  
     protected Throwable rootThrowable;
 71  
 
 72  0
     protected List<Throwable> causes = new ArrayList<Throwable>();
 73  
 
 74  
     protected Clipboard clipboard;
 75  
 
 76  
     protected Image errorIcon;
 77  
 
 78  
     protected Image dialogIcon;
 79  
 
 80  
     /**
 81  
      * {@link UrumaErrorDialog} を構築します。<br />
 82  
      * 
 83  
      * @param parentShell
 84  
      *            親 {@link Shell} オブジェクト
 85  
      * @param title
 86  
      *            ダイアログタイトル
 87  
      * @param message
 88  
      *            メッセージ
 89  
      * @param ex
 90  
      *            例外オブジェクト
 91  
      */
 92  
     public UrumaErrorDialog(final Shell parentShell, final String title,
 93  
             final String message, final Throwable ex) {
 94  0
         super(parentShell);
 95  0
         this.title = (title != null ? title : "Error");
 96  0
         this.message = (message != null ? message : "");
 97  0
         this.rootThrowable = ex;
 98  0
         getCause(ex);
 99  0
         getImageIcons(parentShell);
 100  
 
 101  0
         setShellStyle(getShellStyle() | SWT.RESIZE);
 102  0
     }
 103  
 
 104  
     protected void getCause(final Throwable throwable) {
 105  0
         Throwable cause = throwable.getCause();
 106  0
         if ((cause != null) && !causes.contains(cause)) {
 107  0
             causes.add(cause);
 108  0
             getCause(cause);
 109  
         }
 110  0
     }
 111  
 
 112  
     protected void getImageIcons(final Shell shell) {
 113  0
         ClassLoader loader = getClass().getClassLoader();
 114  
 
 115  0
         InputStream is = loader.getResourceAsStream("images/error.png");
 116  0
         errorIcon = new Image(shell.getDisplay(), is);
 117  
 
 118  0
         is = loader.getResourceAsStream("images/uruma16.png");
 119  0
         dialogIcon = new Image(shell.getDisplay(), is);
 120  0
     }
 121  
 
 122  
     /*
 123  
      * @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell)
 124  
      */
 125  
     @Override
 126  
     protected void configureShell(final Shell shell) {
 127  0
         super.configureShell(shell);
 128  0
         shell.setText(this.title);
 129  0
         shell.setImage(dialogIcon);
 130  0
     }
 131  
 
 132  
     /*
 133  
      * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite)
 134  
      */
 135  
     @Override
 136  
     protected Control createDialogArea(final Composite parent) {
 137  0
         createMessageArea(parent);
 138  
 
 139  
         // create a composite with standard margins and spacing
 140  0
         Composite composite = new Composite(parent, SWT.NONE);
 141  0
         GridLayout layout = new GridLayout();
 142  0
         layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
 143  0
         layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
 144  0
         layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
 145  0
         layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
 146  0
         layout.numColumns = 2;
 147  0
         composite.setLayout(layout);
 148  0
         GridData childData = new GridData(SWT.FILL, SWT.FILL, true, false);
 149  0
         childData.horizontalSpan = 2;
 150  0
         composite.setLayoutData(childData);
 151  0
         composite.setFont(parent.getFont());
 152  
 
 153  0
         return composite;
 154  
     }
 155  
 
 156  
     /*
 157  
      * @see org.eclipse.jface.dialogs.Dialog#createButtonsForButtonBar(org.eclipse.swt.widgets.Composite)
 158  
      */
 159  
     @Override
 160  
     protected void createButtonsForButtonBar(final Composite parent) {
 161  
         // create OK and Details buttons
 162  0
         createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL,
 163  
                 true);
 164  0
         createDetailsButton(parent);
 165  0
     }
 166  
 
 167  
     protected void createDetailsButton(final Composite parent) {
 168  0
         detailsButton = createButton(parent, IDialogConstants.DETAILS_ID,
 169  
                 IDialogConstants.SHOW_DETAILS_LABEL, false);
 170  0
     }
 171  
 
 172  
     protected void toggleDetailsArea() {
 173  0
         Point windowSize = getShell().getSize();
 174  0
         Point oldSize = getShell().computeSize(SWT.DEFAULT, SWT.DEFAULT);
 175  0
         if (detailsCreated) {
 176  0
             detailTreeViewer.getTree().dispose();
 177  0
             detailsCreated = false;
 178  0
             detailsButton.setText(IDialogConstants.SHOW_DETAILS_LABEL);
 179  
         } else {
 180  0
             detailTreeViewer = createDetailsTreeViewer((Composite) getContents());
 181  0
             detailTreeViewer.setInput("");
 182  0
             detailsButton.setText(IDialogConstants.HIDE_DETAILS_LABEL);
 183  0
             detailsCreated = true;
 184  
         }
 185  0
         Point newSize = getShell().computeSize(SWT.DEFAULT, SWT.DEFAULT);
 186  0
         getShell()
 187  
                 .setSize(
 188  
                         new Point(windowSize.x, windowSize.y
 189  
                                 + (newSize.y - oldSize.y)));
 190  0
     }
 191  
 
 192  
     protected TreeViewer createDetailsTreeViewer(final Composite parent) {
 193  0
         TreeViewer viewer = new TreeViewer(parent, SWT.SINGLE
 194  
                 | SWT.FULL_SELECTION | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
 195  0
         Tree tree = viewer.getTree();
 196  
 
 197  0
         GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
 198  0
         data.heightHint = tree.getItemHeight() * DETAILS_ITEM_COUNT;
 199  0
         data.horizontalSpan = 2;
 200  0
         tree.setLayoutData(data);
 201  0
         tree.setFont(parent.getFont());
 202  0
         createContextMenu(tree);
 203  
 
 204  0
         viewer.setContentProvider(new DetailsContentProvider());
 205  0
         viewer.setLabelProvider(new DetailLabelProvider());
 206  0
         viewer.setAutoExpandLevel(2);
 207  0
         return viewer;
 208  
     }
 209  
 
 210  
     protected void createContextMenu(final Tree tree) {
 211  0
         Menu copyMenu = new Menu(tree);
 212  
 
 213  0
         MenuItem allCopyItem = new MenuItem(copyMenu, SWT.NONE);
 214  0
         allCopyItem.addSelectionListener(new SelectionListener() {
 215  
             public void widgetSelected(final SelectionEvent e) {
 216  0
                 copyToClipboard(rootThrowable);
 217  0
             }
 218  
 
 219  0
             public void widgetDefaultSelected(final SelectionEvent e) {
 220  0
                 widgetSelected(e);
 221  0
             }
 222  
         });
 223  0
         allCopyItem.setText(MessageUtil.getMessageWithBundleName(
 224  
                 URUMA_MESSAGE_BASE, "COPY_ALL"));
 225  
 
 226  0
         MenuItem copyItem = new MenuItem(copyMenu, SWT.NONE);
 227  0
         copyItem.addSelectionListener(new SelectionListener() {
 228  
             public void widgetSelected(final SelectionEvent e) {
 229  0
                 StructuredSelection selection = (StructuredSelection) detailTreeViewer
 230  
                         .getSelection();
 231  0
                 if (selection != null) {
 232  0
                     Object selected = selection.getFirstElement();
 233  0
                     copyToClipboard(selected);
 234  
                 }
 235  0
             }
 236  
 
 237  0
             public void widgetDefaultSelected(final SelectionEvent e) {
 238  0
                 widgetSelected(e);
 239  0
             }
 240  
         });
 241  0
         copyItem.setText(MessageUtil.getMessageWithBundleName(
 242  
                 URUMA_MESSAGE_BASE, "COPY_SELECTION"));
 243  
 
 244  0
         tree.setMenu(copyMenu);
 245  0
     }
 246  
 
 247  
     private void copyToClipboard(final Object selected) {
 248  0
         if (clipboard != null) {
 249  0
             clipboard.dispose();
 250  
         }
 251  0
         if (selected == null) {
 252  0
             return;
 253  
         }
 254  
 
 255  0
         StringBuffer statusBuffer = new StringBuffer(8192);
 256  0
         if (selected instanceof Throwable) {
 257  0
             populateCopyBuffer(statusBuffer, (Throwable) selected);
 258  0
         } else if (selected instanceof StackTraceElement) {
 259  0
             populateCopyBuffer(statusBuffer, (StackTraceElement) selected);
 260  
         }
 261  
 
 262  0
         clipboard = new Clipboard(detailTreeViewer.getTree().getDisplay());
 263  0
         clipboard.setContents(new Object[] { statusBuffer.toString() },
 264  
                 new Transfer[] { TextTransfer.getInstance() });
 265  
 
 266  0
     }
 267  
 
 268  
     protected void populateCopyBuffer(final StringBuffer buffer,
 269  
             final Throwable throwable) {
 270  0
         buffer.append(throwable.getClass().getName());
 271  0
         String message = throwable.getMessage();
 272  0
         if (message != null) {
 273  0
             buffer.append(" : ");
 274  0
             buffer.append(message);
 275  
         }
 276  0
         buffer.append("\n");
 277  
 
 278  0
         StackTraceElement[] elements = throwable.getStackTrace();
 279  0
         if (elements != null) {
 280  0
             for (StackTraceElement stackTraceElement : elements) {
 281  0
                 populateCopyBuffer(buffer, stackTraceElement);
 282  
             }
 283  
         }
 284  
 
 285  0
         Throwable cause = throwable.getCause();
 286  0
         if (cause != null) {
 287  0
             buffer.append("\n");
 288  0
             populateCopyBuffer(buffer, cause);
 289  
         }
 290  0
     }
 291  
 
 292  
     protected void populateCopyBuffer(final StringBuffer buffer,
 293  
             final StackTraceElement element) {
 294  0
         buffer.append(NESTING_INDENT);
 295  0
         buffer.append("at " + element + "\n");
 296  0
     }
 297  
 
 298  
     /*
 299  
      * @see org.eclipse.jface.dialogs.Dialog#buttonPressed(int)
 300  
      */
 301  
     @Override
 302  
     protected void buttonPressed(final int id) {
 303  0
         if (id == IDialogConstants.DETAILS_ID) {
 304  0
             toggleDetailsArea();
 305  
         } else {
 306  0
             super.buttonPressed(id);
 307  
         }
 308  0
     }
 309  
 
 310  
     /*
 311  
      * @see org.eclipse.jface.dialogs.Dialog#close()
 312  
      */
 313  
     @Override
 314  
     public boolean close() {
 315  0
         if (clipboard != null) {
 316  0
             clipboard.dispose();
 317  
         }
 318  0
         if ((errorIcon != null) && !errorIcon.isDisposed()) {
 319  0
             errorIcon.dispose();
 320  
         }
 321  0
         if ((dialogIcon != null) && !dialogIcon.isDisposed()) {
 322  0
             dialogIcon.dispose();
 323  
         }
 324  0
         return super.close();
 325  
     }
 326  
 
 327  
     /*
 328  
      * @see org.eclipse.jface.dialogs.IconAndMessageDialog#getImage()
 329  
      */
 330  
     @Override
 331  
     protected Image getImage() {
 332  0
         return getSystemImage(SWT.ICON_ERROR);
 333  
     }
 334  
 
 335  
     protected Image getSystemImage(final int id) {
 336  0
         Shell shell = getShell();
 337  
         final Display display;
 338  0
         if (shell == null) {
 339  0
             shell = getParentShell();
 340  
         }
 341  0
         if (shell == null) {
 342  0
             display = Display.getCurrent();
 343  
         } else {
 344  0
             display = shell.getDisplay();
 345  
         }
 346  
 
 347  0
         final Image[] image = new Image[1];
 348  0
         display.syncExec(new Runnable() {
 349  0
             public void run() {
 350  0
                 image[0] = display.getSystemImage(id);
 351  0
             }
 352  
         });
 353  
 
 354  0
         return image[0];
 355  
     }
 356  
 
 357  
     /**
 358  
      * 例外表示ツリー用のコンテントプロバイダです。<br />
 359  
      * 
 360  
      * @author y-komori
 361  
      */
 362  0
     class DetailsContentProvider implements ITreeContentProvider {
 363  
         /*
 364  
          * @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object)
 365  
          */
 366  
         public Object[] getChildren(final Object parentElement) {
 367  0
             if (parentElement instanceof String) {
 368  0
                 return new Object[] { rootThrowable };
 369  0
             } else if (parentElement == rootThrowable) {
 370  0
                 if (causes.size() > 0) {
 371  0
                     return causes.toArray();
 372  
                 } else {
 373  0
                     return rootThrowable.getStackTrace();
 374  
                 }
 375  0
             } else if (parentElement instanceof Throwable) {
 376  0
                 return ((Throwable) parentElement).getStackTrace();
 377  
             } else {
 378  0
                 return null;
 379  
             }
 380  
         }
 381  
 
 382  
         /*
 383  
          * @see org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang.Object)
 384  
          */
 385  
         public Object getParent(final Object element) {
 386  0
             return null;
 387  
         }
 388  
 
 389  
         /*
 390  
          * @see org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang.Object)
 391  
          */
 392  
         public boolean hasChildren(final Object element) {
 393  0
             if ((element instanceof String) || (element instanceof Throwable)) {
 394  0
                 return true;
 395  
             } else {
 396  0
                 return false;
 397  
             }
 398  
         }
 399  
 
 400  
         /*
 401  
          * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
 402  
          */
 403  
         public Object[] getElements(final Object inputElement) {
 404  0
             return getChildren(inputElement);
 405  
         }
 406  
 
 407  
         /*
 408  
          * @see org.eclipse.jface.viewers.IContentProvider#dispose()
 409  
          */
 410  
         public void dispose() {
 411  0
         }
 412  
 
 413  
         /*
 414  
          * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer,
 415  
          *      java.lang.Object, java.lang.Object)
 416  
          */
 417  
         public void inputChanged(final Viewer viewer, final Object oldInput,
 418  
                 final Object newInput) {
 419  0
         }
 420  
     }
 421  
 
 422  
     /**
 423  
      * 例外表示ツリー用のラベルプロバイダです。<br />
 424  
      * 
 425  
      * @author y-komori
 426  
      */
 427  0
     class DetailLabelProvider implements ILabelProvider {
 428  
         /*
 429  
          * @see org.eclipse.jface.viewers.ILabelProvider#getImage(java.lang.Object)
 430  
          */
 431  
         public Image getImage(final Object element) {
 432  0
             if (element instanceof Throwable) {
 433  0
                 return errorIcon;
 434  
             } else {
 435  0
                 return null;
 436  
             }
 437  
         }
 438  
 
 439  
         /*
 440  
          * @see org.eclipse.jface.viewers.ILabelProvider#getText(java.lang.Object)
 441  
          */
 442  
         public String getText(final Object element) {
 443  0
             if (element instanceof Throwable) {
 444  0
                 return element.getClass().getName() + " "
 445  
                         + ((Throwable) element).getMessage();
 446  0
             } else if (element instanceof StackTraceElement) {
 447  0
                 StackTraceElement st = (StackTraceElement) element;
 448  0
                 String line = "at " + st.toString();
 449  0
                 return line;
 450  
             } else {
 451  0
                 return NULL_STRING;
 452  
             }
 453  
         }
 454  
 
 455  
         /*
 456  
          * @see org.eclipse.jface.viewers.IBaseLabelProvider#addListener(org.eclipse.jface.viewers.ILabelProviderListener)
 457  
          */
 458  
         public void addListener(final ILabelProviderListener listener) {
 459  0
         }
 460  
 
 461  
         /*
 462  
          * @see org.eclipse.jface.viewers.IBaseLabelProvider#dispose()
 463  
          */
 464  
         public void dispose() {
 465  0
         }
 466  
 
 467  
         /*
 468  
          * @see org.eclipse.jface.viewers.IBaseLabelProvider#isLabelProperty(java.lang.Object,
 469  
          *      java.lang.String)
 470  
          */
 471  
         public boolean isLabelProperty(final Object element,
 472  
                 final String property) {
 473  0
             return false;
 474  
         }
 475  
 
 476  
         /*
 477  
          * @see org.eclipse.jface.viewers.IBaseLabelProvider#removeListener(org.eclipse.jface.viewers.ILabelProviderListener)
 478  
          */
 479  
         public void removeListener(final ILabelProviderListener listener) {
 480  0
         }
 481  
     }
 482  
 }