    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    }