PageRenderTime 14ms CodeModel.GetById 2ms app.highlight 9ms RepoModel.GetById 1ms app.codeStats 0ms

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