Search in sources :

Example 1 with ValidationResult

use of org.olat.core.gui.render.ValidationResult in project OpenOLAT by OpenOLAT.

the class ValidatingVisitor method dispatchRequest.

/**
 * @param ureq
 * @param renderOnly
 */
public void dispatchRequest(UserRequest ureq, boolean renderOnly) {
    final HttpServletRequest request = ureq.getHttpReq();
    final HttpServletResponse response = ureq.getHttpResp();
    final String timestampID = ureq.getTimestampID() == null ? "1" : ureq.getTimestampID();
    final String componentID = ureq.getComponentID();
    // case windowId timestamp componentId
    // --------------------------------------------
    // 
    // 1 null     null null -> if (!renderOnly)-> error else doRenderOnly<br>
    // 2 invalid n/a n/a -> not handled here, but in Windows
    // 3 valid valid valid -> dispatch and further handling (check for new
    // window and res. media resource
    // 4 valid valid invalid -> no dispatch (silently) -> rerender (no res.
    // media res and no new window check needed)
    // 5 valid invalid n/a -> asyncRes == null? "doNotUseReload" :
    // getAsyncRes==null? renderInline : serve resource
    // 6 valid null n/a -> no timestamp -> just rerender inline
    // defs:
    // rerender: component validation and inline rendering
    // case 1:
    // simply rerender, no dispatching
    // case 3:
    // dispatch, check for new Window
    // case 5:
    // check newWindow, serve resource/renderInline
    // order:
    // 1. check for timestamp: valid: case 3,4 ; invalid -> case 5, or -1 ->
    // indicator of just rendering and no revalidating needed
    // 2. dispatch to component, unless flag renderOnly in method sig., or
    // inlineRerender set (timestamps indicates)
    boolean inline = false;
    boolean validate = false;
    boolean checkNewWindow = false;
    boolean dispatch = false;
    // increase the timestamp, but not if we are in loadperformancemode: then all url's have
    // to work independant of previous ones -> when no increase: timestamp is always the same here
    // !GUIInterna.isLoadPerformanceMode();
    boolean incTimestamp = false;
    MediaResource mr = null;
    final boolean isDebugLog = log.isDebug();
    StringBuilder debugMsg = null;
    long debug_start = 0;
    if (isDebugLog) {
        debug_start = System.currentTimeMillis();
        debugMsg = new StringBuilder("::winst:");
    }
    synchronized (this) {
        // o_clusterOK by:fj
        // sync dispatching per window to avoid rendering problems
        // when user repeateadly presses reload, and also to distribute bandwidth more
        // evenly.
        // postcondition: each controller's events are called by one gui-thread at a time only.
        GlobalSettings gsettings = wbackofficeImpl.getGlobalSettings();
        boolean bgEnab = gsettings.getAjaxFlags().isIframePostEnabled();
        // -------------------------
        if (bgEnab && (ureq.getMode() & 1) == 1) {
            // first check on "ajax-command-was-not-in-hidden-iframe hint" -> if so, rerender the current window
            if (ureq.getParameter("o_win_jsontop") != null) {
                renderOnly = true;
            } else {
                try {
                    // if target in background (m = mode , 0.bit set)
                    // 1.) do dispatch to component if component timestamp ok
                    // REVIEW:PB: this will be the code allowing back forward navigation
                    // --> boolean inlineAfterBackForward = false;
                    // FIXME:fj:b avoid double traversal to find component again below
                    String s_compID = ureq.getComponentID();
                    if (s_compID == null) {
                        throw new AssertException("no component id found in req:" + ureq.toString());
                    }
                    // throws NumberFormatException if not a number
                    // long compID = Long.parseLong(s_compID);
                    List<Component> foundPath = new ArrayList<Component>(10);
                    Component target = ComponentHelper.findDescendantOrSelfByID(getContentPane(), s_compID, foundPath);
                    final boolean validForDispatching;
                    if (target != null) {
                        // the target was found
                        String cTimest = target.getTimestamp();
                        String urlCTimest = ureq.getComponentTimestamp();
                        validForDispatching = cTimest.equals(urlCTimest);
                        if (!validForDispatching && isDebugLog) {
                            log.debug("Invalid timestamp: ureq.compid:" + ureq.getComponentID() + " ureq.win-ts:" + ureq.getTimestampID() + " ureq.comp-ts:" + ureq.getComponentTimestamp() + " target.timestamp:" + cTimest + " target=" + target);
                        }
                    } else {
                        // this can happen e.g. on quick double-clicks, so that the dom-replacement-command never reaches the client.
                        if (isDebugLog)
                            log.debug("no ajax dispatch: component not found (target=null)");
                        validForDispatching = false;
                        // check no response call
                        String noResponseMarker = ureq.getParameter("no-response");
                        if ("oo-no-response".equals(noResponseMarker)) {
                            return;
                        }
                    }
                    // 2.) collect dirty components (top-down, return from sub-path when first dirty node met)
                    // 3.) return to sender...
                    boolean didDispatch = false;
                    boolean forceReload = false;
                    if (validForDispatching) {
                        DispatchResult dispatchResult = doDispatchToComponent(ureq, null);
                        didDispatch = dispatchResult.isDispatch();
                        incTimestamp = dispatchResult.isIncTimestamp();
                        forceReload = dispatchResult.isForceReload();
                        if (isDebugLog) {
                            long durationAfterDoDispatchToComponent = System.currentTimeMillis() - debug_start;
                            log.debug("Perf-Test: Window durationAfterDoDispatchToComponent=" + durationAfterDoDispatchToComponent);
                        }
                    }
                    MediaResource mmr = null;
                    // -----> if (didDispatch || inlineAfterBackForward) {
                    if (forceReload) {
                        // force RELOAD with a redirect to itself
                        String reRenderUri = buildURIFor(this, timestampID, null);
                        Command rmrcom = CommandFactory.createParentRedirectTo(reRenderUri);
                        wbackofficeImpl.sendCommandTo(rmrcom);
                    } else if (didDispatch || !validForDispatching) {
                        if (validForDispatching) {
                            Window ww = ureq.getDispatchResult().getResultingWindow();
                            if (ww != null) {
                                // FIXME:fj:c think about bodyOnLoad -> win.open(new window url)
                                throw new AssertException("a link in ajax mode should never result in a new window");
                            }
                            mmr = ureq.getDispatchResult().getResultingMediaResource();
                            if (mmr == null) {
                                inline = true;
                            } else {
                                inline = false;
                            }
                        }
                        // -----> if (inline) {
                        if (inline || !validForDispatching) {
                            if (!validForDispatching) {
                                // not valid: fire oldtimestamp event and later rerender
                                fireEvent(ureq, OLDTIMESTAMPCALL);
                            }
                            ComponentCollection top = getContentPane();
                            // always validate here, since we are never in the case of just rerendering (we are in the bg iframe)
                            ValidatingVisitor vv = new ValidatingVisitor(gsettings, jsAndCssAdder);
                            ComponentTraverser ct = new ComponentTraverser(vv, top, false);
                            if (isDebugLog) {
                                long durationBeforeVisitAll = System.currentTimeMillis() - debug_start;
                                log.debug("Perf-Test: Window durationBeforeVisitAll=" + durationBeforeVisitAll);
                            }
                            ct.visitAll(ureq);
                            if (isDebugLog) {
                                long durationAfterVisitAll = System.currentTimeMillis() - debug_start;
                                log.debug("Perf-Test: Window durationAfterVisitAll=" + durationAfterVisitAll);
                            }
                            wbackofficeImpl.fireCycleEvent(Window.AFTER_VALIDATING);
                            ValidationResult vr = vv.getValidationResult();
                            boolean newJsCssAdded = vr.getJsAndCSSAdder().finishAndCheckChange();
                            String newModUri = vr.getNewModuleURI();
                            // !validForDispatching ||
                            if (newJsCssAdded || newModUri != null) {
                                // send 302 redirect so the ajax-iframe's parent window gets reloaded to either include new js/css or to prepare the address bar
                                // url for asynchronous requests when delivering inline-contentpackaging.
                                // set window id to cur id, timestamp to current timestamp,
                                // component id to -1 -> indicates rerender
                                // newModUri == null in case "just" new css or js libs have been added
                                String uri = buildURIForRedirect(newModUri);
                                // set this only for the first request (the .html request), but clear it afterwards for asyncmedia
                                validatingCausedRerendering = true;
                                Command rmrcom = CommandFactory.createParentRedirectTo(uri);
                                wbackofficeImpl.sendCommandTo(rmrcom);
                                // OLAT-4563: so the timestamp is not incremented, we do only a redirect
                                setDirty(false);
                            } else {
                                // inline rendering by selectively replacing the dirty components in the dom tree of the browser
                                wbackofficeImpl.fireCycleEvent(Window.BEFORE_INLINE_RENDERING);
                                // wich might be set by later commands
                                if (!this.isDirty()) {
                                    wbackofficeImpl.sendCommandTo(CommandFactory.createPrepareClientCommand(null));
                                }
                                // Add the js and css files and related pre init commands
                                Command jscsscom = jsAndCssAdder.extractJSCSSCommand();
                                wbackofficeImpl.sendCommandTo(jscsscom);
                                // dependencies to previously loaded js libs
                                if (this.isDirty()) {
                                    // special case: when the window itself is dirty we require
                                    // a full page refresh in any case
                                    String reRenderUri = buildURIFor(this, timestampID, null);
                                    Command rmrcom = CommandFactory.createParentRedirectTo(reRenderUri);
                                    wbackofficeImpl.sendCommandTo(rmrcom);
                                    this.setDirty(false);
                                } else {
                                    // check for dirty child components in the component tree
                                    if (isDebugLog) {
                                        long durationBeforeHandleDirties = System.currentTimeMillis() - debug_start;
                                        log.debug("Perf-Test: Window durationBeforeHandleDirties=" + durationBeforeHandleDirties);
                                    }
                                    Command co;
                                    try {
                                        co = handleDirties();
                                    } catch (CannotReplaceDOMFragmentException e) {
                                        String reRenderUri = buildURIFor(this, timestampID, null);
                                        co = CommandFactory.createParentRedirectTo(reRenderUri);
                                    }
                                    // update the business path
                                    Command co2 = handleBusinessPath(ureq);
                                    if (isDebugLog) {
                                        long durationAfterHandleDirties = System.currentTimeMillis() - debug_start;
                                        log.debug("Perf-Test: Window durationAfterHandleDirties=" + durationAfterHandleDirties);
                                    }
                                    wbackofficeImpl.fireCycleEvent(AFTER_INLINE_RENDERING);
                                    if (co != null) {
                                        // see method handleDirties for the rare case of co == null even if there are dirty components;
                                        wbackofficeImpl.sendCommandTo(co);
                                    }
                                    if (co2 != null) {
                                        // see method handleDirties for the rare case of co == null even if there are dirty components;
                                        wbackofficeImpl.sendCommandTo(co2);
                                    }
                                }
                            }
                        } else {
                            // not inline
                            if (!validForDispatching) {
                                // not valid: fire oldtimestamp event
                                fireEvent(ureq, OLDTIMESTAMPCALL);
                                throw new AssertException("unreachable code reached");
                            }
                            if (isDebugLog) {
                                long durationBeforeCreateMediaResourceMapper = System.currentTimeMillis() - debug_start;
                                log.debug("Perf-Test: Window durationBeforeCreateMediaResourceMapper=" + durationBeforeCreateMediaResourceMapper);
                            }
                            // not inline, new mediaresource
                            // send it to the parent window (e.g. an excel download, but could also be a 302 redirect)
                            // if the browser has e.g. pdf configured to be displayed inline, we want it to fill the whole area (self window), not the hidden iframe.
                            // the same for 302.
                            // -> send a command which offers a new location for the main window.
                            // create a mapper which maps this mediaresource, and serves it once only
                            MediaResourceMapper extMRM = new MediaResourceMapper();
                            extMRM.setMediaResource(mmr);
                            MapperKey mapperKey = CoreSpringFactory.getImpl(MapperService.class).register(ureq.getUserSession(), extMRM);
                            String resUrl = mapperKey.getUrl() + "/";
                            // e.g. res = /olat/m/10001/
                            Command rmrcom = CommandFactory.createParentRedirectForExternalResource(resUrl);
                            wbackofficeImpl.sendCommandTo(rmrcom);
                            if (isDebugLog) {
                                long durationAfterCreateMediaResourceMapper = System.currentTimeMillis() - debug_start;
                                log.debug("Perf-Test: Window durationAfterCreateMediaResourceMapper=" + durationAfterCreateMediaResourceMapper);
                            }
                        }
                    } else {
                        // not dispatched
                        if (isDebugLog) {
                            long durationBeforeBuildURIFor = System.currentTimeMillis() - debug_start;
                            log.debug("Perf-Test: Window durationBeforeBuildURIFor=" + durationBeforeBuildURIFor);
                            log.debug("Found a valid timestamp but could not dispatch to component: ureq.compid:" + ureq.getComponentID() + " ureq.win-ts:" + ureq.getTimestampID() + " ureq.comp-ts:" + ureq.getComponentTimestamp() + " target.timestamp:" + target.getTimestamp() + " target=" + target);
                        }
                        String reRenderUri = buildURIFor(this, timestampID, null);
                        Command rmrcom = CommandFactory.createParentRedirectTo(reRenderUri);
                        wbackofficeImpl.sendCommandTo(rmrcom);
                    }
                    if (isDebugLog) {
                        long durationBeforeServeResource = System.currentTimeMillis() - debug_start;
                        log.debug("Perf-Test: Window durationBeforeServeResource=" + durationBeforeServeResource);
                    }
                    wbackofficeImpl.pushCommands(ureq, request, response);
                } catch (InvalidRequestParameterException e) {
                    try {
                        response.sendError(HttpServletResponse.SC_BAD_REQUEST);
                    } catch (IOException e1) {
                        log.error("An exception occured while handling the invalid request parameter exception...", e1);
                    }
                } catch (Throwable th) {
                    // create the error window
                    try {
                        log.debug("Error in Window, rollback");
                        DBFactory.getInstance().rollback();
                        ChiefController msgcc = MsgFactory.createMessageChiefController(ureq, th);
                        Window errWindow = msgcc.getWindow();
                        errWindow.setUriPrefix(getUriPrefix());
                        // register window
                        Windows.getWindows(ureq).registerWindow(errWindow);
                        // redirect to the error window
                        String newWinUri = buildRenderOnlyURIFor(errWindow);
                        Command rmrcom = CommandFactory.createParentRedirectTo(newWinUri);
                        wbackofficeImpl.sendCommandTo(rmrcom);
                        MediaResource jsonmr = wbackofficeImpl.extractCommands(request);
                        ServletUtil.serveResource(request, response, jsonmr);
                    } catch (Throwable anotherTh) {
                        log.error("Exception while handling exception!!!!", anotherTh);
                    }
                }
                if (isDebugLog) {
                    long durationDispatchRequest = System.currentTimeMillis() - debug_start;
                    log.debug("Perf-Test: Window return from 1 durationDispatchRequest=" + durationDispatchRequest);
                }
                return;
            }
        }
        // -------------------------
        if (renderOnly || timestampID == null) {
            inline = true;
            validate = true;
            wbackofficeImpl.fireCycleEvent(BEFORE_RENDER_ONLY);
        } else if (validatingCausedRerendering && timestampID.equals("-1")) {
            // the first request after the 302 redirect cause by a component validation
            // -> just rerender, but clear the flag for further async media requests
            validatingCausedRerendering = false;
            inline = true;
            // no need to revalidate right now
            validate = false;
            checkNewWindow = false;
            dispatch = false;
        } else {
            // set), then check for an old timestamp
            if (latestTimestamp != null && !timestampID.equals(latestTimestamp)) {
                // asynchronous media
                if (asyncMediaResponsible == null) {
                    // "open in new window/tab" in the browser).
                    if ((componentID != null && componentID.equals("-1")) || (ureq.getParameter("o_winrndo") != null)) {
                    // just rerender
                    } else {
                        // fxdiff BAKS-7: resume controller
                        if (isDebugLog)
                            log.debug("Removed old timestamp event");
                    // fireEvent(ureq, OLDTIMESTAMPCALL);
                    }
                    // just rerender current window
                    inline = true;
                    // do not increment timestamp so that e.g. url in a iframe remain valid
                    incTimestamp = false;
                } else {
                    // some component will take care of it for the moment, so be it
                    mr = asyncMediaResponsible.getAsyncMediaResource(ureq);
                    if (mr == null) {
                        // indicates inline rendering
                        inline = true;
                        // an inline rendered async link should be
                        checkNewWindow = true;
                        // able to produce a new window
                        validate = true;
                    } else {
                    // serve the resource.
                    // all flags remain at their default value
                    }
                }
            } else {
                // latestTimestamp == null || timestampID.equals(latestTimestamp)
                dispatch = true;
                checkNewWindow = true;
                validate = true;
            }
        }
        // end of simple flagging.
        long dstart = 0;
        if (isDebugLog) {
            dstart = System.currentTimeMillis();
            long syncIntroDiff = dstart - debug_start;
            debugMsg.append("sync_bdisp:").append(syncIntroDiff).append(LOG_SEPARATOR);
        }
        boolean forceReload = false;
        if (dispatch) {
            DispatchResult dispatchResult = doDispatchToComponent(ureq, debugMsg);
            boolean didDispatch = dispatchResult.isDispatch();
            forceReload = dispatchResult.isForceReload();
            incTimestamp = dispatchResult.isIncTimestamp();
            if (isDebugLog) {
                long dstop = System.currentTimeMillis();
                long diff = dstop - dstart;
                debugMsg.append("disp_comp:").append(diff).append(LOG_SEPARATOR);
            }
            if (didDispatch) {
                // the component with the given id was found
                mr = ureq.getDispatchResult().getResultingMediaResource();
                if (mr == null) {
                    inline = true;
                } else {
                    inline = false;
                }
            } else {
                // component with id was not found -> probably asynchronous thread changed flow ->
                // just rerender
                inline = true;
                dispatch = false;
                checkNewWindow = false;
                validate = true;
            }
        }
        if (checkNewWindow) {
            Window resWindow = ureq.getDispatchResult().getResultingWindow();
            if (resWindow != null) {
                // register it first, if not done before
                Windows ws = Windows.getWindows(ureq);
                if (!ws.isRegistered(resWindow)) {
                    resWindow.setUriPrefix(uriPrefix);
                    ws.registerWindow(resWindow);
                }
                // render initial state of new window by redirecting (302) to the new
                // window id. needed for asyncronous data like images loaded
                // todo maybe better delegate window registry to the windowbackoffice?
                URLBuilder ubu = new URLBuilder(uriPrefix, resWindow.getInstanceId(), String.valueOf(resWindow.timestamp));
                StringOutput sout = new StringOutput(30);
                ubu.buildURI(sout, null, null);
                mr = new RedirectMediaResource(sout.toString());
                ServletUtil.serveResource(request, response, mr);
                if (isDebugLog) {
                    long diff = System.currentTimeMillis() - debug_start;
                    debugMsg.append("rdirnw:").append(diff).append(LOG_SEPARATOR);
                    log.debug(debugMsg.toString());
                    long durationDispatchRequest = System.currentTimeMillis() - debug_start;
                    log.debug("Perf-Test: Window return from 2 durationDispatchRequest=" + durationDispatchRequest);
                }
                return;
            }
        }
        if (forceReload) {
            // force RELOAD with a redirect to itself (http redirect because we are in non-Ajax mode)
            String reRenderUri = buildURIFor(this, timestampID, null);
            String url = reRenderUri;
            DispatcherModule.redirectTo(response, url);
        } else if (inline) {
            // do inline rendering.
            ComponentCollection top = getContentPane();
            // the component just got dispatched
            if (validate) {
                // do not validate if a previous validate lead to a
                // redirect; validating makes no sense here
                // long t1 = System.currentTimeMillis();
                ValidatingVisitor vv = new ValidatingVisitor(gsettings, jsAndCssAdder);
                ComponentTraverser ct = new ComponentTraverser(vv, top, false);
                ct.visitAll(ureq);
                wbackofficeImpl.fireCycleEvent(Window.AFTER_VALIDATING);
                ValidationResult vr = vv.getValidationResult();
                String newModUri = vr.getNewModuleURI();
                // ignore the return value since we are just about rendering anyway
                vr.getJsAndCSSAdder().finishAndCheckChange();
                if (newModUri != null) {
                    // send 302 redirect without dispatching, but just rerender
                    // inline.
                    // set window id to cur id, timestamp to current timestamp,
                    // component id to -1 -> indicates rerender
                    String uri = buildURIForRedirect(newModUri);
                    MediaResource mrr = new RedirectMediaResource(uri);
                    // set this only for the first request (the .html request), but clear it afterwards for asyncmedia
                    validatingCausedRerendering = true;
                    ServletUtil.serveResource(request, response, mrr);
                    if (isDebugLog) {
                        long diff = System.currentTimeMillis() - debug_start;
                        debugMsg.append("rdirva:").append(diff).append(LOG_SEPARATOR);
                        log.debug(debugMsg.toString());
                        long durationDispatchRequest = System.currentTimeMillis() - debug_start;
                        log.debug("Perf-Test: Window return form 3 durationDispatchRequest=" + durationDispatchRequest);
                    }
                    return;
                }
            }
            wbackofficeImpl.fireCycleEvent(BEFORE_INLINE_RENDERING);
            StringOutput result;
            synchronized (render_mutex) {
                // TODO state-less
                if (incTimestamp) {
                    timestamp++;
                }
                final String newTimestamp = String.valueOf(timestamp);
                // add the businesscontrol path for bookmarking:
                // each url has a part in it (the so called business path), which, in case of an invalid url or invalidated
                // session, can be used as a bookmark. that is, urls from our framework are bookmarkable, but require some little
                // coding effort: setting an appropriate business path and launching for each controller.
                // note: the businesspath may also be used as a easy (but of course not perfect) back-button-solution:
                // if the timestamp of a request is outdated, simply jump to its bookmarked business control path.
                URLBuilder ubu = new URLBuilder(uriPrefix, getInstanceId(), newTimestamp);
                RenderResult renderResult = new RenderResult();
                // if we have an around-component-interception
                // set the handler for this render cycle
                InterceptHandler interceptHandler = wbackofficeImpl.getInterceptHandler();
                if (interceptHandler != null) {
                    InterceptHandlerInstance dhri = interceptHandler.createInterceptHandlerInstance();
                    renderResult.setInterceptHandlerRenderInstance(dhri);
                }
                Renderer fr = Renderer.getInstance(top, top.getTranslator(), ubu, renderResult, gsettings);
                long rstart = 0;
                if (isDebugLog) {
                    rstart = System.currentTimeMillis();
                }
                result = StringOutputPool.allocStringBuilder(100000);
                fr.render(top, result, null);
                if (isDebugLog) {
                    long rstop = System.currentTimeMillis();
                    long diff = rstop - rstart;
                    debugMsg.append("render:").append(diff).append(LOG_SEPARATOR);
                }
                if (renderResult.getRenderException() != null) {
                    throw new OLATRuntimeException(Window.class, renderResult.getLogMsg(), renderResult.getRenderException());
                }
                // to check HTML by reload
                // System.out.println();
                // System.out.println(result.toString());
                // System.out.println();
                // after rendering we know if some component awaits further async
                // calls
                // like images, so get a handler
                AsyncMediaResponsible amr = renderResult.getAsyncMediaResponsible();
                // if amr == null -> we are not
                setAsyncMediaResponsible(amr);
                // excepting
                // any async calls in the near future...
                latestTimestamp = newTimestamp;
            }
            if (isDebugLog) {
                long diff = System.currentTimeMillis() - debug_start;
                debugMsg.append("inl_comp:").append(diff).append(LOG_SEPARATOR);
            }
            wbackofficeImpl.fireCycleEvent(AFTER_INLINE_RENDERING);
            ServletUtil.serveStringResource(response, result);
            StringOutputPool.free(result);
            if (isDebugLog) {
                long diff = System.currentTimeMillis() - debug_start;
                debugMsg.append("inl_serve:").append(diff).append(LOG_SEPARATOR);
            }
        }
    // else serve mediaresource, but postpone serving to when lock has been released,
    // otherwise e.g. a large download blocks the window, so that the user cannot click until the download is finished
    }
    if (!inline) {
        // it can be an async media resource, or a resulting mediaresource (image, an excel download, a 302 redirect, and so on.)
        if (isDebugLog) {
            long diff = System.currentTimeMillis() - debug_start;
            debugMsg.append("mr_comp:").append(diff).append(LOG_SEPARATOR);
        }
        ServletUtil.serveResource(request, response, mr);
        if (isDebugLog) {
            long diff = System.currentTimeMillis() - debug_start;
            debugMsg.append("mr_serve:").append(diff).append(LOG_SEPARATOR);
        }
    }
    if (isDebugLog) {
        // log the collected data now
        log.info(debugMsg.toString());
        long durationDispatchRequest = System.currentTimeMillis() - debug_start;
        log.debug("Perf-Test: Window durationDispatchRequest=" + durationDispatchRequest);
    }
}
Also used : ComponentTraverser(org.olat.core.util.component.ComponentTraverser) ArrayList(java.util.ArrayList) RenderResult(org.olat.core.gui.render.RenderResult) StringOutput(org.olat.core.gui.render.StringOutput) Windows(org.olat.core.gui.Windows) ValidationResult(org.olat.core.gui.render.ValidationResult) InterceptHandlerInstance(org.olat.core.gui.render.intercept.InterceptHandlerInstance) HttpServletRequest(javax.servlet.http.HttpServletRequest) InvalidRequestParameterException(org.olat.core.gui.components.form.flexible.impl.InvalidRequestParameterException) RedirectMediaResource(org.olat.core.gui.media.RedirectMediaResource) MediaResource(org.olat.core.gui.media.MediaResource) RedirectMediaResource(org.olat.core.gui.media.RedirectMediaResource) InterceptHandler(org.olat.core.gui.render.intercept.InterceptHandler) AssertException(org.olat.core.logging.AssertException) MediaResourceMapper(org.olat.core.gui.control.winmgr.MediaResourceMapper) HttpServletResponse(javax.servlet.http.HttpServletResponse) GlobalSettings(org.olat.core.gui.GlobalSettings) IOException(java.io.IOException) ChiefController(org.olat.core.gui.control.ChiefController) URLBuilder(org.olat.core.gui.render.URLBuilder) AsyncMediaResponsible(org.olat.core.gui.media.AsyncMediaResponsible) JSCommand(org.olat.core.gui.control.winmgr.JSCommand) Command(org.olat.core.gui.control.winmgr.Command) OLATRuntimeException(org.olat.core.logging.OLATRuntimeException) Renderer(org.olat.core.gui.render.Renderer) MapperKey(org.olat.core.dispatcher.mapper.manager.MapperKey)

