/** * Outputs the HTML tags of the given component to the given writer. * * @param path the request path. If null, the servlet path is assumed. * @param out the output (never null). * @param richlet the richlet to run. If you have only one component to show and no need process * it under an execution, you could use {@link #render(javax.servlet.ServletContext, * javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, * org.zkoss.zk.ui.Component, String, java.io.Writer)} instead. * @since 5.0.5 */ public static final void render( ServletContext ctx, HttpServletRequest request, HttpServletResponse response, Richlet richlet, String path, Writer out) throws ServletException, IOException { if (path == null) path = Https.getThisServletPath(request); WebManager webman = WebManager.getWebManagerIfAny(ctx); if (webman == null) { final String ATTR = "org.zkoss.zkplus.embed.updateURI"; String updateURI = Library.getProperty(ATTR); if (updateURI == null) updateURI = "/zkau"; else updateURI = Utils.checkUpdateURI(updateURI, ATTR); webman = new WebManager(ctx, updateURI); } final Session sess = WebManager.getSession(ctx, request); final WebApp wapp = sess.getWebApp(); final WebAppCtrl wappc = (WebAppCtrl) wapp; final Object old = I18Ns.setup(sess, request, response, wapp.getConfiguration().getResponseCharset()); Execution exec = null; try { final Desktop desktop = webman.getDesktop(sess, request, response, path, true); if (desktop == null) // forward or redirect return; final RequestInfo ri = new RequestInfoImpl(wapp, sess, desktop, request, PageDefinitions.getLocator(wapp, path)); sess.setAttribute(Attributes.GAE_FIX, new Integer(0)); ((SessionCtrl) sess).notifyClientRequest(true); final UiFactory uf = wappc.getUiFactory(); final Page page = WebManager.newPage(uf, ri, richlet, response, path); exec = new ExecutionImpl(ctx, request, response, desktop, page); exec.setAttribute(Attributes.PAGE_REDRAW_CONTROL, "page"); exec.setAttribute(Attributes.PAGE_RENDERER, new PageRenderer(exec)); wappc.getUiEngine().execNewPage(exec, richlet, page, out); // no need to set device type here, since UiEngine will do it later } finally { I18Ns.cleanup(request, old); if (exec != null) { exec.removeAttribute(Attributes.PAGE_REDRAW_CONTROL); exec.removeAttribute(Attributes.PAGE_RENDERER); } } }
/** * Recovers the desktop if possible. It is called if {@link #getDesktop} returns null. * * <p>The default implementation will look for any failover manager ({@link FailoverManager}) is * registered, and forward the invocation to it if found. * * @return the recovered desktop, or null if failed to recover * @since 5.0.3 */ protected Desktop recoverDesktop( Session sess, HttpServletRequest request, HttpServletResponse response, WebAppCtrl wappc, String dtid) { final FailoverManager failover = wappc.getFailoverManager(); if (failover != null) { Desktop desktop = null; final ServletContext ctx = getServletContext(); try { if (failover.isRecoverable(sess, dtid)) { desktop = WebManager.getWebManager(ctx).getDesktop(sess, request, response, null, true); if (desktop == null) // forward or redirect throw new IllegalStateException("sendRediect or forward not allowed in recovering"); wappc .getUiEngine() .execRecover(new ExecutionImpl(ctx, request, response, desktop, null), failover); return desktop; // success } } catch (Throwable ex) { log.error("Unable to recover " + dtid, ex); if (desktop != null) ((DesktopCtrl) desktop).recoverDidFail(ex); } } return null; }
/** * Process asynchronous update requests from the client. * * @since 3.0.0 */ protected void process(Session sess, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { final String errClient = request.getHeader("ZK-Error-Report"); if (errClient != null) if (log.debugable()) log.debug("Error found at client: " + errClient + "\n" + Servlets.getDetail(request)); // parse desktop ID final WebApp wapp = sess.getWebApp(); final WebAppCtrl wappc = (WebAppCtrl) wapp; final AuDecoder audec = getAuDecoder(wapp); final String dtid = audec.getDesktopId(request); if (dtid == null) { // Bug 1929139: incomplete request (IE only) if (log.debugable()) { final String msg = "Incomplete request\n" + Servlets.getDetail(request); log.debug(msg); } response.sendError(467, "Incomplete request"); return; } Desktop desktop = getDesktop(sess, dtid); if (desktop == null) { final String cmdId = audec.getFirstCommand(request); if (!"rmDesktop".equals(cmdId)) desktop = recoverDesktop(sess, request, response, wappc, dtid); if (desktop == null) { response.setIntHeader("ZK-Error", response.SC_GONE); // denote timeout sessionTimeout(request, response, wapp, dtid); return; } } WebManager.setDesktop(request, desktop); // reason: a new page might be created (such as include) final String sid = request.getHeader("ZK-SID"); if (sid != null) // Some client might not have ZK-SID response.setHeader("ZK-SID", sid); // parse commands final Configuration config = wapp.getConfiguration(); final List aureqs; boolean keepAlive = false; try { final boolean timerKeepAlive = config.isTimerKeepAlive(); aureqs = audec.decode(request, desktop); for (Iterator it = aureqs.iterator(); it.hasNext(); ) { final String cmdId = ((AuRequest) it.next()).getCommand(); keepAlive = !(!timerKeepAlive && Events.ON_TIMER.equals(cmdId)) && !"dummy".equals(cmdId); // dummy is used for PollingServerPush for piggyback if (keepAlive) break; // done } } catch (Throwable ex) { log.warningBriefly(ex); responseError(request, response, Exceptions.getMessage(ex)); return; } if (aureqs.isEmpty()) { final String errmsg = "Illegal request: cmd required"; log.debug(errmsg); responseError(request, response, errmsg); return; } ((SessionCtrl) sess).notifyClientRequest(keepAlive); // if (log.debugable()) log.debug("AU request: "+aureqs); final DesktopCtrl desktopCtrl = (DesktopCtrl) desktop; final Execution exec = new ExecutionImpl(getServletContext(), request, response, desktop, null); if (sid != null) ((ExecutionCtrl) exec).setRequestId(sid); final AuWriter out = AuWriters.newInstance(); out.setCompress(_compress); out.open( request, response, desktop.getDevice().isSupported(Device.RESEND) ? getProcessTimeout(config.getResendDelay()) : 0); // Note: getResendDelay() might return nonpositive try { wappc.getUiEngine().execUpdate(exec, aureqs, out); } catch (RequestOutOfSequenceException ex) { log.warning(ex.getMessage()); response.setHeader("ZK-SID", sid); response.setIntHeader("ZK-Error", AuResponse.SC_OUT_OF_SEQUENCE); } out.close(request, response); }
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { final String pi = Https.getThisPathInfo(request); // if (log.finerable()) log.finer("Path info: "+pi); final ServletContext ctx = getServletContext(); final boolean withpi = pi != null && pi.length() != 0; if (withpi && pi.startsWith(ClassWebResource.PATH_PREFIX)) { // use HttpSession to avoid loading SerializableSession in GAE // and don't retrieve session if possible final ClassWebResource cwr = getClassWebResource(); final HttpSession hsess = shallSession(cwr, pi) ? request.getSession(false) : null; Object oldsess = null; if (hsess == null) { oldsess = SessionsCtrl.getRawCurrent(); SessionsCtrl.setCurrent(new SessionResolverImpl(ctx, request)); // it might be created later } WebApp wapp; Session sess; final Object old = hsess != null ? (wapp = WebManager.getWebAppIfAny(ctx)) != null && (sess = SessionsCtrl.getSession(wapp, hsess)) != null ? I18Ns.setup(sess, request, response, "UTF-8") : I18Ns.setup(hsess, request, response, "UTF-8") : Charsets.setup(null, request, response, "UTF-8"); try { cwr.service(request, response, pi.substring(ClassWebResource.PATH_PREFIX.length())); } finally { if (hsess != null) I18Ns.cleanup(request, old); else { Charsets.cleanup(request, old); SessionsCtrl.setRawCurrent(oldsess); } } return; // done } final Session sess = WebManager.getSession(ctx, request, false); if (withpi) { final AuExtension aue = getAuExtensionByPath(pi); if (aue == null) { response.sendError(response.SC_NOT_FOUND); log.debug("Unknown path info: " + pi); return; } Object oldsess = null; if (sess == null) { oldsess = SessionsCtrl.getRawCurrent(); SessionsCtrl.setCurrent(new SessionResolverImpl(ctx, request)); // it might be created later } final Object old = sess != null ? I18Ns.setup(sess, request, response, "UTF-8") : Charsets.setup(null, request, response, "UTF-8"); try { aue.service(request, response, pi); } finally { if (sess != null) I18Ns.cleanup(request, old); else { Charsets.cleanup(request, old); SessionsCtrl.setRawCurrent(oldsess); } } return; // done } // AU if (sess == null) { response.setIntHeader("ZK-Error", response.SC_GONE); // denote timeout // Bug 1849088: rmDesktop might be sent after invalidate // Bug 1859776: need send response to client for redirect or others final WebApp wapp = WebManager.getWebAppIfAny(ctx); final String dtid = getAuDecoder(wapp).getDesktopId(request); if (dtid != null) sessionTimeout(request, response, wapp, dtid); return; } // Feature 3285074 add no-cache for security risk. response.setHeader("Pragma", "no-cache"); response.setHeader("Cache-Control", "no-cache"); response.setHeader("Cache-Control", "no-store"); response.setHeader("Expires", "-1"); final Object old = I18Ns.setup(sess, request, response, "UTF-8"); try { process(sess, request, response); } finally { I18Ns.cleanup(request, old); } }
private ClassWebResource getClassWebResource() { return WebManager.getWebManager(getServletContext()).getClassWebResource(); }
// Servlet// public void init() throws ServletException { final ServletConfig config = getServletConfig(); final ServletContext ctx = getServletContext(); ctx.setAttribute(ATTR_UPDATE_SERVLET, this); final WebManager webman = WebManager.getWebManager(ctx); String param = config.getInitParameter("compress"); _compress = param == null || param.length() == 0 || "true".equals(param); if (!_compress) webman.getClassWebResource().setCompress(null); // disable all // Copies au extensions defined before DHtmlUpdateServlet is started final WebApp wapp = webman.getWebApp(); final Map aues = (Map) wapp.getAttribute(ATTR_AU_PROCESSORS); if (aues != null) { for (Iterator it = aues.entrySet().iterator(); it.hasNext(); ) { final Map.Entry me = (Map.Entry) it.next(); addAuExtension((String) me.getKey(), (AuExtension) me.getValue()); } wapp.removeAttribute(ATTR_AU_PROCESSORS); } // ZK 5: extension defined in init-param has the higher priority for (int j = 0; ; ++j) { param = config.getInitParameter("extension" + j); if (param == null) { param = config.getInitParameter("processor" + j); // backward compatible if (param == null) break; } final int k = param.indexOf('='); if (k < 0) { log.warning("Ignore init-param: illegal format, " + param); continue; } final String prefix = param.substring(0, k).trim(); final String clsnm = param.substring(k + 1).trim(); try { addAuExtension(prefix, (AuExtension) Classes.newInstanceByThread(clsnm)); } catch (ClassNotFoundException ex) { log.warning("Ignore init-param: class not found, " + clsnm); } catch (ClassCastException ex) { log.warning("Ignore: " + clsnm + " not implement " + AuExtension.class); } catch (Throwable ex) { log.warning("Ignore init-param: failed to add an AU extension, " + param, ex); } } if (getAuExtension("/upload") == null) { try { addAuExtension("/upload", new AuUploader()); } catch (Throwable ex) { final String msg = "Make sure commons-fileupload.jar is installed."; log.warningBriefly("Failed to configure fileupload. " + msg, ex); // still add /upload to generate exception when fileupload is used addAuExtension( "/upload", new AuExtension() { public void init(DHtmlUpdateServlet servlet) {} public void destroy() {} public void service( HttpServletRequest request, HttpServletResponse response, String pi) throws ServletException, IOException { if (Sessions.getCurrent(false) != null) throw new ServletException("Failed to upload. " + msg); } }); } } if (getAuExtension("/view") == null) addAuExtension("/view", new AuDynaMediar()); }