Clover coverage report - PicoContainer - 1.1
Coverage timestamp: Thu Nov 4 2004 11:55:45 CST
file stats: LOC: 136   Methods: 5
NCLOC: 65   Classes: 1
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 100% 100% 100% 100%
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.alternatives;
 11   
 
 12   
 import org.picocontainer.ComponentAdapter;
 13   
 import org.picocontainer.PicoContainer;
 14   
 import org.picocontainer.PicoInitializationException;
 15   
 import org.picocontainer.PicoIntrospectionException;
 16   
 import org.picocontainer.defaults.AssignabilityRegistrationException;
 17   
 import org.picocontainer.defaults.DecoratingComponentAdapter;
 18   
 import org.picocontainer.defaults.NotConcreteRegistrationException;
 19   
 
 20   
 import java.lang.reflect.InvocationHandler;
 21   
 import java.lang.reflect.InvocationTargetException;
 22   
 import java.lang.reflect.Method;
 23   
 import java.lang.reflect.Proxy;
 24   
 import java.util.ArrayList;
 25   
 import java.util.Arrays;
 26   
 import java.util.HashSet;
 27   
 import java.util.Iterator;
 28   
 import java.util.List;
 29   
 import java.util.Set;
 30   
 
 31   
 /**
 32   
  * This component adapter makes it possible to hide the implementation
 33   
  * of a real subject (behind a proxy) provided the key is an interface.
 34   
  * <p/>
 35   
  * This class exists here, because a) it has no deps on external jars, b) dynamic proxy is quite easy.
 36   
  * The user is prompted to look at nanocontainer-proxytoys for alternate and bigger implementations.
 37   
  *
 38   
  * @author Aslak Helles&oslash;y
 39   
  * @author Paul Hammant
 40   
  * @version $Revision: 1.4 $
 41   
  * @see org.nanocontainer.proxytoys.HotSwappingComponentAdapter for a more feature-rich version of this class.
 42   
  * @see org.nanocontainer.proxytoys.HotSwappingComponentAdapterFactory
 43   
  * @since 1.1
 44   
  */
 45   
 public class ImplementationHidingComponentAdapter extends DecoratingComponentAdapter {
 46   
     private final boolean strict;
 47   
 
 48  108
     public ImplementationHidingComponentAdapter(ComponentAdapter delegate, boolean strict) {
 49  108
         super(delegate);
 50  108
         this.strict = strict;
 51   
     }
 52   
 
 53  94
     public Object getComponentInstance(final PicoContainer container)
 54   
             throws PicoInitializationException, PicoIntrospectionException, AssignabilityRegistrationException, NotConcreteRegistrationException {
 55   
 
 56  94
         Object componentKey = getDelegate().getComponentKey();
 57  94
         Class[] classes = null;
 58  94
         if (componentKey instanceof Class && ((Class) getDelegate().getComponentKey()).isInterface()) {
 59  54
             classes = new Class[]{(Class) getDelegate().getComponentKey()};
 60  40
         } else if (componentKey instanceof Class[]) {
 61  4
             classes = (Class[]) componentKey;
 62   
         } else {
 63  36
             if(strict) {
 64  2
                 throw new PicoIntrospectionException("In strict mode, " + getClass().getName() + " only allows components registered with interface keys (java.lang.Class or java.lang.Class[])");
 65   
             }
 66  34
             return getDelegate().getComponentInstance(container);
 67   
         }
 68   
 
 69  58
         Class[] interfaces = verifyInterfacesOnly(classes);
 70  56
         return createProxy(interfaces, container);
 71   
     }
 72   
 
 73  56
     private Object createProxy(Class[] interfaces, final PicoContainer container) {
 74  56
         return Proxy.newProxyInstance(getClass().getClassLoader(),
 75   
                 interfaces, new InvocationHandler() {
 76  24
                     public Object invoke(final Object proxy, final Method method,
 77   
                                          final Object[] args)
 78   
                             throws Throwable {
 79  24
                         try {
 80  24
                             Object componentInstance = getDelegate().getComponentInstance(container);
 81  24
                             return method.invoke(componentInstance, args);
 82   
                         } catch (final InvocationTargetException ite) {
 83  6
                             throw ite.getTargetException();
 84   
                         }
 85   
                     }
 86   
                 });
 87   
     }
 88   
 
 89  58
     private Class[] verifyInterfacesOnly(Class[] classes) {
 90  58
         for (int i = 0; i < classes.length; i++) {
 91  60
             if(!classes[i].isInterface()) {
 92  2
                 throw new PicoIntrospectionException("Class keys must be interfaces. " + classes[i] + " is not an interface.");
 93   
             }
 94   
         }
 95  56
         return classes;
 96   
     }
 97   
 
 98   
     // These two methods are copied from ProxyToys' ClassHierarchyIntrospector
 99   
     // TODO: Why? These two are currently not called in the complete Pico/Nano/Micro codebase ...
 100   
     // they just decrease coverage significantly ...
 101   
     /* *
 102   
      * Get all interfaces of the given type.
 103   
      * If the type is a class, the returned list contains any interface, that is
 104   
      * implemented by the class. If the type is an interface, the all
 105   
      * superinterfaces and the interface itself are included.
 106   
      *
 107   
      * @param clazz type to explore.
 108   
      * @return an array with all interfaces. The array may be empty.
 109   
      */
 110   
     /*
 111   
     public static Class[] getAllInterfaces(Class clazz) {
 112   
         Set interfaces = new HashSet();
 113   
         getInterfaces(clazz, interfaces);
 114   
         return (Class[]) interfaces.toArray(new Class[interfaces.size()]);
 115   
     }
 116   
 
 117   
     private static void getInterfaces(Class clazz, Set interfaces) {
 118   
         if (clazz.isInterface()) {
 119   
             interfaces.add(clazz);
 120   
         }
 121   
         // Class.getInterfaces will return only the interfaces that are
 122   
         // implemented by the current class. Therefore we must loop up
 123   
         // the hierarchy for the superclasses and the superinterfaces.
 124   
         while (clazz != null) {
 125   
             Class[] implemented = clazz.getInterfaces();
 126   
             for (int i = 0; i < implemented.length; i++) {
 127   
                 if (!interfaces.contains(implemented[i])) {
 128   
                     getInterfaces(implemented[i], interfaces);
 129   
                 }
 130   
             }
 131   
             clazz = clazz.getSuperclass();
 132   
         }
 133   
     }
 134   
     */
 135   
 }
 136