001/* 002 * Copyright 2002-2015 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.scripting.support; 018 019import java.util.LinkedHashSet; 020import java.util.List; 021import java.util.Map; 022import java.util.Set; 023import javax.script.Bindings; 024import javax.script.ScriptContext; 025import javax.script.ScriptEngine; 026import javax.script.ScriptEngineFactory; 027import javax.script.ScriptEngineManager; 028import javax.script.SimpleBindings; 029 030/** 031 * Common operations for dealing with a JSR-223 {@link ScriptEngine}. 032 * 033 * @author Juergen Hoeller 034 * @since 4.2.2 035 */ 036public abstract class StandardScriptUtils { 037 038 /** 039 * Retrieve a {@link ScriptEngine} from the given {@link ScriptEngineManager} 040 * by name, delegating to {@link ScriptEngineManager#getEngineByName} but 041 * throwing a descriptive exception if not found or if initialization failed. 042 * @param scriptEngineManager the ScriptEngineManager to use 043 * @param engineName the name of the engine 044 * @return a corresponding ScriptEngine (never {@code null}) 045 * @throws IllegalArgumentException if no matching engine has been found 046 * @throws IllegalStateException if the desired engine failed to initialize 047 */ 048 public static ScriptEngine retrieveEngineByName(ScriptEngineManager scriptEngineManager, String engineName) { 049 ScriptEngine engine = scriptEngineManager.getEngineByName(engineName); 050 if (engine == null) { 051 Set<String> engineNames = new LinkedHashSet<String>(); 052 for (ScriptEngineFactory engineFactory : scriptEngineManager.getEngineFactories()) { 053 List<String> factoryNames = engineFactory.getNames(); 054 if (factoryNames.contains(engineName)) { 055 // Special case: getEngineByName returned null but engine is present... 056 // Let's assume it failed to initialize (which ScriptEngineManager silently swallows). 057 // If it happens to initialize fine now, alright, but we really expect an exception. 058 try { 059 engine = engineFactory.getScriptEngine(); 060 engine.setBindings(scriptEngineManager.getBindings(), ScriptContext.GLOBAL_SCOPE); 061 } 062 catch (Throwable ex) { 063 throw new IllegalStateException("Script engine with name '" + engineName + 064 "' failed to initialize", ex); 065 } 066 } 067 engineNames.addAll(factoryNames); 068 } 069 throw new IllegalArgumentException("Script engine with name '" + engineName + 070 "' not found; registered engine names: " + engineNames); 071 } 072 return engine; 073 } 074 075 static Bindings getBindings(Map<String, Object> bindings) { 076 return (bindings instanceof Bindings ? (Bindings) bindings : new SimpleBindings(bindings)); 077 } 078 079}