1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.directwebremoting.guice;
17
18 import com.google.inject.Binding;
19 import com.google.inject.Inject;
20 import com.google.inject.Injector;
21 import com.google.inject.Key;
22 import com.google.inject.name.Named;
23
24 import java.util.ArrayList;
25 import java.util.List;
26 import static java.util.Map.Entry;
27
28 import javax.servlet.ServletConfig;
29 import javax.servlet.ServletContext;
30 import javax.servlet.ServletException;
31
32 import org.directwebremoting.extend.AjaxFilterManager;
33 import org.directwebremoting.extend.Configurator;
34 import org.directwebremoting.extend.ConverterManager;
35 import org.directwebremoting.extend.CreatorManager;
36 import org.directwebremoting.servlet.DwrServlet;
37 import org.directwebremoting.util.Logger;
38
39 import static org.directwebremoting.guice.DwrGuiceUtil.getInjector;
40 import static org.directwebremoting.guice.DwrGuiceUtil.popServletContext;
41 import static org.directwebremoting.guice.DwrGuiceUtil.pushServletContext;
42 import static org.directwebremoting.guice.ParamName.*;
43 import static org.directwebremoting.impl.ContainerUtil.INIT_CUSTOM_CONFIGURATOR;
44
45 /**
46 * An extension of the basic
47 * {@link org.directwebremoting.servlet.DwrServlet DwrServlet}
48 * that configures itself for dependency injection with Guice.
49 * Must be used in conjunction with
50 * {@link org.directwebremoting.guice.DwrGuiceServletContextFilter DwrGuiceServletContextFilter}.
51 * @author Tim Peierls [tim at peierls dot net]
52 */
53 public class DwrGuiceServlet extends DwrServlet
54 {
55 /**
56 * Copies DWR configuration values from the Guice bindings into
57 * {@code servletConfig} to make these values accessible to the
58 * standard DWR servlet configuration machinery.
59 */
60 @Override public void init(ServletConfig servletConfig) throws ServletException
61 {
62
63 this.servletContext = servletConfig.getServletContext();
64
65
66
67 pushServletContext(this.servletContext);
68 try
69 {
70
71
72
73 ModifiableServletConfig config = new ModifiableServletConfig(servletConfig);
74
75
76 setInitParameters(config);
77
78
79
80
81 configureDelegatedTypes(config);
82
83
84
85 super.init(config);
86
87
88
89 initApplicationScoped();
90 }
91 finally
92 {
93
94 popServletContext();
95 }
96 }
97
98 /**
99 * Closes any {@code Closeable} application-scoped objects.
100 * IO exceptions are collected but ignored.
101 */
102 @Override public void destroy()
103 {
104 pushServletContext(this.servletContext);
105 try
106 {
107
108 List<Exception> exceptions = destroyApplicationScoped();
109
110 super.destroy();
111
112 for (Exception ex : exceptions)
113 {
114 log.warn("During servlet shutdown", ex);
115 }
116 }
117 finally
118 {
119 popServletContext();
120 this.servletContext = null;
121 }
122 }
123
124 /**
125 * Inject some values that might have been configured at bind-time.
126 * Override web.xml <init-param> settings in each case that injection
127 * is successful.
128 */
129 private void setInitParameters(ModifiableServletConfig config)
130 {
131 Injector injector = getInjector();
132 InjectedConfig cfg = new InjectedConfig(config);
133 injector.injectMembers(cfg);
134 cfg.setParameters();
135 }
136
137 private static class InjectedConfig
138 {
139 InjectedConfig(ModifiableServletConfig config)
140 {
141 this.config = config;
142 }
143
144 void setParameter(ParamName paramName, Object value)
145 {
146 if (value != null)
147 {
148 config.setInitParameter(paramName.getName(), value.toString());
149 }
150 }
151
152 void setParameters()
153 {
154 setParameter(ALLOW_GET_FOR_SAFARI, allowGetForSafariButMakeForgeryEasier);
155 setParameter(CROSS_DOMAIN_SESSION_SECURITY, crossDomainSessionSecurity);
156 setParameter(ALLOW_SCRIPT_TAG_REMOTING, allowScriptTagRemoting);
157 setParameter(DEBUG, debug);
158 setParameter(SCRIPT_SESSION_TIMEOUT, scriptSessionTimeout);
159 setParameter(MAX_CALL_COUNT, maxCallCount);
160 setParameter(ACTIVE_REVERSE_AJAX_ENABLED, activeReverseAjaxEnabled);
161 setParameter(MAX_WAIT_AFTER_WRITE, maxWaitAfterWrite);
162 setParameter(DISCONNECTED_TIME, disconnectedTime);
163 setParameter(POLL_AND_COMET_ENABLED, pollAndCometEnabled);
164 setParameter(MAX_WAITING_THREADS, maxWaitingThreads);
165 setParameter(MAX_POLL_HITS_PER_SECOND, maxPollHitsPerSecond);
166 setParameter(PRE_STREAM_WAIT_TIME, preStreamWaitTime);
167 setParameter(POST_STREAM_WAIT_TIME, postStreamWaitTime);
168 setParameter(IGNORE_LAST_MODIFIED, ignoreLastModified);
169 setParameter(SCRIPT_COMPRESSED, scriptCompressed);
170 setParameter(SESSION_COOKIE_NAME, sessionCookieName);
171 setParameter(WELCOME_FILES, welcomeFiles);
172 setParameter(NORMALIZE_INCLUDES_QUERY_STRING, normalizeIncludesQueryString);
173 setParameter(OVERRIDE_PATH, overridePath);
174
175 if (configurator != null)
176 {
177
178
179 config.setInitParameter(INIT_CUSTOM_CONFIGURATOR, InternalConfigurator.class.getName());
180 }
181
182 if (classes != null)
183 {
184 config.setInitParameter(CLASSES.getName(), classListToString(classes));
185 }
186 }
187
188 @Inject(optional=true) @InitParam(ALLOW_GET_FOR_SAFARI) Boolean allowGetForSafariButMakeForgeryEasier = null;
189 @Inject(optional=true) @InitParam(CROSS_DOMAIN_SESSION_SECURITY) Boolean crossDomainSessionSecurity = null;
190 @Inject(optional=true) @InitParam(ALLOW_SCRIPT_TAG_REMOTING) Boolean allowScriptTagRemoting = null;
191 @Inject(optional=true) @InitParam(DEBUG) Boolean debug = null;
192 @Inject(optional=true) @InitParam(SCRIPT_SESSION_TIMEOUT) Long scriptSessionTimeout = null;
193 @Inject(optional=true) @InitParam(MAX_CALL_COUNT) Integer maxCallCount = null;
194 @Inject(optional=true) @InitParam(ACTIVE_REVERSE_AJAX_ENABLED) Boolean activeReverseAjaxEnabled = null;
195 @Inject(optional=true) @InitParam(MAX_WAIT_AFTER_WRITE) Long maxWaitAfterWrite = null;
196 @Inject(optional=true) @InitParam(DISCONNECTED_TIME) Long disconnectedTime = null;
197 @Inject(optional=true) @InitParam(POLL_AND_COMET_ENABLED) Boolean pollAndCometEnabled = null;
198 @Inject(optional=true) @InitParam(MAX_WAITING_THREADS) Integer maxWaitingThreads = null;
199 @Inject(optional=true) @InitParam(MAX_POLL_HITS_PER_SECOND) Integer maxPollHitsPerSecond = null;
200 @Inject(optional=true) @InitParam(PRE_STREAM_WAIT_TIME) Long preStreamWaitTime = null;
201 @Inject(optional=true) @InitParam(POST_STREAM_WAIT_TIME) Long postStreamWaitTime = null;
202 @Inject(optional=true) @InitParam(IGNORE_LAST_MODIFIED) Boolean ignoreLastModified = null;
203 @Inject(optional=true) @InitParam(SCRIPT_COMPRESSED) Boolean scriptCompressed = null;
204 @Inject(optional=true) @InitParam(SESSION_COOKIE_NAME) String sessionCookieName = null;
205 @Inject(optional=true) @InitParam(WELCOME_FILES) String welcomeFiles = null;
206 @Inject(optional=true) @InitParam(NORMALIZE_INCLUDES_QUERY_STRING) Boolean normalizeIncludesQueryString = null;
207 @Inject(optional=true) @InitParam(OVERRIDE_PATH) String overridePath = null;
208
209 @Inject(optional=true) Configurator configurator = null;
210
211 @Inject(optional=true) @InitParam(CLASSES) List<Class> classes = null;
212
213 private final ModifiableServletConfig config;
214 }
215
216
217 private void configureDelegatedTypes(ModifiableServletConfig config)
218 {
219
220
221
222
223
224 InternalCreatorManager.setTypeName(config.getInitParameter(INIT_CREATOR_MANAGER));
225 InternalConverterManager.setTypeName(config.getInitParameter(INIT_CONVERTER_MANAGER));
226 InternalAjaxFilterManager.setTypeName(config.getInitParameter(INIT_AJAX_FILTER_MANAGER));
227
228
229
230
231
232 config.setInitParameter(INIT_CREATOR_MANAGER, InternalCreatorManager.class.getName());
233 config.setInitParameter(INIT_CONVERTER_MANAGER, InternalConverterManager.class.getName());
234 config.setInitParameter(INIT_AJAX_FILTER_MANAGER, InternalAjaxFilterManager.class.getName());
235 }
236
237
238 private static void initApplicationScoped()
239 {
240 Injector injector = getInjector();
241 for (Key<?> key : DwrScopes.APPLICATION.getKeysInScope())
242 {
243
244 injector.getInstance(key);
245 }
246 }
247
248 private static List<Exception> destroyApplicationScoped()
249 {
250 final List<Exception> exceptions = new ArrayList<Exception>();
251 DwrScopes.APPLICATION.closeAll(new ExceptionLoggingCloseableHandler(exceptions));
252 return exceptions;
253 }
254
255
256 static String classListToString(List<Class> classList)
257 {
258 StringBuilder buf = new StringBuilder();
259 int count = 0;
260 for (Class cls : classList)
261 {
262 if (count++ > 0) buf.append(", ");
263 buf.append(cls.getName());
264 }
265 return buf.toString();
266 }
267
268
269 /**
270 * Used to stash context for later use by destroy().
271 */
272 private volatile ServletContext servletContext;
273
274
275 /**
276 * The name DWR uses to look up a CreatorManager implementation class name
277 */
278 private static final String INIT_CREATOR_MANAGER = CreatorManager.class.getName();
279
280 /**
281 * The name DWR uses to look up a ConverterManager implementation class name
282 */
283 private static final String INIT_CONVERTER_MANAGER = ConverterManager.class.getName();
284
285 /**
286 * The name DWR uses to look up an AjaxFilterManager implementation class name
287 */
288 private static final String INIT_AJAX_FILTER_MANAGER = AjaxFilterManager.class.getName();
289
290 /**
291 * The log stream
292 */
293 private static final Logger log = Logger.getLogger(DwrGuiceServlet.class);
294 }