Search in sources :

Example 1 with Windows

use of org.olat.core.gui.Windows in project OpenOLAT by OpenOLAT.

the class AuthenticatedDispatcher method processValidDispatchURI.

private void processValidDispatchURI(UserRequest ureq, UserSession usess, HttpServletRequest request, HttpServletResponse response) {
    Windows ws = Windows.getWindows(ureq);
    Window window = ws.getWindow(ureq);
    if (window == null) {
        // probably a
        if (usess.isSavedSession() && !usess.getHistoryStack().isEmpty()) {
            redirectToDefaultDispatcher(request, response);
        } else {
            DispatcherModule.sendNotFound(request.getRequestURI(), response);
        }
    } else {
        window.dispatchRequest(ureq);
    }
}
Also used : Window(org.olat.core.gui.components.Window) Windows(org.olat.core.gui.Windows)

Example 2 with Windows

use of org.olat.core.gui.Windows 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 3 with Windows

use of org.olat.core.gui.Windows 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 4 with Windows

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

the class AuthenticatedDispatcher method processValidDispatchURI.

private void processValidDispatchURI(UserRequest ureq, UserSession usess, HttpServletRequest request, HttpServletResponse response) {
    Windows ws = Windows.getWindows(ureq);
    Window window = ws.getWindow(ureq);
    if (window == null) {
        // probably a
        if (usess.isSavedSession() && !usess.getHistoryStack().isEmpty()) {
            redirectToDefaultDispatcher(request, response);
        } else {
            DispatcherModule.sendNotFound(request.getRequestURI(), response);
        }
    } else {
        window.dispatchRequest(ureq);
    }
}
Also used : Window(org.olat.core.gui.components.Window) Windows(org.olat.core.gui.Windows)

Example 5 with Windows

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

the class DMZDispatcher method execute.

/**
 * Main method called by OpenOLATServlet. This processess all requests for
 * users who are not authenticated.
 *
 * @param request
 * @param response
 * @param uriPrefix
 */
