📄 definitionloaders.java
字号:
/* DefinitionLoaders.java{{IS_NOTE Purpose: Description: History: Mon Aug 29 21:57:08 2005, Created by tomyeh}}IS_NOTECopyright (C) 2005 Potix Corporation. All Rights Reserved.{{IS_RIGHT This program is distributed under GPL Version 2.0 in the hope that it will be useful, but WITHOUT ANY WARRANTY.}}IS_RIGHT*/package org.zkoss.zk.ui.metainfo;import java.lang.reflect.Field;import java.util.Iterator;import java.util.ListIterator;import java.util.List;import java.util.LinkedList;import java.util.Set;import java.util.HashSet;import java.util.Map;import java.util.HashMap;import java.util.Enumeration;import java.net.URL;import java.io.IOException;import org.zkoss.lang.D;import org.zkoss.lang.Classes;import org.zkoss.lang.Strings;import org.zkoss.util.Utils;import org.zkoss.util.logging.Log;import org.zkoss.util.resource.Locator;import org.zkoss.util.resource.ClassLocator;import org.zkoss.idom.Document;import org.zkoss.idom.Element;import org.zkoss.idom.Attribute;import org.zkoss.idom.ProcessingInstruction;import org.zkoss.idom.input.SAXBuilder;import org.zkoss.idom.util.IDOMs;import org.zkoss.xel.taglib.Taglib;import org.zkoss.web.servlet.JavaScript;import org.zkoss.web.servlet.StyleSheet;import org.zkoss.zk.Version;import org.zkoss.zk.ui.UiException;import org.zkoss.zk.ui.metainfo.impl.*;import org.zkoss.zk.scripting.Interpreters;import org.zkoss.zk.device.Devices;/** * Utilities to load language definitions. * * @author tomyeh */public class DefinitionLoaders { private static final Log log = Log.lookup(DefinitionLoaders.class); private static final int MAX_VERSION_SEGMENT = 4; private static List _addons; /** A map of (String ext, String lang). */ private static Map _exts; private static boolean _loaded, _loading; //CONSIDER: //Sotre language definitions per WebApp, since diff app may add its //own definitions thru WEB-INF's lang-addon, or a JAR in WEB-INF/lib. // //CONSEQUENCE: //Other Web app is affected by another in the current implementation // //WORKAROUND: //Copy ZK libraries into WEB-INF/lib // //DIFFICULTY TO SUPPORT //To support it we have to pass WebApp around. It is a challenge for //1) a working thread (other than servlet/event thread); //2) deserialize LanguageDefinition (and maybe ComponentDefinition) /** Adds a language addon. */ public static void addAddon(Locator locator, URL url) { if (locator == null || url == null) throw new IllegalArgumentException("null"); if (_loaded) { loadAddon(locator, url); } else { if (_addons == null) _addons = new LinkedList(); _addons.add(new Object[] {locator, url}); } } /** Associates an extension to a language. * * @param lang the language name. It cannot be null. * @param ext the extension, e.g., "svg". It cannot be null. * @since 3.0.0 */ public static final void addExtension(String ext, String lang) { if (_loaded) { LanguageDefinition.addExtension(ext, lang); } else { if (lang == null || ext == null) throw new IllegalArgumentException("null"); if (_exts == null) _exts = new HashMap(); _exts.put(ext, lang); } } /** Loads all config.xml, lang.xml and lang-addon.xml found in * the /metainfo/zk path. * * <p>Remember to call {@link #addAddon}, if necessary, before * calling this method. */ /*package*/ static void load() { if (!_loaded) { synchronized (DefinitionLoaders.class) { if (!_loaded && !_loading) { try { _loading = true; //prevent re-entry for the same thread load0(); } finally { _loaded = true; //only once _loading = false; } } } } } private static void load0() { final ClassLocator locator = new ClassLocator(); final int[] zkver = new int[MAX_VERSION_SEGMENT]; for (int j = 0; j < MAX_VERSION_SEGMENT; ++j) zkver[j] = Utils.getSubversion(Version.UID, j); //1. process config.xml (no particular dependency) try { final List xmls = locator.getDependentXMLResources( "metainfo/zk/config.xml", "config-name", "depends"); for (Iterator it = xmls.iterator(); it.hasNext();) { final ClassLocator.Resource res = (ClassLocator.Resource)it.next(); if (log.debugable()) log.debug("Loading "+res.url); try { if (checkVersion(zkver, res.url, res.document)) parseConfig(res.document.getRootElement()); } catch (Exception ex) { throw UiException.Aide.wrap(ex, "Failed to load "+res.url); //abort since it is hardly to work then } } } catch (Exception ex) { throw UiException.Aide.wrap(ex); //abort } //2. process lang.xml (no particular dependency) try { for (Enumeration en = locator.getResources("metainfo/zk/lang.xml"); en.hasMoreElements();) { final URL url = (URL)en.nextElement(); if (log.debugable()) log.debug("Loading "+url); try { final Document doc = new SAXBuilder(false, false, true).build(url); if (checkVersion(zkver, url, doc)) parseLang(doc, locator, false); } catch (Exception ex) { throw UiException.Aide.wrap(ex, "Failed to load "+url); //abort since it is hardly to work then } } } catch (Exception ex) { throw UiException.Aide.wrap(ex); //abort } //3. process lang-addon.xml (with dependency) try { final List xmls = locator.getDependentXMLResources( "metainfo/zk/lang-addon.xml", "addon-name", "depends"); for (Iterator it = xmls.iterator(); it.hasNext();) { final ClassLocator.Resource res = (ClassLocator.Resource)it.next(); try { if (checkVersion(zkver, res.url, res.document)) parseLang(res.document, locator, true); } catch (Exception ex) { log.error("Failed to load addon", ex); //keep running } } } catch (Exception ex) { log.error("Failed to load addon", ex); //keep running } //4. process other addon (from addAddon) if (_addons != null) { for (Iterator it = _addons.iterator(); it.hasNext();) { final Object[] p = (Object[])it.next(); loadAddon((Locator)p[0], (URL)p[1]); } _addons = null; //free memory } //5. process the extension if (_exts != null) { for (Iterator it = _exts.entrySet().iterator(); it.hasNext();) { final Map.Entry me = (Map.Entry)it.next(); LanguageDefinition.addExtension((String)me.getKey(), (String)me.getValue()); } _exts = null; } } /** Loads a language addon. */ private static void loadAddon(Locator locator, URL url) { try { parseLang( new SAXBuilder(false, false, true).build(url), locator, true); } catch (Exception ex) { log.error("Failed to load addon: "+url, ex); //keep running } } /** Checks and returns whether the loaded document's version is correct. */ private static boolean checkVersion(int[] zkver, URL url, Document doc) throws Exception { final Element el = doc.getRootElement().getElement("version"); if (el != null) { final String reqzkver = el.getElementValue("zk-version", true); if (reqzkver != null) { for (int j = 0; j < MAX_VERSION_SEGMENT; ++j) { int v = Utils.getSubversion(reqzkver, j); if (v < zkver[j]) break; //ok if (v > zkver[j]) {//failed log.info("Ignore "+url+"\nCause: ZK version must be "+zkver+" or later, not "+Version.UID); return false; } } } final String clsnm = IDOMs.getRequiredElementValue(el, "version-class"); final String uid = IDOMs.getRequiredElementValue(el, "version-uid"); final Class cls = Classes.forNameByThread(clsnm); final Field fld = cls.getField("UID"); final String uidInClass = (String)fld.get(null); if (uid.equals(uidInClass)) { return true; } else { log.info("Ignore "+url+"\nCause: version not matched; expected="+uidInClass+", xml="+uid); return false; } } else { log.info("Ignore "+url+"\nCause: version not specified"); return false; //backward compatible } } private static void parseConfig(Element el) throws Exception { parseZScriptConfig(el); parseDeviceConfig(el); } private static void parseZScriptConfig(Element root) { for (Iterator it = root.getElements("zscript-config").iterator(); it.hasNext();) { final Element el = (Element)it.next(); Interpreters.add(el); //Note: zscript-config is applied to the whole system, not just langdef } } private static void parseDeviceConfig(Element root) { for (Iterator it = root.getElements("device-config").iterator(); it.hasNext();) { final Element el = (Element)it.next(); Devices.add(el); } } private static void parseLang(Document doc, Locator locator, boolean addon) throws Exception { final Element root = doc.getRootElement(); final String lang = IDOMs.getRequiredElementValue(root, "language-name"); final LanguageDefinition langdef; if (addon) { if (log.debugable()) log.debug("Addon language to "+lang+" from "+root.getElementValue("addon-name", true)); langdef = LanguageDefinition.lookup(lang); if (root.getElement("case-insensitive") != null) throw new UiException("case-insensitive not allowed in addon"); } else { final String ns = (String)IDOMs.getRequiredElementValue(root, "namespace"); final String deviceType = (String)IDOMs.getRequiredElementValue(root, "device-type"); //if (log.debugable()) log.debug("Load language: "+lang+", "+ns); final Map pagemolds = parseMolds(root); final String desktopURI = (String)pagemolds.get("desktop"); final String pageURI = (String)pagemolds.get("page"); if (desktopURI == null || pageURI == null) throw new UiException("Both desktop and page molds must be specified, "+root.getLocator()); if (desktopURI.startsWith("class:") || pageURI.startsWith("class:")) throw new UiException("Both desktop and page molds don't support 'class:', "+root.getLocator());
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -