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 }