package bsh.servlet;
import java.io.*;
import javax.
servlet.*;
import javax.
servlet.
http.*;
import bsh.*;
/**
This file is part of BeanShell - www.beanshell.org
@author Pat Niemeyer
*/
public class
BshServlet extends
HttpServlet
{
static
String bshVersion;
static
String exampleScript = "print(\"hello!\");";
static
String getBshVersion()
{
if (
bshVersion != null )
return
bshVersion;
/*
We have included a getVersion() command to detect the version
of bsh. If bsh is packaged in the WAR file it could access it
directly as a bsh command. But if bsh is in the app server's
classpath it won't see it here, so we will source it directly.
This command works around the lack of a coherent version number
in the early versions.
*/
Interpreter bsh = new
Interpreter();
try {
bsh.
eval( new
InputStreamReader(
BshServlet.class.
getResource(
"getVersion.bsh").
openStream() ) );
bshVersion = (
String)
bsh.
eval( "getVersion()" );
} catch (
Exception e ) {
bshVersion = "BeanShell: unknown version";
}
return
bshVersion;
}
public void doGet(
HttpServletRequest request,
HttpServletResponse response)
throws
ServletException,
IOException
{
String script =
request.
getParameter("bsh.script");
String client =
request.
getParameter("bsh.client");
String output =
request.
getParameter("bsh.servlet.output");
String captureOutErr =
request.
getParameter("bsh.servlet.captureOutErr");
boolean
capture = false;
if (
captureOutErr != null &&
captureOutErr.
equalsIgnoreCase("true") )
capture = true;
Object scriptResult = null;
Exception scriptError = null;
StringBuffer scriptOutput = new
StringBuffer();
if (
script != null ) {
try {
scriptResult =
evalScript(
script,
scriptOutput,
capture,
request,
response );
} catch (
Exception e ) {
scriptError =
e;
}
}
response.
setHeader( "Bsh-Return",
String.
valueOf(
scriptResult) );
if ( (
output != null &&
output.
equalsIgnoreCase("raw"))
|| (
client != null &&
client.
equals("Remote") ) )
sendRaw(
request,
response,
scriptError,
scriptResult,
scriptOutput );
else
sendHTML(
request,
response,
script,
scriptError,
scriptResult,
scriptOutput,
capture );
}
void sendHTML(
HttpServletRequest request,
HttpServletResponse response,
String script,
Exception scriptError,
Object scriptResult,
StringBuffer scriptOutput, boolean
capture )
throws
IOException
{
// Format the output using a simple templating utility
SimpleTemplate st = new
SimpleTemplate(
BshServlet.class.
getResource("page.template") );
st.
replace( "version",
getBshVersion() );
//String requestURI = HttpUtils.getRequestURL( request ).toString()
// I was told this should work
String requestURI =
request.
getRequestURI();
st.
replace( "servletURL",
requestURI );
if (
script != null )
st.
replace( "script",
script );
else
st.
replace( "script",
exampleScript );
if (
capture )
st.
replace( "captureOutErr", "CHECKED" );
else
st.
replace( "captureOutErr", "" );
if (
script != null )
st.
replace( "scriptResult",
formatScriptResultHTML(
script,
scriptResult,
scriptError,
scriptOutput ) );
response.
setContentType("text/html");
PrintWriter out =
response.
getWriter();
st.
write(
out);
out.
flush();
}
void sendRaw(
HttpServletRequest request,
HttpServletResponse response,
Exception scriptError,
Object scriptResult,
StringBuffer scriptOutput )
throws
IOException
{
response.
setContentType("text/plain");
PrintWriter out =
response.
getWriter();
if (
scriptError != null )
out.
println( "Script Error:\n"+
scriptError );
else
out.
println(
scriptOutput.
toString() );
out.
flush();
}
/**
*/
String formatScriptResultHTML(
String script,
Object result,
Exception error,
StringBuffer scriptOutput )
throws
IOException
{
SimpleTemplate tmplt;
if (
error != null )
{
tmplt = new
SimpleTemplate(
getClass().
getResource("error.template") );
String errString;
if (
error instanceof bsh.
EvalError )
{
int
lineNo = ((
EvalError)
error).
getErrorLineNumber();
String msg =
error.
getMessage();
int
contextLines = 4;
errString =
escape(
msg);
if (
lineNo > -1 )
errString += "<hr>"
+
showScriptContextHTML(
script,
lineNo,
contextLines );
} else
errString =
escape(
error.
toString() );
tmplt.
replace("error",
errString );
} else {
tmplt = new
SimpleTemplate(
getClass().
getResource("result.template") );
tmplt.
replace( "value",
escape(
String.
valueOf(
result)) );
tmplt.
replace( "output",
escape(
scriptOutput.
toString()) );
}
return
tmplt.
toString();
}
/*
Show context number lines of string before and after target line.
Add HTML formatting to bold the target line.
*/
String showScriptContextHTML(
String s, int
lineNo, int
context )
{
StringBuffer sb = new
StringBuffer();
BufferedReader br = new
BufferedReader( new
StringReader(
s) );
int
beginLine =
Math.
max( 1,
lineNo-
context );
int
endLine =
lineNo +
context;
for( int
i=1;
i<=
lineNo+
context+1;
i++ )
{
if (
i <
beginLine )
{
try {
br.
readLine();
} catch (
IOException e ) {
throw new
RuntimeException(
e.
toString() );
}
continue;
}
if (
i >
endLine )
break;
String line;
try {
line =
br.
readLine();
} catch (
IOException e ) {
throw new
RuntimeException(
e.
toString() );
}
if (
line == null )
break;
if (
i ==
lineNo )
sb.
append( "<font color=\"red\">"+
i+": "+
line +"</font><br/>" );
else
sb.
append(
i+": " +
line +"<br/>" );
}
return
sb.
toString();
}
public void doPost(
HttpServletRequest request,
HttpServletResponse response)
throws
ServletException,
IOException
{
doGet(
request,
response );
}
Object evalScript(
String script,
StringBuffer scriptOutput, boolean
captureOutErr,
HttpServletRequest request,
HttpServletResponse response )
throws
EvalError
{
// Create a PrintStream to capture output
ByteArrayOutputStream baos = new
ByteArrayOutputStream();
PrintStream pout = new
PrintStream(
baos );
// Create an interpreter instance with a null inputstream,
// the capture out/err stream, non-interactive
Interpreter bsh = new
Interpreter( null,
pout,
pout, false );
// set up interpreter
bsh.
set( "bsh.httpServletRequest",
request );
bsh.
set( "bsh.httpServletResponse",
response );
// Eval the text, gathering the return value or any error.
Object result = null;
String error = null;
PrintStream sout =
System.
out;
PrintStream serr =
System.
err;
if (
captureOutErr ) {
System.
setOut(
pout );
System.
setErr(
pout );
}
try {
// Eval the user text
result =
bsh.
eval(
script );
} finally {
if (
captureOutErr ) {
System.
setOut(
sout );
System.
setErr(
serr );
}
}
pout.
flush();
scriptOutput.
append(
baos.
toString() );
return
result;
}
/**
* Convert special characters to entities for XML output
*/
public static
String escape(
String value)
{
String search = "&<>";
String[]
replace = {"&", "<", ">"};
StringBuffer buf = new
StringBuffer();
for (int
i = 0;
i <
value.
length();
i++)
{
char
c =
value.
charAt(
i);
int
pos =
search.
indexOf(
c);
if (
pos < 0)
buf.
append(
c);
else
buf.
append(
replace[
pos]);
}
return
buf.
toString();
}
}