View Javadoc

1   /*
2    * Copyright 2007 Tim Peierls
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
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); // never used, subverted by InternalConverterManager
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 }