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.behaviors.AbstractBehaviorFactory;
019    import org.picocontainer.LifecycleStrategy;
020    import org.picocontainer.ObjectReference;
021    
022    import java.io.Serializable;
023    import java.util.Properties;
024    import java.util.HashMap;
025    import java.util.Map;
026    
027    /**
028     * @author Paul Hammant
029     */
030    public class Storing extends AbstractBehaviorFactory {
031    
032        private final StoreThreadLocal mapThreadLocalObjectReference = new StoreThreadLocal();
033    
034        public ComponentAdapter createComponentAdapter(ComponentMonitor componentMonitor, LifecycleStrategy lifecycleStrategy, Properties componentProperties, final Object componentKey, Class componentImplementation, Parameter... parameters)
035                throws PicoCompositionException {
036            if (removePropertiesIfPresent(componentProperties, Characteristics.NO_CACHE)) {
037                return super.createComponentAdapter(componentMonitor,
038                                                                                 lifecycleStrategy,
039                                                                                 componentProperties,
040                                                                                 componentKey,
041                                                                                 componentImplementation,
042                                                                                 parameters);
043            }
044            removePropertiesIfPresent(componentProperties, Characteristics.CACHE);
045            return new Cached(super.createComponentAdapter(componentMonitor, lifecycleStrategy,
046                                                                    componentProperties, componentKey, componentImplementation, parameters),
047                              new ObjectReference() {
048                                  public Object get() {
049                                      return ((Map)mapThreadLocalObjectReference.get()).get(componentKey) ;
050                                  }
051                                  public void set(Object item) {
052                                      ((Map)mapThreadLocalObjectReference.get()).put(componentKey, item) ;
053    
054                                  }
055                              });
056    
057        }
058    
059        public ComponentAdapter addComponentAdapter(ComponentMonitor componentMonitor,
060                                        LifecycleStrategy lifecycleStrategy,
061                                        Properties componentProperties,
062                                        final ComponentAdapter adapter) {
063            if (removePropertiesIfPresent(componentProperties, Characteristics.NO_CACHE)) {
064                return super.addComponentAdapter(componentMonitor, lifecycleStrategy, componentProperties, adapter);
065            }
066            removePropertiesIfPresent(componentProperties, Characteristics.CACHE);
067            return new Cached(super.addComponentAdapter(componentMonitor, lifecycleStrategy, componentProperties, adapter),
068                                   new ObjectReference() {
069                                       public Object get() {
070                                           return ((Map)mapThreadLocalObjectReference.get()).get(adapter.getComponentKey()) ;
071                                       }
072    
073                                       public void set(Object item) {
074                                           ((Map)mapThreadLocalObjectReference.get()).put(adapter.getComponentKey(), item) ;
075                                       }
076                                   });
077        }
078    
079        public StoreWrapper getCacheForThread() {
080            StoreWrapper wrappedMap = new StoreWrapper();
081            wrappedMap.wrapped = (Map)mapThreadLocalObjectReference.get();
082            return wrappedMap;
083        }
084    
085        public void putCacheForThread(StoreWrapper wrappedMap) {
086            mapThreadLocalObjectReference.set(wrappedMap.wrapped);
087        }
088    
089        public static class StoreThreadLocal extends ThreadLocal {
090            protected Object initialValue() {
091                return new HashMap();
092            }
093        }
094        public static class StoreWrapper implements Serializable {
095            private Map wrapped;
096        }
097    
098    }