001 package org.picocontainer.behaviors; 002 003 import org.picocontainer.ComponentAdapter; 004 import org.picocontainer.LifecycleStrategy; 005 import org.picocontainer.ObjectReference; 006 import org.picocontainer.PicoCompositionException; 007 import org.picocontainer.PicoContainer; 008 009 import java.lang.reflect.Type; 010 011 /** 012 * behaviour for all behaviours wishing to store 013 * their component in "awkward places" ( object references ) 014 * @author Konstantin Pribluda 015 * 016 * @param <T> 017 */ 018 @SuppressWarnings("serial") 019 public class Stored<T> extends AbstractBehavior<T> { 020 021 protected final boolean delegateHasLifecylce; 022 protected boolean disposed; 023 protected final ObjectReference<T> instanceReference; 024 025 protected boolean started; 026 027 public Stored(ComponentAdapter<T> delegate, ObjectReference<T> reference) { 028 super(delegate); 029 instanceReference = reference; 030 this.disposed = false; 031 this.started = false; 032 this.delegateHasLifecylce = delegate instanceof LifecycleStrategy 033 && ((LifecycleStrategy) delegate).hasLifecycle(delegate.getComponentImplementation()); 034 035 } 036 037 public boolean componentHasLifecycle() { 038 return delegateHasLifecylce; 039 } 040 041 /** 042 * Disposes the cached component instance 043 * {@inheritDoc} 044 */ 045 public void dispose(PicoContainer container) { 046 if ( delegateHasLifecylce ){ 047 if (disposed) throw new IllegalStateException("Already disposed"); 048 dispose(getComponentInstance(container, NOTHING.class)); 049 disposed = true; 050 } 051 } 052 053 /** 054 * Retrieves the stored reference. May be null if it has 055 * never been set, or possibly if the reference has been 056 * flushed. 057 * @return the stored object or null. 058 */ 059 public T getStoredObject() { 060 return instanceReference.get(); 061 } 062 063 /** 064 * Flushes the cache. 065 * If the component instance is started is will stop and dispose it before 066 * flushing the cache. 067 */ 068 public void flush() { 069 Object instance = instanceReference.get(); 070 if ( instance != null && delegateHasLifecylce && started ) { 071 stop(instance); 072 dispose(instance); 073 } 074 instanceReference.set(null); 075 } 076 077 public T getComponentInstance(PicoContainer container, Type into) throws PicoCompositionException { 078 T instance = instanceReference.get(); 079 if (instance == null) { 080 instance = super.getComponentInstance(container, into); 081 instanceReference.set(instance); 082 } 083 return instance; 084 } 085 086 public String getDescriptor() { 087 return "Stored"; 088 } 089 090 /** 091 * Starts the cached component instance 092 * {@inheritDoc} 093 */ 094 public void start(PicoContainer container) { 095 if ( delegateHasLifecylce ){ 096 if (disposed) throw new IllegalStateException("Already disposed"); 097 if (started) throw new IllegalStateException("Already started"); 098 start(getComponentInstance(container, NOTHING.class)); 099 started = true; 100 } 101 } 102 103 /** 104 * Stops the cached component instance 105 * {@inheritDoc} 106 */ 107 public void stop(PicoContainer container) { 108 if ( delegateHasLifecylce ){ 109 if (disposed) throw new IllegalStateException("Already disposed"); 110 if (!started) throw new IllegalStateException("Not started"); 111 stop(getComponentInstance(container, NOTHING.class)); 112 started = false; 113 } 114 } 115 116 }