예제 #1
0
  /** Parse the processing instructions. */
  private static void parsePI(LanguageDefinition langdef, Document doc) throws Exception {
    for (Iterator it = doc.getChildren().iterator(); it.hasNext(); ) {
      final Object o = it.next();
      if (!(o instanceof ProcessingInstruction)) continue;

      final ProcessingInstruction pi = (ProcessingInstruction) o;
      final String target = pi.getTarget();
      final Map<String, String> params = pi.parseData();
      if ("taglib".equals(target)) {
        final String uri = params.remove("uri");
        final String prefix = params.remove("prefix");
        if (!params.isEmpty())
          log.warn("Ignored unknown attribute: " + params + ", " + pi.getLocator());
        if (uri == null || prefix == null)
          throw new UiException(message("Both uri and prefix attribute are required", pi));
        if (log.isDebugEnabled()) log.debug("taglib: prefix=" + prefix + " uri=" + uri);
        langdef.addTaglib(new Taglib(prefix, uri));
      } else {
        log.warn("Unknown processing instruction: " + target);
      }
    }
  }
예제 #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);
    }
  }