KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > wings > session > LowLevelEventDispatcher


1 /*
2  * $Id: LowLevelEventDispatcher.java,v 1.13 2005/05/26 13:18:10 neurolabs Exp $
3  * Copyright 2000,2005 wingS development team.
4  *
5  * This file is part of wingS (http://www.j-wings.org).
6  *
7  * wingS is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU Lesser General Public License
9  * as published by the Free Software Foundation; either version 2.1
10  * of the License, or (at your option) any later version.
11  *
12  * Please see COPYING for the complete licence.
13  */

14 package org.wings.session;
15
16 import org.apache.commons.logging.Log;
17 import org.apache.commons.logging.LogFactory;
18 import org.wings.LowLevelEventListener;
19 import org.wings.SButton;
20 import org.wings.SCheckBox;
21 import org.wings.SClickable;
22 import org.wings.SComponent;
23 import org.wings.SConstants;
24 import org.wings.SFrame;
25 import org.wings.SPageScroller;
26 import org.wings.SRadioButton;
27 import org.wings.SScrollBar;
28 import org.wings.STabbedPane;
29 import org.wings.STable;
30 import org.wings.SToggleButton;
31 import org.wings.STree;
32
33 import java.util.ArrayList JavaDoc;
34 import java.util.Arrays JavaDoc;
35 import java.util.HashMap JavaDoc;
36 import java.util.LinkedList JavaDoc;
37 import java.util.List JavaDoc;
38
39 /**
40  * @author <a HREF="mailto:haaf@mercatis.de">Armin Haaf</a>
41  * @version $Revision: 1.13 $
42  */

