package org.marketcetera.strategy;
import static org.marketcetera.strategy.Messages.COMPILATION_FAILED;
import static org.marketcetera.strategy.Messages.NO_SUPPORT_FOR_LANGUAGE;
import java.util.Vector;
import org.apache.bsf.BSFEngine;
import org.apache.bsf.BSFException;
import org.apache.bsf.BSFManager;
import org.jruby.exceptions.RaiseException;
import org.marketcetera.core.ClassVersion;
import org.marketcetera.event.impl.LogEventBuilder;
import org.marketcetera.strategy.CompilationFailed.Diagnostic;
import org.marketcetera.util.log.I18NBoundMessage1P;
import org.marketcetera.util.log.SLF4JLoggerProxy;
/* $License$ */
/**
* {@link ExecutionEngine} implementation which uses <a href="http://jakarta.apache.org/bsf">Apache Bean Scriping Framewok</a>
* to execute scripts.
*
* @author <a href="mailto:colin@marketcetera.com">Colin DuPlantis</a>
* @version $Id: BeanScriptingFrameworkEngine.java 16154 2012-07-14 16:34:05Z colin $
* @since 1.0.0
*/
@ClassVersion("$Id: BeanScriptingFrameworkEngine.java 16154 2012-07-14 16:34:05Z colin $")
class BeanScriptingFrameworkEngine
implements ExecutionEngine
{
/**
* script engine manager
*/
private static final BSFManager scriptManager = new BSFManager();
/**
* the script engine responsible for executing this script
*/
private static BSFEngine scriptEngine;
/**
* the strategy to execute
*/
private Strategy strategy;
/**
* the processed script to execute
*/
private String processedScript;
/* (non-Javadoc)
* @see org.marketcetera.strategy.ExecutionEngine#prepare(org.marketcetera.strategy.Strategy, java.lang.String)
*/
@Override
public void prepare(Strategy inStrategy,
String inProcessedScript)
throws StrategyException
{
strategy = inStrategy;
processedScript = inProcessedScript;
SLF4JLoggerProxy.debug(this,
"Preparing {}", //$NON-NLS-1$
inStrategy);
registerScriptEngines();
String languageString = inStrategy.getLanguage().name();
try {
synchronized(scriptManager) {
if(scriptEngine == null) {
String classpath = System.getProperty(Strategy.CLASSPATH_PROPERTYNAME);
SLF4JLoggerProxy.debug(this,
"Setting classpath to {}", //$NON-NLS-1$
classpath);
scriptManager.setClassPath(classpath);
scriptEngine = scriptManager.loadScriptingEngine(languageString);
SLF4JLoggerProxy.debug(this,
"Initializing engine..."); //$NON-NLS-1$
scriptEngine.initialize(scriptManager,
languageString,
new Vector<Object>());
} else {
SLF4JLoggerProxy.debug(this,
"Reusing intialized engine..."); //$NON-NLS-1$
}
}
} catch (BSFException e) {
StrategyModule.log(LogEventBuilder.error().withMessage(NO_SUPPORT_FOR_LANGUAGE,
languageString)
.withException(e).create(),
strategy);
throw new StrategyException(e,
new I18NBoundMessage1P(NO_SUPPORT_FOR_LANGUAGE,
languageString));
}
}
/* (non-Javadoc)
* @see org.marketcetera.strategy.ExecutionEngine#start()
*/
@Override
public Object start()
throws StrategyException
{
try {
return scriptEngine.eval(strategy.getLanguage().name(),
0,
0,
processedScript);
} catch (BSFException e) {
CompilationFailed failed = new CompilationFailed(strategy);
if(e.getTargetException() instanceof RaiseException) {
failed.addDiagnostic(Diagnostic.error(RubyExecutor.exceptionAsString(e)));
}
StrategyModule.log(LogEventBuilder.error().withMessage(COMPILATION_FAILED,
String.valueOf(strategy),
failed.toString())
.withException(failed).create(),
strategy);
throw failed;
}
}
/* (non-Javadoc)
* @see org.marketcetera.strategy.ExecutionEngine#stop()
*/
@Override
public void stop()
throws StrategyException
{
}
/**
* Registers script engines needed for language support.
*
* <p>When adding support to this class for a new engine, this method must be modified to support that language
*/
private static void registerScriptEngines()
{
if(!BSFManager.isLanguageRegistered(Language.RUBY.name())) {
BSFManager.registerScriptingEngine(Language.RUBY.name(),
"org.jruby.javasupport.bsf.JRubyEngine", //$NON-NLS-1$
new String[] { "rb" }); //$NON-NLS-1$
}
}
}