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.MetaClass;
36 import groovy.lang.Closure;
37 import groovy.util.GroovyScriptEngine;
38 import groovy.util.ResourceConnector;
39 import groovy.util.ResourceException;
40 import groovy.util.ScriptException;
41
42 import java.io.IOException;
43 import java.net.URL;
44 import java.net.URLConnection;
45 import java.util.Collections;
46 import java.util.Enumeration;
47 import java.util.HashMap;
48 import java.util.Map;
49
50 import javax.servlet.ServletConfig;
51 import javax.servlet.ServletContext;
52 import javax.servlet.ServletException;
53 import javax.servlet.ServletRequest;
54 import javax.servlet.ServletResponse;
55 import javax.servlet.http.HttpServlet;
56 import javax.servlet.http.HttpServletRequest;
57 import javax.servlet.http.HttpServletResponse;
58
59 import org.codehaus.groovy.runtime.GroovyCategorySupport;
60
61 /***
62 * This servlet should be registered to *.groovy in the web.xml.
63 *
64 * <servlet><servlet-name>Groovy</servlet-name><servlet-class>
65 * groovy.servlet.GroovyServlet</servlet-class></servlet>
66 *
67 * <servlet-mapping><servlet-name>Groovy</servlet-name><url-pattern>
68 * *.groovy</url-pattern></servlet-mapping>
69 *
70 * @author Sam Pullara
71 */
72 public class GroovyServlet extends HttpServlet implements ResourceConnector {
73
74 private ServletContext sc;
75
76 private static Map servletCache = Collections.synchronizedMap(new HashMap());
77 private static ClassLoader parent;
78 private static GroovyScriptEngine gse;
79
80 public ServletContext getServletContext() {
81 return sc;
82 }
83
84 private static class ServletCacheEntry {
85 private Class servletScriptClass;
86 private long lastModified;
87 private Map dependencies = new HashMap();
88 }
89
90 public void init(ServletConfig config) {
91
92 MetaClass.setUseReflection(true);
93
94
95 sc = config.getServletContext();
96 sc.log("Groovy servlet initialized");
97
98
99
100 parent = Thread.currentThread().getContextClassLoader();
101 if (parent == null)
102 parent = GroovyServlet.class.getClassLoader();
103
104
105 gse = new GroovyScriptEngine(this);
106 }
107
108 public URLConnection getResourceConnection(String name) throws ResourceException {
109 try {
110 URL url = sc.getResource("/" + name);
111 if (url == null) {
112 url = sc.getResource("/WEB-INF/groovy/" + name);
113 if (url == null) {
114 throw new ResourceException("Resource " + name + " not found");
115 }
116 }
117 return url.openConnection();
118 } catch (IOException ioe) {
119 throw new ResourceException("Problem reading resource " + name);
120 }
121 }
122
123 public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
124
125
126
127 final HttpServletRequest httpRequest = (HttpServletRequest) request;
128 final HttpServletResponse httpResponse = (HttpServletResponse) response;
129
130
131 int contextLength = httpRequest.getContextPath().length();
132 final String scriptFilename = httpRequest.getRequestURI().substring(contextLength).substring(1);
133
134
135 final Binding binding = new Binding();
136 binding.setVariable("request", httpRequest);
137 binding.setVariable("response", httpResponse);
138 binding.setVariable("application", sc);
139 binding.setVariable("session", httpRequest.getSession(true));
140 binding.setVariable("out", httpResponse.getWriter());
141
142
143 for (Enumeration paramEnum = request.getParameterNames(); paramEnum.hasMoreElements();) {
144 String key = (String) paramEnum.nextElement();
145 if (binding.getVariable(key) == null) {
146 String[] values = request.getParameterValues(key);
147 if (values.length == 1) {
148 binding.setVariable(key, values[0]);
149 } else {
150 binding.setVariable(key, values);
151 }
152 }
153 }
154
155
156 response.setContentType("text/html");
157
158
159 try {
160 Closure closure = new Closure(gse) {
161 public Object call() {
162 try {
163 return ((GroovyScriptEngine)getDelegate()).run(scriptFilename, binding);
164 } catch (ResourceException e) {
165 throw new RuntimeException(e);
166 } catch (ScriptException e) {
167 throw new RuntimeException(e);
168 }
169 }
170 };
171 GroovyCategorySupport.use(ServletCategory.class, closure);
172 } catch (RuntimeException re) {
173 Throwable e = re.getCause();
174 if (e instanceof ResourceException) {
175 httpResponse.sendError(404);
176 } else {
177 if (e != null) {
178 sc.log("An error occurred processing the request", e);
179 } else {
180 sc.log("An error occurred processing the request", re);
181 }
182 httpResponse.sendError(500);
183 }
184 }
185 }
186
187 }