1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 package groovy.servlet;
33
34 import groovy.lang.Binding;
35 import groovy.lang.Closure;
36 import groovy.util.GroovyScriptEngine;
37 import groovy.util.ResourceException;
38 import groovy.util.ScriptException;
39
40 import java.io.IOException;
41
42 import javax.servlet.ServletConfig;
43 import javax.servlet.ServletException;
44 import javax.servlet.http.HttpServletRequest;
45 import javax.servlet.http.HttpServletResponse;
46
47 import org.codehaus.groovy.runtime.GroovyCategorySupport;
48
49 /***
50 * This servlet will run Groovy scripts as Groovlets. Groovlets are scripts
51 * with these objects implicit in their scope:
52 *
53 * <ul>
54 * <li>request - the HttpServletRequest</li>
55 * <li>response - the HttpServletResponse</li>
56 * <li>application - the ServletContext associated with the servlet</li>
57 * <li>session - the HttpSession associated with the HttpServletRequest</li>
58 * <li>out - the PrintWriter associated with the ServletRequest</li>
59 * </ul>
60 *
61 * <p>Your script sources can be placed either in your web application's normal
62 * web root (allows for subdirectories) or in /WEB-INF/groovy/* (also allows
63 * subdirectories).
64 *
65 * <p>To make your web application more groovy, you must add the GroovyServlet
66 * to your application's web.xml configuration using any mapping you like, so
67 * long as it follows the pattern *.* (more on this below). Here is the
68 * web.xml entry:
69 *
70 * <pre>
71 * <servlet>
72 * <servlet-name>Groovy</servlet-name>
73 * <servlet-class>groovy.servlet.GroovyServlet</servlet-class>
74 * </servlet>
75 *
76 * <servlet-mapping>
77 * <servlet-name>Groovy</servlet-name>
78 * <url-pattern>*.groovy</url-pattern>
79 * <url-pattern>*.gdo</url-pattern>
80 * </servlet-mapping>
81 * </pre>
82 *
83 * <p>The URL pattern does not require the "*.groovy" mapping. You can, for
84 * example, make it more Struts-like but groovy by making your mapping "*.gdo".
85 *
86 * @author Sam Pullara
87 * @author Mark Turansky (markturansky at hotmail.com)
88 * @author Guillaume Laforge
89 * @author Christian Stein
90 *
91 * @see groovy.servlet.ServletBinding
92 */
93 public class GroovyServlet extends AbstractHttpServlet {
94
95 /***
96 * The script engine executing the Groovy scripts for this servlet
97 */
98 private static GroovyScriptEngine gse;
99
100 /***
101 * Initialize the GroovyServlet.
102 *
103 * @throws ServletException
104 * if this method encountered difficulties
105 */
106 public void init(ServletConfig config) throws ServletException {
107 super.init(config);
108
109
110 gse = new GroovyScriptEngine(this);
111
112 servletContext.log("Groovy servlet initialized on " + gse + ".");
113 }
114
115 /***
116 * Handle web requests to the GroovyServlet
117 */
118 public void service(HttpServletRequest request, HttpServletResponse response) throws IOException {
119
120
121 final String scriptUri = getScriptUri(request);
122
123
124 response.setContentType("text/html");
125
126
127 final Binding binding = new ServletBinding(request, response, servletContext);
128
129
130 try {
131 Closure closure = new Closure(gse) {
132
133 public Object call() {
134 try {
135 return ((GroovyScriptEngine) getDelegate()).run(scriptUri, binding);
136 } catch (ResourceException e) {
137 throw new RuntimeException(e);
138 } catch (ScriptException e) {
139 throw new RuntimeException(e);
140 }
141 }
142
143 };
144 GroovyCategorySupport.use(ServletCategory.class, closure);
145
146
147
148 response.setStatus(HttpServletResponse.SC_OK);
149 } catch (RuntimeException runtimeException) {
150 StringBuffer error = new StringBuffer("GroovyServlet Error: ");
151 error.append(" script: '");
152 error.append(scriptUri);
153 error.append("': ");
154 Throwable e = runtimeException.getCause();
155
156
157
158 if (e == null) {
159 error.append(" Script processing failed.");
160 error.append(runtimeException.getMessage());
161 error.append(runtimeException.getStackTrace()[0].toString());
162 servletContext.log(error.toString());
163 System.err.println(error.toString());
164 runtimeException.printStackTrace(System.err);
165 response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, error.toString());
166 return;
167 }
168
169
170
171 if (e instanceof ResourceException) {
172 error.append(" Script not found, sending 404.");
173 servletContext.log(error.toString());
174 System.err.println(error.toString());
175 response.sendError(HttpServletResponse.SC_NOT_FOUND);
176 return;
177 }
178
179
180
181 servletContext.log("An error occurred processing the request", runtimeException);
182 error.append(e.getMessage());
183 error.append(e.getStackTrace()[0].toString());
184 servletContext.log(e.toString());
185 System.err.println(e.toString());
186 runtimeException.printStackTrace(System.err);
187 response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.toString());
188 } finally {
189
190
191
192 response.flushBuffer();
193
194 }
195 }
196
197 }