001: package bsh.servlet;
002:
003: import java.io.*;
004: import javax.servlet.*;
005: import javax.servlet.http.*;
006: import bsh.*;
007:
008: /**
009: This file is part of BeanShell - www.beanshell.org
010:
011: @author Pat Niemeyer
012: */
013: public class BshServlet extends HttpServlet {
014: static String bshVersion;
015: static String exampleScript = "print(\"hello!\");";
016:
017: static String getBshVersion() {
018: if (bshVersion != null)
019: return bshVersion;
020:
021: /*
022: We have included a getVersion() command to detect the version
023: of bsh. If bsh is packaged in the WAR file it could access it
024: directly as a bsh command. But if bsh is in the app server's
025: classpath it won't see it here, so we will source it directly.
026:
027: This command works around the lack of a coherent version number
028: in the early versions.
029: */
030: Interpreter bsh = new Interpreter();
031: try {
032: bsh.eval(new InputStreamReader(BshServlet.class
033: .getResource("getVersion.bsh").openStream()));
034: bshVersion = (String) bsh.eval("getVersion()");
035: } catch (Exception e) {
036: bshVersion = "BeanShell: unknown version";
037: }
038:
039: return bshVersion;
040: }
041:
042: public void doGet(HttpServletRequest request,
043: HttpServletResponse response) throws ServletException,
044: IOException {
045: String script = request.getParameter("bsh.script");
046: String client = request.getParameter("bsh.client");
047: String output = request.getParameter("bsh.servlet.output");
048: String captureOutErr = request
049: .getParameter("bsh.servlet.captureOutErr");
050: boolean capture = false;
051: if (captureOutErr != null
052: && captureOutErr.equalsIgnoreCase("true"))
053: capture = true;
054:
055: Object scriptResult = null;
056: Exception scriptError = null;
057: StringBuffer scriptOutput = new StringBuffer();
058: if (script != null) {
059: try {
060: scriptResult = evalScript(script, scriptOutput,
061: capture, request, response);
062: } catch (Exception e) {
063: scriptError = e;
064: }
065: }
066:
067: response.setHeader("Bsh-Return", String.valueOf(scriptResult));
068:
069: if ((output != null && output.equalsIgnoreCase("raw"))
070: || (client != null && client.equals("Remote")))
071: sendRaw(request, response, scriptError, scriptResult,
072: scriptOutput);
073: else
074: sendHTML(request, response, script, scriptError,
075: scriptResult, scriptOutput, capture);
076: }
077:
078: void sendHTML(HttpServletRequest request,
079: HttpServletResponse response, String script,
080: Exception scriptError, Object scriptResult,
081: StringBuffer scriptOutput, boolean capture)
082: throws IOException {
083: // Format the output using a simple templating utility
084: SimpleTemplate st = new SimpleTemplate(BshServlet.class
085: .getResource("page.template"));
086: st.replace("version", getBshVersion());
087:
088: //String requestURI = HttpUtils.getRequestURL( request ).toString()
089: // I was told this should work
090: String requestURI = request.getRequestURI();
091:
092: st.replace("servletURL", requestURI);
093: if (script != null)
094: st.replace("script", script);
095: else
096: st.replace("script", exampleScript);
097: if (capture)
098: st.replace("captureOutErr", "CHECKED");
099: else
100: st.replace("captureOutErr", "");
101: if (script != null)
102: st.replace("scriptResult", formatScriptResultHTML(script,
103: scriptResult, scriptError, scriptOutput));
104:
105: response.setContentType("text/html");
106: PrintWriter out = response.getWriter();
107: st.write(out);
108: out.flush();
109: }
110:
111: void sendRaw(HttpServletRequest request,
112: HttpServletResponse response, Exception scriptError,
113: Object scriptResult, StringBuffer scriptOutput)
114: throws IOException {
115: response.setContentType("text/plain");
116: PrintWriter out = response.getWriter();
117: if (scriptError != null)
118: out.println("Script Error:\n" + scriptError);
119: else
120: out.println(scriptOutput.toString());
121: out.flush();
122: }
123:
124: /**
125: */
126: String formatScriptResultHTML(String script, Object result,
127: Exception error, StringBuffer scriptOutput)
128: throws IOException {
129: SimpleTemplate tmplt;
130:
131: if (error != null) {
132: tmplt = new SimpleTemplate(getClass().getResource(
133: "error.template"));
134:
135: String errString;
136:
137: if (error instanceof bsh.EvalError) {
138: int lineNo = ((EvalError) error).getErrorLineNumber();
139: String msg = error.getMessage();
140: int contextLines = 4;
141: errString = escape(msg);
142: if (lineNo > -1)
143: errString += "<hr>"
144: + showScriptContextHTML(script, lineNo,
145: contextLines);
146: } else
147: errString = escape(error.toString());
148:
149: tmplt.replace("error", errString);
150: } else {
151: tmplt = new SimpleTemplate(getClass().getResource(
152: "result.template"));
153: tmplt.replace("value", escape(String.valueOf(result)));
154: tmplt.replace("output", escape(scriptOutput.toString()));
155: }
156:
157: return tmplt.toString();
158: }
159:
160: /*
161: Show context number lines of string before and after target line.
162: Add HTML formatting to bold the target line.
163: */
164: String showScriptContextHTML(String s, int lineNo, int context) {
165: StringBuffer sb = new StringBuffer();
166: BufferedReader br = new BufferedReader(new StringReader(s));
167:
168: int beginLine = Math.max(1, lineNo - context);
169: int endLine = lineNo + context;
170: for (int i = 1; i <= lineNo + context + 1; i++) {
171: if (i < beginLine) {
172: try {
173: br.readLine();
174: } catch (IOException e) {
175: throw new RuntimeException(e.toString());
176: }
177: continue;
178: }
179: if (i > endLine)
180: break;
181:
182: String line;
183: try {
184: line = br.readLine();
185: } catch (IOException e) {
186: throw new RuntimeException(e.toString());
187: }
188:
189: if (line == null)
190: break;
191: if (i == lineNo)
192: sb.append("<font color=\"red\">" + i + ": " + line
193: + "</font><br/>");
194: else
195: sb.append(i + ": " + line + "<br/>");
196: }
197:
198: return sb.toString();
199: }
200:
201: public void doPost(HttpServletRequest request,
202: HttpServletResponse response) throws ServletException,
203: IOException {
204: doGet(request, response);
205: }
206:
207: Object evalScript(String script, StringBuffer scriptOutput,
208: boolean captureOutErr, HttpServletRequest request,
209: HttpServletResponse response) throws EvalError {
210: // Create a PrintStream to capture output
211: ByteArrayOutputStream baos = new ByteArrayOutputStream();
212: PrintStream pout = new PrintStream(baos);
213:
214: // Create an interpreter instance with a null inputstream,
215: // the capture out/err stream, non-interactive
216: Interpreter bsh = new Interpreter(null, pout, pout, false);
217:
218: // set up interpreter
219: bsh.set("bsh.httpServletRequest", request);
220: bsh.set("bsh.httpServletResponse", response);
221:
222: // Eval the text, gathering the return value or any error.
223: Object result = null;
224: String error = null;
225: PrintStream sout = System.out;
226: PrintStream serr = System.err;
227: if (captureOutErr) {
228: System.setOut(pout);
229: System.setErr(pout);
230: }
231: try {
232: // Eval the user text
233: result = bsh.eval(script);
234: } finally {
235: if (captureOutErr) {
236: System.setOut(sout);
237: System.setErr(serr);
238: }
239: }
240: pout.flush();
241: scriptOutput.append(baos.toString());
242: return result;
243: }
244:
245: /**
246: * Convert special characters to entities for XML output
247: */
248: public static String escape(String value) {
249: String search = "&<>";
250: String[] replace = { "&", "<", ">" };
251:
252: StringBuffer buf = new StringBuffer();
253:
254: for (int i = 0; i < value.length(); i++) {
255: char c = value.charAt(i);
256: int pos = search.indexOf(c);
257: if (pos < 0)
258: buf.append(c);
259: else
260: buf.append(replace[pos]);
261: }
262:
263: return buf.toString();
264: }
265:
266: }
|