001/*
002 * (C) Copyright 2012 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     matic
018 */
019package org.nuxeo.ecm.core.test;
020
021import java.util.HashMap;
022import java.util.Map;
023
024import com.google.inject.Key;
025import com.google.inject.OutOfScopeException;
026import com.google.inject.Provider;
027import com.google.inject.Scope;
028
029/**
030 * @author matic
031 */
032public class CoreScope implements Scope {
033
034    protected final ThreadLocal<Map<Key<?>, Object>> values = new ThreadLocal<Map<Key<?>, Object>>() {
035        protected java.util.Map<Key<?>, Object> initialValue() {
036            return new HashMap<Key<?>, Object>();
037        };
038    };
039
040    public final static CoreScope INSTANCE = new CoreScope();
041
042    protected CoreScope() {
043
044    }
045
046    public void enter() {
047        values.get();
048    }
049
050    public void exit() {
051        values.remove();
052    }
053
054    @Override
055    public <T> Provider<T> scope(final Key<T> key, final Provider<T> unscoped) {
056        return new Provider<T>() {
057
058            @Override
059            public T get() {
060                Map<Key<?>, Object> scopedMap = getScopedObjectMap(key);
061                T current = (T) scopedMap.get(key);
062                if (current == null && !scopedMap.containsKey(key)) {
063                    current = unscoped.get();
064                    scopedMap.put(key, current);
065                }
066                return current;
067            }
068
069        };
070    }
071
072    private <T> Map<Key<?>, Object> getScopedObjectMap(Key<T> key) {
073        Map<Key<?>, Object> scopedObjects = values.get();
074        if (scopedObjects == null) {
075            throw new OutOfScopeException("Cannot access " + key + " outside of a scoping block");
076        }
077        return scopedObjects;
078    }
079}