📄 uiengineimpl.java
字号:
/* UiEngineImpl.java{{IS_NOTE Purpose: Description: History: Thu Jun 9 13:05:28 2005, Created by tomyeh}}IS_NOTECopyright (C) 2005 Potix Corporation. All Rights Reserved.{{IS_RIGHT This program is distributed under GPL Version 2.0 in the hope that it will be useful, but WITHOUT ANY WARRANTY.}}IS_RIGHT*/package org.zkoss.zk.ui.impl;import java.util.Iterator;import java.util.Map;import java.util.HashMap;import java.util.IdentityHashMap;import java.util.Set;import java.util.HashSet;import java.util.List;import java.util.LinkedList;import java.util.Collections;import java.io.Writer;import java.io.IOException;import javax.servlet.jsp.el.FunctionMapper;import org.zkoss.lang.D;import org.zkoss.lang.Classes;import org.zkoss.lang.Objects;import org.zkoss.lang.Threads;import org.zkoss.lang.Exceptions;import org.zkoss.lang.Expectable;import org.zkoss.mesg.Messages;import org.zkoss.util.logging.Log;import org.zkoss.zk.mesg.MZk;import org.zkoss.zk.ui.*;import org.zkoss.zk.ui.sys.*;import org.zkoss.zk.ui.event.*;import org.zkoss.zk.ui.metainfo.*;import org.zkoss.zk.ui.ext.AfterCompose;import org.zkoss.zk.ui.util.*;import org.zkoss.zk.au.*;/** * An implementation of {@link UiEngine}. * * @author tomyeh */public class UiEngineImpl implements UiEngine { private static final Log log = Log.lookup(UiEngineImpl.class); /** A pool of idle EventProcessingThread. */ private final List _evtthds = new LinkedList(); /** A map of suspended processing: * (Desktop desktop, IdentityHashMap(Object mutex, List(EventProcessingThread)). */ private final Map _suspended = new HashMap(); /** A map of resumed processing * (Desktop desktop, List(EventProcessingThread)). */ private final Map _resumed = new HashMap(); /** The maximal allowed # of event handling threads.*/ private int _maxEvtThds; public UiEngineImpl() { } //-- UiEngine --// public void start(WebApp wapp) { final Integer v = wapp.getConfiguration().getMaxEventThreads(); final int i = v != null ? v.intValue(): 100; _maxEvtThds = i > 0 ? i: 100; } public void stop(WebApp wapp) { synchronized (_evtthds) { for (Iterator it = _evtthds.iterator(); it.hasNext();) ((EventProcessingThread)it.next()).cease(); _evtthds.clear(); } synchronized (_suspended) { for (Iterator it = _suspended.values().iterator(); it.hasNext();) { final Map map = (Map)it.next(); synchronized (map) { for (Iterator i2 = map.values().iterator(); i2.hasNext();) { final List list = (List)i2.next(); for (Iterator i3 = list.iterator(); i3.hasNext();) ((EventProcessingThread)i3.next()).cease(); } } } _suspended.clear(); } synchronized (_resumed) { for (Iterator it = _resumed.values().iterator(); it.hasNext();) { final List list = (List)it.next(); synchronized (list) { for (Iterator i2 = list.iterator(); i2.hasNext();) ((EventProcessingThread)i2.next()).cease(); } } _resumed.clear(); } } public void cleanup(Desktop desktop) { if (log.debugable()) log.debug("Cleanup "+desktop); final Configuration conf = desktop.getWebApp().getConfiguration(); final Map map; synchronized (_suspended) { map = (Map)_suspended.remove(desktop); } if (map != null) { synchronized (map) { for (Iterator it = map.values().iterator(); it.hasNext();) { final List list = (List)it.next(); for (Iterator i2 = list.iterator(); i2.hasNext();) { final EventProcessingThread evtthd = (EventProcessingThread)i2.next(); evtthd.ceaseSilently(); conf.invokeEventThreadResumeAborts( evtthd.getComponent(), evtthd.getEvent()); } } } } final List list; synchronized (_resumed) { list = (List)_resumed.remove(desktop); } if (list != null) { synchronized (list) { for (Iterator it = list.iterator(); it.hasNext();) { final EventProcessingThread evtthd = (EventProcessingThread)it.next(); evtthd.ceaseSilently(); conf.invokeEventThreadResumeAborts( evtthd.getComponent(), evtthd.getEvent()); } } } } private static UiVisualizer getCurrentVisualizer() { final ExecutionCtrl execCtrl = ExecutionsCtrl.getCurrentCtrl(); if (execCtrl == null) throw new IllegalStateException("Components can be accessed only in event listeners"); return (UiVisualizer)execCtrl.getVisualizer(); } public void pushOwner(Component comp) { getCurrentVisualizer().pushOwner(comp); } public void popOwner() { getCurrentVisualizer().popOwner(); } public void addInvalidate(Page page) { if (page == null) throw new IllegalArgumentException(); getCurrentVisualizer().addInvalidate(page); } public void addInvalidate(Component comp) { if (comp == null) throw new IllegalArgumentException(); getCurrentVisualizer().addInvalidate(comp); } public void addSmartUpdate(Component comp, String attr, String value) { if (comp == null) throw new IllegalArgumentException(); getCurrentVisualizer().addSmartUpdate(comp, attr, value); } public void addResponse(String key, AuResponse response) { getCurrentVisualizer().addResponse(key, response); } public void addMoved(Component comp, Component oldparent, Page oldpg, Page newpg) { if (comp == null) throw new IllegalArgumentException(); getCurrentVisualizer().addMoved(comp, oldparent, oldpg, newpg); } /** Called before changing the component's UUID. * * @param addOnlyMoved if true, it is added only if it was moved * before (see {@link #addMoved}). */ public void addUuidChanged(Component comp, boolean addOnlyMoved) { if (comp == null) throw new IllegalArgumentException(); getCurrentVisualizer().addUuidChanged(comp, addOnlyMoved); } //-- Creating a new page --// public void execNewPage(Execution exec, Richlet richlet, Page page, Writer out) throws IOException { execNewPage0(exec, null, richlet, page, out); } public void execNewPage(Execution exec, PageDefinition pagedef, Page page, Writer out) throws IOException { execNewPage0(exec, pagedef, null, page, out); } /** It assumes exactly one of pagedef and richlet is not null. */ public void execNewPage0(final Execution exec, final PageDefinition pagedef, final Richlet richlet, final Page page, final Writer out) throws IOException { //Update the client type first. If this is the second page and not //belonging to the same client type, an exception is thrown final Desktop desktop = exec.getDesktop(); final LanguageDefinition langdef = //default page pagedef != null ? pagedef.getLanguageDefinition(): richlet != null ? richlet.getLanguageDefinition(): null; if (langdef != null) desktop.setClientType(langdef.getClientType()); //set and check! //It is possible this method is invoked when processing other exec final Execution oldexec = Executions.getCurrent(); final ExecutionCtrl oldexecCtrl = (ExecutionCtrl)oldexec; final UiVisualizer olduv = oldexecCtrl != null ? (UiVisualizer)oldexecCtrl.getVisualizer(): null; final UiVisualizer uv; if (olduv != null) uv = doReactivate(exec, olduv); else uv = doActivate(exec, null); final ExecutionCtrl execCtrl = (ExecutionCtrl)exec; final Page old = execCtrl.getCurrentPage(); final PageDefinition olddef = execCtrl.getCurrentPageDefinition(); execCtrl.setCurrentPage(page); execCtrl.setCurrentPageDefinition(pagedef); final Configuration config = desktop.getWebApp().getConfiguration(); boolean cleaned = false; try { config.invokeExecutionInits(exec, oldexec); if (olduv != null) olduv.setOwner(page); //Cycle 1: Creates all components //Note: //1) stylesheet, tablib are inited in Page's contructor //2) we add variable resolvers before init because //init's zscirpt might depend on it. if (pagedef != null) { page.addFunctionMapper(pagedef.getFunctionMapper()); initVariableResolvers(pagedef, page); final Initiators inits = Initiators.doInit(pagedef, page); try { //Request 1472813: sendRedirect in init; test: sendRedirectNow.zul pagedef.init(page, !uv.isEverAsyncUpdate() && !uv.isAborting(), !uv.isAborting()); if (!uv.isAborting()) execCreate(exec, page, pagedef, null); inits.doAfterCompose(page); } catch(Throwable ex) { inits.doCatch(ex); throw UiException.Aide.wrap(ex); } finally { inits.doFinally(); } } else { //FUTURE: a way to allow richlet to set page ID ((PageCtrl)page).init(null, null, null, null); richlet.service(page); } //Cycle 2: process pending events Event event = nextEvent(uv); do { for (; event != null; event = nextEvent(uv)) { process(desktop, event); //Unlike execUpdate, we don't cache exception here } //Cycle 2a: processing resumed event processing resumeAll(desktop, uv, null); } while ((event = nextEvent(uv)) != null); //Cycle 3: Redraw the page (and responses) List responses = uv.getResponses(); final AbortingReason aborting = uv.getAbortingReason(); if (aborting != null) { final AuResponse abtresp = aborting.getResponse(); if (abtresp != null) responses.add(0, abtresp); } if (olduv != null && olduv.addToFirstAsyncUpdate(responses)) responses = null; //A new ZK page might be included by an async update //(example: ZUL's include). //If so, we cannot generate the responses in the page. //Rather, we shall add them to the async update. ((PageCtrl)page).redraw(responses, out); } catch (Throwable ex) { cleaned = true; config.invokeExecutionCleanups(exec, oldexec, ex, null); //TODO: find a way to send back the error message, if any, returned if (ex instanceof IOException) throw (IOException)ex; throw UiException.Aide.wrap(ex); } finally { if (!cleaned) config.invokeExecutionCleanups(exec, oldexec, null, null); execCtrl.setCurrentPage(old); //restore it execCtrl.setCurrentPageDefinition(olddef); //restore it if (olduv != null) doDereactivate(exec, olduv); else doDeactivate(exec); } } private static final Event nextEvent(UiVisualizer uv) { final Event evt = ((ExecutionCtrl)uv.getExecution()).getNextEvent(); return evt != null && !uv.isAborting() ? evt: null; } /** Cycle 1: * Creates all child components defined in the specified definition. * @return the first component being created. */ private static final Component execCreate(Execution exec, Page page, InstanceDefinition parentdef, Component parent) throws IOException { Component firstCreated = null; final PageDefinition pagedef = parentdef.getPageDefinition(); //note: don't use page.getDefinition because createComponents //might be called from a page other than instance's for (Iterator it = parentdef.getChildren().iterator(); it.hasNext();) { final Object obj = it.next(); if (obj instanceof InstanceDefinition) { final InstanceDefinition childdef = (InstanceDefinition)obj; final ForEach forEach = childdef.getForEach(page, parent); if (forEach == null) { if (isEffective(childdef, page, parent)) { final Component child = execCreateChild(exec, page, parent, childdef); if (firstCreated == null) firstCreated = child; } } else { while (forEach.next()) { if (isEffective(childdef, page, parent)) { final Component child = execCreateChild(exec, page, parent, childdef); if (firstCreated == null) firstCreated = child; } } } } else if (obj instanceof ZScript) { final ZScript script = (ZScript)obj; if (isEffective(script, page, parent)) { final Namespace ns = parent != null ? Namespaces.beforeInterpret(exec, parent): Namespaces.beforeInterpret(exec, page); try { page.interpret(script.getContent(page, parent), ns); } finally { Namespaces.afterInterpret(ns); } } } else { throw new IllegalStateException("Unknown object: "+obj); } } return firstCreated;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -