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.AbstractModule;
19 import com.google.inject.Key;
20 import com.google.inject.Module;
21 import com.google.inject.TypeLiteral;
22 import com.google.inject.binder.AnnotatedBindingBuilder;
23 import com.google.inject.binder.ConstantBindingBuilder;
24 import com.google.inject.binder.LinkedBindingBuilder;
25
26 import java.util.HashMap;
27 import java.util.List;
28 import java.util.Map;
29 import static java.util.Arrays.asList;
30
31 import org.directwebremoting.AjaxFilter;
32 import org.directwebremoting.extend.Configurator;
33 import org.directwebremoting.extend.Converter;
34
35 import static org.directwebremoting.guice.ParamName.CLASSES;
36
37 /**
38 * An extension of {@link AbstractModule} that adds DWR configuration methods,
39 * in conjunction with {@link DwrGuiceServlet}.
40 * @author Tim Peierls [tim at peierls dot net]
41 */
42 public abstract class AbstractDwrModule extends AbstractModule
43 {
44 /**
45 * Implement this method to configure Guice bindings for a DWR-based
46 * web application.
47 */
48 protected abstract void configure();
49
50
51 /**
52 * Configure DWR scopes and bindings for servlet-related types;
53 * incompatible with Guice's {@link ServletModule} because their
54 * bindings for request, response, and session conflict.
55 */
56 protected void bindDwrScopes()
57 {
58 install(new DwrGuiceServletModule(true));
59 }
60
61
62 /**
63 * Configure DWR scopes and bindings for servlet-related types,
64 * specifying whether to include bindings that conflict with those
65 * provided by Guice's {@link ServletModule}.
66 * @param bindPotentiallyConflictingTypes whether to bind request, response,
67 * and session types (risking conflict with Guice)
68 */
69 protected void bindDwrScopes(boolean bindPotentiallyConflictingTypes)
70 {
71 install(new DwrGuiceServletModule(bindPotentiallyConflictingTypes));
72 }
73
74
75 /**
76 * Creates a binding for a conversion for types with names matching
77 * {@code match}.
78 * @param match the string describing which types to convert
79 */
80 protected LinkedBindingBuilder<Converter> bindConversion(String match)
81 {
82 return bind(Converter.class)
83 .annotatedWith(new ConvertingImpl(match));
84 }
85
86
87 /**
88 * Creates a binding for a conversion for {@code type}.
89 * @param type the type to be converted
90 */
91 protected LinkedBindingBuilder<Converter> bindConversion(Class<?> type)
92 {
93 return bind(Converter.class)
94 .annotatedWith(new ConvertingImpl(type));
95 }
96
97
98 /**
99 * Creates a binding for a conversion for {@code type} using an existing
100 * conversion for {@code impl}, which must be assignable to {@code type}.
101 * The check for an existing conversion happens at run-time.
102 * @param type the type to be converted
103 */
104 protected <T> void bindConversion(Class<T> type, Class<? extends T> impl)
105 {
106 bind(Converter.class)
107 .annotatedWith(new ConvertingImpl(type, impl))
108 .to(InternalConverter.class);
109 }
110
111
112 /**
113 * Creates a binding to {@code type} that is used as the target of a
114 * remote method call with the class's unqualified name as the script name.
115 *
116 * <p>Note: if you are scoping the result, don't rely on implicit binding.
117 * Instead, link the type to itself explicitly. For example,
118 * <pre>
119 * bindRemoted(ConcreteService.class)
120 * .to(ConcreteService.class) // this line is required
121 * .in(DwrScopes.SESSION);
122 * </pre>
123 * This could be considered a bug.
124 * @param type the type to bind as a target for remote method calls
125 */
126 protected <T> LinkedBindingBuilder<T> bindRemoted(Class<T> type)
127 {
128 return bind(type)
129 .annotatedWith(new RemotedImpl());
130 }
131
132
133 /**
134 * Creates a binding to a type that is used as the target of a
135 * remote method call with the given {@code scriptName}.
136 *
137 * <p>Note: if you are scoping the result, don't rely on implicit binding.
138 * Instead, link the type to itself explicitly. For example,
139 * <pre>
140 * bindRemotedAs("Mixer", ConcreteService.class)
141 * .to(ConcreteService.class) // this line is required
142 * .in(DwrScopes.SESSION);
143 * </pre>
144 * This could be considered a bug.
145 * @param type the type to bind as a target for remote method calls
146 * @param scriptName the name by which the target type will be known to script callers
147 */
148 protected <T> LinkedBindingBuilder<T> bindRemotedAs(String scriptName, Class<T> type)
149 {
150 return bind(type)
151 .annotatedWith(new RemotedImpl(scriptName));
152 }
153
154
155 /**
156 * Creates a binding for an Ajax filter for the script named
157 * {@code scriptName}.
158 * @param scriptName the script to filter
159 */
160 protected LinkedBindingBuilder<AjaxFilter> bindFilter(String scriptName)
161 {
162 return bind(AjaxFilter.class)
163 .annotatedWith(new FilteringImpl(scriptName));
164 }
165
166
167 /**
168 * Creates a binding for a global Ajax filter.
169 * @param scriptName the script to filter
170 */
171 protected LinkedBindingBuilder<AjaxFilter> bindGlobalFilter()
172 {
173 return bind(AjaxFilter.class)
174 .annotatedWith(new FilteringImpl());
175 }
176
177
178 /**
179 * Call this method in
180 * {@link org.directwebremoting.guice.AbstractDwrModule#configure configure}
181 * to create a binding for a DWR parameter.
182 * @param paramName a parameter name supported by DWR
183 */
184 protected ConstantBindingBuilder bindParameter(ParamName paramName)
185 {
186 return bindConstant()
187 .annotatedWith(new InitParamImpl(paramName));
188 }
189
190
191 /**
192 * Call this method in
193 * {@link org.directwebremoting.guice.AbstractDwrModule#configure configure}
194 * to specify classes that DWR should scan for annotations.
195 * @param classes the classes to be scanned for DWR-specific annotations
196 */
197 protected void bindAnnotatedClasses(Class... classes)
198 {
199 bind(new TypeLiteral<List<Class>>(){})
200 .annotatedWith(new InitParamImpl(CLASSES))
201 .toInstance(asList(classes));
202
203 }
204 }