Example 2 with ValidationResult

use of org.olat.core.gui.render.ValidationResult in project OpenOLAT by OpenOLAT.

the class GuiStackNiceImpl method pushCallout.

@Override
public void pushCallout(Component content, String targetId, CalloutSettings settings) {
    // wrap the component into a modal foreground dialog with alpha-blended-background
    final Panel guiMsgPlace = new Panel("guimsgplace_for_callout");
    VelocityContainer inset = new VelocityContainer("inset", VELOCITY_ROOT + "/callout.html", null, null) {

        public void validate(UserRequest ureq, ValidationResult vr) {
            super.validate(ureq, vr);
            // just before rendering, we need to tell the windowbackoffice that we are a favorite for accepting gui-messages.
            // the windowbackoffice doesn't know about guimessages, it is only a container that keeps them for one render cycle
            List<ZIndexWrapper> zindexed = wbo.getGuiMessages();
            zindexed.add(new ZIndexWrapper(guiMsgPlace, 10));
        }
    };
    inset.put("cont", content);
    inset.put("guimsgplace", guiMsgPlace);
    inset.contextPut("guimsgtarget", targetId);
    int zindex = 900 + (modalLayers * 100) + 5;
    inset.contextPut("zindexoverlay", zindex + 1);
    inset.contextPut("zindexshim", zindex);
    inset.contextPut("zindexarea", zindex + 5);
    inset.contextPut("zindexextwindows", zindex + 50);
    if (settings != null) {
        inset.contextPut("arrow", settings.isArrow());
        inset.contextPut("orientation", settings.getOrientation().name());
    } else {
        inset.contextPut("arrow", Boolean.TRUE);
        inset.contextPut("orientation", CalloutOrientation.bottom.name());
    }
    modalPanel.pushContent(inset);
    modalLayers++;
}
Also used : SimpleStackedPanel(org.olat.core.gui.components.panel.SimpleStackedPanel) LayeredPanel(org.olat.core.gui.components.panel.LayeredPanel) Panel(org.olat.core.gui.components.panel.Panel) StackedPanel(org.olat.core.gui.components.panel.StackedPanel) ZIndexWrapper(org.olat.core.gui.control.util.ZIndexWrapper) ValidationResult(org.olat.core.gui.render.ValidationResult) UserRequest(org.olat.core.gui.UserRequest) VelocityContainer(org.olat.core.gui.components.velocity.VelocityContainer)

