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 }