1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 package org.apache.commons.jexl2.scripting;
19
20 import java.util.Arrays;
21 import java.util.Collections;
22 import java.util.List;
23
24 import javax.script.ScriptEngine;
25 import javax.script.ScriptEngineFactory;
26 import org.apache.commons.jexl2.JexlEngine;
27 import org.apache.commons.jexl2.parser.StringParser;
28
29 /**
30 * Implements the Jexl ScriptEngineFactory for JSF-223.
31 * <p>
32 * Supports the following:<br.>
33 * Language short names: "JEXL", "Jexl", "jexl", "JEXL2", "Jexl2", "jexl2" <br/>
34 * File Extensions: ".jexl", ".jexl2"<br/>
35 * "jexl2" etc. were added for engineVersion="2.0".
36 * </p>
37 * <p>
38 * See
39 * <a href="http://java.sun.com/javase/6/docs/api/javax/script/package-summary.html">Java Scripting API</a>
40 * Javadoc.
41 * @since 2.0
42 */
43 public class JexlScriptEngineFactory implements ScriptEngineFactory {
44
45 /** {@inheritDoc} */
46 public String getEngineName() {
47 return "JEXL Engine";
48 }
49
50 /** {@inheritDoc} */
51 public String getEngineVersion() {
52 return "2.0"; // ensure this is updated if function changes are made to this class
53 }
54
55 /** {@inheritDoc} */
56 public String getLanguageName() {
57 return "JEXL";
58 }
59
60 /** {@inheritDoc} */
61 public String getLanguageVersion() {
62 return "2.0"; // TODO this should be derived from the actual version
63 }
64
65 /** {@inheritDoc} */
66 public String getMethodCallSyntax(String obj, String m, String[] args) {
67 StringBuilder sb = new StringBuilder();
68 sb.append(obj);
69 sb.append('.');
70 sb.append(m);
71 sb.append('(');
72 boolean needComma = false;
73 for(String arg : args){
74 if (needComma) {
75 sb.append(',');
76 }
77 sb.append(arg);
78 needComma = true;
79 }
80 sb.append(')');
81 return sb.toString();
82 }
83
84 /** {@inheritDoc} */
85 public List<String> getExtensions() {
86 return Collections.unmodifiableList(Arrays.asList("jexl", "jexl2"));
87 }
88
89 /** {@inheritDoc} */
90 public List<String> getMimeTypes() {
91 return Collections.unmodifiableList(Arrays.asList("application/x-jexl", "application/x-jexl2"));
92 }
93
94 /** {@inheritDoc} */
95 public List<String> getNames() {
96 return Collections.unmodifiableList(Arrays.asList("JEXL", "Jexl", "jexl", "JEXL2", "Jexl2", "jexl2"));
97 }
98
99 /** {@inheritDoc} */
100 public String getOutputStatement(String toDisplay) {
101 if (toDisplay == null) {
102 return "JEXL.out.print(null)";
103 } else {
104 return "JEXL.out.print("+StringParser.escapeString(toDisplay, '\'')+")";
105 }
106 }
107
108 /** {@inheritDoc} */
109 public Object getParameter(String key) {
110 if (key.equals(ScriptEngine.ENGINE)) {
111 return getEngineName();
112 } else if (key.equals(ScriptEngine.ENGINE_VERSION)) {
113 return getEngineVersion();
114 } else if (key.equals(ScriptEngine.NAME)) {
115 return getNames();
116 } else if (key.equals(ScriptEngine.LANGUAGE)) {
117 return getLanguageName();
118 } else if(key.equals(ScriptEngine.LANGUAGE_VERSION)) {
119 return getLanguageVersion();
120 } else if (key.equals("THREADING")) {
121 /*
122 * To implement multithreading, the scripting engine context (inherited from AbstractScriptEngine)
123 * would need to be made thread-safe; so would the setContext/getContext methods.
124 * It is easier to share the underlying Uberspect and JEXL engine instance, especially
125 * with an expression cache.
126 */
127 return null;
128 }
129 return null;
130 }
131
132 /** {@inheritDoc} */
133 public String getProgram(String[] statements) {
134 StringBuilder sb = new StringBuilder();
135 for(String statement : statements){
136 sb.append(JexlEngine.cleanExpression(statement));
137 if (!statement.endsWith(";")){
138 sb.append(';');
139 }
140 }
141 return sb.toString();
142 }
143
144 /** {@inheritDoc} */
145 public ScriptEngine getScriptEngine() {
146 JexlScriptEngine engine = new JexlScriptEngine(this);
147 return engine;
148 }
149
150 }