Example 3 with ValidationResult

use of org.olat.core.gui.render.ValidationResult in project OpenOLAT by OpenOLAT.

the class GuiStackNiceImpl method pushModalDialog.

/**
 * @param title the title of the modal dialog, can be null
 * @param content the component to push as modal dialog
 */
@Override
public void pushModalDialog(Component content) {
    wbo.sendCommandTo(new ScrollTopCommand());
    // wrap the component into a modal foreground dialog with alpha-blended-background
    final Panel guiMsgPlace = new Panel("guimsgplace_for_modaldialog");
    VelocityContainer inset = new VelocityContainer("inset", VELOCITY_ROOT + "/modalDialog.html", null, null) {

        @Override
        public void validate(UserRequest ureq, ValidationResult vr) {
            super.validate(ureq, vr);
            // just before rendering, we need to tell the windowbackoffice that we are a favorite for accepting gui-messages.
            // the windowbackoffice doesn't know about guimessages, it is only a container that keeps them for one render cycle
            List<ZIndexWrapper> zindexed = wbo.getGuiMessages();
            zindexed.add(new ZIndexWrapper(guiMsgPlace, 10));
        }
    };
    inset.put("cont", content);
    inset.put("guimsgplace", guiMsgPlace);
    int zindex = 900 + (modalLayers * 100) + 5;
    inset.contextPut("zindexoverlay", zindex + 1);
    inset.contextPut("zindexshim", zindex);
    inset.contextPut("zindexarea", zindex + 5);
    inset.contextPut("zindexextwindows", zindex + 50);
    modalPanel.pushContent(inset);
    // the links in the panel cannot be clicked because of the alpha-blended background over it, but if user chooses own css style ->
    // FIXME:fj:b panel.setEnabled(false) causes effects if there is an image component in the panel -> the component is not dispatched
    // and thus renders inline and wastes the timestamp.
    // Needed:solution (a) a flag (a bit of the mode indicator of the urlbuilder can be used) to indicate that a request always needs to be delivered even
    // if the component or a parent is not enabled.
    // alternative solution(b): wrap the imagecomponent into a controller and use a mapper
    // alternative solution(c): introduce a flag to the component to say "dispatch always", even if a parent component is not enabled
    // 
    // - solution a would be easy, but would allow for forced dispatching by manipulating the url's flag.
    // for e.g. a Link button ("make me admin") that is disabled this is a security breach.
    // - solution b needs some wrapping, the advantage (for images) would be that they are cached by the browser if requested more than once
    // within a controller
    // - solution c is a safe and easy way to allow dispatching (only in case a mediaresource is returned as a result of the dispatching) even
    // if parent elements are not enabled
    // proposal: fix for 5.1.0 with solution c; for 5.0.1 the uncommenting of the line below is okay.
    // if (modalLayers == 0) panel.setEnabled(false);
    modalLayers++;
}
Also used : SimpleStackedPanel(org.olat.core.gui.components.panel.SimpleStackedPanel) LayeredPanel(org.olat.core.gui.components.panel.LayeredPanel) Panel(org.olat.core.gui.components.panel.Panel) StackedPanel(org.olat.core.gui.components.panel.StackedPanel) ZIndexWrapper(org.olat.core.gui.control.util.ZIndexWrapper) ValidationResult(org.olat.core.gui.render.ValidationResult) ScrollTopCommand(org.olat.core.gui.control.winmgr.ScrollTopCommand) UserRequest(org.olat.core.gui.UserRequest) VelocityContainer(org.olat.core.gui.components.velocity.VelocityContainer)

