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 }