001: /* Evaluators.java
002:
003: {{IS_NOTE
004: Purpose:
005:
006: Description:
007:
008: History:
009: Fri Sep 14 12:24:23 2007, Created by tomyeh
010: }}IS_NOTE
011:
012: Copyright (C) 2007 Potix Corporation. All Rights Reserved.
013:
014: {{IS_RIGHT
015: This program is distributed under GPL Version 2.0 in the hope that
016: it will be useful, but WITHOUT ANY WARRANTY.
017: }}IS_RIGHT
018: */
019: package org.zkoss.xel.util;
020:
021: import java.util.Iterator;
022: import java.util.Map;
023: import java.util.HashMap;
024: import java.util.Enumeration;
025: import java.net.URL;
026:
027: import org.zkoss.lang.Classes;
028: import org.zkoss.lang.SystemException;
029: import org.zkoss.util.logging.Log;
030: import org.zkoss.util.resource.Locator;
031: import org.zkoss.util.resource.ClassLocator;
032: import org.zkoss.idom.input.SAXBuilder;
033: import org.zkoss.idom.Document;
034: import org.zkoss.idom.Element;
035: import org.zkoss.idom.util.IDOMs;
036:
037: /**
038: * It mapps a name with an evaluator implementation.
039: *
040: * @author tomyeh
041: * @since 3.0.0
042: */
043: public class Evaluators {
044: private static final Log log = Log.lookup(Evaluators.class);
045:
046: /** Map(name, Class/String class); */
047: private static final Map _evals = new HashMap(8);
048: private static boolean _loaded;
049:
050: private Evaluators() {
051: } //prevent from being instantiated
052:
053: /** Returns the implementation for the specified evaluator name.
054: *
055: * @param name the name of the evaluator, say, MVEL.
056: * @exception SystemException if not found or the class not found.
057: */
058: public static final Class getEvaluatorClass(String name) {
059: if (name == null || name.length() == 0)
060: throw new IllegalArgumentException("empty or null");
061:
062: if (!_loaded)
063: load();
064:
065: final String evalnm = name.toLowerCase();
066: final Object clsnm;
067: synchronized (_evals) {
068: clsnm = _evals.get(evalnm);
069: }
070: if (clsnm == null)
071: throw new SystemException("Evaluator not found: " + name);
072:
073: if (clsnm instanceof Class) {
074: return (Class) clsnm;
075: } else {
076: try {
077: return Classes.forNameByThread((String) clsnm);
078: } catch (ClassNotFoundException ex) {
079: throw new SystemException("Failed to load class "
080: + clsnm);
081: }
082: }
083: }
084:
085: /** Tests whether the evaluator (aka., the expression factory)
086: * for the specified evaluator name
087: * exists.
088: *
089: * @param name the name of the evaluator, say, MVEL.
090: */
091: public static final boolean exists(String name) {
092: if (name == null)
093: return false;
094:
095: if (!_loaded)
096: load();
097:
098: name = name.toLowerCase();
099: synchronized (_evals) {
100: return _evals.containsKey(name);
101: }
102: }
103:
104: /** Adds an evaluator
105: * (aka., the expression factory, {@link org.zkoss.xel.ExpressionFactory}).
106: *
107: * @param name the name of the evaluator, say, MVEL.
108: * It is case insensitive.
109: * @param evalcls the class name of the evaluator, aka., the expression factory
110: * ({@link org.zkoss.xel.ExpressionFactory}).
111: * @return the previous class name, or null if not defined yet
112: */
113: public static final String add(String name, String evalcls) {
114: if (name == null || name.length() == 0 || evalcls == null
115: || evalcls.length() == 0)
116: throw new IllegalArgumentException("emty or null");
117:
118: if (log.debugable())
119: log.debug("Evaluator is added: " + name + ", " + evalcls);
120:
121: final String evalnm = name.toLowerCase();
122: final Object old;
123: synchronized (_evals) {
124: old = _evals.put(evalnm, evalcls);
125: }
126:
127: return old instanceof Class ? ((Class) old).getName()
128: : (String) old;
129: }
130:
131: /** Adds an evaluator based on the XML declaration.
132: * The evaluator is also known as the expression factory,
133: * {@link org.zkoss.xel.ExpressionFactory}.
134: *
135: * <pre><code>
136: <xel-config>
137: <evaluator-name>SuperEL</evaluator-name><!-- case insensitive --!>
138: <evaluator-class>my.MySuperEvaluator</evaluator-class>
139: </xel-config>
140: * </code></pre>
141: *
142: * @param config the XML element called zscript-config
143: * @return the previous class, or null if not defined yet
144: */
145: public static final String add(Element config) {
146: //Spec: it is OK to declare an nonexist factory, since
147: //deployer might remove unused jar files.
148: final String name = IDOMs.getRequiredElementValue(config,
149: "evaluator-name");
150: final String clsnm = IDOMs.getRequiredElementValue(config,
151: "evaluator-class");
152: return add(name, clsnm);
153: }
154:
155: /** Loads from metainfo/xel/config
156: */
157: synchronized static final void load() {
158: if (_loaded)
159: return;
160:
161: try {
162: final ClassLocator loc = new ClassLocator();
163: for (Enumeration en = loc
164: .getResources("metainfo/xel/config.xml"); en
165: .hasMoreElements();) {
166: final URL url = (URL) en.nextElement();
167: if (log.debugable())
168: log.debug("Loading " + url);
169: try {
170: final Document doc = new SAXBuilder(false, false,
171: true).build(url);
172: if (IDOMs.checkVersion(doc, url))
173: parseConfig(doc.getRootElement(), loc);
174: } catch (Exception ex) {
175: log.error("Failed to parse " + url, ex); //keep running
176: }
177: }
178: } catch (Exception ex) {
179: log.error(ex); //keep running
180: } finally {
181: _loaded = true;
182: }
183: }
184:
185: /** Parse config.xml. */
186: private static void parseConfig(Element root, Locator loc) {
187: for (Iterator it = root.getElements("xel-config").iterator(); it
188: .hasNext();) {
189: add((Element) it.next());
190: }
191: }
192: }
|