Example #1
0
  /**
   * 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);
      }
    }
  }
Example #2
0
  /**
   * 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;
  }
Example #3
0
  /**
   * 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);
  }
Example #4
0
  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);
    }
  }
Example #5
0
 private ClassWebResource getClassWebResource() {
   return WebManager.getWebManager(getServletContext()).getClassWebResource();
 }
Example #6
0
  // 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());
  }