📄 parser.java
字号:
/* Parser.java{{IS_NOTE Purpose: Description: History: Tue May 31 14:26:18 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.util.List;import java.util.LinkedList;import java.util.Collections;import java.util.Iterator;import java.util.Collection;import java.util.Map;import java.util.HashMap;import java.util.Set;import java.util.LinkedHashSet;import java.io.File;import java.io.Reader;import java.io.FileNotFoundException;import java.net.URL;import org.zkoss.lang.D;import org.zkoss.lang.Classes;import org.zkoss.lang.PotentialDeadLockException;import org.zkoss.util.Maps;import org.zkoss.util.logging.Log;import org.zkoss.util.resource.Locator;import org.zkoss.idom.Namespace;import org.zkoss.idom.Document;import org.zkoss.idom.Element;import org.zkoss.idom.Text;import org.zkoss.idom.CData;import org.zkoss.idom.Item;import org.zkoss.idom.Attribute;import org.zkoss.idom.ProcessingInstruction;import org.zkoss.idom.util.IDOMs;import org.zkoss.idom.input.SAXBuilder;import org.zkoss.el.Taglib;import org.zkoss.web.servlet.Servlets;import org.zkoss.zk.ui.WebApp;import org.zkoss.zk.ui.Component;import org.zkoss.zk.ui.UiException;import org.zkoss.zk.ui.event.Events;import org.zkoss.zk.ui.impl.ZScriptInitiator;import org.zkoss.zk.ui.util.Condition;import org.zkoss.zk.ui.util.ConditionImpl;import org.zkoss.zk.ui.sys.WebAppCtrl;import org.zkoss.zk.ui.sys.RequestInfo;import org.zkoss.zk.ui.sys.UiFactory;import org.zkoss.zk.ui.impl.RequestInfoImpl;/** * Used to prase the ZUL file * @author tomyeh */public class Parser { private static final Log log = Log.lookup(Parser.class); private final WebApp _wapp; private final Locator _locator; /** Constructor. * * @param locator the locator used to locate taglib and other resources. * If null, wapp is assumed ({@link WebApp} is also assumed). */ public Parser(WebApp wapp, Locator locator) { if (wapp == null) throw new IllegalArgumentException("null"); _wapp = wapp; _locator = locator != null ? locator: (Locator)wapp; } /** Parses the specified file. * * @param path the request path. * It is used as {@link org.zkoss.zk.ui.Page#getRequestPath}, or null * if not available. */ public PageDefinition parse(File file, String path) throws Exception { //if (log.debugable()) log.debug("Parsing "+file); final PageDefinition pgdef = parse(new SAXBuilder(true, false, true).build(file), getExtension(file.getName())); pgdef.setRequestPath(path); return pgdef; } /** Parses the specified URL. * * @param path the request path. * It is used as {@link org.zkoss.zk.ui.Page#getRequestPath}, or null * if not available. */ public PageDefinition parse(URL url, String path) throws Exception { //if (log.debugable()) log.debug("Parsing "+url); final PageDefinition pgdef = parse(new SAXBuilder(true, false, true).build(url), getExtension(url.toExternalForm())); pgdef.setRequestPath(path); return pgdef; } private static final String getExtension(String nm) { int j = nm == null ? -1: nm.lastIndexOf('.'); if (j < 0 || j < nm.lastIndexOf('/')) return null; final StringBuffer sb = new StringBuffer(8); for (final int len = nm.length(); ++j < len;) { final char cc = nm.charAt(j); if ((cc < 'a' || cc > 'z') && (cc < 'A' || cc > 'Z') && (cc < '0' || cc > '9')) break; sb.append(cc); } return sb.toString(); } /** Parses from the specified reader. * * @param extension the default extension if doc (of reader) doesn't specify * an language. Ignored if null. * If extension is null and the content doesn't specify a language, * the language called "xul/html" is assumed. */ public PageDefinition parse(Reader reader, String extension) throws Exception { //if (log.debugable()) log.debug("Parsing "+reader); return parse(new SAXBuilder(true, false, true).build(reader), extension); } /** Parss the raw content directly from a DOM tree. * * @param extension the default extension if doc doesn't specify * an language. Ignored if null. * If extension is null and the content doesn't specify a language, * the language called "xul/html" is assumed. */ public PageDefinition parse(Document doc, String extension) throws Exception { //1. parse the page and import directive if any final List pis = new LinkedList(); final List imports = new LinkedList(); String lang = null, title = null, id = null, style = null; 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(); if ("page".equals(target)) { for (Iterator i2 = pi.parseData().entrySet().iterator(); i2.hasNext();) { final Map.Entry me = (Map.Entry)i2.next(); final String nm = (String)me.getKey(); final String val = (String)me.getValue(); if ("language".equals(nm)) { lang = val; noEL("language", lang, pi); } else if ("title".equals(nm)) { title = val; } else if ("style".equals(nm)) { style = val; } else if ("id".equals(nm)) { id = val; } else { log.warning("Ignored unknown attribute: "+nm+", "+pi.getLocator()); } } } else if ("import".equals(target)) { //import final Map params = pi.parseData(); final String src = (String)params.remove("src"); if (isEmpty(src)) throw new UiException("The src attribute is required, "+pi.getLocator()); if (!params.isEmpty()) log.warning("Ignored unknown attributes: "+params.keySet()+", "+pi.getLocator()); noEL("src", src, pi); imports.add(src); } else { pis.add(pi); } } //2. Create PageDefinition final LanguageDefinition langdef = extension != null && lang == null? LanguageDefinition.getByExtension(extension): LanguageDefinition.lookup(lang); final PageDefinition pgdef = new PageDefinition(langdef, id, title, style, getLocator()); //3. resolve imports if (!imports.isEmpty()) { final RequestInfo ri = new RequestInfoImpl(_wapp, null, null, null, _locator); final UiFactory uf = ((WebAppCtrl)_wapp).getUiFactory(); for (Iterator it = imports.iterator(); it.hasNext();) { final String path = (String)it.next(); try { final PageDefinition pd = uf.getPageDefinition(ri, path); if (pd == null) throw new UiException("Import page not found: "+path); pgdef.imports(pd); } catch (PotentialDeadLockException ex) { throw new UiException("Recursive import: "+path, ex); } } } //4. Processing the rest of processing instructions at the top level for (Iterator it = pis.iterator(); it.hasNext();) parse(pgdef, (ProcessingInstruction)it.next()); //5. Processing from the root element final Element root = doc.getRootElement(); if (root != null) parse(pgdef, pgdef, root, new AnnotInfo()); return pgdef; } private static Class locateClass(String clsnm) throws Exception { try { return Classes.forNameByThread(clsnm); } catch (ClassNotFoundException ex) { throw new ClassNotFoundException("Class not found: "+clsnm, ex); } } //-- derive to override --// /** returns locator for locating resources. */ public Locator getLocator() { return _locator; } /** Parse processing instruction. */ private void parse(PageDefinition pgdef, ProcessingInstruction pi) throws Exception { final String target = pi.getTarget(); final Map params = pi.parseData(); if ("taglib".equals(target)) { final String uri = (String)params.remove("uri"); final String prefix = (String)params.remove("prefix"); if (!params.isEmpty()) log.warning("Ignored unknown attributes: "+params.keySet()+", "+pi.getLocator()); if (uri == null || prefix == null) throw new UiException("Both uri and prefix attribute are required, "+pi.getLocator()); //if (D.ON && log.debugable()) log.debug("taglib: prefix="+prefix+" uri="+uri); noEL("prefix", prefix, pi); noEL("uri", uri, pi); //not support EL (kind of chicken-egg issue) pgdef.addTaglib(new Taglib(prefix, toAbsoluteURI(uri, false))); } else if ("init".equals(target)) { final List args = new LinkedList(); for (int j = 0;; ++j) { final String arg = (String)params.remove("arg" + j); if (arg == null) break; args.add(arg); } final String clsnm = (String)params.remove("class"); final String zsrc = (String)params.remove("zscript"); if (!params.isEmpty()) log.warning("Ignored unknown attributes: "+params.keySet()+", "+pi.getLocator()); if (isEmpty(clsnm)) { if (isEmpty(zsrc)) throw new UiException("Either the class or zscript attribute must be specified, "+pi.getLocator()); final ZScript zs; if (zsrc.indexOf("${") >= 0) { zs = new ZScript(zsrc, null, getLocator()); } else { final URL url = getLocator().getResource(zsrc); if (url == null) throw new FileNotFoundException("File not found: "+zsrc+", at "+pi.getLocator()); zs = new ZScript(url, null); } pgdef.addInitiatorDefinition( new InitiatorDefinition(new ZScriptInitiator(zs), args)); } else { if (!isEmpty(zsrc)) throw new UiException("You cannot specify both class and zscript, "+pi.getLocator()); pgdef.addInitiatorDefinition( clsnm.indexOf("${") >= 0 ? //class supports EL new InitiatorDefinition(clsnm, args): new InitiatorDefinition(locateClass(clsnm), args)); //Note: we don't resolve the class name later because //no zscript run before init (and better performance) } } else if ("variable-resolver".equals(target)) { final String clsnm = (String)params.remove("class"); if (isEmpty(clsnm)) throw new UiException("The class attribute is required, "+pi.getLocator()); if (!params.isEmpty()) log.warning("Ignored unknown attributes: "+params.keySet()+", "+pi.getLocator()); pgdef.addVariableResolverDefinition( clsnm.indexOf("${") >= 0 ? //class supports EL new VariableResolverDefinition(clsnm): new VariableResolverDefinition(locateClass(clsnm))); } else if ("component".equals(target)) { //declare a component final String name = (String)params.remove("name"); if (isEmpty(name)) throw new UiException("name is required, "+pi.getLocator()); noEL("name", name, pi); //note: macro-uri supports EL final String macroURI = (String)params.remove("macro-uri"); final String extds = (String)params.remove("extends"); final String clsnm = (String)params.remove("class"); ComponentDefinition compdef; if (macroURI != null) { //if (D.ON && log.finerable()) log.finer("macro component definition: "+name); noEL("macro-uri", macroURI, pi); //no EL because pagedef must be loaded to resolve //the impl class before creating an instance of macro compdef = new ComponentDefinition( null, name, toAbsoluteURI(macroURI, false)); pgdef.getLanguageDefinition().initMacroDefinition(compdef); if (!isEmpty(clsnm)) { noEL("class", clsnm, pi); compdef.setImplementationClass(clsnm); //Resolve later since might defined in zscript } } else if (extds != null) { //extends //if (D.ON && log.finerable()) log.finer("Override component definition: "+name); noEL("extends", extds, pi); final ComponentDefinition ref = pgdef.getLanguageDefinition() .getComponentDefinition(extds); if (ref.isMacro()) throw new UiException("Unable to extend from a macro component, "+pi.getLocator()); compdef = (ComponentDefinition)ref.clone(name); compdef.setLanguageDefinition(null); if (!isEmpty(clsnm)) { noEL("class", clsnm, pi); compdef.setImplementationClass(clsnm); //Resolve later since might defined in zscript } } else { //if (D.ON && log.finerable()) log.finer("Add component definition: name="+name); if (isEmpty(clsnm)) throw new UiException("class is required"); noEL("class", clsnm, pi); compdef = new ComponentDefinition(null, name, (Class)null); compdef.setImplementationClass(clsnm); //Resolve later since might be defined in zscript } pgdef.addComponentDefinition(compdef); final String moldnm = (String)params.remove("mold-name"); noEL("mold-name", moldnm, pi); final String moldURI = (String)params.remove("mold-uri"); if (!isEmpty(moldURI)) compdef.addMold(isEmpty(moldnm) ? "default": moldnm,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -