1 16 package org.directwebremoting.guice; 17 18 import com.google.inject.Binder; 19 import com.google.inject.Inject; 20 import com.google.inject.Injector; 21 import com.google.inject.Key; 22 import com.google.inject.Provider; 23 24 import java.lang.reflect.Constructor ; 25 import java.lang.reflect.Method ; 26 import java.lang.reflect.InvocationTargetException ; 27 import static java.lang.reflect.Modifier.isStatic ; 28 29 66 public class BindUtil 67 { 68 72 public interface BindingProvider<T> extends Provider<T> 73 { 74 78 BindingProvider<T> injecting(String methodName, Key... paramKeys); 79 } 80 81 86 public static <T> BindingProvider<T> fromConstructor(Class <T> type, final Key... keys) 87 { 88 return new ConstructorBindingProvider<T>(null, type, keys); 89 } 90 91 97 public static <T> BindingProvider<T> fromConstructor(Binder binder, Class <T> type, final Key... keys) 98 { 99 return new ConstructorBindingProvider<T>(binder, type, keys); 100 } 101 102 109 public static <T> BindingProvider<T> fromFactoryMethod( 110 Class <T> providedType, Class <?> factoryType, String methodName, final Key... keys) 111 { 112 return new FactoryMethodBindingProvider<T>( 113 null, providedType, Key.get(factoryType), methodName, keys); 114 } 115 116 124 public static <T> BindingProvider<T> fromFactoryMethod( 125 Binder binder, Class <T> providedType, 126 Class <?> factoryType, String methodName, final Key... keys) 127 { 128 return new FactoryMethodBindingProvider<T>( 129 binder, providedType, Key.get(factoryType), methodName, keys); 130 } 131 132 139 public static <T> BindingProvider<T> fromFactoryMethod( 140 Class <T> providedType, Key<?> factoryKey, String methodName, final Key... keys) 141 { 142 return new FactoryMethodBindingProvider<T>( 143 null, providedType, factoryKey, methodName, keys); 144 } 145 146 154 public static <T> BindingProvider<T> fromFactoryMethod( 155 Binder binder, Class <T> providedType, 156 Key<?> factoryKey, String methodName, final Key... keys) 157 { 158 return new FactoryMethodBindingProvider<T>( 159 binder, providedType, factoryKey, methodName, keys); 160 } 161 162 163 167 private static abstract class AbstractBindingProvider<T> implements BindingProvider<T> 168 { 169 protected AbstractBindingProvider(Binder binder, Class <T> type, Key... keys) 170 { 171 this.binder = binder; 172 this.type = type; 173 this.keys = keys; 174 } 175 176 public final T get() 177 { 178 return get(theInjector); 179 } 180 181 protected abstract T get(Injector injector); 182 183 public final BindingProvider<T> injecting(String methodName, Key... paramKeys) 184 { 185 return new MethodBindingProvider(this, type, methodName, paramKeys); 186 } 187 188 protected final Class [] getTypes() 189 { 190 Class [] types = new Class [keys.length]; 191 int i = 0; 192 for (Key key : keys) 193 { 194 @SuppressWarnings ("unchecked") 195 Class type = (Class ) key.getTypeLiteral().getType(); 196 types[i++] = type; 197 } 198 return types; 199 } 200 201 protected final Object [] getValues(Injector injector) 202 { 203 Object [] values = new Object [keys.length]; 204 int i = 0; 205 for (Key key : keys) 206 { 207 Object param = injector.getInstance(key); 208 values[i++] = param; 209 } 210 return values; 211 } 212 213 protected final Binder binder; 214 protected final Class <T> type; 215 protected final Key[] keys; 216 217 222 @Inject private Injector theInjector; 223 } 224 225 private static class ConstructorBindingProvider<T> extends AbstractBindingProvider<T> 226 { 227 ConstructorBindingProvider(Binder binder, Class <T> type, Key... keys) 228 { 229 super(binder, type, keys); 230 231 Constructor <T> constructor = null; 232 try 233 { 234 constructor = type.getConstructor(getTypes()); 235 } 236 catch (NoSuchMethodException e) 237 { 238 if (binder == null) 239 { 240 throw new IllegalArgumentException ("no such constructor", e); 241 } 242 else 243 { 244 binder.addError(e); 245 } 246 } 247 248 this.constructor = constructor; 249 } 250 251 public T get(Injector injector) 252 { 253 try 254 { 255 return constructor.newInstance(getValues(injector)); 256 } 257 catch (InstantiationException e) 258 { 259 throw new IllegalStateException (e); 260 } 261 catch (IllegalAccessException e) 262 { 263 throw new IllegalStateException (e); 264 } 265 catch (InvocationTargetException e) 266 { 267 throw new IllegalStateException (e); 268 } 269 } 270 271 private final Constructor <T> constructor; 272 } 273 274 private static class MethodBindingProvider<T> extends AbstractBindingProvider<T> { 275 276 MethodBindingProvider(AbstractBindingProvider<T> prev, 277 Class <T> type, String methodName, Key... keys) 278 { 279 super(prev.binder, type, keys); 280 281 Method method = null; 282 try 283 { 284 method = type.getMethod(methodName, getTypes()); 285 } 286 catch (NoSuchMethodException e) 287 { 288 if (binder == null) 289 { 290 throw new IllegalArgumentException ("no such method", e); 291 } 292 else 293 { 294 binder.addError(e); 295 } 296 } 297 298 this.prev = prev; 299 this.method = method; 300 } 301 302 public T get(Injector injector) 303 { 304 T target = prev.get(injector); 305 try 306 { 307 method.invoke(target, getValues(injector)); 308 } 309 catch (IllegalAccessException e) 310 { 311 throw new IllegalStateException (e); 312 } 313 catch (InvocationTargetException e) 314 { 315 throw new IllegalStateException (e); 316 } 317 return target; 318 } 319 320 private final AbstractBindingProvider<T> prev; 321 private final Method method; 322 } 323 324 325 private static class FactoryMethodBindingProvider<T> extends AbstractBindingProvider<T> 326 { 327 FactoryMethodBindingProvider(Binder binder, Class <T> providedType, 328 Key<?> factoryKey, String methodName, Key... keys) 329 { 330 super(binder, providedType, keys); 331 332 Method method = null; 333 boolean isStaticFactory = false; 334 try 335 { 336 @SuppressWarnings ("unchecked") 337 Class factoryType = (Class ) factoryKey.getTypeLiteral().getType(); 338 method = factoryType.getMethod(methodName, getTypes()); 339 method.getReturnType().asSubclass(providedType); 340 } 341 catch (NoSuchMethodException e) 342 { 343 if (binder == null) 344 { 345 throw new IllegalArgumentException ("no such method", e); 346 } 347 else 348 { 349 binder.addError(e); 350 } 351 } 352 catch (ClassCastException e) 353 { 354 if (binder == null) 355 { 356 throw new IllegalArgumentException ("bad return type", e); 357 } 358 else 359 { 360 binder.addError(e); 361 } 362 } 363 364 this.method = method; 365 this.factoryKey = factoryKey; 366 } 367 368 public T get(Injector injector) 369 { 370 try 371 { 372 Object target = null; 373 if (!isStatic(method.getModifiers())) 374 { 375 target = injector.getInstance(factoryKey); 376 } 377 @SuppressWarnings ("unchecked") 378 T result = (T) method.invoke(target, getValues(injector)); 379 return result; 380 } 381 catch (IllegalAccessException e) 382 { 383 throw new IllegalStateException (e); 384 } 385 catch (InvocationTargetException e) 386 { 387 throw new IllegalStateException (e); 388 } 389 } 390 391 private final Method method; 392 private final Key<?> factoryKey; 393 } 394 } 395 | Popular Tags |