001/* 002 * Copyright 2002-2016 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; 023 024import javax.script.Bindings; 025import javax.script.ScriptContext; 026import javax.script.ScriptEngine; 027import javax.script.ScriptEngineFactory; 028import javax.script.ScriptEngineManager; 029import javax.script.SimpleBindings; 030 031/** 032 * Common operations for dealing with a JSR-223 {@link ScriptEngine}. 033 * 034 * @author Juergen Hoeller 035 * @since 4.2.2 036 */ 037public abstract class StandardScriptUtils { 038 039 /** 040 * Retrieve a {@link ScriptEngine} from the given {@link ScriptEngineManager} 041 * by name, delegating to {@link ScriptEngineManager#getEngineByName} but 042 * throwing a descriptive exception if not found or if initialization failed. 043 * @param scriptEngineManager the ScriptEngineManager to use 044 * @param engineName the name of the engine 045 * @return a corresponding ScriptEngine (never {@code null}) 046 * @throws IllegalArgumentException if no matching engine has been found 047 * @throws IllegalStateException if the desired engine failed to initialize 048 */ 049 public static ScriptEngine retrieveEngineByName(ScriptEngineManager scriptEngineManager, String engineName) { 050 ScriptEngine engine = scriptEngineManager.getEngineByName(engineName); 051 if (engine == null) { 052 Set<String> engineNames = new LinkedHashSet<>(); 053 for (ScriptEngineFactory engineFactory : scriptEngineManager.getEngineFactories()) { 054 List<String> factoryNames = engineFactory.getNames(); 055 if (factoryNames.contains(engineName)) { 056 // Special case: getEngineByName returned null but engine is present... 057 // Let's assume it failed to initialize (which ScriptEngineManager silently swallows). 058 // If it happens to initialize fine now, alright, but we really expect an exception. 059 try { 060 engine = engineFactory.getScriptEngine(); 061 engine.setBindings(scriptEngineManager.getBindings(), ScriptContext.GLOBAL_SCOPE); 062 } 063 catch (Throwable ex) { 064 throw new IllegalStateException("Script engine with name '" + engineName + 065 "' failed to initialize", ex); 066 } 067 } 068 engineNames.addAll(factoryNames); 069 } 070 throw new IllegalArgumentException("Script engine with name '" + engineName + 071 "' not found; registered engine names: " + engineNames); 072 } 073 return engine; 074 } 075 076 static Bindings getBindings(Map<String, Object> bindings) { 077 return (bindings instanceof Bindings ? (Bindings) bindings : new SimpleBindings(bindings)); 078 } 079 080}