Beispiel #1
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();
  }
Beispiel #2
0
  private static void parseLang(Document doc, Locator locator, URL url, boolean addon)
      throws Exception {
    final Element root = doc.getRootElement();
    final String lang = IDOMs.getRequiredElementValue(root, "language-name");
    final LanguageDefinition langdef;
    final Device device;
    if (addon) {
      if (log.isDebugEnabled())
        log.debug(
            "Addon language to " + lang + " from " + root.getElementValue("addon-name", true));
      langdef = LanguageDefinition.lookup(lang);
      device = Devices.getDevice(langdef.getDeviceType());

      if (root.getElement("case-insensitive") != null)
        throw new UiException(message("case-insensitive not allowed in addon", root));
    } else {
      final String ns = IDOMs.getRequiredElementValue(root, "namespace");
      final String deviceType = IDOMs.getRequiredElementValue(root, "device-type");
      String treeBuilderClass = root.getElementValue("treebuilder-class", true);

      if (treeBuilderClass == null) // XulTreeBuilder as default
      treeBuilderClass = XmlTreeBuilder.class.getName();

      // if (log.isDebugEnabled()) log.debug("Load language: "+lang+", "+ns);

      PageRenderer pageRenderer =
          (PageRenderer)
              locateClass(IDOMs.getRequiredElementValue(root, "renderer-class"), PageRenderer.class)
                  .newInstance();

      final List<String> exts = parseExtensions(root);
      if (exts.isEmpty())
        throw new UiException(message("The extension must be specified for " + lang, root));

      String ignoreCase = root.getElementValue("case-insensitive", true);
      String bNative = root.getElementValue("native-namespace", true);

      langdef =
          new LanguageDefinition(
              deviceType,
              lang,
              ns,
              exts,
              pageRenderer,
              "true".equals(ignoreCase),
              "true".equals(bNative),
              locator,
              treeBuilderClass);
      device = Devices.getDevice(deviceType);
    }

    parsePI(langdef, doc);
    parseLabelTemplate(langdef, root);
    parseDynamicTag(langdef, root);
    parseMacroTemplate(langdef, root);
    parseNativeTemplate(langdef, root);
    parseShadowTemplate(langdef, root);

    for (Element el : root.getElements("message-loader-class")) {
      final String clsname = el.getText().trim();
      if (Strings.isEmpty(clsname))
        throw new UiException("Empty class name of message loader for " + lang);
      MessageLoader msgLoader = (MessageLoader) locateClass(clsname).newInstance();
      langdef.addMessageLoader(msgLoader);
    }

    for (Element el : root.getElements("library-property")) {
      ConfigParser.parseLibProperty(el);
    }
    for (Iterator it = root.getElements("system-property").iterator(); it.hasNext(); ) {
      final Element el = (Element) it.next();
      final String nm = IDOMs.getRequiredElementValue(el, "name");
      final String val = IDOMs.getRequiredElementValue(el, "value");
      System.setProperty(nm, val);
    }

    for (Iterator it = root.getElements("javascript").iterator(); it.hasNext(); ) {
      final Element el = (Element) it.next();
      String src = el.getAttributeValue("src"), pkg = el.getAttributeValue("package");
      String mergeTo = el.getAttributeValue("merge");
      final boolean merge = mergeTo != null && !"false".equals(mergeTo);
      if (merge && "true".equals(mergeTo)) mergeTo = "zk";
      final boolean ondemand = "true".equals(el.getAttributeValue("ondemand"));
      // ondemand means to cancel the previous definition (merge or not)
      if (pkg != null) {
        if (src != null)
          log.warn("The src attribute ignored because package is specified, " + el.getLocator());
        if (!ondemand && !merge) {
          src = "~." + device.packageToPath(pkg);
          pkg = null;
        }
      }

      final String ctn = el.getText(true);
      final JavaScript js;
      if (pkg != null && pkg.length() > 0) {
        if (ondemand) { // ondemand has the higher priority than merge
          langdef.removeJavaScript("~." + device.packageToPath(pkg));
          langdef.unmergeJavaScriptPackage(pkg, mergeTo);
        } else { // merge must be true
          langdef.mergeJavaScriptPackage(pkg, mergeTo);
        }
        continue; // TODO
      } else if (src != null && src.length() > 0) {
        if (ctn != null && ctn.length() > 0)
          throw new UiException(
              message("You cannot specify the content if the src attribute is specified", el));
        final String charset = el.getAttributeValue("charset");
        js = new JavaScript(src, charset);
      } else if (ctn != null && ctn.length() > 0) {
        js = new JavaScript(ctn);
      } else {
        log.warn(
            "Ignored: none of the src or package attribute, or the content specified, "
                + el.getLocator());
        continue;
      }
      langdef.addJavaScript(js);
    }
    for (Iterator it = root.getElements("javascript-module").iterator(); it.hasNext(); ) {
      final Element el = (Element) it.next();
      langdef.addJavaScriptModule(
          IDOMs.getRequiredAttributeValue(el, "name"),
          IDOMs.getRequiredAttributeValue(el, "version"));
    }

    for (Iterator it = root.getElements("stylesheet").iterator(); it.hasNext(); ) {
      final Element el = (Element) it.next();
      final String href = el.getAttributeValue("href");
      final String ctn = el.getText(true);
      final StyleSheet ss;
      if (href != null && href.length() > 0) {
        if (ctn != null && ctn.length() > 0)
          throw new UiException(
              message("You cannot specify the content if the href attribute is specified", el));
        ss =
            new StyleSheet(
                href, el.getAttributeValue("type"), el.getAttributeValue("media"), false);
      } else if (ctn != null && ctn.length() > 0) {
        ss = new StyleSheet(ctn, el.getAttributeValue("type"), el.getAttributeValue("media"), true);
      } else {
        throw new UiException(
            message("You must specify either the href attribute or the content", el));
      }
      langdef.addStyleSheet(ss);
    }

    for (Iterator it = root.getElements("zscript").iterator(); it.hasNext(); ) {
      final Element el = (Element) it.next();
      final String zslang;
      final Attribute attr = el.getAttributeItem("language");
      if (attr == null) {
        zslang = "Java";
      } else {
        zslang = attr.getValue();
        if (zslang == null || zslang.length() == 0)
          throw new UiException(message("The language attribute cannot be empty", attr));
      }
      final String s = el.getText(true);
      final String eachTime = el.getAttributeValue("each-time");
      if ("true".equals(eachTime)) langdef.addEachTimeScript(zslang, s);
      else langdef.addInitScript(zslang, s);
    }

    for (Iterator it = root.getElements("component").iterator(); it.hasNext(); ) {
      final Element el = (Element) it.next();
      final String name = IDOMs.getRequiredElementValue(el, "component-name");

      String clsnm = el.getElementValue("component-class", true);
      Class<? extends Component> cls = null;
      if (clsnm != null) {
        if (clsnm.length() > 0) {
          noEL("component-class", clsnm, el);
          try {
            cls = locateClass(clsnm, Component.class);
          } catch (Throwable ex) { // Feature 1873426
            log.warn(
                "Component "
                    + name
                    + " ignored. Reason: unable to load "
                    + clsnm
                    + " due to "
                    + ex.getClass().getName()
                    + ": "
                    + ex.getMessage()
                    + (ex instanceof NoClassDefFoundError ? "" : "\n" + el.getLocator()));
            log.debug("", ex);
            // keep processing (Feature 2060367)
          }
        } else {
          clsnm = null;
        }
      }

      final String macroURI = el.getElementValue("macro-uri", true);
      final String templateURI = el.getElementValue("template-uri", true);
      final ComponentDefinitionImpl compdef;
      boolean extend = false;
      if (macroURI != null && macroURI.length() != 0) {
        if (log.isTraceEnabled()) log.trace("macro component definition: " + name);

        final String inline = el.getElementValue("inline", true);
        compdef =
            (ComponentDefinitionImpl)
                langdef.getMacroDefinition(name, macroURI, "true".equals(inline), null);

        if (cls != null) compdef.setImplementationClass(cls);
        else if (clsnm != null) compdef.setImplementationClass(clsnm);

        compdef.setDeclarationURL(url);
        langdef.addComponentDefinition(compdef);
      } else if (templateURI != null && templateURI.length() != 0) { // apply template uri
        extend = true;
        String extendedCls = "apply";
        final ComponentDefinition ref =
            (ComponentDefinitionImpl) langdef.getShadowDefinitionIfAny(extendedCls);

        if (extendedCls.equals(name)) {
          compdef = (ComponentDefinitionImpl) ref;
        } else {
          compdef = (ComponentDefinitionImpl) ref.clone(ref.getLanguageDefinition(), name);
          compdef.setDeclarationURL(url);
        }

        if (cls != null) compdef.setImplementationClass(cls);
        else if (clsnm != null) compdef.setImplementationClass(clsnm);
        langdef.addShadowDefinition(compdef);
        compdef.addProperty("templateURI", templateURI);
      } else if (el.getElement("extends") != null) { // extends
        extend = true;

        final String extnm = el.getElementValue("extends", true);
        if (log.isTraceEnabled())
          log.trace("Extends component definition, " + name + ", from " + extnm);
        ComponentDefinition tmpRef = langdef.getComponentDefinitionIfAny(extnm);

        if (tmpRef == null) // search Shadow
        tmpRef = langdef.getShadowDefinitionIfAny(extnm);

        final ComponentDefinition ref = tmpRef;

        if (ref == null) {
          log.warn(
              "Component "
                  + name
                  + " ignored. Reason: extends a non-existent component "
                  + extnm
                  + ".\n"
                  + el.getLocator());
          // not throw exception since the derived component might be
          // ignored due to class-not-found
          continue;
        }

        if (ref.isMacro())
          throw new UiException(message("Unable to extend from a macro component", el));

        if (extnm.equals(name)) {
          compdef = (ComponentDefinitionImpl) ref;
        } else {
          compdef = (ComponentDefinitionImpl) ref.clone(ref.getLanguageDefinition(), name);
          compdef.setDeclarationURL(url);
        }

        if (cls != null) compdef.setImplementationClass(cls);
        else if (clsnm != null) compdef.setImplementationClass(clsnm);

        if (compdef.isShadowElement()) {
          langdef.addShadowDefinition(compdef);
        } else {
          langdef.addComponentDefinition(compdef);
        }
        // Note: setImplementationClass before addComponentDefinition
      } else {
        if (log.isTraceEnabled()) log.trace("Add component definition: name=" + name);

        if (cls == null && clsnm == null)
          throw new UiException(message("component-class is required", el));
        String s = el.getElementValue("shadow-element", true);
        if (s != null && !"false".equals(s)) {
          compdef =
              cls != null
                  ? new ShadowDefinitionImpl(langdef, null, name, cls)
                  : new ShadowDefinitionImpl(langdef, null, name, clsnm);
          compdef.setDeclarationURL(url);
          langdef.addShadowDefinition(compdef);
        } else {
          compdef =
              cls != null
                  ? new ComponentDefinitionImpl(langdef, null, name, cls)
                  : new ComponentDefinitionImpl(langdef, null, name, clsnm);
          compdef.setDeclarationURL(url);
          langdef.addComponentDefinition(compdef);
        }
      }

      parseTextAs(compdef, el.getElement("text-as"));

      String s = el.getElementValue("preserve-blank", true);
      compdef.setBlankPreserved((s != null && !"false".equals(s)));

      String wgtnm = el.getElementValue("widget-class", true);
      WidgetDefinition wgtdef = null;
      if (wgtnm == null && extend) wgtnm = compdef.getDefaultWidgetClass(null);
      if (wgtnm != null) {
        if (!withEL(wgtnm)) wgtdef = getWidgetDefinition(langdef, compdef, wgtnm);
        compdef.setDefaultWidgetClass(wgtnm);
      }

      s = el.getElementValue("component-apply", true);
      if (s == null) s = el.getElementValue("apply", true); // backward-compatible
      compdef.setApply(s);

      for (Iterator i = el.getElements("mold").iterator(); i.hasNext(); ) {
        final Element e = (Element) i.next();
        final String nm = IDOMs.getRequiredElementValue(e, "mold-name");
        final String moldURI = e.getElementValue("mold-uri", true);
        String cssURI = e.getElementValue("css-uri", true);
        final String wn = e.getElementValue("widget-class", true);
        noEL("mold-uri", moldURI, e); // 5.0 limitation
        noEL("css-uri", cssURI, e);

        compdef.addMold(nm, wn != null ? wn : wgtnm);

        WidgetDefinition wd =
            wn == null ? wgtdef : withEL(wn) ? null : getWidgetDefinition(langdef, compdef, wn);
        if (moldURI != null) {
          if (wd != null) wd.addMold(nm, moldURI);
          else
            log.error(
                "Mold "
                    + nm
                    + " for "
                    + name
                    + " ignored because "
                    + ((wn != null && withEL(wn)) || (wgtnm != null && withEL(wgtnm))
                        ? "widget-class contains EL expressions"
                        : "widget-class is required")
                    + ", "
                    + e.getLocator());
        }

        if (cssURI != null && cssURI.length() > 0) {
          final char cc = cssURI.charAt(0);
          if (cc != '/' && cc != '~') {
            String n = wn != null ? wn : wgtnm;
            if (!withEL(n)) {
              int k = n.lastIndexOf('.');
              cssURI =
                  "~." + device.toAbsolutePath(n.substring(0, k).replace('.', '/') + '/' + cssURI);
            } else {
              log.error(
                  "Absolute path required for cssURI, since the widget class contains EL expressions, "
                      + e.getLocator());
            }
          }
          langdef.addCSSURI(cssURI);
        }
      }

      for (Iterator e = parseCustAttrs(el).entrySet().iterator(); e.hasNext(); ) {
        final Map.Entry me = (Map.Entry) e.next();
        compdef.addCustomAttribute((String) me.getKey(), (String) me.getValue());
      }

      for (Iterator e = parseProps(el).entrySet().iterator(); e.hasNext(); ) {
        final Map.Entry me = (Map.Entry) e.next();
        compdef.addProperty((String) me.getKey(), (String) me.getValue());
      }

      parseAnnots(compdef, el);
    }
  }