Clover coverage report - PicoContainer - 1.0-RC-1
Coverage timestamp: Tue May 18 2004 16:19:33 EDT
file stats: LOC: 136   Methods: 6
NCLOC: 79   Classes: 2
30 day Evaluation Version distributed via the Maven Jar Repository. Clover is not free. You have 30 days to evaluate it. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover
 
 Source file Conditionals Statements Methods TOTAL
ImplementationHidingComponentAdapter.java 75% 84.8% 100% 83.6%
coverage coverage
 1   
 /*****************************************************************************
 2   
  * Copyright (C) PicoContainer Organization. All rights reserved.            *
 3   
  * ------------------------------------------------------------------------- *
 4   
  * The software in this package is published under the terms of the BSD      *
 5   
  * style license a copy of which has been included with this distribution in *
 6   
  * the LICENSE.txt file.                                                     *
 7   
  *                                                                           *
 8   
  * Original code by                                                          *
 9   
  *****************************************************************************/
 10   
 package org.picocontainer.defaults;
 11   
 
 12   
 import org.picocontainer.ComponentAdapter;
 13   
 import org.picocontainer.PicoInitializationException;
 14   
 import org.picocontainer.PicoIntrospectionException;
 15   
 
 16   
 import java.lang.reflect.InvocationHandler;
 17   
 import java.lang.reflect.Method;
 18   
 import java.lang.reflect.Proxy;
 19   
 import java.util.ArrayList;
 20   
 import java.util.List;
 21   
 
 22   
 /**
 23   
  * This component adapter makes it possible to hide the implementation
 24   
  * of a real subject (behind a proxy).
 25   
  * If the key of the component is of type {@link java.lang.Class} and that class represents an interface, the proxy
 26   
  * will only implement the interface represented by that Class. Otherwise (if the key is
 27   
  * something else), the proxy will implement all the interfaces of the underlying subject.
 28   
  * In any case, the proxy will also implement
 29   
  * {@link Swappable}, making it possible to swap out the underlying
 30   
  * subject at runtime.
 31   
  * <p>
 32   
  * <em>
 33   
  * Note that this class doesn't cache instances. If you want caching,
 34   
  * use a {@link CachingComponentAdapter} around this one.
 35   
  * </em>
 36   
  *
 37   
  * @deprecated Use {@link org.nanocontainer.proxytoys.HotSwappingComponentAdapter} instead.
 38   
  * @author Paul Hammant
 39   
  * @author Aslak Helles&oslash;y
 40   
  * @version $Revision: 1.15 $
 41   
  */
 42   
 public class ImplementationHidingComponentAdapter extends DecoratingComponentAdapter {
 43   
     private static Method hotswap;
 44   
     static {
 45  3
         try {
 46  3
             hotswap = Swappable.class.getMethod("hotswap", new Class[]{Object.class});
 47   
         } catch (NoSuchMethodException e) {
 48  0
             throw new InternalError();
 49   
         }
 50   
     }
 51   
 
 52   
     private final boolean strict;
 53   
 
 54   
     /**
 55   
      * Alternative constructor allowing to set interface-only strictness.
 56   
      * @param delegate the delegate adapter
 57   
      * @param strict true if the adapter should only accept classes that are hideable behind interfaces.
 58   
      * If false, a non-implementation hidden instance will be created instead of throwing an exception.
 59   
      */
 60  19
     public ImplementationHidingComponentAdapter(ComponentAdapter delegate, boolean strict) {
 61  19
         super(delegate);
 62  19
         this.strict = strict;
 63   
     }
 64   
 
 65   
 
 66   
     /**
 67   
      * Creates a strict ImplementationHidingComponentAdapter that will throw an exception
 68   
      * when trying to instantiate a class that doesn't implement any interfaces.
 69   
      * @param delegate the delegate adapter
 70   
      */
 71  3
     public ImplementationHidingComponentAdapter(ComponentAdapter delegate) {
 72  3
         this(delegate, true);
 73   
     }
 74   
 
 75  18
     public Object getComponentInstance()
 76   
             throws PicoInitializationException, PicoIntrospectionException, AssignabilityRegistrationException, NotConcreteRegistrationException {
 77   
 
 78  18
         List interfaces = new ArrayList();
 79  18
         if(getDelegate().getComponentKey() instanceof Class && ((Class)getDelegate().getComponentKey()).isInterface()) {
 80  5
             interfaces.add(getDelegate().getComponentKey());
 81   
         } else {
 82  13
             interfaces.addAll(ClassHierarchyIntrospector.getAllInterfaces(getDelegate().getComponentImplementation()));
 83   
         }
 84  18
         if (interfaces.size() == 0) {
 85  3
             if(strict) {
 86  0
                 throw new PicoIntrospectionException("Can't hide implementation for " + getDelegate().getComponentImplementation().getName() + ". It doesn't implement any interfaces.");
 87   
             } else {
 88  3
                 return getDelegate().getComponentInstance();
 89   
             }
 90   
         }
 91  15
         interfaces.add(Swappable.class);
 92  15
         final DelegatingInvocationHandler delegatingInvocationHandler = new DelegatingInvocationHandler();
 93  15
         return Proxy.newProxyInstance(
 94   
                 getClass().getClassLoader(),
 95   
                 (Class[]) interfaces.toArray(new Class[interfaces.size()]),
 96   
                 delegatingInvocationHandler);
 97   
     }
 98   
 
 99  11
     private Object getDelegatedComponentInstance() {
 100  11
         return super.getComponentInstance();
 101   
     }
 102   
 
 103   
     private class DelegatingInvocationHandler implements InvocationHandler {
 104   
         private Object delegatedInstance;
 105   
 
 106  37
         public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
 107  37
             Class declaringClass = method.getDeclaringClass();
 108  37
             if (declaringClass.equals(Object.class)) {
 109  2
                 if (method.equals(ClassHierarchyIntrospector.hashCode)) {
 110   
                     // Return the hashCode of ourself, as Proxy.newProxyInstance() may
 111   
                     // return cached proxies. We want a unique hashCode for each created proxy!
 112  2
                     return new Integer(System.identityHashCode(this));
 113   
                 }
 114  0
                 if (method.equals(ClassHierarchyIntrospector.equals)) {
 115  0
                     return new Boolean(proxy == args[0]);
 116   
                 }
 117   
                 // If it's any other method defined by Object, call on ourself.
 118  0
                 return method.invoke(this, args);
 119  35
             } else if (hotswap.equals(method)) {
 120  6
                 return hotswap(args[0]);
 121   
             } else {
 122  29
                 if (delegatedInstance == null) {
 123  11
                     delegatedInstance = ImplementationHidingComponentAdapter.this.getDelegatedComponentInstance();
 124   
                 }
 125  29
                 return method.invoke(delegatedInstance, args);
 126   
             }
 127   
         }
 128   
 
 129  6
         private Object hotswap(Object newSubject) {
 130  6
             Object result = delegatedInstance;
 131  6
             delegatedInstance = newSubject;
 132  6
             return result;
 133   
         }
 134   
     }
 135   
 }
 136