package net.grinder.scriptengine.jython;
import java.util.ArrayList;
import java.util.List;
import net.grinder.common.GrinderProperties;
import net.grinder.engine.common.EngineException;
import net.grinder.engine.common.ScriptLocation;
import net.grinder.scriptengine.DCRContext;
import net.grinder.scriptengine.Instrumenter;
import net.grinder.scriptengine.ScriptEngineService;
import net.grinder.scriptengine.jython.instrumentation.dcr.Jython22Instrumenter;
import net.grinder.scriptengine.jython.instrumentation.dcr.Jython25Instrumenter;
import net.grinder.scriptengine.jython.instrumentation.traditional.TraditionalJythonInstrumenter;
import net.grinder.util.FileExtensionMatcher;
import net.grinder.util.weave.WeavingException;
/**
* Jython {@link net.grinder.scriptengine.ScriptEngineService} implementation.
*
* @author Philip Aston
* @author JunHo Yoon (modified by)
*/
@SuppressWarnings("UnusedDeclaration")
public final class JythonScriptEngineService implements ScriptEngineService {
private final FileExtensionMatcher m_pyFileMatcher = new FileExtensionMatcher(".py");
private final boolean m_forceDCRInstrumentation;
private final DCRContext m_dcrContext;
/**
* Constructor.
*
* @param properties Properties.
* @param dcrContext DCR context.
* @param scriptLocation Script location.
*/
public JythonScriptEngineService(GrinderProperties properties, DCRContext dcrContext, ScriptLocation scriptLocation) {
// This property name is poor, since it really means "If DCR
// instrumentation is available, avoid the traditional Jython
// instrumenter". I'm not renaming it, since I expect it only to last
// a few releases, until DCR becomes the default.
m_forceDCRInstrumentation = properties.getBoolean("grinder.dcrinstrumentation", false) ||
// Hack: force DCR instrumentation for non-Jython scripts.
!m_pyFileMatcher.accept(scriptLocation.getFile());
m_dcrContext = dcrContext;
}
/**
* Constructor used when DCR is unavailable.
*/
public JythonScriptEngineService() {
m_dcrContext = null;
m_forceDCRInstrumentation = false;
}
public void noOp() {
}
/**
* {@inheritDoc}
*/
@Override
public List<Instrumenter> createInstrumenters() throws EngineException {
final List<Instrumenter> instrumenters = new ArrayList<Instrumenter>();
try {
if (!m_forceDCRInstrumentation) {
try {
instrumenters.add(new TraditionalJythonInstrumenter());
} catch (EngineException e) {
noOp();
} catch (VerifyError e) {
noOp();
}
}
if (m_dcrContext != null) {
if (instrumenters.size() == 0) {
try {
instrumenters.add(new Jython25Instrumenter(m_dcrContext));
} catch (WeavingException e) {
// Jython 2.5 not available, try Jython 2.1/2.2.
instrumenters.add(new Jython22Instrumenter(m_dcrContext));
}
}
}
} catch (NoClassDefFoundError e) {
noOp();
}
return instrumenters;
}
/**
* {@inheritDoc}
*/
@Override
public ScriptEngine createScriptEngine(ScriptLocation script) throws EngineException {
if (m_pyFileMatcher.accept(script.getFile())) {
return new JythonScriptEngine(script);
}
return null;
}
}