    001    /*****************************************************************************
    002     * Copyright (c) PicoContainer Organization. All rights reserved.            *
    003     * ------------------------------------------------------------------------- *
    004     * The software in this package is published under the terms of the BSD      *
    005     * style license a copy of which has been included with this distribution in *
    006     * the LICENSE.txt file.                                                     *
    007     *                                                                           *
    008     * Idea by Rachel Davies, Original code by Aslak Hellesoy and Paul Hammant   *
    009     *****************************************************************************/
    010
    011    package org.picocontainer.behaviors;
    012
    013    import org.picocontainer.ComponentAdapter;
    014    import org.picocontainer.Parameter;
    015    import org.picocontainer.PicoCompositionException;
    016    import org.picocontainer.Characteristics;
    017    import org.picocontainer.ComponentMonitor;
    018    import org.picocontainer.LifecycleStrategy;
    019    import org.picocontainer.references.ThreadLocalMapObjectReference;
    020
    021    import java.io.Serializable;
    022    import java.util.Properties;
    023    import java.util.HashMap;
    024    import java.util.Map;
    025    import java.util.Collections;
    026    import java.util.concurrent.ConcurrentHashMap;
    027
    028    /**
    029     * @author Paul Hammant
    030     */
    031    @SuppressWarnings("serial")
    032    public class Storing extends AbstractBehaviorFactory {
    033
    034        private final StoreThreadLocal mapThreadLocalObjectReference = new StoreThreadLocal();
    035
    036        public <T> ComponentAdapter<T>  createComponentAdapter(ComponentMonitor componentMonitor, LifecycleStrategy lifecycleStrategy, Properties componentProperties, final Object componentKey, Class<T> componentImplementation, Parameter... parameters)
    037
    038                throws PicoCompositionException {
    039            if (removePropertiesIfPresent(componentProperties, Characteristics.NO_CACHE)) {
    040                return super.createComponentAdapter(componentMonitor,
    041                                                                                 lifecycleStrategy,
    042                                                                                 componentProperties,
    043                                                                                 componentKey,
    044                                                                                 componentImplementation,
    045                                                                                 parameters);
    046            }
    047            removePropertiesIfPresent(componentProperties, Characteristics.CACHE);
    048            return componentMonitor.newBehavior(new Stored<T>(super.createComponentAdapter(componentMonitor, lifecycleStrategy,
    049                                                                    componentProperties, componentKey, componentImplementation, parameters),
    050                              new ThreadLocalMapObjectReference(mapThreadLocalObjectReference, componentKey)));
    051
    052        }
    053
    054        public <T> ComponentAdapter<T> addComponentAdapter(ComponentMonitor componentMonitor,
    055                                        LifecycleStrategy lifecycleStrategy,
    056                                        Properties componentProperties,
    057                                        final ComponentAdapter<T> adapter) {
    058            if (removePropertiesIfPresent(componentProperties, Characteristics.NO_CACHE)) {
    059                return super.addComponentAdapter(componentMonitor, lifecycleStrategy, componentProperties, adapter);
    060            }
    061            removePropertiesIfPresent(componentProperties, Characteristics.CACHE);
    062
    063            return componentMonitor.newBehavior(new Stored<T>(super.addComponentAdapter(componentMonitor, lifecycleStrategy, componentProperties, adapter),
    064                              new ThreadLocalMapObjectReference(mapThreadLocalObjectReference, adapter.getComponentKey())));
    065        }
    066
    067        public StoreWrapper getCacheForThread() {
    068            StoreWrapper wrappedMap = new StoreWrapper();
    069            wrappedMap.wrapped = (Map)mapThreadLocalObjectReference.get();
    070            return wrappedMap;
    071        }
    072
    073        public void putCacheForThread(StoreWrapper wrappedMap) {
    074            mapThreadLocalObjectReference.set(wrappedMap.wrapped);
    075        }
    076
    077        public StoreWrapper resetCacheForThread() {
    078            Map map = new ConcurrentHashMap();
    079            mapThreadLocalObjectReference.set(map);
    080            StoreWrapper storeWrapper = new StoreWrapper();
    081            storeWrapper.wrapped = map;
    082            return storeWrapper;
    083        }
    084
    085        public void invalidateCacheForThread() {
    086            mapThreadLocalObjectReference.set(Collections.unmodifiableMap(Collections.emptyMap()));
    087        }
    088
    089        public int getCacheSize() {
    090            return ((Map)mapThreadLocalObjectReference.get()).size();
    091        }
    092
    093        public static class StoreThreadLocal extends ThreadLocal<Map> implements Serializable {
    094            protected Map initialValue() {
    095                return new ConcurrentHashMap();
    096            }
    097        }
    098
    099        public static class StoreWrapper implements Serializable {
    100            private Map wrapped;
    101        }
    102
    103    }