📄 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.lang.reflect.Modifier;import java.lang.reflect.Method;import java.util.List;import java.util.LinkedList;import java.util.Collections;import java.util.Collection;import java.util.ListIterator;import java.util.Iterator;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.net.URL;import org.zkoss.lang.D;import org.zkoss.lang.Classes;import org.zkoss.lang.PotentialDeadLockException;import org.zkoss.util.CollectionsX;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.xel.taglib.Taglib;import org.zkoss.xel.util.Evaluators;import org.zkoss.xel.util.MethodFunction;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.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;import org.zkoss.zk.ui.impl.ZScriptInitiator;import org.zkoss.zk.ui.metainfo.impl.*;/** * 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), Servlets.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), Servlets.getExtension(url.toExternalForm())); pgdef.setRequestPath(path); return pgdef; } /** 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; 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)) { //we handle only the language attribute here final Map params = pi.parseData(); final String l = (String)params.remove("language"); if (l != null) { noEL("language", l, pi); lang = l; } if (!params.isEmpty()) pis.add(pi); //process it later } else if ("import".equals(target)) { //import final Map params = pi.parseData(); final String src = (String)params.remove("src"); if (!params.isEmpty()) log.warning("Ignored unknown attributes: "+params.keySet()+", "+pi.getLocator()); noELnorEmpty("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, 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 AnnotationHelper()); 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 ("page".equals(target)) { parsePageDirective(pgdef, pi, params); } else if ("init".equals(target)) { parseInitDirective(pgdef, pi, params); } 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.addVariableResolverInfo( clsnm.indexOf("${") >= 0 ? //class supports EL new VariableResolverInfo(clsnm): new VariableResolverInfo(locateClass(clsnm))); } else if ("component".equals(target)) { //declare a component parseComponentDirective(pgdef, pi, params); } else 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 ("evaluator".equals(target)) { parseEvaluatorDirective(pgdef, pi, params); } else if ("xel-method".equals(target)) { parseXelMethod(pgdef, pi, params); } else if ("link".equals(target) || "meta".equals(target)) { //declare a header element pgdef.addHeaderInfo(new HeaderInfo(target, params)); } else if ("root-attributes".equals(target)) { for (Iterator it = pi.parseData().entrySet().iterator(); it.hasNext();) { final Map.Entry me = (Map.Entry)it.next(); pgdef.setRootAttribute((String)me.getKey(), (String)me.getValue()); } } else if ("import".equals(target)) { //import throw new UiException("The import directive can be used only at the top level, "+pi.getLocator()); } else { log.warning("Unknown processing instruction: "+target+", "+pi.getLocator()); } } /** Process the init directive. */ private void parseInitDirective(PageDefinition pgdef, ProcessingInstruction pi, Map params) throws Exception { 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; final String zslang = pgdef.getZScriptLanguage(); if (zsrc.indexOf("${") >= 0) { zs = new ZScript(pgdef.getEvaluatorRef(), zslang, zsrc, null, getLocator()); //URL in EL } else { final URL url = getLocator().getResource(zsrc); if (url == null) throw new UiException("File not found: "+zsrc+", at "+pi.getLocator()); //don't throw FileNotFoundException since Tomcat 'eats' it zs = new ZScript(pgdef.getEvaluatorRef(), zslang, url, null); } pgdef.addInitiatorInfo( new InitiatorInfo(new ZScriptInitiator(zs), args)); } else { if (!isEmpty(zsrc)) throw new UiException("You cannot specify both class and zscript, "+pi.getLocator()); pgdef.addInitiatorInfo( clsnm.indexOf("${") >= 0 ? //class supports EL new InitiatorInfo(clsnm, args): new InitiatorInfo(locateClass(clsnm), args)); //Note: we don't resolve the class name later because //no zscript run before init (and better performance) } } /** Process the page directive. */ private static void parsePageDirective(PageDefinition pgdef, ProcessingInstruction pi, Map params) throws Exception { for (Iterator it = pi.parseData().entrySet().iterator(); it.hasNext();) { final Map.Entry me = (Map.Entry)it.next(); final String nm = (String)me.getKey(); final String val = (String)me.getValue(); if ("language".equals(nm)) { if (!(pi.getParent() instanceof Document)) log.warning("Ignored language attribute since the page directive is not at the top level, "+pi.getLocator()); } else if ("title".equals(nm)) { pgdef.setTitle(val); } else if ("style".equals(nm)) { pgdef.setStyle(val); } else if ("id".equals(nm)) { pgdef.setId(val); } else if ("zscriptLanguage".equals(nm) || "zscript-language".equals(nm)) { //backward compatible with 2.4.x noELnorEmpty("zscriptLanguage", val, pi); pgdef.setZScriptLanguage(val); } else if ("cacheable".equals(nm)) { noELnorEmpty("cacheable", val, pi); pgdef.setCacheable(Boolean.valueOf("true".equals(val))); } else if ("contentType".equals(nm)) { noEmpty("contentType", val, pi); pgdef.setContentType(val); } else if ("docType".equals(nm)) { noEmpty("docType", val, pi); pgdef.setDocType("<!DOCTYPE " + val + '>');
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -