001: package org.uispec4j.interception.toolkit;
002:
003: import junit.framework.AssertionFailedError;
004: import org.uispec4j.Window;
005: import org.uispec4j.interception.handlers.InterceptionHandler;
006: import org.uispec4j.utils.ComponentUtils;
007: import org.uispec4j.utils.ExceptionContainer;
008: import org.uispec4j.utils.Utils;
009:
010: import javax.swing.*;
011: import java.awt.*;
012: import java.util.ArrayList;
013: import java.util.Iterator;
014: import java.util.List;
015: import java.util.Stack;
016:
017: /**
018: * Virtual display used by the interception mechanism.
019: *
020: * @see UISpecToolkit
021: */
022: public class UISpecDisplay {
023:
024: private static final UISpecDisplay singletonInstance = new UISpecDisplay();
025: private Stack handlerStack = new Stack();
026: private JPopupMenu currentPopup;
027: private ExceptionContainer exceptionContainer = new ExceptionContainer();
028: private List threads = new ArrayList();
029:
030: public static UISpecDisplay instance() {
031: return singletonInstance;
032: }
033:
034: public void showFrame(JFrame frame) {
035: processWindow(new Window(frame));
036: }
037:
038: public void showFrame(Frame frame) {
039: if (frame instanceof JFrame) {
040: showFrame((JFrame) frame);
041: } else {
042: processWindow(new Window(frame));
043: }
044: }
045:
046: public void showDialog(JDialog dialog) {
047: processWindow(new Window(dialog));
048: }
049:
050: public void showWindow(java.awt.Window window) {
051: processWindow(new Window(window));
052: }
053:
054: public void add(InterceptionHandler handler) {
055: synchronized (handlerStack) {
056: handlerStack.push(handler);
057: }
058: }
059:
060: public void reset() {
061: synchronized (handlerStack) {
062: handlerStack.clear();
063: }
064: exceptionContainer.reset();
065: for (Iterator iterator = threads.iterator(); iterator.hasNext();) {
066: Thread thread = (Thread) iterator.next();
067: try {
068: thread.join(10);
069: } catch (InterruptedException e) {
070: throw new RuntimeException(e);
071: }
072: if (thread.isAlive()) {
073: thread.interrupt();
074: }
075: }
076: threads.clear();
077: }
078:
079: public void remove(InterceptionHandler handler) {
080: synchronized (handlerStack) {
081: handlerStack.remove(handler);
082: }
083: }
084:
085: public void rethrowIfNeeded() {
086: exceptionContainer.rethrowIfNeeded();
087: }
088:
089: private UISpecDisplay() {
090: // Constructor is private since this is a singleton class
091: }
092:
093: private void processWindow(Window window) {
094: try {
095: InterceptionHandler handler;
096: synchronized (handlerStack) {
097: if (!assertAcceptsWindow(window)) {
098: return;
099: }
100: handler = (InterceptionHandler) handlerStack.pop();
101: }
102: handler.process(window);
103: } catch (Throwable e) {
104: ComponentUtils.close(window);
105: store(e);
106: }
107: }
108:
109: public boolean assertAcceptsWindow(Window window) {
110: if (!handlerStack.isEmpty()) {
111: return true;
112: }
113:
114: AssertionFailedError error = new AssertionFailedError(
115: "Unexpected window shown - this window should be handled with "
116: + "WindowInterceptor. " + Utils.LINE_SEPARATOR
117: + "Window contents:" + Utils.LINE_SEPARATOR
118: + window.getDescription());
119: if (interceptionInProgress()) {
120: store(error);
121: ComponentUtils.close(window);
122: } else {
123: throw error;
124: }
125: return false;
126: }
127:
128: private boolean interceptionInProgress() {
129: return !handlerStack.isEmpty();
130: }
131:
132: public void setCurrentPopup(JPopupMenu popupMenu) {
133: this .currentPopup = popupMenu;
134: }
135:
136: public JPopupMenu getCurrentPopup() {
137: return currentPopup;
138: }
139:
140: public void store(Throwable throwable) {
141: exceptionContainer.set(throwable);
142: }
143:
144: public int getHandlerCount() {
145: return handlerStack.size();
146: }
147:
148: public void runInNewThread(Runnable runnable) {
149: Thread thread = new Thread(runnable);
150: threads.add(thread);
151: thread.start();
152: }
153: }
|