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 /**
010 * abstract base behaviour for all behaviours wishing to store
011 * their component in "awkward places" ( object references )
012 * @author Konstantin Pribluda
013 *
014 * @param <T>
015 */
016 public abstract class Stored<T> extends AbstractBehavior<T> {
017
018
019 protected final boolean delegateHasLifecylce;
020 protected boolean disposed;
021 protected final ObjectReference<T> instanceReference;
022
023 protected boolean started;
024
025 public Stored(ComponentAdapter<T> delegate, ObjectReference<T> reference) {
026 super(delegate);
027 instanceReference = reference;
028 this.disposed = false;
029 this.started = false;
030 this.delegateHasLifecylce = delegate instanceof LifecycleStrategy
031 && ((LifecycleStrategy) delegate).hasLifecycle(delegate.getComponentImplementation());
032
033 }
034
035 public boolean componentHasLifecycle() {
036 return delegateHasLifecylce;
037 }
038
039 /**
040 * Disposes the cached component instance
041 * {@inheritDoc}
042 */
043 public void dispose(PicoContainer container) {
044 if ( delegateHasLifecylce ){
045 if (disposed) throw new IllegalStateException("Already disposed");
046 dispose(getComponentInstance(container));
047 disposed = true;
048 }
049 }
050
051 /**
052 * Flushes the cache.
053 * If the component instance is started is will stop and dispose it before
054 * flushing the cache.
055 */
056 public void flush() {
057 Object instance = instanceReference.get();
058 if ( instance != null && delegateHasLifecylce && started ) {
059 stop(instance);
060 dispose(instance);
061 }
062 instanceReference.set(null);
063 }
064
065 public T getComponentInstance(PicoContainer container) throws PicoCompositionException {
066 T instance = instanceReference.get();
067 if (instance == null) {
068 instance = super.getComponentInstance(container);
069 instanceReference.set(instance);
070 }
071 return (T)instance;
072 }
073
074 /**
075 * Starts the cached component instance
076 * {@inheritDoc}
077 */
078 public void start(PicoContainer container) {
079 if ( delegateHasLifecylce ){
080 if (disposed) throw new IllegalStateException("Already disposed");
081 if (started) throw new IllegalStateException("Already started");
082 start(getComponentInstance(container));
083 started = true;
084 }
085 }
086
087 /**
088 * Stops the cached component instance
089 * {@inheritDoc}
090 */
091 public void stop(PicoContainer container) {
092 if ( delegateHasLifecylce ){
093 if (disposed) throw new IllegalStateException("Already disposed");
094 if (!started) throw new IllegalStateException("Not started");
095 stop(getComponentInstance(container));
096 started = false;
097 }
098 }
099
100 }