@Override
public void execute(HttpServletRequest request, HttpServletResponse response) {
    if (rejectRequest(request, response)) {
        return;
    }
    UserRequest ureq = null;
    String uriPrefix = DispatcherModule.getLegacyUriPrefix(request);
    try {
        // upon creation URL is checked for
        ureq = new UserRequestImpl(uriPrefix, request, response);
    } catch (NumberFormatException nfe) {
        // a 404 message must be shown -> e.g. robots correct their links.
        if (log.isDebug()) {
            log.debug("Bad Request " + request.getPathInfo());
        }
        DispatcherModule.sendBadRequest(request.getPathInfo(), response);
        return;
    }
    try {
        // find out about which subdispatcher is meant
        // e.g. got here because of /dmz/...
        // maybe something like /dmz/registration/
        // 
        // add the context path to align with uriPrefix e.g. /olat/dmz/
        String pathInfo = request.getContextPath() + request.getPathInfo();
        ChiefControllerCreator subPathccc = null;
        // if /olat/dmz/
        boolean dmzOnly = pathInfo.equals(uriPrefix);
        if (!dmzOnly) {
            int sl = pathInfo.indexOf('/', uriPrefix.length());
            String sub;
            if (sl > 1) {
                // e.g. something like /registration/ or /pwchange/
                sub = pathInfo.substring(uriPrefix.length() - 1, sl + 1);
            } else {
                // e.g. something like /info.html from (/dmz/info.html)
                sub = pathInfo;
            }
            // chief controller creator for sub path, e.g.
            subPathccc = dmzServicesByPath.get(sub);
            if (subPathccc != null) {
                UserSession usess = ureq.getUserSession();
                Windows ws = Windows.getWindows(usess);
                synchronized (ws) {
                    // o_clusterOK by:fj per user session
                    ChiefController occ = subPathccc.createChiefController(ureq);
                    Window window = occ.getWindow();
                    window.setUriPrefix(uriPrefix);
                    ws.registerWindow(window);
                    window.dispatchRequest(ureq, true);
                    return;
                }
            }
        }
        // else a /olat/dmz/ request
        UserSession usess = ureq.getUserSession();
        Windows ws = Windows.getWindows(usess);
        // and make it useless under heavily load or 2 concurrent requests
        synchronized (usess) {
            // o_clusterOK by:fj per user session
            Window window;
            boolean windowHere = ws.isExisting(uriPrefix, ureq.getWindowID());
            boolean validDispatchUri = ureq.isValidDispatchURI();
            if (validDispatchUri && !windowHere) {
                // probably valid framework link from previous user && new Session(no window):
                // when a previous user logged off, and 30min later (when the httpsession is invalidated), the next user clicks e.g. on
                // the log-in link in the -same- browser window ->
                // -> there is no window -> create a new one
                window = null;
                CoreSpringFactory.getImpl(UserSessionManager.class).signOffAndClear(usess);
                usess.setLocale(LocaleNegotiator.getPreferedLocale(ureq));
                // update locale infos
                I18nManager.updateLocaleInfoToThread(usess);
                // request new windows since it is a new usersession, the old one was purged
                ws = Windows.getWindows(usess);
            } else if (validDispatchUri) {
                window = ws.getWindow(ureq);
            } else if (dmzOnly) {
                // e.g. /dmz/ -> start screen, clear previous session data
                window = null;
                CoreSpringFactory.getImpl(UserSessionManager.class).signOffAndClear(usess);
                usess.setLocale(LocaleNegotiator.getPreferedLocale(ureq));
                // update locale infos
                I18nManager.updateLocaleInfoToThread(usess);
                OAuthLoginModule oauthModule = CoreSpringFactory.getImpl(OAuthLoginModule.class);
                if (canRedirectConfigurableOAuth(request, response, oauthModule)) {
                    return;
                } else if (canRedirectOAuth(request, oauthModule)) {
                    OAuthSPI oauthSpi = oauthModule.getRootProvider();
                    HttpSession session = request.getSession();
                    OAuthResource.redirect(oauthSpi, response, session);
                    return;
                }
                // request new windows since it is a new usersession, the old one was purged
                ws = Windows.getWindows(usess);
            } else {
                response.sendError(HttpServletResponse.SC_BAD_REQUEST);
                return;
            }
            if (window == null) {
                // no window found, -> start a new WorkFlow/Controller and obtain the window
                // main controller which also implements the windowcontroller for pagestatus and modal dialogs
                Object wSettings = usess.getEntry(WINDOW_SETTINGS);
                ChiefController occ = chiefControllerCreator.createChiefController(ureq);
                window = occ.getWindow();
                window.setUriPrefix(uriPrefix);
                ws.registerWindow(window);
                String businessPath = (String) usess.removeEntryFromNonClearedStore(DMZDISPATCHER_BUSINESSPATH);
                if (businessPath != null) {
                    List<ContextEntry> ces = BusinessControlFactory.getInstance().createCEListFromString(businessPath);
                    window.getDTabs().activate(ureq, null, ces);
                }
                // apply the settings forward
                usess.putEntryInNonClearedStore(WINDOW_SETTINGS, wSettings);
            }
            window.dispatchRequest(ureq);
        }
    } 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) {
        try {
            ChiefController msgcc = MsgFactory.createMessageChiefController(ureq, th);
            // the controller's window must be failsafe also
            msgcc.getWindow().dispatchRequest(ureq, true);
        // do not dispatch (render only), since this is a new Window created as
        // a result of another window's click.
        } catch (Throwable t) {
            log.error("An exception occured while handling the exception...", t);
        }
    }
}
Also used : Window(org.olat.core.gui.components.Window) OAuthLoginModule(org.olat.login.oauth.OAuthLoginModule) HttpSession(javax.servlet.http.HttpSession) Windows(org.olat.core.gui.Windows) ChiefController(org.olat.core.gui.control.ChiefController) IOException(java.io.IOException) ContextEntry(org.olat.core.id.context.ContextEntry) UserSessionManager(org.olat.core.util.session.UserSessionManager) InvalidRequestParameterException(org.olat.core.gui.components.form.flexible.impl.InvalidRequestParameterException) ChiefControllerCreator(org.olat.core.gui.control.ChiefControllerCreator) UserSession(org.olat.core.util.UserSession) OAuthSPI(org.olat.login.oauth.OAuthSPI) UserRequest(org.olat.core.gui.UserRequest) UserRequestImpl(org.olat.core.gui.UserRequestImpl)

Aggregations

Windows (org.olat.core.gui.Windows)10 Window (org.olat.core.gui.components.Window)8 UserSession (org.olat.core.util.UserSession)6 IOException (java.io.IOException)4 UserRequest (org.olat.core.gui.UserRequest)4 UserRequestImpl (org.olat.core.gui.UserRequestImpl)4 InvalidRequestParameterException (org.olat.core.gui.components.form.flexible.impl.InvalidRequestParameterException)4 ChiefController (org.olat.core.gui.control.ChiefController)4 Identity (org.olat.core.id.Identity)4 UserSessionManager (org.olat.core.util.session.UserSessionManager)4 UnsupportedEncodingException (java.io.UnsupportedEncodingException)2 ArrayList (java.util.ArrayList)2 Locale (java.util.Locale)2 HttpServletRequest (javax.servlet.http.HttpServletRequest)2 HttpServletResponse (javax.servlet.http.HttpServletResponse)2 HttpSession (javax.servlet.http.HttpSession)2 MapperKey (org.olat.core.dispatcher.mapper.manager.MapperKey)2 GlobalSettings (org.olat.core.gui.GlobalSettings)2 ChiefControllerCreator (org.olat.core.gui.control.ChiefControllerCreator)2 Command (org.olat.core.gui.control.winmgr.Command)2