001: /*
002: * Copyright 2001-2006 C:1 Financial Services GmbH
003: *
004: * This software is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License Version 2.1, as published by the Free Software Foundation.
007: *
008: * This software is distributed in the hope that it will be useful,
009: * but WITHOUT ANY WARRANTY; without even the implied warranty of
010: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
011: * Lesser General Public License for more details.
012: *
013: * You should have received a copy of the GNU Lesser General Public
014: * License along with this library; if not, write to the Free Software
015: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
016: */
017:
018: package de.finix.contelligent.client.remote;
019:
020: import java.awt.Color;
021: import java.awt.Dimension;
022: import java.awt.Toolkit;
023: import java.beans.PropertyChangeEvent;
024: import java.beans.PropertyChangeListener;
025: import java.lang.reflect.InvocationTargetException;
026: import java.text.DateFormat;
027: import java.util.ArrayList;
028: import java.util.Date;
029: import java.util.Iterator;
030: import java.util.List;
031: import java.util.Vector;
032: import java.util.logging.Level;
033: import java.util.logging.Logger;
034:
035: import javax.swing.JComponent;
036: import javax.swing.JDialog;
037: import javax.swing.JLabel;
038: import javax.swing.JOptionPane;
039: import javax.swing.JScrollPane;
040: import javax.swing.JTextArea;
041: import javax.swing.SwingUtilities;
042:
043: import org.w3c.dom.Element;
044:
045: import de.finix.contelligent.client.ContelligentClient;
046: import de.finix.contelligent.client.i18n.Resources;
047: import de.finix.contelligent.client.util.EscapeDialog;
048:
049: public class ActionResult {
050:
051: private final static Logger logger = Logger
052: .getLogger(ActionResult.class.getName());
053:
054: public final static String FAILED = "failed";
055:
056: public final static String OK = "ok";
057:
058: public final static String DEBUG = "debug";
059:
060: public final static String INFO = "info";
061:
062: public final static String WARNING = "warning";
063:
064: public final static String ERROR = "error";
065:
066: public final static String SERVER = "server";
067:
068: public final static String DATABASE = "database";
069:
070: public final static String COMPONENT = "component";
071:
072: private List errors = new ArrayList();
073:
074: private List paths = new ArrayList();
075:
076: private String state;
077:
078: private Element content = null;
079:
080: /**
081: * For future extensions to detetmine whether this is running in a
082: * Swing-Client or is a module without Swing support
083: */
084: private static boolean IS_SWING_CLIENT = true;
085:
086: public final static boolean isSwingClient() {
087: return IS_SWING_CLIENT;
088: }
089:
090: public final static void setSwingClient(boolean isSwingClient) {
091: IS_SWING_CLIENT = isSwingClient;
092: }
093:
094: public void setContent(Element content) {
095: this .content = content;
096: }
097:
098: public Element getContent() {
099: return content;
100: }
101:
102: public void addError(String errorPath, String faultstring,
103: String faultmessage, String details, String exceptionClass,
104: String exceptionMessage, String exceptionStackTrace,
105: String level, String origin, String timestamp, String path) {
106: Error error = new Error(errorPath, faultstring, faultmessage,
107: details, exceptionClass, exceptionMessage,
108: exceptionStackTrace, level, origin, timestamp, path);
109: errors.add(error);
110: }
111:
112: public void setState(String state) {
113: this .state = state;
114: }
115:
116: public String getState() {
117: return state;
118: }
119:
120: public void addPath(String path) {
121: paths.add(path);
122: }
123:
124: public List getPaths() {
125: return paths;
126: }
127:
128: public boolean hasError(String errorPath) {
129: for (Iterator i = errors.iterator(); i.hasNext();) {
130: Error error = (Error) i.next();
131: if (error.getErrorPath().equals(errorPath)) {
132: return true;
133: }
134: }
135: return false;
136: }
137:
138: public boolean hasError() {
139: return (errors.size() > 0);
140: }
141:
142: public List getErrors() {
143: return errors;
144: }
145:
146: public void showErrors() {
147: for (Iterator i = errors.iterator(); i.hasNext();) {
148: Error error = (Error) i.next();
149: error.show();
150: }
151: }
152:
153: public void showErrorsIgnore(String errorId) {
154: for (Iterator i = errors.iterator(); i.hasNext();) {
155: Error error = (Error) i.next();
156: if (!error.getErrorPath().equals(errorId)) {
157: error.show();
158: }
159: }
160: }
161:
162: public static class Error {
163: private final static String OK = Resources.getLocalString("ok");
164:
165: private final static String SHOW_DETAILS = Resources
166: .getLocalString("show_details");
167:
168: private final static String HIDE_DETAILS = Resources
169: .getLocalString("hide_details");
170:
171: private final static boolean PLAIN = false;
172:
173: private final static boolean HIGHLIGHT = true;
174:
175: private String errorPath, faultstring, faultmessage, details,
176: exceptionClass, exceptionMessage, exceptionStackTrace,
177: level, origin, timestamp, path;
178:
179: public Error(String errorPath, String faultstring,
180: String faultmessage, String details,
181: String exceptionClass, String exceptionMessage,
182: String exceptionStackTrace, String level,
183: String origin, String timestamp, String path) {
184: this .errorPath = errorPath;
185: this .faultstring = faultstring;
186: this .faultmessage = faultmessage;
187: this .details = details;
188: this .exceptionClass = exceptionClass;
189: this .exceptionMessage = exceptionMessage;
190: this .exceptionStackTrace = exceptionStackTrace;
191: this .level = level;
192: this .origin = origin;
193: this .timestamp = timestamp;
194: this .path = path;
195: }
196:
197: public String getErrorPath() {
198: return errorPath;
199: }
200:
201: public String getPath() {
202: return path;
203: }
204:
205: public String getDetails() {
206: return details;
207: }
208:
209: public void show() {
210: if (ActionResult.isSwingClient()) {
211: if (!SwingUtilities.isEventDispatchThread()) {
212: logger
213: .log(
214: Level.WARNING,
215: "Show was not called in AWT-Event-Thread even though it must - requeueing it now!");
216: try {
217: SwingUtilities.invokeAndWait(new Runnable() {
218: public void run() {
219: swingShow();
220: }
221: });
222: } catch (InterruptedException ie) {
223: logger.log(Level.WARNING,
224: "Interrupted while showing error", ie);
225: } catch (InvocationTargetException ite) {
226: logger.log(Level.WARNING,
227: "Could not show error", ite);
228: }
229: } else {
230: swingShow();
231: }
232: } else {
233: textShow();
234: }
235: }
236:
237: // FIXME reserved for future extensions
238: private void textShow() {
239: }
240:
241: private void swingShow() {
242: final JOptionPane optionPane = new JOptionPane();
243: final List messageList = new Vector();
244: final List detailedMessageList = new Vector();
245:
246: if (errorPath.equals("contelligent.core.relation.dead")) {
247: // Special error display for dead relations message, since the
248: // details message containing the relations list is
249: // practically unreadable
250: JComponent faultstringLabel = generateLabel(
251: faultstring, HIGHLIGHT);
252: messageList.add(faultstringLabel);
253: JComponent faultmessageLabel = generateLabel(
254: faultmessage, PLAIN);
255: messageList.add(faultmessageLabel);
256:
257: // Reformat details message
258: StringBuffer newDetails = new StringBuffer();
259: String referenceList = details.substring(details
260: .indexOf('{') + 1, details.indexOf('}'));
261: int startPos = 0;
262: int eqPos = 0;
263: while ((eqPos = referenceList.indexOf('=', startPos)) != -1) {
264: newDetails.append(referenceList.substring(startPos,
265: eqPos));
266: newDetails.append("\n");
267: int stopPos = referenceList.indexOf(']', eqPos);
268: String sourceList = referenceList.substring(
269: eqPos + 2, stopPos);
270: int sourceStartPos = 0;
271: int sourceSeparatorPos = 0;
272: while ((sourceSeparatorPos = sourceList.indexOf(
273: ',', sourceStartPos)) != -1) {
274: newDetails.append(" <- ");
275: newDetails.append(sourceList.substring(
276: sourceStartPos, sourceSeparatorPos));
277: newDetails.append("\n");
278: sourceStartPos = sourceSeparatorPos + 2;
279: }
280: ;
281: newDetails.append(" <- ");
282: newDetails.append(sourceList
283: .substring(sourceStartPos));
284: newDetails.append("\n\n");
285: startPos = stopPos + 3;
286: }
287:
288: JTextArea detailsText = new JTextArea(newDetails
289: .toString(), 12, 60);
290: detailsText.setEditable(false);
291: detailsText.setOpaque(false);
292: JScrollPane detailsScroller = new JScrollPane(
293: detailsText);
294: messageList.add(detailsScroller);
295:
296: optionPane.setMessage(messageList.toArray());
297:
298: String title = Resources.getLocalString("error");
299: optionPane.setMessageType(JOptionPane.ERROR_MESSAGE);
300: final JDialog dialog = new EscapeDialog(
301: ContelligentClient.getActiveFrame(), title,
302: true);
303: optionPane.setOptions(new Object[] { OK });
304: optionPane
305: .addPropertyChangeListener(new PropertyChangeListener() {
306: public void propertyChange(
307: PropertyChangeEvent e) {
308: String prop = e.getPropertyName();
309: if (dialog.isVisible()
310: && (e.getSource() == optionPane)
311: && (prop
312: .equals(JOptionPane.VALUE_PROPERTY) || prop
313: .equals(JOptionPane.INPUT_VALUE_PROPERTY))) {
314: Object value = optionPane
315: .getValue();
316: if (value.equals(OK)) {
317: dialog.dispose();
318: }
319: }
320: }
321: });
322: dialog.setContentPane(optionPane);
323: dialog.pack();
324: centerDialog(dialog);
325: dialog.setVisible(true);
326: return;
327: }
328:
329: if (faultstring != null) {
330: JComponent faultstringLabel = generateLabel(
331: faultstring, HIGHLIGHT);
332: messageList.add(faultstringLabel);
333: detailedMessageList.add(faultstringLabel);
334: }
335: if (faultmessage != null) {
336: JComponent faultmessageLabel = generateLabel(
337: faultmessage, PLAIN);
338: messageList.add(faultmessageLabel);
339: detailedMessageList.add(faultmessageLabel);
340: }
341: if (details != null) {
342: JTextArea detailsText = new JTextArea(details, 10, 50);
343: detailsText.setEditable(false);
344: detailsText.setOpaque(false);
345: JScrollPane stackTrace = new JScrollPane(detailsText);
346: detailedMessageList.add(stackTrace);
347: }
348: if (exceptionClass != null) {
349: JLabel exceptionLabel = new JLabel(Resources
350: .getLocalString("exception_message")
351: + ":");
352: JComponent exceptionMessageLabel = generateLabel(
353: exceptionMessage, PLAIN);
354:
355: JLabel originLabel = new JLabel(Resources
356: .getLocalString("origin")
357: + ": " + origin);
358:
359: Date date = new Date(Long.valueOf(timestamp)
360: .longValue());
361: String dateString = DateFormat.getDateTimeInstance(
362: DateFormat.FULL, DateFormat.FULL).format(date);
363: JLabel dateLabel = new JLabel(Resources
364: .getLocalString("date")
365: + ": " + dateString);
366:
367: JTextArea stack = new JTextArea(exceptionStackTrace,
368: 10, 50);
369: stack.setEditable(false);
370: stack.setOpaque(false);
371: JScrollPane stackTrace = new JScrollPane(stack);
372: detailedMessageList.add(exceptionLabel);
373: detailedMessageList.add(exceptionMessageLabel);
374: detailedMessageList.add(originLabel);
375: detailedMessageList.add(dateLabel);
376: detailedMessageList.add(stackTrace);
377: }
378:
379: optionPane.setMessage(messageList.toArray());
380: String title;
381: if (level.equals(ERROR)) {
382: title = Resources.getLocalString("error");
383: optionPane.setMessageType(JOptionPane.ERROR_MESSAGE);
384: } else if (level.equals(WARNING)) {
385: title = Resources.getLocalString("warning");
386: optionPane.setMessageType(JOptionPane.WARNING_MESSAGE);
387: } else {
388: title = Resources.getLocalString("info");
389: optionPane
390: .setMessageType(JOptionPane.INFORMATION_MESSAGE);
391: }
392: optionPane.setOptionType(JOptionPane.DEFAULT_OPTION);
393: if (exceptionClass != null || details != null) {
394: optionPane
395: .setOptions(new Object[] { OK, SHOW_DETAILS });
396: } else {
397: optionPane.setOptions(new Object[] { OK });
398: }
399:
400: final JDialog dialog = new EscapeDialog(ContelligentClient
401: .getActiveFrame(), title, true);
402:
403: optionPane
404: .addPropertyChangeListener(new PropertyChangeListener() {
405: public void propertyChange(PropertyChangeEvent e) {
406: String prop = e.getPropertyName();
407: if (dialog.isVisible()
408: && (e.getSource() == optionPane)
409: && (prop
410: .equals(JOptionPane.VALUE_PROPERTY) || prop
411: .equals(JOptionPane.INPUT_VALUE_PROPERTY))) {
412: Object value = optionPane.getValue();
413: if (value == JOptionPane.UNINITIALIZED_VALUE) {
414: // ignore reset
415: return;
416: }
417:
418: if (value.equals(SHOW_DETAILS)) {
419: optionPane
420: .setMessage(detailedMessageList
421: .toArray());
422: optionPane.setOptions(new Object[] {
423: OK, HIDE_DETAILS });
424: dialog.pack();
425: } else if (value.equals(HIDE_DETAILS)) {
426: optionPane.setMessage(messageList
427: .toArray());
428: optionPane.setOptions(new Object[] {
429: OK, SHOW_DETAILS });
430: dialog.pack();
431: } else if (value.equals(OK)) {
432: dialog.setVisible(false);
433: }
434: }
435: }
436: });
437:
438: dialog.setContentPane(optionPane);
439: dialog.pack();
440: centerDialog(dialog);
441: // dialog.setResizable(true);
442: dialog.setVisible(true);
443: }
444:
445: public void centerDialog(JDialog dialog) {
446: Dimension screenDim = Toolkit.getDefaultToolkit()
447: .getScreenSize();
448: Dimension winDim = dialog.getSize();
449: dialog.setLocation((screenDim.width - winDim.width) / 2,
450: (screenDim.height - winDim.height) / 2);
451: }
452:
453: public JComponent generateLabel(String messageString,
454: boolean highlight) {
455: if (messageString.length() > 60) {
456: JTextArea message = new JTextArea(messageString, Math
457: .min(5, (messageString.length() / 50) + 2), 50);
458: message.setEditable(false);
459: message.setOpaque(false);
460: message.setLineWrap(true);
461: message.setWrapStyleWord(true);
462: if (highlight) {
463: message.setForeground(Color.red);
464: }
465: JScrollPane messageScrollPane = new JScrollPane(message);
466: messageScrollPane.setBorder(null);
467: return messageScrollPane;
468: } else {
469: JLabel message = new JLabel(messageString);
470: if (highlight) {
471: message.setForeground(Color.red);
472: }
473: return message;
474: }
475: }
476: }
477: }
|