/*
* Scripted.java
*
* Created on 03 January 2005, 09:33
*/
package org.owasp.webscarab.plugin.scripted;
import java.util.ArrayList;
import java.util.List;
import org.owasp.webscarab.httpclient.ConversationHandler;
import org.owasp.webscarab.model.Preferences;
import org.owasp.webscarab.model.ConversationID;
import org.owasp.webscarab.model.Request;
import org.owasp.webscarab.model.Response;
import org.owasp.webscarab.model.StoreException;
import org.owasp.webscarab.httpclient.FetcherQueue;
import org.owasp.webscarab.httpclient.HTTPClientFactory;
import org.owasp.webscarab.plugin.FrameworkModelWrapper;
import org.owasp.webscarab.plugin.Plugin;
import org.owasp.webscarab.plugin.Framework;
import org.owasp.webscarab.plugin.Hook;
import org.apache.bsf.BSFManager;
import org.apache.bsf.BSFException;
import java.util.logging.Logger;
import java.io.File;
import java.io.Reader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.PrintStream;
/**
*
* @author rogan
*/
public class Scripted implements Plugin, ConversationHandler {
private Framework _framework;
private ScriptedUI _ui = null;
private File _scriptFile = null;
private String _script = null;
private String _scriptLanguage = null;
private BSFManager _bsfManager = new BSFManager();
private Thread _pluginThread = null;
private Logger _logger = Logger.getLogger(getClass().getName());
private boolean _running = false;
private boolean _stopping = false;
private boolean _runScript = false;
private String _status = "Stopped";
private Object _lock = new Object();
private ScriptedObjectModel _som;
private FrameworkModelWrapper _wrapper;
private int _threads = 4;
private FetcherQueue _fetcherQueue = null;
private List<Object> _responseQueue = new ArrayList<Object>();
private PrintStream _out = System.out;
private PrintStream _err = System.err;
/** Creates a new instance of Scripted */
public Scripted(Framework framework) {
_framework = framework;
_som = new ScriptedObjectModel(_framework, this);
_wrapper = new FrameworkModelWrapper(_framework.getModel());
try {
String defaultScript = Preferences.getPreference("Scripted.script");
if (defaultScript != null && !defaultScript.equals("")) {
loadScript(new File(defaultScript));
} else {
InputStream is = getClass().getResourceAsStream("script.bsh");
String language = "beanshell";
if (is == null) return;
loadScript(language, new InputStreamReader(is));
}
} catch (IOException ioe) {
_logger.warning("Error loading default script" + ioe.getMessage());
}
}
public void setUI(ScriptedUI ui) {
_ui = ui;
if (_ui == null) {
_out = System.out;
_err = System.err;
}
}
public void setOut(PrintStream out) {
if (out != null) {
_out = out;
} else {
_out = System.out;
}
}
public void setErr(PrintStream err) {
_err = err;
}
public void loadScript(File file) throws IOException {
if (file == null) {
_scriptFile = null;
if (_ui != null) _ui.scriptFileChanged(file);
setScript("", "");
return;
}
String language = "Unknown";
try {
language = BSFManager.getLangFromFilename(file.getName());
} catch (Throwable t) {}
loadScript(language, new FileReader(file));
_scriptFile = file;
if (_ui != null) _ui.scriptFileChanged(file);
}
public void saveScript(File file) throws IOException {
BufferedWriter bw = new BufferedWriter(new FileWriter(file));
bw.write(_script);
bw.close();
}
private void loadScript(String language, Reader reader) throws IOException {
_scriptFile = null;
setScript("", "");
BufferedReader br = new BufferedReader(reader);
String line;
StringBuffer script = new StringBuffer();
while ((line = br.readLine()) != null) {
script.append(line).append("\n");
}
br.close();
setScript(language, script.toString());
}
public File getScriptFile() {
return _scriptFile;
}
public String getScriptLanguage() {
return _scriptLanguage;
}
public String getScript() {
return _script;
}
public void setScript(String language, String script) {
_scriptLanguage = language;
_script = script;
if (_ui != null) {
_ui.scriptLanguageChanged(language);
_ui.scriptChanged(script);
}
}
public void analyse(ConversationID id, Request request, Response response, String origin) {
// we do no analysis in this plugin
}
public void flush() throws StoreException {
}
public String getPluginName() {
return "Scripted";
}
public String getStatus() {
return _status;
}
public boolean isBusy() {
return false;
}
public boolean isModified() {
return false;
}
public boolean isRunning() {
return _running;
}
public void run() {
_pluginThread = Thread.currentThread();
_running = true;
_stopping = false;
while (! _stopping) {
synchronized(_lock) {
try {
_status = "Idle";
_lock.wait();
} catch (InterruptedException ie) {
// interrupted by shutting down the plugin
}
}
if (_runScript) {
_runScript = false;
if (_ui != null) _ui.scriptStarted();
_status = "Running";
_fetcherQueue = new FetcherQueue("Scripted", this, _threads, 0);
try {
// _bsfManager.declareBean("framework", _framework, _framework.getClass());
_bsfManager.declareBean("model", _wrapper, _wrapper.getClass());
_bsfManager.declareBean("scripted", _som, _som.getClass());
_bsfManager.declareBean("out", _out, _out.getClass());
_bsfManager.declareBean("err", _err, _err.getClass());
_bsfManager.exec(_scriptLanguage, "Scripted", 0, 0, _script);
} catch (BSFException bsfe) {
if (_ui != null) _ui.scriptError("Unknown reason", bsfe);
}
_fetcherQueue.stop();
_fetcherQueue = null;
synchronized(_responseQueue) {
_responseQueue.clear();
}
if (_ui != null) _ui.scriptStopped();
}
}
_running = false;
}
Response fetchResponse(Request request) throws IOException {
return HTTPClientFactory.getInstance().fetchResponse(request);
}
boolean hasAsyncCapacity() {
return _fetcherQueue.getRequestsQueued() < _threads;
}
void submitAsyncRequest(Request request) {
_fetcherQueue.submit(request);
}
boolean isAsyncBusy() {
return _fetcherQueue.isBusy();
}
boolean hasAsyncResponse() {
synchronized (_responseQueue) {
return _responseQueue.size()>0;
}
}
public void requestError(Request request, IOException ioe) {
synchronized (_responseQueue) {
_responseQueue.add(ioe);
_responseQueue.notify();
}
}
public void responseReceived(Response response) {
synchronized (_responseQueue) {
_responseQueue.add(response);
_responseQueue.notify();
}
}
Response getAsyncResponse() throws IOException {
synchronized (_responseQueue) {
while (_responseQueue.size() == 0) {
try {
_responseQueue.wait();
} catch (InterruptedException ie) {}
}
Object obj = _responseQueue.remove(0);
if (obj instanceof Response) return (Response) obj;
throw (IOException) obj;
}
}
public void setSession(String type, Object store, String session) throws StoreException {
// we handle no persistent storage in this plugin
}
public boolean stop() {
_running = false;
stopScript();
return ! _running;
}
public void stopScript() {
if (_pluginThread != null && _pluginThread.isAlive())
_pluginThread.interrupt();
}
public void runScript() {
if (_scriptLanguage != null && _script != null) {
_runScript = true;
synchronized (_lock) {
_lock.notifyAll();
}
}
}
public Object getScriptableObject() {
return null;
}
public Hook[] getScriptingHooks() {
return new Hook[0];
}
}