43 public final class LowLevelEventDispatcher
44         implements java.io.Serializable JavaDoc {
45     private final transient static Log log = LogFactory.getLog(LowLevelEventDispatcher.class);
46
47     private final HashMap JavaDoc listeners = new HashMap JavaDoc();
48
49     protected boolean namedEvents = true;
50     
51     /**
52      * This array contains classes whose events should be filtered, since they
53      * are caused by button tags, and IE's button tag support is buggy.
54      *
55      */

56     private static final List JavaDoc ieButtonFixClasses = Arrays.asList(new Class JavaDoc[] {
57             SButton.class, SToggleButton.class, SClickable.class,
58             SPageScroller.class, SRadioButton.class, SScrollBar.class,
59             STabbedPane.class, STable.class, STree.class});
60
61     public LowLevelEventDispatcher() {}
62
63     public final void addLowLevelEventListener(LowLevelEventListener gl,
64                                                String JavaDoc eventId) {
65         List JavaDoc l = (List JavaDoc) listeners.get(eventId);
66         if (l == null) {
67             l = new ArrayList JavaDoc(2);
68             l.add(gl);
69             listeners.put(eventId, l);
70         } else if (!l.contains(gl))
71             l.add(gl);
72     }
73
74     public final void removeLowLevelEventListener(LowLevelEventListener gl,
75                                                   String JavaDoc eventId) {
76         List JavaDoc l = (List JavaDoc) listeners.get(eventId);
77         if (l != null) {
78             l.remove(gl);
79             if (l.size() == 0)
80                 listeners.remove(eventId);
81         }
82     }
83
84     public final LowLevelEventListener getLowLevelEventListener(String JavaDoc eventId) {
85         return (LowLevelEventListener) listeners.get(eventId);
86     }
87
88     public final void setNamedEvents(boolean b) {
89         namedEvents = b;
90     }
91
92     /**
93      * Registers a listeners. The NamePrefix of the listeners is stored in the
94      * HashMap as key. The value is a Set (ArrayList) of {@link LowLevelEventListener}s.
95      *
96      * @param gl listeners
97      */

98     public void register(LowLevelEventListener gl) {
99         if (gl == null)
100             return;
101
102         String JavaDoc key = gl.getLowLevelEventId();
103
104         log.debug("dispatcher: register '" + key + "' type: " + gl.getClass());
105         addLowLevelEventListener(gl, key);
106
107         if (namedEvents) {
108             key = gl.getName();
109             if (key != null && key.trim().length() > 0) {
110                 log.debug("dispatcher: register named '" + key + "'");
111                 addLowLevelEventListener(gl, key);
112             }
113         }
114     }
115
116     /**
117      * This should remove the GetListener from the HashMap, not the Names of
118      * the GetListener (Names may change)
119      */

120     public void unregister(LowLevelEventListener gl) {
121         if (gl == null)
122             return;
123
124         String JavaDoc key = gl.getLowLevelEventId();
125
126         log.debug("unregister '" + key + "'");
127         removeLowLevelEventListener(gl, key);
128
129         key = gl.getName();
130         if (key != null && key.trim().length() > 0) {
131             log.debug("unregister named '" + key + "'");
132             removeLowLevelEventListener(gl, key);
133         }
134
135     }
136
137     /**
138      * dispatch the events, encoded as [name/(multiple)values]
139      * in the HTTP request.
140      * @param name
141      * @param values
142      * @return if the event has been dispatched
143      */

144     public boolean dispatch(String JavaDoc name, String JavaDoc[] values) {
145         if (log.isDebugEnabled())
146             log.debug("dispatch " + name + " = " + Arrays.asList(values));
147
148         boolean result = false;
149         int dividerIndex = name.indexOf(SConstants.UID_DIVIDER);
150         String JavaDoc epoch = null;
151         boolean isIE = SessionManager.getSession().getUserAgent().getBrowserType() == BrowserType.IE;
152
153         // no Alias
154
if (dividerIndex > 0) {
155             epoch = name.substring(0, dividerIndex);
156             name = name.substring(dividerIndex + 1);
157         }
158
159         // make ImageButtons work in Forms .. browsers return
160
// the click position as .x and .y suffix of the name
161
if (name.endsWith(".x") || name.endsWith(".X")) {
162             name = name.substring(0, name.length() - 2);
163         } else if (name.endsWith(".y") || name.endsWith(".Y")) {
164             // .. but don't process the same event twice.
165
log.debug("discard '.y' part of image event");
166             return false;
167         }
168         
169         // is value encoded in name ? Then append it to the values we have.
170
int p = name.indexOf(SConstants.UID_DIVIDER);
171         if (p > -1) {
172             String JavaDoc v = name.substring(p + 1);
173             name = name.substring(0, p);
174             String JavaDoc[] va = new String JavaDoc[values.length + 1];
175             System.arraycopy(values, 0, va, 0, values.length);
176             va[values.length] = v;
177             values = va;
178         }
179
180         /*
181          * This is a workaround for IE's buggy button tag support.
182          * (Might change with IE7)
183          *
184          * Normal behavior is to send only the pressed button's name value
185          * pair. IE sends all buttons in a form, no matter which one was
186          * pressed. Also, it doesn't send the values, but instead their
187          * innerHtml property.
188          *
189          * So what we do is when a button is pressed in IE, we attach a hidden
190          * field to the form using javascript, containing info about the
191          * pressed button. This is read here and the event processing is
192          * triggered.
193          *
194          * Below in the normal event dispatching, we discard all events
195          * originating from Components which are represented by buttons.
196          * These are right now:
197          * - SButton
198          * - SToggleButton
199          */

200         if (isIE && name.equals(SConstants.IEFIX_BUTTONACTION)) {
201             String JavaDoc buttonId = values[0];
202             String JavaDoc[] vals = new String JavaDoc[] {""};
203             int pos = buttonId.indexOf(SConstants.UID_DIVIDER);
204             if (pos > -1) {
205                 String JavaDoc val = buttonId.substring(pos + 1);
206                 buttonId = buttonId.substring(0, pos);
207                 vals[0] = val;
208             }
209             List JavaDoc l = (List JavaDoc) listeners.get(buttonId);
210             if (l != null && l.size() > 0) {
211                 if (log.isDebugEnabled()) {
212                     log.debug("process special IE workaround event '" + epoch + SConstants.UID_DIVIDER + name + "'");
213                 }
214                 for (int i = 0; i < l.size(); ++i) {
215                     LowLevelEventListener gl = (LowLevelEventListener) l.get(i);
216                     if (gl.isEnabled()) {
217                         if (checkEpoch(epoch, buttonId, gl)) {
218                             if (log.isDebugEnabled()) {
219                                 log.debug("process event '" + buttonId + "' by " +
220                                         gl.getClass() + "(" + gl.getLowLevelEventId() +
221                                         ")");
222                             }
223                             gl.processLowLevelEvent(buttonId,vals);
224                             result = true;
225                         }
226                     }
227                 }
228             }
229         }
230         List JavaDoc l = (List JavaDoc) listeners.get(name);
231         if (l != null && l.size() > 0) {
232             log.debug("process event '" + epoch + SConstants.UID_DIVIDER + name + "'");
233             for (int i = 0; i < l.size(); ++i) {
234                 LowLevelEventListener gl = (LowLevelEventListener) l.get(i);
235                 if (gl.isEnabled()) {
236                     if (checkEpoch(epoch, name, gl)) {
237                         if (isIE) {
238                             // see comment above, is this a form event?
239
boolean isFormEvent = ((SComponent)gl).getResidesInForm() && ((SComponent)gl).getShowAsFormComponent();
240                             if (isFormEvent) {
241                                 // was the button represented by a button html tag?
242
boolean isButton = ieButtonFixClasses.contains(gl.getClass());
243                                 if (isButton) {
244                                     log.debug("circumventing IE bug, not processing event '" + name + "' by " +
245                                             gl.getClass() + "(" + gl.getLowLevelEventId() +
246                                             ")");
247                                 } else {
248                                     log.debug("process form event not caused by a button tag'" + name + "' by " +
249                                             gl.getClass() + "(" + gl.getLowLevelEventId() +
250                                             ")");
251                                     gl.processLowLevelEvent(name, values);
252                                     result = true;
253                                 }
254                             } else {
255                                 log.debug("process event '" + name + "' by " +
256                                         gl.getClass() + "(" + gl.getLowLevelEventId() +
257                                         ")");
258                                 gl.processLowLevelEvent(name, values);
259                                 result = true;
260                             }
261                         } else {
262                             log.debug("process event '" + name + "' by " +
263                                     gl.getClass() + "(" + gl.getLowLevelEventId() +
264                                     ")");
265                             gl.processLowLevelEvent(name, values);
266                             result = true;
267                         }
268                     }
269                 }
270             }
271         }
272         return result;
273     }
274
275     protected boolean checkEpoch(String JavaDoc epoch, String JavaDoc name,
276                                  LowLevelEventListener gl) {
277         if (epoch != null) {
278             SFrame frame = ((SComponent) gl).getParentFrame();
279             if (frame == null) {
280                 if (log.isDebugEnabled())
281                     log.debug("request for dangling component '" + epoch + SConstants.UID_DIVIDER + name);
282                 unregister(gl);
283                 return false;
284             }
285             if (!epoch.equals(frame.getEventEpoch())) {
286                 if (log.isDebugEnabled()) {
287                     log.debug("### got outdated event '" + epoch + SConstants.UID_DIVIDER + name
288                             + "' from frame '" + frame.getName() + "'; expected epoch: " + frame.getEventEpoch());
289                 }
290                 frame.fireInvalidLowLevelEventListener(gl);
291                 return false;
292             }
293         }
294         return true;
295     }
296
297     void clear() {
298         listeners.clear();
299     }
300 }
301
302
303
Popular Tags