001    /**
002     * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
014    
015    package com.liferay.portal.scripting.ruby;
016    
017    import com.liferay.portal.kernel.scripting.ExecutionException;
018    import com.liferay.portal.kernel.scripting.ScriptingException;
019    import com.liferay.portal.kernel.scripting.ScriptingExecutor;
020    import com.liferay.portal.kernel.util.PortalClassLoaderUtil;
021    import com.liferay.portal.kernel.util.StringPool;
022    
023    import java.util.ArrayList;
024    import java.util.HashMap;
025    import java.util.Map;
026    import java.util.Set;
027    
028    import org.jruby.Ruby;
029    import org.jruby.RubyInstanceConfig;
030    import org.jruby.exceptions.RaiseException;
031    import org.jruby.internal.runtime.GlobalVariables;
032    import org.jruby.javasupport.JavaEmbedUtils;
033    
034    /**
035     * @author Alberto Montero
036     */
037    public class RubyExecutor implements ScriptingExecutor {
038    
039            public static final String LANGUAGE = "ruby";
040    
041            public RubyExecutor() {
042                    RubyInstanceConfig rubyInstanceConfig = new RubyInstanceConfig();
043    
044                    rubyInstanceConfig.setLoader(PortalClassLoaderUtil.getClassLoader());
045    
046                    _ruby = JavaEmbedUtils.initialize(
047                            new ArrayList<String>(), rubyInstanceConfig);
048            }
049    
050            public void clearCache() {
051            }
052    
053            public String getLanguage() {
054                    return LANGUAGE;
055            }
056    
057            public Map<String, Object> eval(
058                            Set<String> allowedClasses, Map<String, Object> inputObjects,
059                            Set<String> outputNames, String script)
060                    throws ScriptingException {
061    
062                    if (allowedClasses != null) {
063                            throw new ExecutionException(
064                                    "Constrained execution not supported for Ruby");
065                    }
066    
067                    try {
068                            GlobalVariables globalVariables = _ruby.getGlobalVariables();
069    
070                            for (Map.Entry<String, Object> entry : inputObjects.entrySet()) {
071                                    String inputName = entry.getKey();
072                                    Object inputObject = entry.getValue();
073    
074                                    if (!inputName.startsWith(StringPool.DOLLAR)) {
075                                            inputName = StringPool.DOLLAR + inputName;
076                                    }
077    
078                                    BeanGlobalVariable beanGlobalVariable = new BeanGlobalVariable(
079                                            _ruby, inputObject, inputObject.getClass());
080    
081                                    globalVariables.define(inputName, beanGlobalVariable);
082                            }
083    
084                            _ruby.evalScriptlet(script);
085    
086                            if (outputNames == null) {
087                                    return null;
088                            }
089    
090                            Map<String, Object> outputObjects = new HashMap<String, Object>();
091    
092                            for (String outputName : outputNames) {
093                                    outputObjects.put(outputName, globalVariables.get(outputName));
094                            }
095    
096                            return outputObjects;
097                    }
098                    catch (RaiseException re) {
099                            throw new ScriptingException(
100                                    re.getException().message.asJavaString() + "\n\n", re);
101                    }
102                    finally {
103                            JavaEmbedUtils.terminate(_ruby);
104                    }
105            }
106    
107            private Ruby _ruby;
108    
109    }