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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79 package org.seasar.groovy.servlet;
80
81 import groovy.lang.Binding;
82 import groovy.lang.Closure;
83 import groovy.lang.MetaClass;
84 import groovy.servlet.GroovyServlet;
85 import groovy.servlet.ServletCategory;
86 import groovy.util.GroovyScriptEngine;
87 import groovy.util.ResourceConnector;
88 import groovy.util.ResourceException;
89 import groovy.util.ScriptException;
90
91 import java.io.IOException;
92 import java.net.URL;
93 import java.net.URLConnection;
94 import java.util.ArrayList;
95 import java.util.Collections;
96 import java.util.Enumeration;
97 import java.util.HashMap;
98 import java.util.List;
99 import java.util.Map;
100
101 import javax.servlet.ServletConfig;
102 import javax.servlet.ServletContext;
103 import javax.servlet.ServletException;
104 import javax.servlet.ServletRequest;
105 import javax.servlet.ServletResponse;
106 import javax.servlet.http.HttpServlet;
107 import javax.servlet.http.HttpServletRequest;
108 import javax.servlet.http.HttpServletResponse;
109
110 import org.codehaus.groovy.runtime.GroovyCategorySupport;
111 import org.seasar.framework.container.S2Container;
112 import org.seasar.framework.container.factory.SingletonS2ContainerFactory;
113 import org.seasar.framework.util.StringUtil;
114
115 /***
116 *
117 * @author takai
118 * @version $Revision: 1.2 $
119 */
120 public class S2GroovyServlet extends HttpServlet implements ResourceConnector {
121
122 private static class ServletCacheEntry {
123
124 private Map dependencies = new HashMap();
125
126 private long lastModified;
127
128 private Class servletScriptClass;
129 }
130
131 public static final String CONFIG_PATH_KEY = "configPath";
132
133 private static GroovyScriptEngine gse;
134
135 private static ClassLoader parent;
136
137 private static Map servletCache = Collections
138 .synchronizedMap(new HashMap());
139
140 public static S2Container getContainer() {
141 return SingletonS2ContainerFactory.getContainer();
142 }
143
144 private ServletContext sc;
145
146 public void destroy() {
147 SingletonS2ContainerFactory.destroy();
148 }
149
150 public URLConnection getResourceConnection(String name)
151 throws ResourceException {
152 try {
153 URL url = sc.getResource("/" + name);
154 if (url == null) {
155 url = sc.getResource("/WEB-INF/groovy/" + name);
156 if (url == null) {
157 throw new ResourceException("Resource " + name
158 + " not found");
159 }
160 }
161 return url.openConnection();
162 } catch (IOException ioe) {
163 throw new ResourceException("Problem reading resource " + name);
164 }
165 }
166
167 public ServletContext getServletContext() {
168 return sc;
169 }
170
171 public void init() {
172 initGroovy();
173 initS2();
174 }
175
176 /***
177 * @param config
178 */
179 protected void initGroovy() {
180 final ServletConfig config = getServletConfig();
181
182
183 MetaClass.setUseReflection(true);
184
185
186 sc = config.getServletContext();
187 sc.log("Groovy servlet initialized");
188
189
190
191 parent = Thread.currentThread().getContextClassLoader();
192 if (parent == null)
193 parent = GroovyServlet.class.getClassLoader();
194
195
196 gse = new GroovyScriptEngine(this);
197 }
198
199 protected void initS2() {
200 final ServletConfig config = getServletConfig();
201 String configPath = null;
202
203 if (config != null) {
204 configPath = config.getInitParameter(CONFIG_PATH_KEY);
205 }
206 if (!StringUtil.isEmpty(configPath)) {
207 SingletonS2ContainerFactory.setConfigPath(configPath);
208 }
209 SingletonS2ContainerFactory.setServletContext(getServletContext());
210 SingletonS2ContainerFactory.init();
211 }
212
213 public void service(ServletRequest request, ServletResponse response)
214 throws ServletException, IOException {
215
216
217
218 final HttpServletRequest httpRequest = (HttpServletRequest) request;
219 final HttpServletResponse httpResponse = (HttpServletResponse) response;
220
221
222 final S2Container container = getContainer();
223 container.setRequest(httpRequest);
224
225
226 int contextLength = httpRequest.getContextPath().length();
227 final String scriptFilename = httpRequest.getRequestURI().substring(
228 contextLength).substring(1);
229
230
231 final Binding binding = new Binding();
232 binding.setVariable("request", httpRequest);
233 binding.setVariable("response", httpResponse);
234 binding.setVariable("application", sc);
235 binding.setVariable("session", httpRequest.getSession(true));
236 binding.setVariable("out", httpResponse.getWriter());
237
238 binding.setVariable("container", container);
239
240
241 for (Enumeration paramEnum = request.getParameterNames(); paramEnum
242 .hasMoreElements();) {
243 String key = (String) paramEnum.nextElement();
244 if (binding.getVariable(key) == null) {
245 String[] values = request.getParameterValues(key);
246 if (values.length == 1) {
247 binding.setVariable(key, values[0]);
248 } else {
249 binding.setVariable(key, values);
250 }
251 }
252 }
253
254
255 response.setContentType("text/html");
256
257
258 try {
259 Closure closure = new Closure(gse) {
260 public Object call() {
261 try {
262 return ((GroovyScriptEngine) getDelegate()).run(
263 scriptFilename, binding);
264 } catch (ResourceException e) {
265 throw new RuntimeException(e);
266 } catch (ScriptException e) {
267 throw new RuntimeException(e);
268 }
269 }
270 };
271
272 List categories = new ArrayList();
273 categories.add(ServletCategory.class);
274 categories.add(S2GroovyServletCategory.class);
275 GroovyCategorySupport.use(categories, closure);
276
277 } catch (RuntimeException re) {
278 Throwable e = re.getCause();
279 if (e instanceof ResourceException) {
280 httpResponse.sendError(404);
281 } else {
282 if (e != null) {
283 sc.log("An error occurred processing the request", e);
284 } else {
285 sc.log("An error occurred processing the request", re);
286 }
287 httpResponse.sendError(500);
288 }
289 }
290 }
291 }