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     * Original code by                                                          *
009     *****************************************************************************/
010    package org.picocontainer.gems.behaviors;
011    
012    import org.picocontainer.ComponentAdapter;
013    import org.picocontainer.PicoContainer;
014    import org.picocontainer.behaviors.Cached;
015    
016    import java.lang.reflect.Type;
017    
018    
019    /**
020     * This component adapter makes it possible to hide the implementation of a real subject (behind a proxy). If the key of the
021     * component is of type {@link Class} and that class represents an interface, the proxy will only implement the interface
022     * represented by that Class. Otherwise (if the key is something else), the proxy will implement all the interfaces of the
023     * underlying subject. In any case, the proxy will also implement {@link com.thoughtworks.proxy.toys.hotswap.Swappable}, making
024     * it possible to swap out the underlying subject at runtime. <p/> <em>
025     * Note that this class doesn't cache instances. If you want caching,
026     * use a {@link Cached} around this one.
027     * </em>
028     *
029     * @author Paul Hammant
030     */
031    @SuppressWarnings("serial")
032    public class HotSwappable<T> extends AsmHiddenImplementation<T> {
033    
034            private final Swappable swappable = new Swappable();
035        
036            private T instance;
037    
038        public HotSwappable(final ComponentAdapter<T> delegate) {
039            super(delegate);
040        }
041    
042        @Override
043            protected Swappable getSwappable() {
044            return swappable;
045        }
046    
047        @SuppressWarnings("unchecked")
048            public T swapRealInstance(final T instance) {
049            return (T) swappable.swap(instance);
050        }
051    
052        @SuppressWarnings("unchecked")
053            public T getRealInstance() {
054            return (T) swappable.getInstance();
055        }
056    
057    
058        @Override
059            public T getComponentInstance(final PicoContainer container, final Type into) {
060            synchronized (swappable) {
061                if (instance == null) {
062                    instance = super.getComponentInstance(container, into);
063                }
064            }
065            return instance;
066        }
067    
068        @Override
069            public String getDescriptor() {
070            return "HotSwappable";
071        }
072    
073        public static class Swappable {
074    
075            private transient Object delegate;
076    
077            public Object getInstance() {
078                return delegate;
079            }
080    
081            public Object swap(final Object delegate) {
082                Object old = this.delegate;
083                this.delegate = delegate;
084                return old;
085            }
086    
087        }
088    
089    }