Example 4 with ValidationResult

use of org.olat.core.gui.render.ValidationResult in project openolat by klemens.

the class ValidatingVisitor method dispatchRequest.

/**
 * @param ureq
 * @param renderOnly
 */
public void dispatchRequest(UserRequest ureq, boolean renderOnly) {
    final HttpServletRequest request = ureq.getHttpReq();
    final HttpServletResponse response = ureq.getHttpResp();
    final String timestampID = ureq.getTimestampID() == null ? "1" : ureq.getTimestampID();
    final String componentID = ureq.getComponentID();
    // case windowId timestamp componentId
    // --------------------------------------------
    // 
    // 1 null     null null -> if (!renderOnly)-> error else doRenderOnly<br>
    // 2 invalid n/a n/a -> not handled here, but in Windows
    // 3 valid valid valid -> dispatch and further handling (check for new
    // window and res. media resource
    // 4 valid valid invalid -> no dispatch (silently) -> rerender (no res.
    // media res and no new window check needed)
    // 5 valid invalid n/a -> asyncRes == null? "doNotUseReload" :
    // getAsyncRes==null? renderInline : serve resource
    // 6 valid null n/a -> no timestamp -> just rerender inline
    // defs:
    // rerender: component validation and inline rendering
    // case 1:
    // simply rerender, no dispatching
    // case 3:
    // dispatch, check for new Window
    // case 5:
    // check newWindow, serve resource/renderInline
    // order:
    // 1. check for timestamp: valid: case 3,4 ; invalid -> case 5, or -1 ->
    // indicator of just rendering and no revalidating needed
    // 2. dispatch to component, unless flag renderOnly in method sig., or
    // inlineRerender set (timestamps indicates)
    boolean inline = false;
    boolean validate = false;
    boolean checkNewWindow = false;
    boolean dispatch = false;
    // increase the timestamp, but not if we are in loadperformancemode: then all url's have
    // to work independant of previous ones -> when no increase: timestamp is always the same here
    // !GUIInterna.isLoadPerformanceMode();
    boolean incTimestamp = false;
    MediaResource mr = null;
    final boolean isDebugLog = log.isDebug();
    StringBuilder debugMsg = null;
    long debug_start = 0;
    if (isDebugLog) {
        debug_start = System.currentTimeMillis();
        debugMsg = new StringBuilder("::winst:");
    }
    synchronized (this) {
        // o_clusterOK by:fj
        // sync dispatching per window to avoid rendering problems
        // when user repeateadly presses reload, and also to distribute bandwidth more
        // evenly.
        // postcondition: each controller's events are called by one gui-thread at a time only.
        GlobalSettings gsettings = wbackofficeImpl.getGlobalSettings();
        boolean bgEnab = gsettings.getAjaxFlags().isIframePostEnabled();
        // -------------------------
        if (bgEnab && (ureq.getMode() & 1) == 1) {
            // first check on "ajax-command-was-not-in-hidden-iframe hint" -> if so, rerender the current window
            if (ureq.getParameter("o_win_jsontop") != null) {
                renderOnly = true;
            } else {
                try {
                    // if target in background (m = mode , 0.bit set)
                    // 1.) do dispatch to component if component timestamp ok
                    // REVIEW:PB: this will be the code allowing back forward navigation
                    // --> boolean inlineAfterBackForward = false;
                    // FIXME:fj:b avoid double traversal to find component again below
                    String s_compID = ureq.getComponentID();
                    if (s_compID == null) {
                        throw new AssertException("no component id found in req:" + ureq.toString());
                    }
                    // throws NumberFormatException if not a number
                    // long compID = Long.parseLong(s_compID);
                    List<Component> foundPath = new ArrayList<Component>(10);
                    Component target = ComponentHelper.findDescendantOrSelfByID(getContentPane(), s_compID, foundPath);
                    final boolean validForDispatching;
                    if (target != null) {
                        // the target was found
                        String cTimest = target.getTimestamp();
                        String urlCTimest = ureq.getComponentTimestamp();
                        validForDispatching = cTimest.equals(urlCTimest);
                        if (!validForDispatching && isDebugLog) {
                            log.debug("Invalid timestamp: ureq.compid:" + ureq.getComponentID() + " ureq.win-ts:" + ureq.getTimestampID() + " ureq.comp-ts:" + ureq.getComponentTimestamp() + " target.timestamp:" + cTimest + " target=" + target);
                        }
                    } else {
                        // this can happen e.g. on quick double-clicks, so that the dom-replacement-command never reaches the client.
                        if (isDebugLog)
                            log.debug("no ajax dispatch: component not found (target=null)");
                        validForDispatching = false;
                        // check no response call
                        String noResponseMarker = ureq.getParameter("no-response");
                        if ("oo-no-response".equals(noResponseMarker)) {
                            return;
                        }
                    }
                    // 2.) collect dirty components (top-down, return from sub-path when first dirty node met)
                    // 3.) return to sender...
                    boolean didDispatch = false;
                    boolean forceReload = false;
                    if (validForDispatching) {
                        DispatchResult dispatchResult = doDispatchToComponent(ureq, null);
                        didDispatch = dispatchResult.isDispatch();
                        incTimestamp = dispatchResult.isIncTimestamp();
                        forceReload = dispatchResult.isForceReload();
                        if (isDebugLog) {
                            long durationAfterDoDispatchToComponent = System.currentTimeMillis() - debug_start;
                            log.debug("Perf-Test: Window durationAfterDoDispatchToComponent=" + durationAfterDoDispatchToComponent);
                        }
                    }
                    MediaResource mmr = null;
                    // -----> if (didDispatch || inlineAfterBackForward) {
                    if (forceReload) {
                        // force RELOAD with a redirect to itself
                        String reRenderUri = buildURIFor(this, timestampID, null);
                        Command rmrcom = CommandFactory.createParentRedirectTo(reRenderUri);
                        wbackofficeImpl.sendCommandTo(rmrcom);
                    } else if (didDispatch || !validForDispatching) {
                        if (validForDispatching) {
                            Window ww = ureq.getDispatchResult().getResultingWindow();
                            if (ww != null) {
                                // FIXME:fj:c think about bodyOnLoad -> win.open(new window url)
                                throw new AssertException("a link in ajax mode should never result in a new window");
                            }
                            mmr = ureq.getDispatchResult().getResultingMediaResource();
                            if (mmr == null) {
                                inline = true;
                            } else {
                                inline = false;
                            }
                        }
                        // -----> if (inline) {
                        if (inline || !validForDispatching) {
                            if (!validForDispatching) {
                                // not valid: fire oldtimestamp event and later rerender
                                fireEvent(ureq, OLDTIMESTAMPCALL);
                            }
                            ComponentCollection top = getContentPane();
                            // always validate here, since we are never in the case of just rerendering (we are in the bg iframe)
                            ValidatingVisitor vv = new ValidatingVisitor(gsettings, jsAndCssAdder);
                            ComponentTraverser ct = new ComponentTraverser(vv, top, false);
                            if (isDebugLog) {
                                long durationBeforeVisitAll = System.currentTimeMillis() - debug_start;
                                log.debug("Perf-Test: Window durationBeforeVisitAll=" + durationBeforeVisitAll);
                            }
                            ct.visitAll(ureq);
                            if (isDebugLog) {
                                long durationAfterVisitAll = System.currentTimeMillis() - debug_start;
                                log.debug("Perf-Test: Window durationAfterVisitAll=" + durationAfterVisitAll);
                            }
                            wbackofficeImpl.fireCycleEvent(Window.AFTER_VALIDATING);
                            ValidationResult vr = vv.getValidationResult();
                            boolean newJsCssAdded = vr.getJsAndCSSAdder().finishAndCheckChange();
                            String newModUri = vr.getNewModuleURI();
                            // !validForDispatching ||
                            if (newJsCssAdded || newModUri != null) {
                                // send 302 redirect so the ajax-iframe's parent window gets reloaded to either include new js/css or to prepare the address bar
                                // url for asynchronous requests when delivering inline-contentpackaging.
                                // set window id to cur id, timestamp to current timestamp,
                                // component id to -1 -> indicates rerender
                                // newModUri == null in case "just" new css or js libs have been added
                                String uri = buildURIForRedirect(newModUri);
                                // set this only for the first request (the .html request), but clear it afterwards for asyncmedia
                                validatingCausedRerendering = true;
                                Command rmrcom = CommandFactory.createParentRedirectTo(uri);
                                wbackofficeImpl.sendCommandTo(rmrcom);
                                // OLAT-4563: so the timestamp is not incremented, we do only a redirect
                                setDirty(false);
                            } else {
                                // inline rendering by selectively replacing the dirty components in the dom tree of the browser
                                wbackofficeImpl.fireCycleEvent(Window.BEFORE_INLINE_RENDERING);
                                // wich might be set by later commands
                                if (!this.isDirty()) {
                                    wbackofficeImpl.sendCommandTo(CommandFactory.createPrepareClientCommand(null));
                                }
                                // Add the js and css files and related pre init commands
                                Command jscsscom = jsAndCssAdder.extractJSCSSCommand();
                                wbackofficeImpl.sendCommandTo(jscsscom);
                                // dependencies to previously loaded js libs
                                if (this.isDirty()) {
                                    // special case: when the window itself is dirty we require
                                    // a full page refresh in any case
                                    String reRenderUri = buildURIFor(this, timestampID, null);
                                    Command rmrcom = CommandFactory.createParentRedirectTo(reRenderUri);
                                    wbackofficeImpl.sendCommandTo(rmrcom);
                                    this.setDirty(false);
                                } else {
                                    // check for dirty child components in the component tree
                                    if (isDebugLog) {
                                        long durationBeforeHandleDirties = System.currentTimeMillis() - debug_start;
                                        log.debug("Perf-Test: Window durationBeforeHandleDirties=" + durationBeforeHandleDirties);
                                    }
                                    Command co;
                                    try {
                                        co = handleDirties();
                                    } catch (CannotReplaceDOMFragmentException e) {
                                        String reRenderUri = buildURIFor(this, timestampID, null);
                                        co = CommandFactory.createParentRedirectTo(reRenderUri);
                                    }
                                    // update the business path
                                    Command co2 = handleBusinessPath(ureq);
                                    if (isDebugLog) {
                                        long durationAfterHandleDirties = System.currentTimeMillis() - debug_start;
                                        log.debug("Perf-Test: Window durationAfterHandleDirties=" + durationAfterHandleDirties);
                                    }
                                    wbackofficeImpl.fireCycleEvent(AFTER_INLINE_RENDERING);
                                    if (co != null) {
                                        // see method handleDirties for the rare case of co == null even if there are dirty components;
                                        wbackofficeImpl.sendCommandTo(co);
                                    }
                                    if (co2 != null) {
                                        // see method handleDirties for the rare case of co == null even if there are dirty components;
                                        wbackofficeImpl.sendCommandTo(co2);
                                    }
                                }
                            }
                        } else {
                            // not inline
                            if (!validForDispatching) {
                                // not valid: fire oldtimestamp event
                                fireEvent(ureq, OLDTIMESTAMPCALL);
                                throw new AssertException("unreachable code reached");
                            }
                            if (isDebugLog) {
                                long durationBeforeCreateMediaResourceMapper = System.currentTimeMillis() - debug_start;
                                log.debug("Perf-Test: Window durationBeforeCreateMediaResourceMapper=" + durationBeforeCreateMediaResourceMapper);
                            }
                            // not inline, new mediaresource
                            // send it to the parent window (e.g. an excel download, but could also be a 302 redirect)
                            // if the browser has e.g. pdf configured to be displayed inline, we want it to fill the whole area (self window), not the hidden iframe.
                            // the same for 302.
                            // -> send a command which offers a new location for the main window.
                            // create a mapper which maps this mediaresource, and serves it once only
                            MediaResourceMapper extMRM = new MediaResourceMapper();
                            extMRM.setMediaResource(mmr);
                            MapperKey mapperKey = CoreSpringFactory.getImpl(MapperService.class).register(ureq.getUserSession(), extMRM);
                            String resUrl = mapperKey.getUrl() + "/";
                            // e.g. res = /olat/m/10001/
                            Command rmrcom = CommandFactory.createParentRedirectForExternalResource(resUrl);
                            wbackofficeImpl.sendCommandTo(rmrcom);
                            if (isDebugLog) {
                                long durationAfterCreateMediaResourceMapper = System.currentTimeMillis() - debug_start;
                                log.debug("Perf-Test: Window durationAfterCreateMediaResourceMapper=" + durationAfterCreateMediaResourceMapper);
                            }
                        }
                    } else {
                        // not dispatched
                        if (isDebugLog) {
                            long durationBeforeBuildURIFor = System.currentTimeMillis() - debug_start;
                            log.debug("Perf-Test: Window durationBeforeBuildURIFor=" + durationBeforeBuildURIFor);
                            log.debug("Found a valid timestamp but could not dispatch to component: ureq.compid:" + ureq.getComponentID() + " ureq.win-ts:" + ureq.getTimestampID() + " ureq.comp-ts:" + ureq.getComponentTimestamp() + " target.timestamp:" + target.getTimestamp() + " target=" + target);
                        }
                        String reRenderUri = buildURIFor(this, timestampID, null);
                        Command rmrcom = CommandFactory.createParentRedirectTo(reRenderUri);
                        wbackofficeImpl.sendCommandTo(rmrcom);
                    }
                    if (isDebugLog) {
                        long durationBeforeServeResource = System.currentTimeMillis() - debug_start;
                        log.debug("Perf-Test: Window durationBeforeServeResource=" + durationBeforeServeResource);
                    }
                    wbackofficeImpl.pushCommands(ureq, request, response);
                } catch (InvalidRequestParameterException e) {
                    try {
                        response.sendError(HttpServletResponse.SC_BAD_REQUEST);
                    } catch (IOException e1) {
                        log.error("An exception occured while handling the invalid request parameter exception...", e1);
                    }
                } catch (Throwable th) {
                    // create the error window
                    try {
                        log.debug("Error in Window, rollback");
                        DBFactory.getInstance().rollback();
                        ChiefController msgcc = MsgFactory.createMessageChiefController(ureq, th);
                        Window errWindow = msgcc.getWindow();
                        errWindow.setUriPrefix(getUriPrefix());
                        // register window
                        Windows.getWindows(ureq).registerWindow(errWindow);
                        // redirect to the error window
                        String newWinUri = buildRenderOnlyURIFor(errWindow);
                        Command rmrcom = CommandFactory.createParentRedirectTo(newWinUri);
                        wbackofficeImpl.sendCommandTo(rmrcom);
                        MediaResource jsonmr = wbackofficeImpl.extractCommands(request);
                        ServletUtil.serveResource(request, response, jsonmr);
                    } catch (Throwable anotherTh) {
                        log.error("Exception while handling exception!!!!", anotherTh);
                    }
                }
                if (isDebugLog) {
                    long durationDispatchRequest = System.currentTimeMillis() - debug_start;
                    log.debug("Perf-Test: Window return from 1 durationDispatchRequest=" + durationDispatchRequest);
                }
                return;
            }
        }
        // -------------------------
        if (renderOnly || timestampID == null) {
            inline = true;
            validate = true;
            wbackofficeImpl.fireCycleEvent(BEFORE_RENDER_ONLY);
        } else if (validatingCausedRerendering && timestampID.equals("-1")) {
            // the first request after the 302 redirect cause by a component validation
            // -> just rerender, but clear the flag for further async media requests
            validatingCausedRerendering = false;
            inline = true;
            // no need to revalidate right now
            validate = false;
            checkNewWindow = false;
            dispatch = false;
        } else {
            // set), then check for an old timestamp
            if (latestTimestamp != null && !timestampID.equals(latestTimestamp)) {
                // asynchronous media
                if (asyncMediaResponsible == null) {
                    // "open in new window/tab" in the browser).
                    if ((componentID != null && componentID.equals("-1")) || (ureq.getParameter("o_winrndo") != null)) {
                    // just rerender
                    } else {
                        // fxdiff BAKS-7: resume controller
                        if (isDebugLog)
                            log.debug("Removed old timestamp event");
                    // fireEvent(ureq, OLDTIMESTAMPCALL);
                    }
                    // just rerender current window
                    inline = true;
                    // do not increment timestamp so that e.g. url in a iframe remain valid
                    incTimestamp = false;
                } else {
                    // some component will take care of it for the moment, so be it
                    mr = asyncMediaResponsible.getAsyncMediaResource(ureq);
                    if (mr == null) {
                        // indicates inline rendering
                        inline = true;
                        // an inline rendered async link should be
                        checkNewWindow = true;
                        // able to produce a new window
                        validate = true;
                    } else {
                    // serve the resource.
                    // all flags remain at their default value
                    }
                }
            } else {
                // latestTimestamp == null || timestampID.equals(latestTimestamp)
                dispatch = true;
                checkNewWindow = true;
                validate = true;
            }
        }
        // end of simple flagging.
        long dstart = 0;
        if (isDebugLog) {
            dstart = System.currentTimeMillis();
            long syncIntroDiff = dstart - debug_start;
            debugMsg.append("sync_bdisp:").append(syncIntroDiff).append(LOG_SEPARATOR);
        }
        boolean forceReload = false;
        if (dispatch) {
            DispatchResult dispatchResult = doDispatchToComponent(ureq, debugMsg);
            boolean didDispatch = dispatchResult.isDispatch();
            forceReload = dispatchResult.isForceReload();
            incTimestamp = dispatchResult.isIncTimestamp();
            if (isDebugLog) {
                long dstop = System.currentTimeMillis();
                long diff = dstop - dstart;
                debugMsg.append("disp_comp:").append(diff).append(LOG_SEPARATOR);
            }
            if (didDispatch) {
                // the component with the given id was found
                mr = ureq.getDispatchResult().getResultingMediaResource();
                if (mr == null) {
                    inline = true;
                } else {
                    inline = false;
                }
            } else {
                // component with id was not found -> probably asynchronous thread changed flow ->
                // just rerender
                inline = true;
                dispatch = false;
                checkNewWindow = false;
                validate = true;
            }
        }
        if (checkNewWindow) {
            Window resWindow = ureq.getDispatchResult().getResultingWindow();
            if (resWindow != null) {
                // register it first, if not done before
                Windows ws = Windows.getWindows(ureq);
                if (!ws.isRegistered(resWindow)) {
                    resWindow.setUriPrefix(uriPrefix);
                    ws.registerWindow(resWindow);
                }
                // render initial state of new window by redirecting (302) to the new
                // window id. needed for asyncronous data like images loaded
                // todo maybe better delegate window registry to the windowbackoffice?
                URLBuilder ubu = new URLBuilder(uriPrefix, resWindow.getInstanceId(), String.valueOf(resWindow.timestamp));
                StringOutput sout = new StringOutput(30);
                ubu.buildURI(sout, null, null);
                mr = new RedirectMediaResource(sout.toString());
                ServletUtil.serveResource(request, response, mr);
                if (isDebugLog) {
                    long diff = System.currentTimeMillis() - debug_start;
                    debugMsg.append("rdirnw:").append(diff).append(LOG_SEPARATOR);
                    log.debug(debugMsg.toString());
                    long durationDispatchRequest = System.currentTimeMillis() - debug_start;
                    log.debug("Perf-Test: Window return from 2 durationDispatchRequest=" + durationDispatchRequest);
                }
                return;
            }
        }
        if (forceReload) {
            // force RELOAD with a redirect to itself (http redirect because we are in non-Ajax mode)
            String reRenderUri = buildURIFor(this, timestampID, null);
            String url = reRenderUri;
            DispatcherModule.redirectTo(response, url);
        } else if (inline) {
            // do inline rendering.
            ComponentCollection top = getContentPane();
            // the component just got dispatched
            if (validate) {
                // do not validate if a previous validate lead to a
                // redirect; validating makes no sense here
                // long t1 = System.currentTimeMillis();
                ValidatingVisitor vv = new ValidatingVisitor(gsettings, jsAndCssAdder);
                ComponentTraverser ct = new ComponentTraverser(vv, top, false);
                ct.visitAll(ureq);
                wbackofficeImpl.fireCycleEvent(Window.AFTER_VALIDATING);
                ValidationResult vr = vv.getValidationResult();
                String newModUri = vr.getNewModuleURI();
                // ignore the return value since we are just about rendering anyway
                vr.getJsAndCSSAdder().finishAndCheckChange();
                if (newModUri != null) {
                    // send 302 redirect without dispatching, but just rerender
                    // inline.
                    // set window id to cur id, timestamp to current timestamp,
                    // component id to -1 -> indicates rerender
                    String uri = buildURIForRedirect(newModUri);
                    MediaResource mrr = new RedirectMediaResource(uri);
                    // set this only for the first request (the .html request), but clear it afterwards for asyncmedia
                    validatingCausedRerendering = true;
                    ServletUtil.serveResource(request, response, mrr);
                    if (isDebugLog) {
                        long diff = System.currentTimeMillis() - debug_start;
                        debugMsg.append("rdirva:").append(diff).append(LOG_SEPARATOR);
                        log.debug(debugMsg.toString());
                        long durationDispatchRequest = System.currentTimeMillis() - debug_start;
                        log.debug("Perf-Test: Window return form 3 durationDispatchRequest=" + durationDispatchRequest);
                    }
                    return;
                }
            }
            wbackofficeImpl.fireCycleEvent(BEFORE_INLINE_RENDERING);
            StringOutput result;
            synchronized (render_mutex) {
                // TODO state-less
                if (incTimestamp) {
                    timestamp++;
                }
                final String newTimestamp = String.valueOf(timestamp);
                // add the businesscontrol path for bookmarking:
                // each url has a part in it (the so called business path), which, in case of an invalid url or invalidated
                // session, can be used as a bookmark. that is, urls from our framework are bookmarkable, but require some little
                // coding effort: setting an appropriate business path and launching for each controller.
                // note: the businesspath may also be used as a easy (but of course not perfect) back-button-solution:
                // if the timestamp of a request is outdated, simply jump to its bookmarked business control path.
                URLBuilder ubu = new URLBuilder(uriPrefix, getInstanceId(), newTimestamp);
                RenderResult renderResult = new RenderResult();
                // if we have an around-component-interception
                // set the handler for this render cycle
                InterceptHandler interceptHandler = wbackofficeImpl.getInterceptHandler();
                if (interceptHandler != null) {
                    InterceptHandlerInstance dhri = interceptHandler.createInterceptHandlerInstance();
                    renderResult.setInterceptHandlerRenderInstance(dhri);
                }
                Renderer fr = Renderer.getInstance(top, top.getTranslator(), ubu, renderResult, gsettings);
                long rstart = 0;
                if (isDebugLog) {
                    rstart = System.currentTimeMillis();
                }
                result = StringOutputPool.allocStringBuilder(100000);
                fr.render(top, result, null);
                if (isDebugLog) {
                    long rstop = System.currentTimeMillis();
                    long diff = rstop - rstart;
                    debugMsg.append("render:").append(diff).append(LOG_SEPARATOR);
                }
                if (renderResult.getRenderException() != null) {
                    throw new OLATRuntimeException(Window.class, renderResult.getLogMsg(), renderResult.getRenderException());
                }
                // to check HTML by reload
                // System.out.println();
                // System.out.println(result.toString());
                // System.out.println();
                // after rendering we know if some component awaits further async
                // calls
                // like images, so get a handler
                AsyncMediaResponsible amr = renderResult.getAsyncMediaResponsible();
                // if amr == null -> we are not
                setAsyncMediaResponsible(amr);
                // excepting
                // any async calls in the near future...
                latestTimestamp = newTimestamp;
            }
            if (isDebugLog) {
                long diff = System.currentTimeMillis() - debug_start;
                debugMsg.append("inl_comp:").append(diff).append(LOG_SEPARATOR);
            }
            wbackofficeImpl.fireCycleEvent(AFTER_INLINE_RENDERING);
            ServletUtil.serveStringResource(response, result);
            StringOutputPool.free(result);
            if (isDebugLog) {
                long diff = System.currentTimeMillis() - debug_start;
                debugMsg.append("inl_serve:").append(diff).append(LOG_SEPARATOR);
            }
        }
    // else serve mediaresource, but postpone serving to when lock has been released,
    // otherwise e.g. a large download blocks the window, so that the user cannot click until the download is finished
    }
    if (!inline) {
        // it can be an async media resource, or a resulting mediaresource (image, an excel download, a 302 redirect, and so on.)
        if (isDebugLog) {
            long diff = System.currentTimeMillis() - debug_start;
            debugMsg.append("mr_comp:").append(diff).append(LOG_SEPARATOR);
        }
        ServletUtil.serveResource(request, response, mr);
        if (isDebugLog) {
            long diff = System.currentTimeMillis() - debug_start;
            debugMsg.append("mr_serve:").append(diff).append(LOG_SEPARATOR);
        }
    }
    if (isDebugLog) {
        // log the collected data now
        log.info(debugMsg.toString());
        long durationDispatchRequest = System.currentTimeMillis() - debug_start;
        log.debug("Perf-Test: Window durationDispatchRequest=" + durationDispatchRequest);
    }
}
Also used : ComponentTraverser(org.olat.core.util.component.ComponentTraverser) ArrayList(java.util.ArrayList) RenderResult(org.olat.core.gui.render.RenderResult) StringOutput(org.olat.core.gui.render.StringOutput) Windows(org.olat.core.gui.Windows) ValidationResult(org.olat.core.gui.render.ValidationResult) InterceptHandlerInstance(org.olat.core.gui.render.intercept.InterceptHandlerInstance) HttpServletRequest(javax.servlet.http.HttpServletRequest) InvalidRequestParameterException(org.olat.core.gui.components.form.flexible.impl.InvalidRequestParameterException) RedirectMediaResource(org.olat.core.gui.media.RedirectMediaResource) MediaResource(org.olat.core.gui.media.MediaResource) RedirectMediaResource(org.olat.core.gui.media.RedirectMediaResource) InterceptHandler(org.olat.core.gui.render.intercept.InterceptHandler) AssertException(org.olat.core.logging.AssertException) MediaResourceMapper(org.olat.core.gui.control.winmgr.MediaResourceMapper) HttpServletResponse(javax.servlet.http.HttpServletResponse) GlobalSettings(org.olat.core.gui.GlobalSettings) IOException(java.io.IOException) ChiefController(org.olat.core.gui.control.ChiefController) URLBuilder(org.olat.core.gui.render.URLBuilder) AsyncMediaResponsible(org.olat.core.gui.media.AsyncMediaResponsible) JSCommand(org.olat.core.gui.control.winmgr.JSCommand) Command(org.olat.core.gui.control.winmgr.Command) OLATRuntimeException(org.olat.core.logging.OLATRuntimeException) Renderer(org.olat.core.gui.render.Renderer) MapperKey(org.olat.core.dispatcher.mapper.manager.MapperKey)

