📄 uiengineimpl.java
字号:
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, false); } 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. * @param recovering whether it is in recovering, i.e., * cause by {@link FailoverManager#recover}. * If true, the requests argument must be 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, boolean recovering) { if (Executions.getCurrent() != null) throw new IllegalStateException("Use doReactivate instead"); final Desktop desktop = exec.getDesktop(); final DesktopCtrl desktopCtrl = (DesktopCtrl)desktop; final Session sess = desktop.getSession();// if (log.finerable()) log.finer("Activating "+desktop); final boolean asyncupd = requests != null; assert D.OFF || !recovering || !asyncupd; //to simplify the following codes, asyncupd and recovering //cannot be both true final boolean inProcess = asyncupd && !isRecovering(desktop) && desktopCtrl.getRequestQueue().addRequests(requests); //used as flag to know whether to add the requests //to the previous execution, if any. //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; //done 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, recovering)); desktopCtrl.setExecution(exec); } final ExecutionCtrl execCtrl = (ExecutionCtrl)exec; execCtrl.setVisualizer(uv); ExecutionsCtrl.setCurrent(exec); execCtrl.onActivate(); return uv; } /** Returns whether the desktop is being recovered. */ private static final boolean isRecovering(Desktop desktop) { final Execution exec = desktop.getExecution(); return exec != null && ((ExecutionCtrl)exec).isRecovering(); } /** 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 { //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.onDeactivate(); 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); curCtrl.onActivate(); 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; curCtrl.onDeactivate(); 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; } } //Handling Native Component// /** Sets the prolog of the specified native component. */ private static final void setProlog(CreateInfo ci, Component comp, NativeInfo compInfo) { final Native nc = (Native)comp; StringBuffer sb = null; final List prokids = compInfo.getPrologChildren(); if (!prokids.isEmpty()) { sb = new StringBuffer(256); getNativeContent(ci, sb, comp, prokids); } final NativeInfo splitInfo = compInfo.getSplitChild(); if (splitInfo != null && splitInfo.isEffective(comp)) { if (sb == null) sb = new StringBuffer(256); getNativeFirstHalf(ci, sb, comp, splitInfo); } if (sb != null && sb.length() > 0) nc.setPrologContent( sb.insert(0, (String)nc.getPrologContent()).toString()); } /** Sets the epilog of the specified native component. * @param comp the native component */ private static final void setEpilog(CreateInfo ci, Component comp, NativeInfo compInfo) { final Native nc = (Native)comp; StringBuffer sb = null; final NativeInfo splitInfo = compInfo.getSplitChild(); if (splitInfo != null && splitInfo.isEffective(comp)) { sb = new StringBuffer(256); getNativeSecondHalf(ci, sb, comp, splitInfo); } final List epikids = compInfo.getEpilogChildren(); if (!epikids.isEmpty()) { if (sb == null) sb = new StringBuffer(256); getNativeContent(ci, sb, comp, epikids); } if (sb != null && sb.length() > 0) nc.setEpilogContent( sb.append(nc.getEpilogContent()).toString()); } /** * @param comp the native component */ private static final void getNativeContent(CreateInfo ci, StringBuffer sb, Component comp, List children) { for (Iterator it = children.iterator(); it.hasNext();) { final Object meta = it.next(); if (meta instanceof NativeInfo) { final NativeInfo childInfo = (NativeInfo)meta; final ForEach forEach = childInfo.getForEach(ci.page, comp); if (forEach == null) { if (childInfo.isEffective(comp)) { getNativeFirstHalf(ci, sb, comp, childInfo); getNativeSecondHalf(ci, sb, comp, childInfo); } } else { while (forEach.next()) { if (childInfo.isEffective(comp)) { getNativeFirstHalf(ci, sb, comp, childInfo); getNativeSecondHalf(ci, sb, comp, childInfo); } } } } else if (meta instanceof TextInfo) { final String s = ((TextInfo)meta).getValue(comp); ((Native)comp).getHelper().appendText(sb, s); } else { execNonComponent(ci, comp, meta); } } } /** Before calling this method, childInfo.isEffective must be examined */ private static final void getNativeFirstHalf(CreateInfo ci, StringBuffer sb, Component comp, NativeInfo childInfo) { ((Native)comp).getHelper() .getFirstHalf(sb, childInfo.getTag(), evalProperties(comp, childInfo.getProperties()), childInfo.getDeclaredNamespaces()); final List prokids = childInfo.getPrologChildren(); if (!prokids.isEmpty()) getNativeContent(ci, sb, comp, prokids); final NativeInfo splitInfo = childInfo.getSplitChild(); if (splitInfo != null && splitInfo.isEffective(comp)) getNativeFirstHalf(ci, sb, comp, splitInfo); //recursive } /** Before calling this method, childInfo.isEffective must be examined */ private static final void getNativeSecondHalf(CreateInfo ci, StringBuffer sb, Component comp, NativeInfo childInfo) { final NativeInfo splitInfo = childInfo.getSplitChild(); if (splitInfo != null && splitInfo.isEffective(comp)) getNativeSecondHalf(ci, sb, comp, splitInfo); //recursive final List epikids = childInfo.getEpilogChildren(); if (!epikids.isEmpty()) getNativeContent(ci, sb, comp, epikids); ((Native)comp).getHelper().getSecondHalf(sb, childInfo.getTag()); } /** Returns a map of properties, (String name, String value). */ private static final Map evalProperties(Component comp, List props) { if (props == null || props.isEmpty()) return Collections.EMPTY_MAP; final Map map = new LinkedHashMap(props.size() * 2); for (Iterator it = props.iterator(); it.hasNext();) { final Property prop = (Property)it.next(); if (prop.isEffective(comp)) map.put(prop.getName(), Classes.coerce(String.class, prop.getValue(comp))); } return map; } //Supporting Classes// /** The listener to create children when the fulfill condition is * satisfied. */ private static class FulfillListener implements EventListener, Express, java.io.Serializable, Cloneable, ComponentSerializationListener, ComponentCloneListener { private transient String _evtnm; private transient Component _target, _comp; private final ComponentInfo _compInfo; private final String _fulfill; private FulfillListener(String fulfill, ComponentInfo compInfo, Component comp) { _fulfill = fulfill; _compInfo = compInfo; _comp = comp; init(); _target.addEventListener(_evtnm, this); } private void init() { final Object[] result = ComponentsCtrl.parseEventExpression(_comp, _fulfill, _comp, false); _target = (Component)result[0]; _evtnm = (String)result[1]; } public void onEvent(Event evt) throws Exception { _target.removeEventListener(_evtnm, this); //one shot only final Execution exec = Executions.getCurrent(); execCreate0( new CreateInfo( ((WebAppCtrl)exec.getDesktop().getWebApp()).getUiFactory(), exec, _comp.getPage()), _compInfo, _comp); } //ComponentSerializationListener// public void willSerialize(Component comp) { } public void didDeserialize(Component comp) { _comp = comp; init(); } //ComponentCloneListener// public Object clone(Component comp) { final FulfillListener clone; try { clone = (FulfillListener)clone(); } catch (CloneNotSupportedException e) { throw new InternalError(); } clone._comp = comp; clone.init(); return clone; } } /** Info used with execCreate */ private static class CreateInfo { private final Execution exec; private final Page page; private final UiFactory uf; private CreateInfo(UiFactory uf, Execution exec, Page page) { this.exec = exec; this.page = page; this.uf = uf; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -