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.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 }