📄 eventprocessingthread.java
字号:
* Application developers * shall use {@link org.zkoss.zk.ui.event.Events#sendEvent} instead. * * @return whether the event has been processed completely or just be suspended. * Recycle it only if true is returned. */ public boolean processEvent(Component comp, Event event) { if (Thread.currentThread() instanceof EventProcessingThread) throw new IllegalStateException("processEvent cannot be called in an event thread"); if (comp == null || event == null) throw new IllegalArgumentException("null"); if (_ceased) throw new InternalError("The event thread has beeing stopped"); if (_comp != null) throw new InternalError("reentering processEvent not allowed"); _desktop = comp.getDesktop(); if (_desktop == null) throw new InternalError("Not belonging to any desktop? "+comp); _comp = comp; _locale = Locales.getCurrent(); _timeZone = TimeZones.getCurrent(); _ex = null; final Configuration config = _desktop.getWebApp().getConfiguration(); _evtThdInits = config.newEventThreadInits(comp, event); try { synchronized (_evtmutex) { _event = event; //Bug 1577842: don't let event thread start (and end) too early _evtmutex.notify(); //ask the event thread to handle it if (!_ceased) _evtmutex.wait(); //wait until the event thread to complete or suspended } } catch (InterruptedException ex) { throw new UiException(ex); } finally { //_evtThdCleanups is null if //1) no listener; //2) the event thread is suspended (then handled by doResume). invokeEventThreadCompletes(config, comp, event); } checkError(); //check any error occurs return isIdle(); } private void invokeEventThreadCompletes(Configuration config, Component comp, Event event) throws UiException { if (_evtThdCleanups != null && !_evtThdCleanups.isEmpty()) { final List errs = _ex != null ? null: new LinkedList(); config.invokeEventThreadCompletes(_evtThdCleanups, comp, event, errs); _evtThdCleanups = null; if (errs != null && !errs.isEmpty()) throw UiException.Aide.wrap((Throwable)errs.get(0)); } } /** Setup for execution. */ synchronized private void setup() { SessionsCtrl.setCurrent(_desktop.getSession()); final Execution exec = _desktop.getExecution(); ExecutionsCtrl.setCurrent(exec); ((ExecutionCtrl)exec).setCurrentPage(_comp.getPage()); //Note: _com.getPage might return null because this method //is also called when resumed. } /** Cleanup for executionl. */ synchronized private void cleanup() { _comp = null; _event = null; _desktop = null; } private void checkError() { if (_ex != null) { //failed to process if (log.debugable()) log.realCause(_ex); final Throwable ex = _ex; _ex = null; throw UiException.Aide.wrap(ex); } } //-- Thread --// public void run() { ++_nThd; try { while (!_ceased) { final boolean evtAvail = !isIdle(); if (evtAvail) { Configuration config = _desktop.getWebApp().getConfiguration(); boolean cleaned = false; ++_nBusyThd; try { if (D.ON && log.finerable()) log.finer("Processing event: "+_event); Locales.setThreadLocal(_locale); TimeZones.setThreadLocal(_timeZone); setup(); config.invokeEventThreadInits(_evtThdInits, _comp, _event); _evtThdInits = null; process0(); } catch (Throwable ex) { _ex = ex; cleaned = true; _evtThdCleanups = config.newEventThreadCleanups(_comp, _event, ex, null); } finally { --_nBusyThd; if (!cleaned) { final List errs = new LinkedList(); _evtThdCleanups = config.newEventThreadCleanups(_comp, _event, null, errs); if (_ex == null && !errs.isEmpty()) _ex = (Throwable)errs.get(0); //propogate back the first exception } cleanup(); ExecutionsCtrl.setCurrent(null); SessionsCtrl.setCurrent(null); Locales.setThreadLocal(_locale = null); TimeZones.setThreadLocal(_timeZone = null); if (D.ON && log.finerable()) log.finer("Real processing is done; "+_event); } } synchronized (_evtmutex) { if (evtAvail) _evtmutex.notify(); //wake the main thread OR the resuming thread if (!_ceased) _evtmutex.wait(); //wait the main thread to issue another request } } if (_silent) { if (log.debugable()) log.debug("The event processing thread stops"); } else { System.out.println("The event processing thread stops"); //Don't use log because it might be stopped } } catch (InterruptedException ex) { if (_silent) { if (log.debugable()) log.debug("The event processing thread interrupted: "+Exceptions.getMessage(ex) +"\n"+Exceptions.getFirstStackTrace(ex)); } else { System.out.println("The event processing thread interrupted: "+Exceptions.getMessage(ex)); //Don't use log because it might be stopped } } finally { --_nThd; } } /** Sends the specified component and event and processes the event * synchronously. Used to implements {@link org.zkoss.zk.ui.event.Events#sendEvent}. */ public void sendEvent(final Component comp, Event event) throws Exception { if (D.ON && log.finerable()) log.finer("Process sent event: "+event); if (event == null || comp == null) throw new IllegalArgumentException("Both comp and event must be specified"); if (!(Thread.currentThread() instanceof EventProcessingThread)) throw new IllegalStateException("Only callable when processing an event"); if (_desktop != comp.getDesktop()) throw new IllegalStateException("Must in the same desktop"); final Component oldComp = _comp; final Event oldEvent = _event; try { _comp = comp; _event = event; setup(); process0(); } finally { _comp = oldComp; _event = oldEvent; setup(); } } /** Processes the component and event. */ private void process0() throws Exception { if (_comp == null || _event == null) throw new IllegalStateException("comp and event must be initialized"); //Bug 1506712: event listeners might be zscript, so we have to //keep built-in variables as long as possible final Namespace ns = Namespaces.beforeInterpret(null, _comp); ns.backupVariable("event", false); ns.setVariable("event", _event, true); try { process1(ns); } finally { Namespaces.afterInterpret(ns); } } private void process1(Namespace ns) throws Exception { final Page page = _comp.getPage(); final String evtnm = _event.getName(); for (Iterator it = _comp.getListenerIterator(evtnm); it.hasNext();) { final Object el = it.next(); if (el instanceof Express) { ((EventListener)el).onEvent(_event); if (!_event.isPropagatable()) return; //done } } final String script = ((ComponentCtrl)_comp).getMilieu().getEventHandler(_comp, evtnm); if (script != null) { page.interpret(script, ns); if (!_event.isPropagatable()) return; //done } for (Iterator it = _comp.getListenerIterator(evtnm); it.hasNext();) { final Object el = it.next(); if (!(el instanceof Express)) { ((EventListener)el).onEvent(_event); if (!_event.isPropagatable()) return; //done } } final Method mtd = ExecutionsCtrl .getEventMethod(_comp.getClass(), evtnm); if (mtd != null) { if (D.ON && log.finerable()) log.finer("Method for event="+evtnm+" comp="+_comp+" method="+mtd); if (mtd.getParameterTypes().length == 0) mtd.invoke(_comp, null); else mtd.invoke(_comp, new Object[] {_event}); if (!_event.isPropagatable()) return; //done } for (Iterator it = page.getListenerIterator(evtnm); it.hasNext();) { ((EventListener)it.next()).onEvent(_event); if (!_event.isPropagatable()) return; //done } } //-- Object --// public String toString() { return "[Event processing thread: event="+_event+", ceased="+_ceased+']'; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -