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 }