예제 #1
0
  /** @param wapp the Web application (or null if not available yet) */
  private void sessionTimeout(
      HttpServletRequest request, HttpServletResponse response, WebApp wapp, String dtid)
      throws ServletException, IOException {
    final String sid = request.getHeader("ZK-SID");
    if (sid != null) response.setHeader("ZK-SID", sid);

    final AuWriter out = AuWriters.newInstance().open(request, response, 0);

    if (!getAuDecoder(wapp).isIgnorable(request, wapp)) {
      final String deviceType = getDeviceType(request);
      URIInfo ui =
          wapp != null ? (URIInfo) wapp.getConfiguration().getTimeoutURI(deviceType) : null;
      String uri = ui != null ? ui.uri : null;
      out.write(new AuConfirmClose(null)); // Bug: B50-3147382
      final AuResponse resp;
      if (uri != null) {
        if (uri.length() != 0) uri = Encodes.encodeURL(getServletContext(), request, response, uri);
        resp = new AuSendRedirect(uri, null);
      } else {
        String msg = wapp.getConfiguration().getTimeoutMessage(deviceType);
        if (msg != null && msg.startsWith("label:")) {
          final String key;
          msg = Labels.getLabel(key = msg.substring(6), new Object[] {dtid});
          if (msg == null) log.warning("Label not found, " + key);
        }
        if (msg == null) msg = Messages.get(MZk.UPDATE_OBSOLETE_PAGE, dtid);
        resp = new AuObsolete(dtid, msg);
      }
      out.write(resp);
    }

    out.close(request, response);
  }
예제 #2
0
 /** Returns whether to generate JS files that is easy to debug. */
 public boolean isDebugJS() {
   if (_debugJS == null) {
     final WebApp wapp = getWebApp();
     if (wapp == null) return true; // zk lighter
     _debugJS = Boolean.valueOf(wapp.getConfiguration().isDebugJS());
   }
   return _debugJS.booleanValue();
 }
예제 #3
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);
      }
    }
  }
예제 #4
0
  /**
   * Adds an AU extension and associates it with the specified prefix, even before {@link
   * DHtmlUpdateServlet} is started.
   *
   * <p>Unlike {@link #addAuExtension(String, AuExtension)}, it can be called even if the update
   * servlet is not loaded yet ({@link #getUpdateServlet} returns null).
   *
   * <p>If there was an AU extension associated with the same name, the the old AU extension will be
   * replaced.
   *
   * @since 5.0.0
   */
  public static final AuExtension addAuExtension(WebApp wapp, String prefix, AuExtension extension)
      throws ServletException {
    DHtmlUpdateServlet upsv = DHtmlUpdateServlet.getUpdateServlet(wapp);
    if (upsv == null) {
      synchronized (DHtmlUpdateServlet.class) {
        upsv = DHtmlUpdateServlet.getUpdateServlet(wapp);
        if (upsv == null) {
          checkAuExtension(prefix, extension);
          Map aues = (Map) wapp.getAttribute(ATTR_AU_PROCESSORS);
          if (aues == null) wapp.setAttribute(ATTR_AU_PROCESSORS, aues = new HashMap(4));
          return (AuExtension) aues.put(prefix, extension);
        }
      }
    }

    return upsv.addAuExtension(prefix, extension);
  }
예제 #5
0
  /**
   * Generates the special JavaScript code, such as the application's name. It shall be called,
   * before generating "zkmx(" and "zkx(".
   *
   * @since 5.0.6
   */
  public static final String outSpecialJS(Desktop desktop) {
    final StringBuffer sb = new StringBuffer();

    // output application name
    String oldnm = (String) desktop.getAttribute(ATTR_APPNM);
    if (oldnm == null) oldnm = "ZK";
    final String appnm = desktop.getWebApp().getAppName();
    if (!oldnm.equals(appnm)) {
      sb.append("zk.appName='");
      Strings.escape(sb, appnm, Strings.ESCAPE_JAVASCRIPT).append("';");
      desktop.setAttribute(ATTR_APPNM, appnm);
    }

    // output zktheme cookie
    String oldthemenm = (String) desktop.getAttribute(ATTR_THEMENM);
    if (oldthemenm == null) oldthemenm = "";
    final Object request = desktop.getExecution().getNativeRequest();
    String themenm = "";
    if (request instanceof HttpServletRequest) {
      themenm = ThemeFns.getThemeResolver().getTheme((HttpServletRequest) request);
    }
    if (!oldthemenm.equals(themenm)) {
      sb.append("zk.themeName='");
      Strings.escape(sb, themenm, Strings.ESCAPE_JAVASCRIPT).append("';");
      desktop.setAttribute(ATTR_THEMENM, themenm);
    }

    // output ZK ICON
    final Session sess = Sessions.getCurrent();
    if (sess != null) {
      WebApp wapp = desktop.getWebApp();
      if (wapp == null
          || "CE".equals(WebApps.getEdition())
          || wapp.getAttribute("org.zkoss.zk.ui.notice") != null) {
        final PI pi = (PI) sess.getAttribute(ATTR_PI);
        boolean show = pi == null;
        if (show) sess.setAttribute(ATTR_PI, new PI());
        else show = pi.show();
        if (show) sb.append("zk.pi=1;");
      }
    }
    return sb.toString();
  }
