📄 uiengineimpl.java
字号:
} public void notify(Object mutex) { notify(Executions.getCurrent().getDesktop(), mutex); } public void notify(Desktop desktop, Object mutex) { if (desktop == null || mutex == null) throw new IllegalArgumentException("desktop and mutex cannot be null"); final Map map; synchronized (_suspended) { map = (Map)_suspended.get(desktop); if (map == null) return; //nothing to notify } final EventProcessingThread evtthd; synchronized (map) { final List list = (List)map.get(mutex); if (list == null) return; //nothing to notify //Note: list is never empty evtthd = (EventProcessingThread)list.remove(0); if (list.isEmpty()) map.remove(mutex); //clean up } addResumed(desktop, evtthd); } public void notifyAll(Object mutex) { final Execution exec = Executions.getCurrent(); if (exec == null) throw new UiException("resume can be called only in processing a request"); notifyAll(exec.getDesktop(), mutex); } public void notifyAll(Desktop desktop, Object mutex) { if (desktop == null || mutex == null) throw new IllegalArgumentException("desktop and mutex cannot be null"); final Map map; synchronized (_suspended) { map = (Map)_suspended.get(desktop); if (map == null) return; //nothing to notify } final List list; synchronized (map) { list = (List)map.remove(mutex); if (list == null) return; //nothing to notify } for (Iterator it = list.iterator(); it.hasNext();) addResumed(desktop, (EventProcessingThread)it.next()); } /** Adds to _resumed */ private void addResumed(Desktop desktop, EventProcessingThread evtthd) { if (D.ON && log.finerable()) log.finer("Ready to resume "+evtthd); List list; synchronized (_resumed) { list = (List)_resumed.get(desktop); if (list == null) _resumed.put(desktop, list = new LinkedList()); } synchronized (list) { list.add(evtthd); } } /** Does the real resume. * Note: {@link #resume} only puts a thread into a resume queue in execution. */ private void resumeAll(Desktop desktop, UiVisualizer uv, List errs) { //We have to loop because a resumed thread might resume others for (;;) { final List list; synchronized (_resumed) { list = (List)_resumed.remove(desktop); if (list == null) return; //nothing to resume; done } synchronized (list) { for (Iterator it = list.iterator(); it.hasNext();) { final EventProcessingThread evtthd = (EventProcessingThread)it.next(); if (D.ON && log.finerable()) log.finer("Resume "+evtthd); if (uv.isAborting()) { evtthd.ceaseSilently(); } else { try { if (evtthd.doResume()) //wait it complete or suspend again recycleEventThread(evtthd); //completed } catch (Throwable ex) { recycleEventThread(evtthd); if (errs == null) { log.error("Unable to resume "+evtthd, ex); throw UiException.Aide.wrap(ex); } handleError(ex, uv, errs); } } } } } } /** Process an event. */ private void processEvent(Component comp, Event event) { if (comp.getPage() == null) { if (D.ON && log.debugable()) log.debug("Event is ignored due to dead"); return; //nothing to do } EventProcessingThread evtthd = null; synchronized (_evtthds) { if (!_evtthds.isEmpty()) evtthd = (EventProcessingThread)_evtthds.remove(0); } if (evtthd == null) evtthd = new EventProcessingThread(); try { if (evtthd.processEvent(comp, event)) recycleEventThread(evtthd); } catch (Throwable ex) { recycleEventThread(evtthd); throw UiException.Aide.wrap(ex); } } private void recycleEventThread(EventProcessingThread evtthd) { if (!evtthd.isCeased()) { if (evtthd.isIdle()) { synchronized (_evtthds) { if (_evtthds.size() < _maxEvtThds) { _evtthds.add(evtthd); //return to pool return; //done } } } evtthd.ceaseSilently(); } } //-- Generate output from a response --// /** Output the next response sequence ID. */ private static void responseSequenceId(Desktop desktop, Writer out) throws IOException { final String attr = "org.zkoss.zk.ui.respId"; final Integer val = (Integer)desktop.getAttribute(attr); final int i = val == null ? 0: (val.intValue() + 1) & 0x3ff; //range: 0 ~ 1023 desktop.setAttribute(attr, new Integer(i)); out.write("\n<sid>"); out.write(Integer.toString(i)); out.write("</sid>"); } public void response(AuResponse response, Writer out) throws IOException { out.write("\n<r><c>"); out.write(response.getCommand()); out.write("</c>"); final String[] data = response.getData(); if (data != null) { for (int j = 0; j < data.length; ++j) { out.write("\n<d>"); encodeXML(data[j], out); out.write("</d>"); } } out.write("\n</r>"); } public void response(List responses, Writer out) throws IOException { for (Iterator it = responses.iterator(); it.hasNext();) response((AuResponse)it.next(), out); } private static void encodeXML(String data, Writer out) throws IOException { if (data == null || data.length() == 0) return; //20051208: Tom Yeh //The following codes are tricky. //Reason: //1. nested CDATA is not allowed //2. Firefox (1.0.7)'s XML parser cannot handle over 4096 chars // if CDATA is not used int j = 0; for (int k; (k = data.indexOf("]]>", j)) >= 0;) { encodeByCData(data.substring(j, k), out); out.write("]]>"); j = k + 3; } encodeByCData(data.substring(j), out); } private static void encodeByCData(String data, Writer out) throws IOException { for (int j = data.length(); --j >= 0;) { final char cc = data.charAt(j); if (cc == '<' || cc == '>' || cc == '&') { out.write("<![CDATA["); out.write(data); out.write("]]>"); return; } } out.write(data); } public void activate(Execution exec) { assert D.OFF || ExecutionsCtrl.getCurrentCtrl() == null: "Impossible to re-activate for update: old="+ExecutionsCtrl.getCurrentCtrl()+", new="+exec; doActivate(exec, null); } public void deactivate(Execution exec) { doDeactivate(exec); } //-- Common private utilities --// /** Activates the specified execution for processing. * * @param requests a list of requests to process. * Activation assumes it is asynchronous update if it is not null. * @return the exec info if the execution is granted; * null if request has been added to the exec currently activated */ private static UiVisualizer doActivate(Execution exec, List requests) { final Desktop desktop = exec.getDesktop(); final DesktopCtrl desktopCtrl = (DesktopCtrl)desktop; final Session sess = desktop.getSession(); final boolean asyncupd = requests != null; if (log.finerable()) log.finer("Activating "+desktop); assert D.OFF || Executions.getCurrent() == null: "Use doReactivate instead"; final boolean inProcess = asyncupd && desktopCtrl.getRequestQueue().addRequests(requests); //lock desktop final UiVisualizer uv; final Map eis = getVisualizers(sess); synchronized (eis) { for (;;) { final UiVisualizer old = (UiVisualizer)eis.get(desktop); if (old == null) break; //grantable if (inProcess) return null; try { eis.wait(120*1000); } catch (InterruptedException ex) { throw UiException.Aide.wrap(ex); } } //grant if (asyncupd) desktopCtrl.getRequestQueue().setInProcess(); //set the flag asap to free more following executions eis.put(desktop, uv = new UiVisualizer(exec, asyncupd)); desktopCtrl.setExecution(exec); } final ExecutionCtrl execCtrl = (ExecutionCtrl)exec; execCtrl.setVisualizer(uv); ExecutionsCtrl.setCurrent(exec); try { execCtrl.onActivate(); } catch (Throwable ex) { doDeactivate(exec); throw UiException.Aide.wrap(ex); } return uv; } /** Deactivates the execution. */ private static final void doDeactivate(Execution exec) { final Desktop desktop = exec.getDesktop(); final Session sess = desktop.getSession(); if (log.finerable()) log.finer("Deactivating "+desktop); final ExecutionCtrl execCtrl = (ExecutionCtrl)exec; try { try { execCtrl.onDeactivate(); } catch (Throwable ex) { log.warning("Ignored: failed to deactivate "+desktop, ex); } //Unlock desktop final Map eis = getVisualizers(sess); synchronized (eis) { final Object o = eis.remove(desktop); assert D.OFF || o != null; ((DesktopCtrl)desktop).setExecution(null); eis.notify(); //wakeup doActivate's wait } } finally { execCtrl.setCurrentPage(null); execCtrl.setVisualizer(null); ExecutionsCtrl.setCurrent(null); } final SessionCtrl sessCtrl = (SessionCtrl)sess; if (sessCtrl.isInvalidated()) sessCtrl.invalidateNow(); } /** Re-activates for another execution. It is callable only for * creating new page (execNewPage). It is not allowed for async-update. * <p>Note: doActivate cannot handle reactivation. In other words, * the caller has to detect which method to use. */ private static UiVisualizer doReactivate(Execution curExec, UiVisualizer olduv) { final Desktop desktop = curExec.getDesktop(); final Session sess = desktop.getSession(); if (log.finerable()) log.finer("Re-activating "+desktop); assert D.OFF || olduv.getExecution().getDesktop() == desktop: "old dt: "+olduv.getExecution().getDesktop()+", new:"+desktop; final UiVisualizer uv = new UiVisualizer(olduv, curExec); final Map eis = getVisualizers(sess); synchronized (eis) { final Object o = eis.put(desktop, uv); if (o != olduv) throw new InternalError(); //wrong olduv ((DesktopCtrl)desktop).setExecution(curExec); } final ExecutionCtrl curCtrl = (ExecutionCtrl)curExec; curCtrl.setVisualizer(uv); ExecutionsCtrl.setCurrent(curExec); try { curCtrl.onActivate(); } catch (Throwable ex) { doDereactivate(curExec, olduv); throw UiException.Aide.wrap(ex); } return uv; } /** De-reactivated exec. Work with {@link #doReactivate}. */ private static void doDereactivate(Execution curExec, UiVisualizer olduv) { if (olduv == null) throw new IllegalArgumentException("null"); final Desktop desktop = curExec.getDesktop(); final Session sess = desktop.getSession(); if (log.finerable()) log.finer("Deactivating "+desktop); final ExecutionCtrl curCtrl = (ExecutionCtrl)curExec; try { curCtrl.onDeactivate(); } catch (Throwable ex) { log.warning("Ignored: failed to deactivate "+desktop, ex); } curCtrl.setCurrentPage(null); curCtrl.setVisualizer(null); //free memory final Execution oldexec = olduv.getExecution(); final Map eis = getVisualizers(sess); synchronized (eis) { eis.put(desktop, olduv); ((DesktopCtrl)desktop).setExecution(oldexec); } ExecutionsCtrl.setCurrent(oldexec); } /** Returns a map of (Page, UiVisualizer). */ private static Map getVisualizers(Session sess) { synchronized (sess) { final String attr = "org.zkoss.zk.ui.Visualizers"; Map eis = (Map)sess.getAttribute(attr); if (eis == null) sess.setAttribute(attr, eis = new HashMap()); return eis; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -