001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018 package org.apache.commons.jexl2.scripting;
019
020 import java.util.Arrays;
021 import java.util.Collections;
022 import java.util.List;
023
024 import javax.script.ScriptEngine;
025 import javax.script.ScriptEngineFactory;
026 import org.apache.commons.jexl2.JexlEngine;
027 import org.apache.commons.jexl2.parser.StringParser;
028
029 /**
030 * Implements the Jexl ScriptEngineFactory for JSF-223.
031 * <p>
032 * Supports the following:<br.>
033 * Language short names: "JEXL", "Jexl", "jexl" <br/>
034 * Extension: "jexl"
035 * </p>
036 * <p>
037 * See
038 * <a href="http://java.sun.com/javase/6/docs/api/javax/script/package-summary.html">Java Scripting API</a>
039 * Javadoc.
040 * @since 2.0
041 */
042 public class JexlScriptEngineFactory implements ScriptEngineFactory {
043
044 /** {@inheritDoc} */
045 public String getEngineName() {
046 return "JEXL Engine";
047 }
048
049 /** {@inheritDoc} */
050 public String getEngineVersion() {
051 return "1.0"; // ensure this is updated if function changes are made to this class
052 }
053
054 /** {@inheritDoc} */
055 public String getLanguageName() {
056 return "JEXL";
057 }
058
059 /** {@inheritDoc} */
060 public String getLanguageVersion() {
061 return "2.0"; // TODO this should be derived from the actual version
062 }
063
064 /** {@inheritDoc} */
065 public String getMethodCallSyntax(String obj, String m, String... args) {
066 StringBuilder sb = new StringBuilder();
067 sb.append(obj);
068 sb.append('.');
069 sb.append(m);
070 sb.append('(');
071 boolean needComma = false;
072 for(String arg : args){
073 if (needComma) {
074 sb.append(',');
075 }
076 sb.append(arg);
077 needComma = true;
078 }
079 sb.append(')');
080 return sb.toString();
081 }
082
083 /** {@inheritDoc} */
084 public List<String> getExtensions() {
085 return Collections.unmodifiableList(Arrays.asList("jexl"));
086 }
087
088 /** {@inheritDoc} */
089 public List<String> getMimeTypes() {
090 return Collections.unmodifiableList(Arrays.asList("application/x-jexl"));
091 }
092
093 /** {@inheritDoc} */
094 public List<String> getNames() {
095 return Collections.unmodifiableList(Arrays.asList("JEXL", "Jexl", "jexl"));
096 }
097
098 /** {@inheritDoc} */
099 public String getOutputStatement(String toDisplay) {
100 if (toDisplay == null) {
101 return "JEXL.out.print(null)";
102 } else {
103 return "JEXL.out.print("+StringParser.escapeString(toDisplay)+")";
104 }
105 }
106
107 /** {@inheritDoc} */
108 public Object getParameter(String key) {
109 if (key.equals(ScriptEngine.ENGINE)) {
110 return getEngineName();
111 } else if (key.equals(ScriptEngine.ENGINE_VERSION)) {
112 return getEngineVersion();
113 } else if (key.equals(ScriptEngine.NAME)) {
114 return getNames();
115 } else if (key.equals(ScriptEngine.LANGUAGE)) {
116 return getLanguageName();
117 } else if(key.equals(ScriptEngine.LANGUAGE_VERSION)) {
118 return getLanguageVersion();
119 } else if (key.equals("THREADING")) {
120 /*
121 * To implement multithreading, the scripting engine context (inherited from AbstractScriptEngine)
122 * would need to be made thread-safe; so would the setContext/getContext methods.
123 * It is easier to share the underlying Uberspect and JEXL engine instance, especially
124 * with an expression cache.
125 */
126 return null;
127 }
128 return null;
129 }
130
131 /** {@inheritDoc} */
132 public String getProgram(String... statements) {
133 StringBuilder sb = new StringBuilder();
134 for(String statement : statements){
135 sb.append(JexlEngine.cleanExpression(statement));
136 if (!statement.endsWith(";")){
137 sb.append(';');
138 }
139 }
140 return sb.toString();
141 }
142
143 /** {@inheritDoc} */
144 public ScriptEngine getScriptEngine() {
145 JexlScriptEngine engine = new JexlScriptEngine(this);
146 return engine;
147 }
148
149 }