예제 #6
0
 /**
  * Returns the AU extension that is associated the specified prefix.
  *
  * @since 5.0.0
  */
 public static final AuExtension getAuExtension(WebApp wapp, String prefix) {
   DHtmlUpdateServlet upsv = DHtmlUpdateServlet.getUpdateServlet(wapp);
   if (upsv == null) {
     synchronized (DHtmlUpdateServlet.class) {
       upsv = DHtmlUpdateServlet.getUpdateServlet(wapp);
       if (upsv == null) {
         Map aues = (Map) wapp.getAttribute(ATTR_AU_PROCESSORS);
         return aues != null ? (AuExtension) aues.get(prefix) : null;
       }
     }
   }
   return upsv.getAuExtension(prefix);
 }
예제 #7
0
  /**
   * Returns a list of {@link StyleSheet} that shall be generated to the client for the specified
   * execution.
   *
   * @param exec the execution (never null)
   * @param wapp the Web application. If null, exec.getDesktop().getWebApp() is used. So you have to
   *     specify it if the execution is not associated with desktop (a fake execution, such as
   *     JSP/DSP).
   * @param deviceType the device type, such as ajax. If null, exec.getDesktop().getDeviceType() is
   *     used. So you have to specify it if the execution is not associated with desktop (a fake
   *     execution).
   */
  public static final List<StyleSheet> getStyleSheets(
      Execution exec, WebApp wapp, String deviceType) {
    if (wapp == null) wapp = exec.getDesktop().getWebApp();
    if (deviceType == null) deviceType = exec.getDesktop().getDeviceType();

    final Configuration config = wapp.getConfiguration();
    final Set<String> disabled = config.getDisabledThemeURIs();
    final List<StyleSheet> sses = new LinkedList<StyleSheet>(); // a list of StyleSheet
    for (LanguageDefinition langdef : LanguageDefinition.getByDeviceType(deviceType)) {
      for (StyleSheet ss : langdef.getStyleSheets()) {
        if (!disabled.contains(ss.getHref())) sses.add(ss);
      }
    }

    // Process configuration
    final ThemeProvider themeProvider = config.getThemeProvider();
    if (themeProvider != null) {
      final List<Object> orgss = new LinkedList<Object>();
      for (StyleSheet ss : sses) {
        final String href = ss.getHref();
        if (href != null && href.length() > 0)
          orgss.add(ss.getMedia() != null ? ss : href); // we don't support getContent
      }

      final String[] hrefs = config.getThemeURIs();
      for (int j = 0; j < hrefs.length; ++j) orgss.add(hrefs[j]);

      sses.clear();
      final Collection<?> res = themeProvider.getThemeURIs(exec, orgss);
      if (res != null) {
        for (Object re : res) {
          sses.add(
              re instanceof StyleSheet ? (StyleSheet) re : new StyleSheet((String) re, "text/css"));
        }
      }
    } else {
      final String[] hrefs = config.getThemeURIs();
      for (int j = 0; j < hrefs.length; ++j) sses.add(new StyleSheet(hrefs[j], "text/css"));
    }
    return sses;
  }
