001/* A Spark stub base class for executing a ScriptEngine.
002 * 
003 * Copyright (c) 2014 The Regents of the University of California.
004 * All rights reserved.
005 *
006 * '$Author: crawl $'
007 * '$Date: 2014-07-03 17:54:32 +0000 (Thu, 03 Jul 2014) $' 
008 * '$Revision: 32819 $'
009 * 
010 * Permission is hereby granted, without written agreement and without
011 * license or royalty fees, to use, copy, modify, and distribute this
012 * software and its documentation for any purpose, provided that the above
013 * copyright notice and the following two paragraphs appear in all copies
014 * of this software.
015 *
016 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
017 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
018 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
019 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
020 * SUCH DAMAGE.
021 *
022 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
023 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
024 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
025 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
026 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
027 * ENHANCEMENTS, OR MODIFICATIONS.
028 *
029 */
030package org.kepler.spark.stub;
031
032import java.util.LinkedList;
033import java.util.List;
034
035import javax.script.Invocable;
036import javax.script.ScriptEngine;
037import javax.script.ScriptEngineFactory;
038
039import org.apache.commons.logging.Log;
040import org.apache.commons.logging.LogFactory;
041import org.kepler.ddp.Utilities;
042
043/** A Spark stub base class for executing a ScriptEngine.
044 * 
045 *  @author Daniel Crawl
046 *  @version $Id: ScriptEnginePairFlatMapFunction.java 32819 2014-07-03 17:54:32Z crawl $
047 *  
048 */
049public abstract class ScriptEnginePairFlatMapFunction<T,K,V> extends PairFlatMapFunctionBase<T,K,V> {
050    
051    /** Free resources. */
052    protected void _cleanup() throws Exception
053    {
054        _engine = null;
055        _resultKeys = null;
056        _resultValues = null;
057    }
058
059    /** Configure the stub by loading the workflow and initialize the
060     *  class fields.
061     */
062    protected void _initialize() throws Exception {
063        
064        // get the script engine factory name
065        String scriptEngineFactoryName = 
066                _parameters.get(Utilities.CONFIGURATION_KEPLER_SCRIPT_ENGINE_FACTORY_NAME, null);
067        if(scriptEngineFactoryName == null) {
068            throw new RuntimeException("No script engine factory specified.");
069        }
070        
071        // get the code
072        String codeStr = _parameters.get(Utilities.CONFIGURATION_KEPLER_STUB_CODE, null);
073        if(codeStr == null) {
074            throw new RuntimeException("No code specified.");
075        }
076
077        // create the engine
078        
079        try {
080            Class<?> clazz = Class.forName(scriptEngineFactoryName);
081            ScriptEngineFactory factory = (ScriptEngineFactory)clazz.newInstance();
082            _engine = factory.getScriptEngine();
083        } catch(Throwable t) {
084            throw new RuntimeException("Error creating script engine for " + scriptEngineFactoryName, t);
085        }
086        
087        if(_engine == null) {
088            throw new RuntimeException("Could not find script engine for " + scriptEngineFactoryName);
089        }
090        
091        // works in java
092        // not in groovy
093        //_engine.eval("List resultKeys = new LinkedList(); List resultValues = new LinkedList();");
094        
095        
096        // not in groovy
097        //List resultKeys = new LinkedList(); List resultValues = new LinkedList();
098        //_engine.put("resultKeys", resultKeys);
099        //_engine.put("resultValues", resultValues);
100        
101        // parse the code
102        _engine.eval(codeStr);
103        
104        if(!(_engine instanceof Invocable)) {
105            throw new RuntimeException("Script engine for " + scriptEngineFactoryName + " is not invocable.");
106        }
107
108        _invocable = (Invocable) _engine;
109       
110        _resultKeys = new LinkedList<Object>();
111        _resultValues = new LinkedList<Object>();        
112    }
113        
114    /** The engine to parse scripts. */
115    private ScriptEngine _engine;
116    
117    /** Interface to execute functions in scripts. */
118    protected Invocable _invocable;
119    
120    /** A list of result keys. */
121    protected List<?> _resultKeys;
122    
123    /** A list of result values. */
124    protected List<?> _resultValues;
125
126    /** Logging. */
127    private static final Log LOG = LogFactory.getLog(ScriptEnginePairFlatMapFunction.class);
128    
129}