Clover coverage report - Ivory - 1.0-alpha-5
Coverage timestamp: Sun Nov 9 2003 22:02:40 EST
file stats: LOC: 224   Methods: 5
NCLOC: 95   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
IvoryAvalonProvider.java 50% 82.6% 100% 77.8%
coverage coverage
 1   
 package org.codehaus.ivory.provider;
 2   
 
 3   
 import java.lang.reflect.InvocationHandler;
 4   
 import java.lang.reflect.InvocationTargetException;
 5   
 import java.lang.reflect.Method;
 6   
 import java.lang.reflect.Proxy;
 7   
 
 8   
 import javax.xml.rpc.server.ServiceLifecycle;
 9   
 
 10   
 import org.apache.avalon.framework.service.ServiceManager;
 11   
 import org.apache.axis.AxisFault;
 12   
 import org.apache.axis.MessageContext;
 13   
 import org.apache.axis.handlers.soap.SOAPService;
 14   
 
 15   
 /**
 16   
  * 
 17   
  * @author <a href="mailto:dan@envoisolutions.com">Dan Diephouse</a>
 18   
  * @since May 23, 2003
 19   
  */
 20   
 public class IvoryAvalonProvider
 21   
     extends IvoryProvider
 22   
 {
 23   
     /**
 24   
      * Constant used to retrieve the ServiceManager reference
 25   
      * from the MessageContext object.
 26   
      */
 27   
     public static final String SERVICE_MANAGER = "service-manager";
 28   
 
 29   
     /**
 30   
      * Constant which represents the name of the ROLE this
 31   
      * provider should <i>lookup</i> to service a request with. This is
 32   
      * specified in the &lt;parameter name="" value=""/&gt; part of the
 33   
      * deployment xml.
 34   
      */
 35   
     public static final String ROLE = "role";
 36   
 
 37   
     /**
 38   
      * Returns the service object.
 39   
      * 
 40   
      * @param msgContext the message context
 41   
      * @param role the Avalon ROLE to lookup to find the service object implementation
 42   
      * @return an object that implements the service
 43   
      * @exception Exception if an error occurs
 44   
      */
 45  1
     protected Object makeNewServiceObject(
 46   
         MessageContext msgContext,
 47   
         String role)
 48   
         throws Exception
 49   
     {
 50  1
         ServiceManager manager =
 51   
             (ServiceManager) msgContext
 52   
                 .getAxisEngine()
 53   
                 .getApplicationSession()
 54   
                 .get( SERVICE_MANAGER );
 55   
 
 56  1
         if (manager == null)
 57  0
             throw new AxisFault("Could not access Avalon ServiceManager");
 58   
 
 59  1
         return decorate(manager.lookup(role), manager);
 60   
     }
 61   
 
 62   
     /**
 63   
      * Helper method for decorating a <code>Component</code> with a Handler
 64   
      * proxy (see below).
 65   
      *
 66   
      * @param object a <code>Component</code> instance
 67   
      * @param manager a <code>ComponentManager</code> instance
 68   
      * @return the <code>Proxy</code> wrapped <code>Component</code> instance
 69   
      * @exception Exception if an error occurs
 70   
      */
 71  1
     private Object decorate(final Object object, final ServiceManager manager)
 72   
         throws Exception
 73   
     {
 74   
         // obtain a list of all interfaces this object implements
 75  1
         Class[] interfaces = object.getClass().getInterfaces();
 76   
 
 77   
         // add ServiceLifecycle to it
 78  1
         Class[] adjusted = new Class[interfaces.length + 1];
 79  1
         System.arraycopy(interfaces, 0, adjusted, 0, interfaces.length);
 80  1
         adjusted[interfaces.length] = ServiceLifecycle.class;
 81   
 
 82   
         // create a proxy implementing those interfaces
 83  1
         Object proxy =
 84   
             Proxy.newProxyInstance(
 85   
                 this.getClass().getClassLoader(),
 86   
                 adjusted,
 87   
                 new Handler(object, manager));
 88   
 
 89   
         // return the proxy
 90  1
         return proxy;
 91   
     }
 92   
 
 93   
     /**
 94   
      * Get the service class description
 95   
      * 
 96   
      * @param role the Avalon ROLE name
 97   
      * @param service a <code>SOAPService</code> instance
 98   
      * @param msgContext the message context
 99   
      * @return service class description
 100   
      * @exception AxisFault if an error occurs
 101   
      */
 102  5
     protected Class getServiceClass(
 103   
         String role,
 104   
         SOAPService service,
 105   
         MessageContext msgContext)
 106   
         throws AxisFault
 107   
     {
 108   
         // Assuming ExcaliburComponentManager semantics the ROLE name is
 109   
         // actually the class name, potentially with a variant following
 110   
         // the class name with a '/' separator
 111   
 
 112  5
         int i;
 113   
 
 114  ?
         if ((i = role.indexOf('/')) != -1)
 115   
         {
 116  0
             return super.getServiceClass( role.substring(0, i), service, msgContext );
 117   
         }
 118   
         else
 119   
         {
 120  5
             return super.getServiceClass( role, service, msgContext );
 121   
         }
 122   
 
 123   
     }
 124   
 
 125   
     /**
 126   
      * <code>InvocationHandler</code> class for managing Avalon
 127   
      * <code>Components</code>.
 128   
      *
 129   
      * <p>
 130   
      *  Components retrieved from an Avalon ComponentManager must be
 131   
      *  returned to the manager when they are no longer required.
 132   
      * </p>
 133   
      *
 134   
      * <p>
 135   
      *  The returning of Components to their ComponentManager is handled
 136   
      *  by a Proxy class which uses the following InvocationHandler.
 137   
      * </p>
 138   
      *
 139   
      * <p>
 140   
      *  Each Component returned by this Provider is wrapped inside a 
 141   
      *  Proxy class which implements all of the Component's interfaces
 142   
      *  including javax.xml.rpc.server.ServiceLifecycle.
 143   
      * </p>
 144   
      *
 145   
      * <p>
 146   
      *  When Axis is finished with the object returned by this provider,
 147   
      *  it invokes ServiceLifecycle.destroy(). This is intercepted by the
 148   
      *  InvocationHandler and the Component is returned at this time back
 149   
      *  to the ComponentManager it was retrieved from.
 150   
      * </p>
 151   
      *
 152   
      * <p>
 153   
      *  <b>Note</b>, when Axis invokes ServiceLifecycle.destroy() is dependant
 154   
      *  on the scope of the service (ie. Request, Session & Application).
 155   
      * </p>
 156   
      */
 157   
     final class Handler implements InvocationHandler
 158   
     {
 159   
         // Constants describing the ServiceLifecycle.destroy method
 160   
         private final String SL_DESTROY = "destroy";
 161   
         private final Class SL_CLASS = ServiceLifecycle.class;
 162   
 
 163   
         // Component & ServiceManager references
 164   
         private final Object m_object;
 165   
         private final ServiceManager m_manager;
 166   
 
 167   
         /**
 168   
          * Simple constructor, sets all internal references
 169   
          *
 170   
          * @param object a <code>Component</code> instance
 171   
          * @param manager a <code>ComponentManager</code> instance
 172   
          * @param log a <code>Logger</code> instance
 173   
          */
 174  1
         public Handler(final Object object, final ServiceManager manager)
 175   
         {
 176  1
             m_object = object;
 177  1
             m_manager = manager;
 178   
         }
 179   
 
 180   
         /**
 181   
          * <code>invoke</code> method, handles all method invocations for this
 182   
          * particular proxy.
 183   
          *
 184   
          * <p>
 185   
          *  Usually the invocation is passed through to the
 186   
          *  actual component the proxy wraps, unless the method belongs to
 187   
          *  the <code>ServiceLifecycle</code> interface where it is handled
 188   
          *  locally.
 189   
          * </p>
 190   
          *
 191   
          * @param proxy the <code>Proxy</code> instance the method was invoked on
 192   
          * @param method the invoked method <code>Method</code> object
 193   
          * @param args an <code>Object[]</code> array of arguments
 194   
          * @return an <code>Object</code> value or null if none
 195   
          * @exception Throwable if an error occurs
 196   
          */
 197  2
         public Object invoke(Object proxy, Method method, Object[] args)
 198   
             throws Throwable
 199   
         {
 200  2
             try
 201   
             {
 202   
                 // if ServiceLifecycle.destroy() called, return to CM
 203  2
                 if (method.getDeclaringClass().equals(SL_CLASS))
 204   
                 {
 205  1
                     if (method.getName().equals(SL_DESTROY))
 206   
                     {
 207  0
                         m_manager.release(m_object);
 208   
                     }
 209   
     
 210  1
                     return null;
 211   
                 }
 212   
                 else // otherwise pass call to the real object
 213   
                     {
 214  1
                     return method.invoke(m_object, args);
 215   
                 }
 216   
             }
 217   
             catch ( InvocationTargetException e )
 218   
             {
 219  0
                 throw e.getTargetException();
 220   
             }
 221   
         }
 222   
     }
 223   
 }
 224