예제 #8
0
  /**
   * Returns HTML tags to include all JavaScript files and codes that are required when loading a
   * ZUML page (never null).
   *
   * <p>FUTURE CONSIDERATION: we might generate the inclusion on demand instead of all at once.
   *
   * @param exec the execution (never null)
   * @param wapp the Web application. If null, exec.getDesktop().getWebApp() is used. So you have to
   *     specify it if the execution is not associated with desktop (a fake execution, such as
   *     JSP/DSP).
   * @param deviceType the device type, such as ajax. If null, exec.getDesktop().getDeviceType() is
   *     used. So you have to specify it if the execution is not associated with desktop (a fake
   *     execution).
   */
  public static final String outLangJavaScripts(Execution exec, WebApp wapp, String deviceType) {
    if (exec.isAsyncUpdate(null) || exec.getAttribute(ATTR_LANG_JS_GENED) != null)
      return ""; // nothing to generate
    exec.setAttribute(ATTR_LANG_JS_GENED, Boolean.TRUE);

    final Desktop desktop = exec.getDesktop();
    if (wapp == null) wapp = desktop.getWebApp();
    if (deviceType == null) deviceType = desktop != null ? desktop.getDeviceType() : "ajax";

    final StringBuffer sb = new StringBuffer(1536);

    final Set<JavaScript> jses = new LinkedHashSet<JavaScript>(32);
    for (LanguageDefinition langdef : LanguageDefinition.getByDeviceType(deviceType))
      jses.addAll(langdef.getJavaScripts());
    for (JavaScript js : jses) append(sb, js);

    sb.append("\n<!-- ZK ").append(wapp.getVersion());
    if (WebApps.getFeature("ee")) sb.append(" EE");
    else if (WebApps.getFeature("pe")) sb.append(" PE");
    sb.append(' ').append(wapp.getBuild());
    Object o = wapp.getAttribute("org.zkoss.zk.ui.notice");
    if (o != null) sb.append(o);
    sb.append(" -->\n");

    int tmout = 0;
    final Boolean autoTimeout = getAutomaticTimeout(desktop);
    if (autoTimeout != null
        ? autoTimeout.booleanValue()
        : wapp.getConfiguration().isAutomaticTimeout(deviceType)) {
      if (desktop != null) {
        tmout = desktop.getSession().getMaxInactiveInterval();
      } else {
        Object req = exec.getNativeRequest();
        if (req instanceof HttpServletRequest) {
          final HttpSession hsess = ((HttpServletRequest) req).getSession(false);
          if (hsess != null) {
            final Session sess = SessionsCtrl.getSession(wapp, hsess);
            if (sess != null) {
              tmout = sess.getMaxInactiveInterval();
            } else {
              // try configuration first since HttpSession's timeout is set
              // when ZK Session is created (so it is not set yet)
              // Note: no need to setMaxInactiveInternval here since it will
              // be set later or not useful at the end
              tmout = wapp.getConfiguration().getSessionMaxInactiveInterval();
              if (tmout <= 0) // system default
              tmout = hsess.getMaxInactiveInterval();
            }
          } else tmout = wapp.getConfiguration().getSessionMaxInactiveInterval();
        }
      }
      if (tmout > 0) { // unit: seconds
        int extra = tmout / 8;
        tmout += extra > 60 ? 60 : extra < 5 ? 5 : extra;
        // Add extra seconds to ensure it is really timeout
      }
    }

    final boolean
        keepDesktop =
            exec.getAttribute(Attributes.NO_CACHE) == null
                && !"page".equals(ExecutionsCtrl.getPageRedrawControl(exec)),
        groupingAllowed = isGroupingAllowed(desktop);
    final String progressboxPos =
        org.zkoss.lang.Library.getProperty("org.zkoss.zul.progressbox.position", "");
    if (tmout > 0 || keepDesktop || progressboxPos.length() > 0 || !groupingAllowed) {
      sb.append("<script class=\"z-runonce\" type=\"text/javascript\">\nzkopt({");

      if (keepDesktop) sb.append("kd:1,");
      if (!groupingAllowed) sb.append("gd:1,");
      if (tmout > 0) sb.append("to:").append(tmout).append(',');
      if (progressboxPos.length() > 0) sb.append("ppos:'").append(progressboxPos).append('\'');

      if (sb.charAt(sb.length() - 1) == ',') sb.setLength(sb.length() - 1);
      sb.append("});\n</script>");
    }

    final Device device = Devices.getDevice(deviceType);
    String s = device.getEmbedded();
    if (s != null) sb.append(s).append('\n');
    return sb.toString();
  }
 public SpringTransactionSynchronizationListener() {
   final WebApp app = Executions.getCurrent().getDesktop().getWebApp();
   _enabled = app.getConfiguration().isEventThreadEnabled();
 }
예제 #10
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);
  }
예제 #11
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());
  }
예제 #12
0
 /**
  * Returns the update servlet of the specified application, or null if not loaded yet. Note: if
  * the update servlet is not loaded, it returns null.
  *
  * @since 3.0.2
  */
 public static DHtmlUpdateServlet getUpdateServlet(WebApp wapp) {
   return (DHtmlUpdateServlet)
       ((ServletContext) wapp.getNativeContext()).getAttribute(ATTR_UPDATE_SERVLET);
 }
예제 #13
0
 public CustomContentLoader(WebApp wapp) {
   _wapp = wapp;
   _ctx =
       WebApplicationContextUtils.getRequiredWebApplicationContext(
           (ServletContext) wapp.getNativeContext());
 }