View Javadoc
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.jexl3.scripting;
19  
20  import org.apache.commons.jexl3.parser.StringParser;
21  
22  import javax.script.ScriptEngine;
23  import javax.script.ScriptEngineFactory;
24  import java.util.Arrays;
25  import java.util.Collections;
26  import java.util.List;
27  
28  /**
29   * Implements the JEXL ScriptEngineFactory for JSF-223.
30   * <p>
31   * Supports the following:<br>
32   * Language short names: "JEXL", "Jexl", "jexl", "JEXL2", "Jexl2", "jexl2", "JEXL3", "Jexl3", "jexl3" <br>
33   * File Extensions: ".jexl", ".jexl2", ".jexl3"<br>
34   * "jexl3" etc. were added for engineVersion="3.0".
35   * </p>
36   * <p>
37   * See
38   * <a href="http://java.sun.com/javase/6/docs/api/javax/script/package-summary.html">Java Scripting API</a>
39   * Javadoc.
40   *
41   * @since 2.0
42   */
43  public class JexlScriptEngineFactory implements ScriptEngineFactory {
44  
45      @Override
46      public String getEngineName() {
47          return "JEXL Engine";
48      }
49  
50      @Override
51      public String getEngineVersion() {
52          return "3.3"; // ensure this is updated if function changes are made to this class
53      }
54  
55      @Override
56      public String getLanguageName() {
57          return "JEXL";
58      }
59  
60      @Override
61      public String getLanguageVersion() {
62          return "3.3"; // this should be derived from the actual version
63      }
64  
65      @Override
66      public String getMethodCallSyntax(final String obj, final String m, final String... args) {
67          final StringBuilder sb = new StringBuilder();
68          sb.append(obj);
69          sb.append('.');
70          sb.append(m);
71          sb.append('(');
72          boolean needComma = false;
73          for(final 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      @Override
85      public List<String> getExtensions() {
86          return Collections.unmodifiableList(Arrays.asList("jexl", "jexl2", "jexl3"));
87      }
88  
89      @Override
90      public List<String> getMimeTypes() {
91          return Collections.unmodifiableList(Arrays.asList("application/x-jexl",
92                                                            "application/x-jexl2",
93                                                            "application/x-jexl3"));
94      }
95  
96      @Override
97      public List<String> getNames() {
98          return Collections.unmodifiableList(Arrays.asList("JEXL", "Jexl", "jexl",
99                                                            "JEXL2", "Jexl2", "jexl2",
100                                                           "JEXL3", "Jexl3", "jexl3"));
101     }
102 
103     @Override
104     public String getOutputStatement(final String toDisplay) {
105         if (toDisplay == null) {
106             return "JEXL.out.print(null)";
107         }
108         return "JEXL.out.print("+StringParser.escapeString(toDisplay, '\'')+")";
109     }
110 
111     @Override
112     public Object getParameter(final String key) {
113         switch (key) {
114             case ScriptEngine.ENGINE:
115                 return getEngineName();
116             case ScriptEngine.ENGINE_VERSION:
117                 return getEngineVersion();
118             case ScriptEngine.NAME:
119                 return getNames();
120             case ScriptEngine.LANGUAGE:
121                 return getLanguageName();
122             case ScriptEngine.LANGUAGE_VERSION:
123                 return getLanguageVersion();
124             case "THREADING":
125                 /*
126                  * To implement multithreading, the scripting engine context (inherited from AbstractScriptEngine)
127                  * would need to be made thread-safe; so would the setContext/getContext methods.
128                  * It is easier to share the underlying Uberspect and JEXL engine instance, especially
129                  * with an expression cache.
130                  */
131             default:
132                 return null;
133         }
134     }
135 
136     @Override
137     public String getProgram(final String... statements) {
138         final StringBuilder sb = new StringBuilder();
139         for(final String statement : statements){
140             sb.append(statement.trim());
141             if (!statement.endsWith(";")){
142                 sb.append(';');
143             }
144         }
145         return sb.toString();
146     }
147 
148     @Override
149     public ScriptEngine getScriptEngine() {
150         return new JexlScriptEngine(this);
151     }
152 
153 }