Example 5 with ValidationResult

use of org.olat.core.gui.render.ValidationResult in project openolat by klemens.

the class GuiStackNiceImpl method pushModalDialog.

/**
 * @param title the title of the modal dialog, can be null
 * @param content the component to push as modal dialog
 */
@Override
public void pushModalDialog(Component content) {
    wbo.sendCommandTo(new ScrollTopCommand());
    // wrap the component into a modal foreground dialog with alpha-blended-background
    final Panel guiMsgPlace = new Panel("guimsgplace_for_modaldialog");
    VelocityContainer inset = new VelocityContainer("inset", VELOCITY_ROOT + "/modalDialog.html", null, null) {

        @Override
        public void validate(UserRequest ureq, ValidationResult vr) {
            super.validate(ureq, vr);
            // just before rendering, we need to tell the windowbackoffice that we are a favorite for accepting gui-messages.
            // the windowbackoffice doesn't know about guimessages, it is only a container that keeps them for one render cycle
            List<ZIndexWrapper> zindexed = wbo.getGuiMessages();
            zindexed.add(new ZIndexWrapper(guiMsgPlace, 10));
        }
    };
    inset.put("cont", content);
    inset.put("guimsgplace", guiMsgPlace);
    int zindex = 900 + (modalLayers * 100) + 5;
    inset.contextPut("zindexoverlay", zindex + 1);
    inset.contextPut("zindexshim", zindex);
    inset.contextPut("zindexarea", zindex + 5);
    inset.contextPut("zindexextwindows", zindex + 50);
    modalPanel.pushContent(inset);
    // the links in the panel cannot be clicked because of the alpha-blended background over it, but if user chooses own css style ->
    // FIXME:fj:b panel.setEnabled(false) causes effects if there is an image component in the panel -> the component is not dispatched
    // and thus renders inline and wastes the timestamp.
    // Needed:solution (a) a flag (a bit of the mode indicator of the urlbuilder can be used) to indicate that a request always needs to be delivered even
    // if the component or a parent is not enabled.
    // alternative solution(b): wrap the imagecomponent into a controller and use a mapper
    // alternative solution(c): introduce a flag to the component to say "dispatch always", even if a parent component is not enabled
    // 
    // - solution a would be easy, but would allow for forced dispatching by manipulating the url's flag.
    // for e.g. a Link button ("make me admin") that is disabled this is a security breach.
    // - solution b needs some wrapping, the advantage (for images) would be that they are cached by the browser if requested more than once
    // within a controller
    // - solution c is a safe and easy way to allow dispatching (only in case a mediaresource is returned as a result of the dispatching) even
    // if parent elements are not enabled
    // proposal: fix for 5.1.0 with solution c; for 5.0.1 the uncommenting of the line below is okay.
    // if (modalLayers == 0) panel.setEnabled(false);
    modalLayers++;
}
Also used : SimpleStackedPanel(org.olat.core.gui.components.panel.SimpleStackedPanel) LayeredPanel(org.olat.core.gui.components.panel.LayeredPanel) Panel(org.olat.core.gui.components.panel.Panel) StackedPanel(org.olat.core.gui.components.panel.StackedPanel) ZIndexWrapper(org.olat.core.gui.control.util.ZIndexWrapper) ValidationResult(org.olat.core.gui.render.ValidationResult) ScrollTopCommand(org.olat.core.gui.control.winmgr.ScrollTopCommand) UserRequest(org.olat.core.gui.UserRequest) VelocityContainer(org.olat.core.gui.components.velocity.VelocityContainer)

