001: package org.mvel.jsr223;
002:
003: import static org.mvel.MVEL.*;
004:
005: import javax.script.ScriptEngine;
006: import javax.script.ScriptEngineFactory;
007: import java.util.Arrays;
008: import java.util.Collections;
009: import java.util.List;
010:
011: /**
012: * Instances of ScriptEngineFactory are the Objects located by the
013: * Script Engine Discovery Mechanism. See 4.2.4 of the Scripting
014: * for the Java Platform Specification for more information.
015: * @author Richard L. Burton III
016: * @version 1.0
017: * @since MVEL 1.2
018: */
019: public class MVELScriptEngineFactory implements ScriptEngineFactory {
020:
021: /**
022: * The string literl to be used for a null argument when building
023: * the method syntax.
024: */
025: private static final String NULL_SYMBOL = "null";
026:
027: /**
028: * The string literal used when terminating a statement.
029: */
030: private static final String STATEMENT_TERMINATOR = ";";
031:
032: /**
033: * A list of filename extensions
034: */
035: static final List<String> extentions = Collections
036: .unmodifiableList(Arrays.asList("mvel"));
037:
038: /**
039: * A list of mimetypes, associated with scripts that can be executed by the
040: * engine.
041: */
042: static final List<String> mimeTypes = Collections
043: .unmodifiableList(Arrays.asList("application/x-mvel",
044: "application/x-mvel-source"));
045:
046: /**
047: * A list of the full names of the ScriptEngine.
048: */
049: static final List<String> names = Collections
050: .unmodifiableList(Arrays.asList("mvel"));
051:
052: /**
053: * Returns the full name of the ScriptEngine.
054: * @return The name of the engine implementation.
055: */
056: public String getEngineName() {
057: return NAME;
058: }
059:
060: /**
061: * Returns the version of the ScriptEngine.
062: * @return The ScriptEngine implementation version.
063: */
064: public String getEngineVersion() {
065: return VERSION;
066: }
067:
068: /**
069: * Returns an immutable list of filename extensions, which generally identify scripts written
070: * in the language supported by this ScriptEngine. The array is used by the ScriptEngineManager
071: * to implement its getEngineByExtension method.
072: * @return The list of extensions.
073: */
074: public List<String> getExtensions() {
075: return extentions;
076: }
077:
078: /**
079: * Returns an immutable list of mimetypes, associated with scripts that can be executed by the
080: * engine. The list is used by the ScriptEngineManager class to implement its getEngineByMimetype
081: * method.
082: * @return The list of mime types.
083: */
084: public List<String> getMimeTypes() {
085: return mimeTypes;
086: }
087:
088: /**
089: * Returns an immutable list of short names for the ScriptEngine, which may
090: * be used to identify the ScriptEngine by the ScriptEngineManager.
091: * @return Returns an immutable list of short names for the ScriptEngine, which may be
092: * used to identify the ScriptEngine by the ScriptEngineManager.
093: */
094: public List<String> getNames() {
095: return names;
096: }
097:
098: /**
099: * Returns the name of the scripting langauge supported by this ScriptEngine
100: * @return The name of the supported language.
101: */
102: public String getLanguageName() {
103: return NAME;
104: }
105:
106: /**
107: * Returns the version of the scripting language supported by this ScriptEngine.
108: * @return The version of the supported language.
109: */
110: public String getLanguageVersion() {
111: return VERSION;
112: }
113:
114: /**
115: * Returns the value of an attribute whose meaning may be implementation-specific.
116: * Keys for which the value is defined in all implementations are:
117: * <p/>
118: * <ol>
119: * <li>ScriptEngine.ENGINE
120: * <li>ScriptEngine.ENGINE_VERSION
121: * <li>ScriptEngine.NAME
122: * <li>ScriptEngine.LANGUAGE
123: * <li>ScriptEngine.LANGUAGE_VERSION
124: * </ol>
125: * The values for these keys are the Strings returned by getEngineName, getEngineVersion,
126: * getName, getLanguageName and getLanguageVersion respectively.
127: * <p/>
128: * A reserved key, THREADING, whose value describes the behavior of the engine with respect
129: * to concurrent execution of scripts and maintenance of state is also defined. These values
130: * for the THREADING key are:
131: * <p/>
132: * <ol>
133: * <li>null - The engine implementation is not thread safe, and cannot be used to execute scripts
134: * concurrently on multiple threads.
135: * <li>"MULTITHREADED" - The engine implementation is internally thread-safe and scripts may execute
136: * concurrently although effects of script execution on one thread may be visible to scripts on other threads.
137: * <li>"THREAD-ISOLATED" - The implementation satisfies the requirements of "MULTITHREADED", and also,
138: * the engine maintains independent values for symbols in scripts executing on different threads.
139: * <li>"STATELESS" - The implementation satisfies the requirements of "THREAD-ISOLATED". In addition,
140: * script executions do not alter the mappings in the Bindings which is the engine scope of the ScriptEngine.
141: * In particular, the keys in the Bindings and their associated values are the same before and after the
142: * execution of the script.
143: * <p/>
144: * Implementations may define implementation-specific keys.
145: * @param param The name of the parameter
146: * @return The value for the given parameter. Returns null if no value is assigned to the key.
147: */
148: public Object getParameter(String param) {
149: if (param.equals(ScriptEngine.ENGINE))
150: return getEngineName();
151: if (param.equals(ScriptEngine.ENGINE_VERSION))
152: return getEngineVersion();
153: if (param.equals(ScriptEngine.NAME))
154: return getEngineName();
155: if (param.equals(ScriptEngine.LANGUAGE))
156: return getLanguageName();
157: if (param.equals(ScriptEngine.LANGUAGE_VERSION))
158: return getLanguageVersion();
159: if (param.equals("THREADING"))
160: return (isThreadSafe()) ? "MULTITHREADED" : null;
161:
162: return null;
163: }
164:
165: /**
166: * Returns a String which can be used to invoke a method of a Java object using the
167: * syntax of the supported scripting language. For more information on the syntax
168: * that MVEL uses, please see <a href="http://mvel.codehaus.org">http://mvel.codehaus.org</a>
169: * @param object The name representing the object whose method is to be invoked.
170: * The name is the one used to create bindings using the put method
171: * of ScriptEngine, the put method of an ENGINE_SCOPE Bindings, or
172: * the setAttribute method of ScriptContext. The identifier used in
173: * scripts may be a decorated form of the specified one.
174: * @param method The name of the method to invoke
175: * @param arguments The names of the arguments in the method call.
176: * @return The String used to invoke the method in the syntax of the scripting language.
177: */
178: public String getMethodCallSyntax(String object, String method,
179: String... arguments) {
180:
181: StringBuffer sb = new StringBuffer();
182: if (object != null) {
183: sb.append(object).append('.');
184: }
185:
186: sb.append(method).append('(');
187:
188: if (arguments.length > 0) {
189: sb.append(' ');
190: }
191:
192: for (int i = 0; i < arguments.length; i++) {
193: sb
194: .append(
195: (arguments[i] == null) ? NULL_SYMBOL
196: : arguments[i]).append(
197: i < (arguments.length - 1) ? ", " : ' ');
198: }
199:
200: sb.append(')');
201: return sb.toString();
202: }
203:
204: /**
205: * Returns a String that can be used as a statement to display
206: * the specified String using the syntax of the supported scripting
207: * language.
208: * @param message The String to be displayed by the returned statement.
209: * @return The string used to display the String in the syntax of the scripting language.
210: */
211: public String getOutputStatement(String message) {
212: return message;
213: }
214:
215: /**
216: * Returns A valid scripting language executable progam with given statements.
217: * @param statements The statements to be executed. May be return values of calls
218: * to the getMethodCallSyntax and getOutputStatement methods.
219: * @return The Program that can be invoked by the engine.
220: */
221: public String getProgram(String... statements) {
222:
223: StringBuffer sb = new StringBuffer();
224:
225: for (String stmt : statements) {
226: sb.append(stmt);
227: if (!stmt.endsWith(STATEMENT_TERMINATOR))
228: sb.append(STATEMENT_TERMINATOR);
229:
230: sb.append('\n');
231: }
232:
233: // The purpose of this check is to remove the last
234: // occurrence \n from the generated string.
235: if (sb.length() > 0) {
236: return sb.substring(0, sb.length() - 1);
237: } else {
238: return "";
239: }
240: }
241:
242: /**
243: * Returns an instance of the ScriptEngine associated with this ScriptEngineFactory.
244: * A new ScriptEngine is generally returned, but implementations may pool, share or reuse engines.
245: * In the case of MVFlex, a new instance is returned very time.
246: * @return A new ScriptEngine instance.
247: */
248: public ScriptEngine getScriptEngine() {
249: return new MVELScriptEngine(this);
250: }
251:
252: }
|