001/*
002 * (C) Copyright 2012 Nuxeo SA (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     matic
016 */
017package org.nuxeo.ecm.core.test;
018
019import java.util.HashMap;
020import java.util.Map;
021
022import com.google.inject.Key;
023import com.google.inject.OutOfScopeException;
024import com.google.inject.Provider;
025import com.google.inject.Scope;
026
027/**
028 * @author matic
029 */
030public class CoreScope implements Scope {
031
032    protected final ThreadLocal<Map<Key<?>, Object>> values = new ThreadLocal<Map<Key<?>, Object>>() {
033        protected java.util.Map<Key<?>, Object> initialValue() {
034            return new HashMap<Key<?>, Object>();
035        };
036    };
037
038    public final static CoreScope INSTANCE = new CoreScope();
039
040    protected CoreScope() {
041
042    }
043
044    public void enter() {
045        values.get();
046    }
047
048    public void exit() {
049        values.remove();
050    }
051
052    @Override
053    public <T> Provider<T> scope(final Key<T> key, final Provider<T> unscoped) {
054        return new Provider<T>() {
055
056            @Override
057            public T get() {
058                Map<Key<?>, Object> scopedMap = getScopedObjectMap(key);
059                T current = (T) scopedMap.get(key);
060                if (current == null && !scopedMap.containsKey(key)) {
061                    current = unscoped.get();
062                    scopedMap.put(key, current);
063                }
064                return current;
065            }
066
067        };
068    }
069
070    private <T> Map<Key<?>, Object> getScopedObjectMap(Key<T> key) {
071        Map<Key<?>, Object> scopedObjects = values.get();
072        if (scopedObjects == null) {
073            throw new OutOfScopeException("Cannot access " + key + " outside of a scoping block");
074        }
075        return scopedObjects;
076    }
077}