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.Key;
19 import com.google.inject.Injector;
20 import com.google.inject.Provider;
21
22 import java.util.Collection;
23 import java.util.Map;
24
25 import org.directwebremoting.dwrp.DefaultConverterManager;
26 import org.directwebremoting.extend.*;
27 import org.directwebremoting.util.Logger;
28
29 import static org.directwebremoting.guice.DwrGuiceUtil.getInjector;
30 import static org.directwebremoting.guice.DwrGuiceUtil.getServletContext;
31
32 /**
33 * Extends an existing converter manager with an injected list of converters
34 * specified at Guice bind-time. Only to be used in conjection with
35 * {@link DwrGuiceServlet}.
36 * @author Tim Peierls [tim at peierls dot net]
37 */
38 public class InternalConverterManager implements ConverterManager
39 {
40 /**
41 * Retrieves an underlying converter manager from thread-local state
42 * to which this class delegates {@link ConverterManager} calls.
43 */
44 public InternalConverterManager()
45 {
46 this.converterManager = getConverterManager();
47 addConverters();
48 }
49
50
51 public void addConverterType(String id, String className)
52 {
53 converterManager.addConverterType(id, className);
54 }
55
56 public void addConverter(String match, String type, Map params) throws IllegalArgumentException, InstantiationException, IllegalAccessException
57 {
58 converterManager.addConverter(match, type, params);
59 }
60
61 public void addConverter(String match, Converter converter) throws IllegalArgumentException
62 {
63 converterManager.addConverter(match, converter);
64 }
65
66 public Collection getConverterMatchStrings()
67 {
68 return converterManager.getConverterMatchStrings();
69 }
70
71 public Converter getConverterByMatchString(String match)
72 {
73 return converterManager.getConverterByMatchString(match);
74 }
75
76 public boolean isConvertable(Class paramType)
77 {
78 return converterManager.isConvertable(paramType);
79 }
80
81 public Object convertInbound(Class paramType, InboundVariable iv, InboundContext inctx, TypeHintContext incc) throws MarshallException
82 {
83 return converterManager.convertInbound(paramType, iv, inctx, incc);
84 }
85
86 public OutboundVariable convertOutbound(Object object, OutboundContext outctx) throws MarshallException
87 {
88 return converterManager.convertOutbound(object, outctx);
89 }
90
91 public void setExtraTypeInfo(TypeHintContext thc, Class type)
92 {
93 converterManager.setExtraTypeInfo(thc, type);
94 }
95
96 public Class getExtraTypeInfo(TypeHintContext thc)
97 {
98 return converterManager.getExtraTypeInfo(thc);
99 }
100
101 public void setConverters(Map converters)
102 {
103 converterManager.setConverters(converters);
104 }
105
106
107 private final ConverterManager converterManager;
108
109 private void addConverters()
110 {
111 Injector injector = getInjector();
112 for (Key<?> key : injector.getBindings().keySet())
113 {
114 Class<?> atype = key.getAnnotationType();
115 if (atype != null && Converting.class.isAssignableFrom(atype))
116 {
117 Converting ann = Converting.class.cast(key.getAnnotation());
118
119 String match = ann.match();
120 Class type = ann.type();
121 Class impl = ann.impl();
122
123 if ("".equals(match))
124 {
125
126 match = type.getName();
127 }
128
129 Provider<Converter> provider = null;
130 Class cvtType;
131
132 if (impl.equals(Void.class))
133 {
134
135
136
137 provider = injector.getProvider((Key<Converter>) key);
138 cvtType = type;
139 }
140 else
141 {
142
143
144
145
146
147 try
148 {
149
150
151 Key<Converter> ikey = Key.get(Converter.class, new ConvertingImpl(impl));
152 provider = injector.getProvider(ikey);
153 }
154 catch (RuntimeException e)
155 {
156
157 }
158
159 if (provider == null)
160 {
161
162
163
164 final String implMatch = impl.getName();
165 provider = new Provider<Converter>()
166 {
167 public Converter get()
168 {
169 return getConverterByMatchString(implMatch);
170 }
171 };
172 }
173
174 cvtType = impl;
175 }
176 addConverter(match, new InternalConverter(cvtType, provider));
177 }
178 }
179 }
180
181 /**
182 * Stores a type name in a thread-local variable for later retrieval by
183 * {@code getConverterManager}.
184 */
185 static void setTypeName(String name)
186 {
187 typeName.set(name);
188 }
189
190 private static ConverterManager getConverterManager()
191 {
192 String name = typeName.get();
193 try
194 {
195 Class<? extends ConverterManager> cls =
196 (Class<? extends ConverterManager>) Class.forName(name);
197 return cls.newInstance();
198 }
199 catch (Exception e)
200 {
201 if (name != null && !"".equals(name)) {
202 log.warn("Couldn't make ConverterManager from type: " + name);
203 }
204 return new DefaultConverterManager();
205 }
206 }
207
208
209 /**
210 * Place to stash a type name for retrieval in same thread.
211 */
212 private static final ThreadLocal<String> typeName = new ThreadLocal<String>();
213
214
215 /**
216 * The log stream
217 */
218 private static final Logger log = Logger.getLogger(InternalConverterManager.class);
219 }