/sigmah/src/test/java/org/sigmah/test/SimpleScope.java

http://sigma-h.googlecode.com/ · Java · 120 lines · 64 code · 15 blank · 41 comment · 7 complexity · 1cddb0096e04246c0c433d25d762024f MD5 · raw file

  1. /*
  2. * All Sigmah code is released under the GNU General Public License v3
  3. * See COPYRIGHT.txt and LICENSE.txt.
  4. */
  5. package org.sigmah.test;
  6. import com.google.inject.Key;
  7. import com.google.inject.OutOfScopeException;
  8. import com.google.inject.Provider;
  9. import com.google.inject.Scope;
  10. import java.util.Map;
  11. import static com.google.common.base.Preconditions.checkState;
  12. /**
  13. * Scopes a single execution of a block of code. Apply this scope with a
  14. * try/finally block: <pre> {@code
  15. * <p/>
  16. * scope.enter();
  17. * try {
  18. * // explicitly seed some seed objects...
  19. * scope.seed(Key.get(SomeObject.class), someObject);
  20. * // create and access scoped objects
  21. * } finally {
  22. * scope.exit();
  23. * }
  24. * }</pre>
  25. * <p/>
  26. * The scope can be initialized with one or more seed values by calling
  27. * <code>seed(key, value)</code> before the injector will be called upon to
  28. * provide for this key. A typical use is for a servlet filter to enter/exit the
  29. * scope, representing a Request Scope, and seed HttpServletRequest and
  30. * HttpServletResponse. For each key inserted with seed(), it's good practice
  31. * (since you have to provide <i>some</i> binding anyhow) to include a
  32. * corresponding binding that will throw an exception if Guice is asked to
  33. * provide for that key if it was not yet seeded: <pre> {@code
  34. * <p/>
  35. * bind(key)
  36. * .toProvider(SimpleScope.<KeyClass>seededKeyProvider())
  37. * .in(ScopeAnnotation.class);
  38. * }</pre>
  39. *
  40. * @author Jesse Wilson
  41. * @author Fedor Karpelevitch
  42. */
  43. public class SimpleScope implements Scope {
  44. private static final Provider<Object> SEEDED_KEY_PROVIDER =
  45. new Provider<Object>() {
  46. public Object get() {
  47. throw new IllegalStateException("If you got here then it means that" +
  48. " your code asked for scoped object which should have been" +
  49. " explicitly seeded in this scope by calling" +
  50. " SimpleScope.seed(), but was not.");
  51. }
  52. };
  53. private final ThreadLocal<Map<Key<?>, Object>> values
  54. = new ThreadLocal<Map<Key<?>, Object>>();
  55. public void enter() {
  56. checkState(values.get() == null, "A scoping block is already in progress");
  57. values.set(com.google.inject.internal.util.$Maps.<Key<?>, Object>newHashMap());
  58. }
  59. public void exit() {
  60. checkState(values.get() != null, "No scoping block in progress");
  61. values.remove();
  62. }
  63. public <T> void seed(Key<T> key, T value) {
  64. Map<Key<?>, Object> scopedObjects = getScopedObjectMap(key);
  65. checkState(!scopedObjects.containsKey(key), "A value for the key %s was " +
  66. "already seeded in this scope. Old value: %s New value: %s", key,
  67. scopedObjects.get(key), value);
  68. scopedObjects.put(key, value);
  69. }
  70. public <T> void seed(Class<T> clazz, T value) {
  71. seed(Key.get(clazz), value);
  72. }
  73. public <T> Provider<T> scope(final Key<T> key, final Provider<T> unscoped) {
  74. return new Provider<T>() {
  75. public T get() {
  76. Map<Key<?>, Object> scopedObjects = getScopedObjectMap(key);
  77. @SuppressWarnings("unchecked")
  78. T current = (T) scopedObjects.get(key);
  79. if (current == null && !scopedObjects.containsKey(key)) {
  80. current = unscoped.get();
  81. scopedObjects.put(key, current);
  82. }
  83. return current;
  84. }
  85. };
  86. }
  87. private <T> Map<Key<?>, Object> getScopedObjectMap(Key<T> key) {
  88. Map<Key<?>, Object> scopedObjects = values.get();
  89. if (scopedObjects == null) {
  90. throw new OutOfScopeException("Cannot access " + key
  91. + " outside of a scoping block");
  92. }
  93. return scopedObjects;
  94. }
  95. /**
  96. * Returns a provider that always throws exception complaining that the object
  97. * in question must be seeded before it can be injected.
  98. *
  99. * @return typed provider
  100. */
  101. @SuppressWarnings({"unchecked"})
  102. public static <T> Provider<T> seededKeyProvider() {
  103. return (Provider<T>) SEEDED_KEY_PROVIDER;
  104. }
  105. }