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 027 /** 028 * @author Paul Hammant 029 */ 030 @SuppressWarnings("serial") 031 public class Storing extends AbstractBehaviorFactory { 032 033 private final StoreThreadLocal mapThreadLocalObjectReference = new StoreThreadLocal(); 034 035 public <T> ComponentAdapter<T> createComponentAdapter(ComponentMonitor componentMonitor, LifecycleStrategy lifecycleStrategy, Properties componentProperties, final Object componentKey, Class<T> componentImplementation, Parameter... parameters) 036 037 throws PicoCompositionException { 038 if (removePropertiesIfPresent(componentProperties, Characteristics.NO_CACHE)) { 039 return super.createComponentAdapter(componentMonitor, 040 lifecycleStrategy, 041 componentProperties, 042 componentKey, 043 componentImplementation, 044 parameters); 045 } 046 removePropertiesIfPresent(componentProperties, Characteristics.CACHE); 047 return new Stored<T>(super.createComponentAdapter(componentMonitor, lifecycleStrategy, 048 componentProperties, componentKey, componentImplementation, parameters), 049 new ThreadLocalMapObjectReference(mapThreadLocalObjectReference, componentKey)); 050 051 } 052 053 public <T> ComponentAdapter<T> addComponentAdapter(ComponentMonitor componentMonitor, 054 LifecycleStrategy lifecycleStrategy, 055 Properties componentProperties, 056 final ComponentAdapter<T> adapter) { 057 if (removePropertiesIfPresent(componentProperties, Characteristics.NO_CACHE)) { 058 return super.addComponentAdapter(componentMonitor, lifecycleStrategy, componentProperties, adapter); 059 } 060 removePropertiesIfPresent(componentProperties, Characteristics.CACHE); 061 062 return new Stored<T>(super.addComponentAdapter(componentMonitor, lifecycleStrategy, componentProperties, adapter), 063 new ThreadLocalMapObjectReference(mapThreadLocalObjectReference, adapter.getComponentKey())); 064 } 065 066 public StoreWrapper getCacheForThread() { 067 StoreWrapper wrappedMap = new StoreWrapper(); 068 wrappedMap.wrapped = (Map)mapThreadLocalObjectReference.get(); 069 return wrappedMap; 070 } 071 072 public void putCacheForThread(StoreWrapper wrappedMap) { 073 mapThreadLocalObjectReference.set(wrappedMap.wrapped); 074 } 075 076 public StoreWrapper resetCacheForThread() { 077 HashMap map = new HashMap(); 078 mapThreadLocalObjectReference.set(map); 079 StoreWrapper storeWrapper = new StoreWrapper(); 080 storeWrapper.wrapped = map; 081 return storeWrapper; 082 } 083 084 public void invalidateCacheForThread() { 085 mapThreadLocalObjectReference.set(Collections.unmodifiableMap(Collections.emptyMap())); 086 } 087 088 public int getCacheSize() { 089 return ((Map)mapThreadLocalObjectReference.get()).size(); 090 } 091 092 public static class StoreThreadLocal extends ThreadLocal<Map> implements Serializable { 093 protected Map initialValue() { 094 return new HashMap(); 095 } 096 } 097 098 public static class StoreWrapper implements Serializable { 099 private Map wrapped; 100 } 101 102 }