Aggregations

ValidationResult (org.olat.core.gui.render.ValidationResult)6 UserRequest (org.olat.core.gui.UserRequest)4 LayeredPanel (org.olat.core.gui.components.panel.LayeredPanel)4 Panel (org.olat.core.gui.components.panel.Panel)4 SimpleStackedPanel (org.olat.core.gui.components.panel.SimpleStackedPanel)4 StackedPanel (org.olat.core.gui.components.panel.StackedPanel)4 VelocityContainer (org.olat.core.gui.components.velocity.VelocityContainer)4 ZIndexWrapper (org.olat.core.gui.control.util.ZIndexWrapper)4 IOException (java.io.IOException)2 ArrayList (java.util.ArrayList)2 HttpServletRequest (javax.servlet.http.HttpServletRequest)2 HttpServletResponse (javax.servlet.http.HttpServletResponse)2 MapperKey (org.olat.core.dispatcher.mapper.manager.MapperKey)2 GlobalSettings (org.olat.core.gui.GlobalSettings)2 Windows (org.olat.core.gui.Windows)2 InvalidRequestParameterException (org.olat.core.gui.components.form.flexible.impl.InvalidRequestParameterException)2 ChiefController (org.olat.core.gui.control.ChiefController)2 Command (org.olat.core.gui.control.winmgr.Command)2 JSCommand (org.olat.core.gui.control.winmgr.JSCommand)2 MediaResourceMapper (org.olat.core.gui.control.winmgr.MediaResourceMapper)2