1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.seasar.cubby.plugins.guice;
17
18 import java.util.Collection;
19 import java.util.Collections;
20 import java.util.HashSet;
21 import java.util.LinkedHashSet;
22 import java.util.Set;
23
24 import javax.servlet.http.HttpServletRequest;
25
26 import org.seasar.cubby.action.ActionContext;
27 import org.seasar.cubby.action.ActionErrors;
28 import org.seasar.cubby.action.FlashMap;
29 import org.seasar.cubby.action.impl.ActionContextImpl;
30 import org.seasar.cubby.action.impl.ActionErrorsImpl;
31 import org.seasar.cubby.action.impl.FlashMapImpl;
32 import org.seasar.cubby.controller.FormatPattern;
33 import org.seasar.cubby.controller.MessagesBehaviour;
34 import org.seasar.cubby.controller.RequestParser;
35 import org.seasar.cubby.controller.impl.DefaultFormatPattern;
36 import org.seasar.cubby.controller.impl.DefaultMessagesBehaviour;
37 import org.seasar.cubby.controller.impl.DefaultRequestParser;
38 import org.seasar.cubby.controller.impl.MultipartRequestParser;
39 import org.seasar.cubby.converter.Converter;
40 import org.seasar.cubby.converter.impl.BigDecimalConverter;
41 import org.seasar.cubby.converter.impl.BigIntegerConverter;
42 import org.seasar.cubby.converter.impl.BooleanConverter;
43 import org.seasar.cubby.converter.impl.ByteArrayFileItemConverter;
44 import org.seasar.cubby.converter.impl.ByteConverter;
45 import org.seasar.cubby.converter.impl.CharacterConverter;
46 import org.seasar.cubby.converter.impl.DateConverter;
47 import org.seasar.cubby.converter.impl.DoubleConverter;
48 import org.seasar.cubby.converter.impl.EnumConverter;
49 import org.seasar.cubby.converter.impl.FloatConverter;
50 import org.seasar.cubby.converter.impl.InputStreamFileItemConverter;
51 import org.seasar.cubby.converter.impl.IntegerConverter;
52 import org.seasar.cubby.converter.impl.LongConverter;
53 import org.seasar.cubby.converter.impl.ShortConverter;
54 import org.seasar.cubby.converter.impl.SqlDateConverter;
55 import org.seasar.cubby.converter.impl.SqlTimeConverter;
56 import org.seasar.cubby.converter.impl.SqlTimestampConverter;
57 import org.seasar.cubby.plugins.guice.spi.GuiceContainerProvider;
58 import org.seasar.cubby.plugins.guice.spi.GuiceConverterProvider;
59 import org.seasar.cubby.plugins.guice.spi.GuicePathResolverProvider;
60 import org.seasar.cubby.plugins.guice.spi.GuiceRequestParserProvider;
61 import org.seasar.cubby.routing.PathResolver;
62 import org.seasar.cubby.routing.PathTemplateParser;
63 import org.seasar.cubby.routing.impl.PathResolverImpl;
64 import org.seasar.cubby.routing.impl.PathTemplateParserImpl;
65 import org.seasar.cubby.spi.BeanDescProvider;
66 import org.seasar.cubby.spi.ContainerProvider;
67 import org.seasar.cubby.spi.ConverterProvider;
68 import org.seasar.cubby.spi.PathResolverProvider;
69 import org.seasar.cubby.spi.RequestParserProvider;
70 import org.seasar.cubby.spi.beans.impl.DefaultBeanDescProvider;
71 import org.seasar.cubby.util.ActionUtils;
72
73 import com.google.inject.AbstractModule;
74 import com.google.inject.Injector;
75 import com.google.inject.Key;
76 import com.google.inject.Module;
77 import com.google.inject.Provides;
78 import com.google.inject.Singleton;
79 import com.google.inject.TypeLiteral;
80 import com.google.inject.matcher.AbstractMatcher;
81 import com.google.inject.servlet.RequestScoped;
82 import com.google.inject.spi.TypeEncounter;
83 import com.google.inject.spi.TypeListener;
84
85
86
87
88
89
90 public class CubbyModule extends AbstractModule {
91
92
93 private final Set<Class<?>> actionClasses = new LinkedHashSet<Class<?>>();
94
95
96 private final Set<Key<? extends Converter>> converterKeys = new LinkedHashSet<Key<? extends Converter>>();
97
98
99 private final Set<Key<? extends RequestParser>> requestParserKeys = new LinkedHashSet<Key<? extends RequestParser>>();
100
101
102
103
104 @Override
105 public void configure() {
106 configureTypeListeners();
107 configureProviders();
108 configureComponents();
109 configureDefaultRequestParsers();
110 configureDefaultConverters();
111 }
112
113
114
115
116 private void configureTypeListeners() {
117
118 bindListener(new AbstractMatcher<TypeLiteral<?>>() {
119
120 public boolean matches(final TypeLiteral<?> typeLiteral) {
121 final boolean matches = ActionUtils.isActionClass(typeLiteral
122 .getRawType());
123 return matches;
124 }
125
126 }, new TypeListener() {
127
128 public <I> void hear(final TypeLiteral<I> typeLiteral,
129 final TypeEncounter<I> typeEncounter) {
130 final Class<?> actionClass = typeLiteral.getRawType();
131 actionClasses.add(actionClass);
132 }
133
134 });
135
136
137 bindListener(new AbstractMatcher<TypeLiteral<?>>() {
138
139 public boolean matches(final TypeLiteral<?> typeLiteral) {
140 final boolean matches = Converter.class
141 .isAssignableFrom(typeLiteral.getRawType());
142 return matches;
143 }
144
145 }, new TypeListener() {
146
147 public <I> void hear(final TypeLiteral<I> typeLiteral,
148 final TypeEncounter<I> typeEncounter) {
149 final Key<? extends Converter> key = key(typeLiteral);
150 converterKeys.add(key);
151 }
152
153 });
154
155
156 bindListener(new AbstractMatcher<TypeLiteral<?>>() {
157
158 public boolean matches(final TypeLiteral<?> typeLiteral) {
159 final boolean matches = RequestParser.class
160 .isAssignableFrom(typeLiteral.getRawType());
161 return matches;
162 }
163
164 }, new TypeListener() {
165
166 public <I> void hear(final TypeLiteral<I> typeLiteral,
167 final TypeEncounter<I> typeEncounter) {
168 final Key<? extends RequestParser> key = key(typeLiteral);
169 requestParserKeys.add(key);
170 }
171
172 });
173 }
174
175
176
177
178
179
180
181
182
183
184
185 private void configureProviders() {
186 bind(ContainerProvider.class).to(GuiceContainerProvider.class)
187 .asEagerSingleton();
188 bind(BeanDescProvider.class).to(DefaultBeanDescProvider.class)
189 .asEagerSingleton();
190 bind(RequestParserProvider.class).to(GuiceRequestParserProvider.class)
191 .asEagerSingleton();
192 bind(ConverterProvider.class).to(GuiceConverterProvider.class)
193 .asEagerSingleton();
194 bind(PathResolverProvider.class).to(GuicePathResolverProvider.class)
195 .asEagerSingleton();
196 }
197
198
199
200
201
202
203
204
205 private void configureComponents() {
206 bind(MessagesBehaviour.class).to(DefaultMessagesBehaviour.class)
207 .asEagerSingleton();
208 bind(FormatPattern.class).to(DefaultFormatPattern.class)
209 .asEagerSingleton();
210 }
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230 protected void configureDefaultRequestParsers() {
231 bind(MultipartRequestParser.class).asEagerSingleton();
232 bind(DefaultRequestParser.class).asEagerSingleton();
233 }
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260 protected void configureDefaultConverters() {
261 bind(BigDecimalConverter.class).asEagerSingleton();
262 bind(BigIntegerConverter.class).asEagerSingleton();
263 bind(BooleanConverter.class).asEagerSingleton();
264 bind(ByteArrayFileItemConverter.class).asEagerSingleton();
265 bind(ByteConverter.class).asEagerSingleton();
266 bind(CharacterConverter.class).asEagerSingleton();
267 bind(DateConverter.class).asEagerSingleton();
268 bind(DoubleConverter.class).asEagerSingleton();
269 bind(EnumConverter.class).asEagerSingleton();
270 bind(FloatConverter.class).asEagerSingleton();
271 bind(InputStreamFileItemConverter.class).asEagerSingleton();
272 bind(IntegerConverter.class).asEagerSingleton();
273 bind(LongConverter.class).asEagerSingleton();
274 bind(ShortConverter.class).asEagerSingleton();
275 bind(SqlDateConverter.class).asEagerSingleton();
276 bind(SqlTimeConverter.class).asEagerSingleton();
277 bind(SqlTimestampConverter.class).asEagerSingleton();
278 }
279
280
281
282 @Provides
283 @Singleton
284 Collection<RequestParser> provideRequestParsers(final Injector injector) {
285 final Set<RequestParser> requestParsers = new LinkedHashSet<RequestParser>();
286 for (final Key<? extends RequestParser> key : requestParserKeys) {
287 final RequestParser requestParser = injector.getInstance(key);
288 requestParsers.add(requestParser);
289 }
290 return Collections.unmodifiableCollection(requestParsers);
291 }
292
293 @Provides
294 @Singleton
295 Collection<Converter> provideConverters(final Injector injector) {
296 final Set<Converter> converters = new HashSet<Converter>();
297 for (final Key<? extends Converter> key : converterKeys) {
298 final Converter converter = injector.getInstance(key);
299 converters.add(converter);
300 }
301 return Collections.unmodifiableCollection(converters);
302 }
303
304 @Provides
305 @Singleton
306 PathTemplateParser providePathTemplateParser() {
307 final PathTemplateParser pathTemplateParser = new PathTemplateParserImpl();
308 return pathTemplateParser;
309 }
310
311 @Provides
312 @Singleton
313 PathResolver providePathResolver(final PathTemplateParser pathTemplateParser) {
314 final PathResolver pathResolver = new PathResolverImpl(
315 pathTemplateParser);
316 for (final Class<?> actionClass : actionClasses) {
317 pathResolver.add(actionClass);
318 }
319 return pathResolver;
320 }
321
322 @Provides
323 @RequestScoped
324 ActionErrors provideActionErrors() {
325 final ActionErrors actionErrors = new ActionErrorsImpl();
326 return actionErrors;
327 }
328
329 @Provides
330 @RequestScoped
331 FlashMap provideFlashMap(final HttpServletRequest request) {
332 final FlashMap flashMap = new FlashMapImpl(request);
333 return flashMap;
334 }
335
336 @Provides
337 @RequestScoped
338 ActionContext provideActionContext() {
339 final ActionContext actionContext = new ActionContextImpl();
340 return actionContext;
341 }
342
343 private static <T> Key<T> key(final TypeLiteral<?> typeLiteral) {
344 @SuppressWarnings("unchecked")
345 final Key<T> key = (Key<T>) Key.get(typeLiteral);
346 return key;
347 }
348
349 }