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 HashMap(); 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 HashMap(); 096 } 097 } 098 099 public static class StoreWrapper implements Serializable { 100 private Map wrapped; 101 } 102 103 }