1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
53
54
55
56 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 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
82
83
84
85
86
87
88
89
90
91
92 public UrumaErrorDialog(final Shell parentShell, final String title,
93 final String message, final Throwable ex) {
94 super(parentShell);
95 this.title = (title != null ? title : "Error");
96 this.message = (message != null ? message : "");
97 this.rootThrowable = ex;
98 getCause(ex);
99 getImageIcons(parentShell);
100
101 setShellStyle(getShellStyle() | SWT.RESIZE);
102 }
103
104 protected void getCause(final Throwable throwable) {
105 Throwable cause = throwable.getCause();
106 if ((cause != null) && !causes.contains(cause)) {
107 causes.add(cause);
108 getCause(cause);
109 }
110 }
111
112 protected void getImageIcons(final Shell shell) {
113 ClassLoader loader = getClass().getClassLoader();
114
115 InputStream is = loader.getResourceAsStream("images/error.png");
116 errorIcon = new Image(shell.getDisplay(), is);
117
118 is = loader.getResourceAsStream("images/uruma16.png");
119 dialogIcon = new Image(shell.getDisplay(), is);
120 }
121
122
123
124
125 @Override
126 protected void configureShell(final Shell shell) {
127 super.configureShell(shell);
128 shell.setText(this.title);
129 shell.setImage(dialogIcon);
130 }
131
132
133
134
135 @Override
136 protected Control createDialogArea(final Composite parent) {
137 createMessageArea(parent);
138
139
140 Composite composite = new Composite(parent, SWT.NONE);
141 GridLayout layout = new GridLayout();
142 layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
143 layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
144 layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
145 layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
146 layout.numColumns = 2;
147 composite.setLayout(layout);
148 GridData childData = new GridData(SWT.FILL, SWT.FILL, true, false);
149 childData.horizontalSpan = 2;
150 composite.setLayoutData(childData);
151 composite.setFont(parent.getFont());
152
153 return composite;
154 }
155
156
157
158
159 @Override
160 protected void createButtonsForButtonBar(final Composite parent) {
161
162 createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL,
163 true);
164 createDetailsButton(parent);
165 }
166
167 protected void createDetailsButton(final Composite parent) {
168 detailsButton = createButton(parent, IDialogConstants.DETAILS_ID,
169 IDialogConstants.SHOW_DETAILS_LABEL, false);
170 }
171
172 protected void toggleDetailsArea() {
173 Point windowSize = getShell().getSize();
174 Point oldSize = getShell().computeSize(SWT.DEFAULT, SWT.DEFAULT);
175 if (detailsCreated) {
176 detailTreeViewer.getTree().dispose();
177 detailsCreated = false;
178 detailsButton.setText(IDialogConstants.SHOW_DETAILS_LABEL);
179 } else {
180 detailTreeViewer = createDetailsTreeViewer((Composite) getContents());
181 detailTreeViewer.setInput("");
182 detailsButton.setText(IDialogConstants.HIDE_DETAILS_LABEL);
183 detailsCreated = true;
184 }
185 Point newSize = getShell().computeSize(SWT.DEFAULT, SWT.DEFAULT);
186 getShell()
187 .setSize(
188 new Point(windowSize.x, windowSize.y
189 + (newSize.y - oldSize.y)));
190 }
191
192 protected TreeViewer createDetailsTreeViewer(final Composite parent) {
193 TreeViewer viewer = new TreeViewer(parent, SWT.SINGLE
194 | SWT.FULL_SELECTION | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
195 Tree tree = viewer.getTree();
196
197 GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
198 data.heightHint = tree.getItemHeight() * DETAILS_ITEM_COUNT;
199 data.horizontalSpan = 2;
200 tree.setLayoutData(data);
201 tree.setFont(parent.getFont());
202 createContextMenu(tree);
203
204 viewer.setContentProvider(new DetailsContentProvider());
205 viewer.setLabelProvider(new DetailLabelProvider());
206 viewer.setAutoExpandLevel(2);
207 return viewer;
208 }
209
210 protected void createContextMenu(final Tree tree) {
211 Menu copyMenu = new Menu(tree);
212
213 MenuItem allCopyItem = new MenuItem(copyMenu, SWT.NONE);
214 allCopyItem.addSelectionListener(new SelectionListener() {
215 public void widgetSelected(final SelectionEvent e) {
216 copyToClipboard(rootThrowable);
217 }
218
219 public void widgetDefaultSelected(final SelectionEvent e) {
220 widgetSelected(e);
221 }
222 });
223 allCopyItem.setText(MessageUtil.getMessageWithBundleName(
224 URUMA_MESSAGE_BASE, "COPY_ALL"));
225
226 MenuItem copyItem = new MenuItem(copyMenu, SWT.NONE);
227 copyItem.addSelectionListener(new SelectionListener() {
228 public void widgetSelected(final SelectionEvent e) {
229 StructuredSelection selection = (StructuredSelection) detailTreeViewer
230 .getSelection();
231 if (selection != null) {
232 Object selected = selection.getFirstElement();
233 copyToClipboard(selected);
234 }
235 }
236
237 public void widgetDefaultSelected(final SelectionEvent e) {
238 widgetSelected(e);
239 }
240 });
241 copyItem.setText(MessageUtil.getMessageWithBundleName(
242 URUMA_MESSAGE_BASE, "COPY_SELECTION"));
243
244 tree.setMenu(copyMenu);
245 }
246
247 private void copyToClipboard(final Object selected) {
248 if (clipboard != null) {
249 clipboard.dispose();
250 }
251 if (selected == null) {
252 return;
253 }
254
255 StringBuffer statusBuffer = new StringBuffer(8192);
256 if (selected instanceof Throwable) {
257 populateCopyBuffer(statusBuffer, (Throwable) selected);
258 } else if (selected instanceof StackTraceElement) {
259 populateCopyBuffer(statusBuffer, (StackTraceElement) selected);
260 }
261
262 clipboard = new Clipboard(detailTreeViewer.getTree().getDisplay());
263 clipboard.setContents(new Object[] { statusBuffer.toString() },
264 new Transfer[] { TextTransfer.getInstance() });
265
266 }
267
268 protected void populateCopyBuffer(final StringBuffer buffer,
269 final Throwable throwable) {
270 buffer.append(throwable.getClass().getName());
271 String message = throwable.getMessage();
272 if (message != null) {
273 buffer.append(" : ");
274 buffer.append(message);
275 }
276 buffer.append("\n");
277
278 StackTraceElement[] elements = throwable.getStackTrace();
279 if (elements != null) {
280 for (StackTraceElement stackTraceElement : elements) {
281 populateCopyBuffer(buffer, stackTraceElement);
282 }
283 }
284
285 Throwable cause = throwable.getCause();
286 if (cause != null) {
287 buffer.append("\n");
288 populateCopyBuffer(buffer, cause);
289 }
290 }
291
292 protected void populateCopyBuffer(final StringBuffer buffer,
293 final StackTraceElement element) {
294 buffer.append(NESTING_INDENT);
295 buffer.append("at " + element + "\n");
296 }
297
298
299
300
301 @Override
302 protected void buttonPressed(final int id) {
303 if (id == IDialogConstants.DETAILS_ID) {
304 toggleDetailsArea();
305 } else {
306 super.buttonPressed(id);
307 }
308 }
309
310
311
312
313 @Override
314 public boolean close() {
315 if (clipboard != null) {
316 clipboard.dispose();
317 }
318 if ((errorIcon != null) && !errorIcon.isDisposed()) {
319 errorIcon.dispose();
320 }
321 if ((dialogIcon != null) && !dialogIcon.isDisposed()) {
322 dialogIcon.dispose();
323 }
324 return super.close();
325 }
326
327
328
329
330 @Override
331 protected Image getImage() {
332 return getSystemImage(SWT.ICON_ERROR);
333 }
334
335 protected Image getSystemImage(final int id) {
336 Shell shell = getShell();
337 final Display display;
338 if (shell == null) {
339 shell = getParentShell();
340 }
341 if (shell == null) {
342 display = Display.getCurrent();
343 } else {
344 display = shell.getDisplay();
345 }
346
347 final Image[] image = new Image[1];
348 display.syncExec(new Runnable() {
349 public void run() {
350 image[0] = display.getSystemImage(id);
351 }
352 });
353
354 return image[0];
355 }
356
357
358
359
360
361
362 class DetailsContentProvider implements ITreeContentProvider {
363
364
365
366 public Object[] getChildren(final Object parentElement) {
367 if (parentElement instanceof String) {
368 return new Object[] { rootThrowable };
369 } else if (parentElement == rootThrowable) {
370 if (causes.size() > 0) {
371 return causes.toArray();
372 } else {
373 return rootThrowable.getStackTrace();
374 }
375 } else if (parentElement instanceof Throwable) {
376 return ((Throwable) parentElement).getStackTrace();
377 } else {
378 return null;
379 }
380 }
381
382
383
384
385 public Object getParent(final Object element) {
386 return null;
387 }
388
389
390
391
392 public boolean hasChildren(final Object element) {
393 if ((element instanceof String) || (element instanceof Throwable)) {
394 return true;
395 } else {
396 return false;
397 }
398 }
399
400
401
402
403 public Object[] getElements(final Object inputElement) {
404 return getChildren(inputElement);
405 }
406
407
408
409
410 public void dispose() {
411 }
412
413
414
415
416
417 public void inputChanged(final Viewer viewer, final Object oldInput,
418 final Object newInput) {
419 }
420 }
421
422
423
424
425
426
427 class DetailLabelProvider implements ILabelProvider {
428
429
430
431 public Image getImage(final Object element) {
432 if (element instanceof Throwable) {
433 return errorIcon;
434 } else {
435 return null;
436 }
437 }
438
439
440
441
442 public String getText(final Object element) {
443 if (element instanceof Throwable) {
444 return element.getClass().getName() + " "
445 + ((Throwable) element).getMessage();
446 } else if (element instanceof StackTraceElement) {
447 StackTraceElement st = (StackTraceElement) element;
448 String line = "at " + st.toString();
449 return line;
450 } else {
451 return NULL_STRING;
452 }
453 }
454
455
456
457
458 public void addListener(final ILabelProviderListener listener) {
459 }
460
461
462
463
464 public void dispose() {
465 }
466
467
468
469
470
471 public boolean isLabelProperty(final Object element,
472 final String property) {
473 return false;
474 }
475
476
477
478
479 public void removeListener(final ILabelProviderListener listener) {
480 }
481 }
482 }