001
014
015 package com.liferay.portal.scripting.ruby;
016
017 import com.liferay.portal.kernel.scripting.BaseScriptingExecutor;
018 import com.liferay.portal.kernel.scripting.ExecutionException;
019 import com.liferay.portal.kernel.scripting.ScriptingException;
020 import com.liferay.portal.kernel.util.PortalClassLoaderUtil;
021 import com.liferay.portal.kernel.util.StringPool;
022 import com.liferay.portal.util.PortalUtil;
023 import com.liferay.portal.util.PropsValues;
024
025 import java.io.File;
026 import java.io.FileInputStream;
027 import java.io.FileNotFoundException;
028
029 import java.util.ArrayList;
030 import java.util.HashMap;
031 import java.util.List;
032 import java.util.Map;
033 import java.util.Set;
034
035 import org.jruby.RubyInstanceConfig.CompileMode;
036 import org.jruby.RubyInstanceConfig;
037 import org.jruby.embed.LocalContextScope;
038 import org.jruby.embed.ScriptingContainer;
039 import org.jruby.embed.internal.LocalContextProvider;
040 import org.jruby.exceptions.RaiseException;
041
042
046 public class RubyExecutor extends BaseScriptingExecutor {
047
048 public static final String LANGUAGE = "ruby";
049
050 public RubyExecutor() {
051 _scriptingContainer = new ScriptingContainer(
052 LocalContextScope.THREADSAFE);
053
054 LocalContextProvider localContextProvider =
055 _scriptingContainer.getProvider();
056
057 RubyInstanceConfig rubyInstanceConfig =
058 localContextProvider.getRubyInstanceConfig();
059
060 rubyInstanceConfig.setLoader(PortalClassLoaderUtil.getClassLoader());
061
062 if (PropsValues.SCRIPTING_JRUBY_COMPILE_MODE.equals(
063 _COMPILE_MODE_FORCE)) {
064
065 rubyInstanceConfig.setCompileMode(CompileMode.FORCE);
066 }
067 else if (PropsValues.SCRIPTING_JRUBY_COMPILE_MODE.equals(
068 _COMPILE_MODE_JIT)) {
069
070 rubyInstanceConfig.setCompileMode(CompileMode.JIT);
071 }
072
073 rubyInstanceConfig.setJitThreshold(
074 PropsValues.SCRIPTING_JRUBY_COMPILE_THRESHOLD);
075
076 _basePath = PortalUtil.getPortalLibDir();
077
078 _loadPaths = new ArrayList<String>(
079 PropsValues.SCRIPTING_JRUBY_LOAD_PATHS.length);
080
081 for (String gemLibPath : PropsValues.SCRIPTING_JRUBY_LOAD_PATHS) {
082 _loadPaths.add(gemLibPath);
083 }
084
085 rubyInstanceConfig.setLoadPaths(_loadPaths);
086
087 _scriptingContainer.setCurrentDirectory(_basePath);
088 }
089
090 @Override
091 public Map<String, Object> eval(
092 Set<String> allowedClasses, Map<String, Object> inputObjects,
093 Set<String> outputNames, File scriptFile)
094 throws ScriptingException {
095
096 return eval(
097 allowedClasses, inputObjects, outputNames, scriptFile, null);
098 }
099
100 public Map<String, Object> eval(
101 Set<String> allowedClasses, Map<String, Object> inputObjects,
102 Set<String> outputNames, String script)
103 throws ScriptingException {
104
105 return eval(allowedClasses, inputObjects, outputNames, null, script);
106 }
107
108 public String getLanguage() {
109 return LANGUAGE;
110 }
111
112 protected Map<String, Object> eval(
113 Set<String> allowedClasses, Map<String, Object> inputObjects,
114 Set<String> outputNames, File scriptFile, String script)
115 throws ScriptingException {
116
117 if (allowedClasses != null) {
118 throw new ExecutionException(
119 "Constrained execution not supported for Ruby");
120 }
121
122 try {
123 LocalContextProvider localContextProvider =
124 _scriptingContainer.getProvider();
125
126 RubyInstanceConfig rubyInstanceConfig =
127 localContextProvider.getRubyInstanceConfig();
128
129 rubyInstanceConfig.setCurrentDirectory(_basePath);
130 rubyInstanceConfig.setLoadPaths(_loadPaths);
131
132 for (Map.Entry<String, Object> entry : inputObjects.entrySet()) {
133 String inputName = entry.getKey();
134 Object inputObject = entry.getValue();
135
136 if (!inputName.startsWith(StringPool.DOLLAR)) {
137 inputName = StringPool.DOLLAR + inputName;
138 }
139
140 _scriptingContainer.put(inputName, inputObject);
141 }
142
143 if (scriptFile != null) {
144 _scriptingContainer.runScriptlet(
145 new FileInputStream(scriptFile), scriptFile.toString());
146 }
147 else {
148 _scriptingContainer.runScriptlet(script);
149 }
150
151 if (outputNames == null) {
152 return null;
153 }
154
155 Map<String, Object> outputObjects = new HashMap<String, Object>();
156
157 for (String outputName : outputNames) {
158 outputObjects.put(
159 outputName, _scriptingContainer.get(outputName));
160 }
161
162 return outputObjects;
163 }
164 catch (RaiseException re) {
165 throw new ScriptingException(
166 re.getException().message.asJavaString() + "\n\n", re);
167 }
168 catch (FileNotFoundException fnfe) {
169 throw new ScriptingException(fnfe);
170 }
171 }
172
173 private static final String _COMPILE_MODE_FORCE = "force";
174
175 private static final String _COMPILE_MODE_JIT = "jit";
176
177 private String _basePath;
178 private List<String> _loadPaths;
179 private ScriptingContainer _scriptingContainer;
180
181 }