📄 uiengineimpl.java
字号:
} private static Component execCreateChild(Execution exec, Page page, Component parent, InstanceDefinition childdef) throws IOException { if (ComponentDefinition.ZK == childdef.getComponentDefinition()) { return execCreate(exec, page, childdef, parent); } else { final Component child = ((WebAppCtrl)exec.getDesktop().getWebApp()) .getUiFactory().newComponent(page, parent, childdef); execCreate(exec, page, childdef, child); //recursive if (child instanceof AfterCompose) ((AfterCompose)child).afterCompose(); if (Events.isListenerAvailable(child, Events.ON_CREATE, false)) Events.postEvent( new CreateEvent(Events.ON_CREATE, child, exec.getArg())); return child; } } private static final boolean isEffective(Condition cond, Page page, Component comp) { return comp != null ? cond.isEffective(comp): cond.isEffective(page); } public Component createComponents(Execution exec, PageDefinition pagedef, Page page, Component parent, Map arg) { if (pagedef == null) throw new IllegalArgumentException("pagedef"); if (parent != null) page = parent.getPage(); else if (page != null) parent = ((PageCtrl)page).getDefaultParent(); final ExecutionCtrl execCtrl = (ExecutionCtrl)exec; if (!execCtrl.isActivated()) throw new IllegalStateException("Not activated yet"); final Page old = execCtrl.getCurrentPage(); final PageDefinition olddef = execCtrl.getCurrentPageDefinition(); execCtrl.setCurrentPage(page); execCtrl.setCurrentPageDefinition(pagedef); exec.pushArg(arg != null ? arg: Collections.EMPTY_MAP); //Note: we add taglib, stylesheets and var-resolvers to the page //it might cause name pollution but we got no choice since they //are used as long as components created by this method are alive if (page != null) page.addFunctionMapper(pagedef.getFunctionMapper()); initVariableResolvers(pagedef, page); final Initiators inits = Initiators.doInit(pagedef, page); try { final Component comp = execCreate(exec, page, pagedef, parent); inits.doAfterCompose(page); return comp; } catch (Throwable ex) { inits.doCatch(ex); throw UiException.Aide.wrap(ex); } finally { exec.popArg(); execCtrl.setCurrentPage(old); //restore it execCtrl.setCurrentPageDefinition(olddef); //restore it inits.doFinally(); } } private static final void initVariableResolvers(PageDefinition pagedef, Page page) { final List resolvs = pagedef.newVariableResolvers(page); if (!resolvs.isEmpty()) for (Iterator it = resolvs.iterator(); it.hasNext();) page.addVariableResolver((VariableResolver)it.next()); } public void sendRedirect(String uri, String target) { if (uri != null && uri.length() == 0) uri = null; final UiVisualizer uv = getCurrentVisualizer(); uv.setAbortingReason( new AbortBySendRedirect( uri != null ? uv.getExecution().encodeURL(uri): "", target)); } public void setAbortingReason(AbortingReason aborting) { final UiVisualizer uv = getCurrentVisualizer(); uv.setAbortingReason(aborting); } //-- Asynchronous updates --// public void execUpdate(Execution exec, List requests, Writer out) throws IOException { if (requests == null) throw new IllegalArgumentException("null requests"); assert D.OFF || ExecutionsCtrl.getCurrentCtrl() == null: "Impossible to re-activate for update: old="+ExecutionsCtrl.getCurrentCtrl()+", new="+exec+", reqs="+requests; final Execution oldexec = Executions.getCurrent(); final UiVisualizer uv = doActivate(exec, requests); if (uv == null) return; //done (request is added to the exec currently activated) final Desktop desktop = exec.getDesktop(); final Configuration config = desktop.getWebApp().getConfiguration(); final Monitor monitor = config.getMonitor(); if (monitor != null) { try { monitor.beforeUpdate(desktop, requests); } catch (Throwable ex) { log.error(ex); } } boolean cleaned = false; try { config.invokeExecutionInits(exec, oldexec); final RequestQueue rque = ((DesktopCtrl)desktop).getRequestQueue(); final List errs = new LinkedList(); final long tmexpired = System.currentTimeMillis() + 3000; //Tom Yeh: 20060120 //Don't process all requests if this thread has processed //a while. Thus, user could see the response sooner. for (AuRequest request; System.currentTimeMillis() < tmexpired && (request = rque.nextRequest()) != null;) { //Cycle 1: Process one request //Don't process more such that requests will be queued //adn we have the chance to optimize them try { process(exec, request, !errs.isEmpty()); } catch (ComponentNotFoundException ex) { //possible because the previous might remove some comp //so ignore it if (log.debugable()) log.debug("Component not found: "+request); } catch (Throwable ex) { handleError(ex, uv, errs); //we don't skip request to avoid mis-match between c/s } //Cycle 2: Process any pending events posted by components Event event = nextEvent(uv); do { for (; event != null; event = nextEvent(uv)) { try { process(desktop, event); } catch (Throwable ex) { handleError(ex, uv, errs); break; //skip the rest of events! } } //Cycle 2a: processing resumed event processing resumeAll(desktop, uv, errs); } while ((event = nextEvent(uv)) != null); } //Cycle 3: Generate output if (!uv.isAborting()) { List responses; try { //Note: we have to call visualizeErrors before uv.getResponses, //since it might create/update components if (!errs.isEmpty()) visualizeErrors(exec, uv, errs); responses = uv.getResponses(); } catch (Throwable ex) { responses = new LinkedList(); responses.add(new AuAlert(Exceptions.getMessage(ex))); log.error(ex); errs.add(ex); //so invokeExecutionCleanups knows it } cleaned = true; final List cleanerrs = new LinkedList(); config.invokeExecutionCleanups( exec, oldexec, errs.isEmpty() ? null: (Throwable)errs.get(0), cleanerrs); if (!cleanerrs.isEmpty()) { final StringBuffer errmsg = new StringBuffer(100); for (Iterator it = cleanerrs.iterator(); it.hasNext();) { final Throwable t = (Throwable)it.next(); if (errmsg.length() > 0) errmsg.append('\n'); errmsg.append(Exceptions.getMessage(t)); } responses.add(new AuAlert(errmsg.toString())); } if (rque.hasRequest()) responses.add(new AuEcho()); responseSequenceId(desktop, out); response(responses, out); if (log.debugable()) if (responses.size() < 5 || log.finerable()) log.debug("Responses: "+responses); else log.debug("Responses: "+responses.subList(0, 5)+"..."); } final AbortingReason aborting = uv.getAbortingReason(); if (aborting != null) { final AuResponse abtresp = aborting.getResponse(); if (abtresp != null) { responseSequenceId(desktop, out); response(abtresp, out); } } out.flush(); //flush before deactivating to make sure it has been sent } catch (Throwable ex) { if (!cleaned) { cleaned = true; config.invokeExecutionCleanups(exec, oldexec, ex, null); } if (ex instanceof IOException) throw (IOException)ex; throw UiException.Aide.wrap(ex); } finally { if (!cleaned) config.invokeExecutionCleanups(exec, oldexec, null, null); doDeactivate(exec); if (monitor != null) { try { monitor.afterUpdate(desktop); } catch (Throwable ex) { log.error(ex); } } } } /** Handles each error. The erros will be queued to the errs list * and processed later by {@link #visualizeErrors}. */ private static final void handleError(Throwable ex, UiVisualizer uv, List errs) { final Throwable err = ex; final Throwable t = Exceptions.findCause(ex, Expectable.class); if (t == null) { log.realCauseBriefly(ex); } else { ex = t; if (log.debugable()) log.debug(Exceptions.getRealCause(ex)); } final String msg = Exceptions.getMessage(ex); if (ex instanceof WrongValueException) { final Component comp = ((WrongValueException)ex).getComponent(); if (comp != null) { uv.addResponse("wrongValue", new AuAlert(comp, msg)); return; } } errs.add(err); } /** Post-process the errors to represent them to the user. */ private final void visualizeErrors(Execution exec, UiVisualizer uv, List errs) { final StringBuffer sb = new StringBuffer(128); for (Iterator it = errs.iterator(); it.hasNext();) { final Throwable t = (Throwable)it.next(); if (sb.length() > 0) sb.append('\n'); sb.append(Exceptions.getMessage(t)); } final String msg = sb.toString(); final Throwable err = (Throwable)errs.get(0); final String location = exec.getDesktop().getWebApp().getConfiguration().getErrorPage(err); if (location != null) { try { exec.setAttribute("javax.servlet.error.message", msg); exec.setAttribute("javax.servlet.error.exception", err); exec.setAttribute("javax.servlet.error.exception_type", err.getClass()); exec.setAttribute("javax.servlet.error.status_code", new Integer(500)); final Component c = exec.createComponents(location, null, null); if (c == null) { log.error("No component in "+location); } else { process(exec.getDesktop(), new Event(Events.ON_MODAL, c, null)); return; //done } } catch (Throwable ex) { log.realCause("Unable to generate custom error page, "+location, ex); } } uv.addResponse(null, new AuAlert(msg)); //default handling } /** Processing the request and stores result into UiVisualizer. * @param everError whether any error ever occured before processing this * request. */ private void process(Execution exec, AuRequest request, boolean everError) { if (log.debugable()) log.debug("Processing request: "+request); final ExecutionCtrl execCtrl = (ExecutionCtrl)exec; execCtrl.setCurrentPage(request.getPage()); request.getCommand().process(request, everError); } /** Processing the event and stores result into UiVisualizer. */ private void process(Desktop desktop, Event event) { if (log.debugable()) log.debug("Processing event: "+event); final Component comp = event.getTarget(); if (comp != null) { //Note: a component might be removed before event being processed if (comp.getPage() != null) processEvent(comp, event); } else { //since an event might change the page/desktop/component relation, //we copy roots first final List roots = new LinkedList(); for (Iterator it = desktop.getPages().iterator(); it.hasNext();) { roots.addAll(((Page)it.next()).getRoots()); } for (Iterator it = roots.iterator(); it.hasNext();) { final Component c = (Component)it.next(); if (c.getPage() != null) //might be removed, so check first processEvent(c, event); } } } public void wait(Object mutex) throws InterruptedException { if (mutex == null) throw new IllegalArgumentException("null mutex"); final Thread thd = Thread.currentThread(); if (!(thd instanceof EventProcessingThread)) throw new UiException("This method can be called only in an event listener, not in paging loading."); if (D.ON && log.finerable()) log.finer("Suspend "+thd+" on "+mutex); final Execution exec = Executions.getCurrent(); final Desktop desktop = exec.getDesktop(); final EventProcessingThread evtthd = (EventProcessingThread)thd; desktop.getWebApp().getConfiguration() .invokeEventThreadSuspends( evtthd.getComponent(), evtthd.getEvent(), mutex); //it might throw an exception, so process it before updating //_suspended Map map; synchronized (_suspended) { map = (Map)_suspended.get(desktop); if (map == null) _suspended.put(desktop, map = new IdentityHashMap(3)); //note: we have to use IdentityHashMap because user might //use Integer or so as mutex } synchronized (map) { List list = (List)map.get(mutex); if (list == null) map.put(mutex, list = new LinkedList()); list.add(evtthd); } try { EventProcessingThread.doSuspend(mutex); } catch (Throwable ex) { //error recover synchronized (map) { final List list = (List)map.get(mutex); if (list != null) { list.remove(evtthd); if (list.isEmpty()) map.remove(mutex); } } if (ex instanceof InterruptedException) throw (InterruptedException)ex; throw UiException.Aide.wrap(ex, "Unable to suspend "+evtthd); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -