Coverage Report - org.mule.component.DefaultLifecycleAdapter
 
Classes in this File Line Coverage Branch Coverage Complexity
DefaultLifecycleAdapter
46%
42/91
38%
12/32
3.8
 
 1  
 /*
 2  
  * $Id: DefaultLifecycleAdapter.java 11517 2008-03-31 21:34:19Z dirk.olmes $
 3  
  * --------------------------------------------------------------------------------------
 4  
  * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.com
 5  
  *
 6  
  * The software in this package is published under the terms of the CPAL v1.0
 7  
  * license, a copy of which has been included with this distribution in the
 8  
  * LICENSE.txt file.
 9  
  */
 10  
 
 11  
 package org.mule.component;
 12  
 
 13  
 import org.mule.RequestContext;
 14  
 import org.mule.VoidResult;
 15  
 import org.mule.api.DefaultMuleException;
 16  
 import org.mule.api.MuleEvent;
 17  
 import org.mule.api.MuleException;
 18  
 import org.mule.api.MuleMessage;
 19  
 import org.mule.api.component.JavaComponent;
 20  
 import org.mule.api.component.LifecycleAdapter;
 21  
 import org.mule.api.interceptor.Invocation;
 22  
 import org.mule.api.lifecycle.Disposable;
 23  
 import org.mule.api.lifecycle.Initialisable;
 24  
 import org.mule.api.lifecycle.InitialisationException;
 25  
 import org.mule.api.lifecycle.Startable;
 26  
 import org.mule.api.lifecycle.Stoppable;
 27  
 import org.mule.api.model.EntryPointResolverSet;
 28  
 import org.mule.api.routing.NestedRouter;
 29  
 import org.mule.api.service.ServiceAware;
 30  
 import org.mule.api.service.ServiceException;
 31  
 import org.mule.config.i18n.CoreMessages;
 32  
 import org.mule.model.resolvers.LegacyEntryPointResolverSet;
 33  
 import org.mule.model.resolvers.NoSatisfiableMethodsException;
 34  
 import org.mule.model.resolvers.TooManySatisfiableMethodsException;
 35  
 import org.mule.routing.nested.NestedInvocationHandler;
 36  
 import org.mule.transformer.TransformerTemplate;
 37  
 import org.mule.util.ClassUtils;
 38  
 
 39  
 import java.lang.reflect.Method;
 40  
 import java.lang.reflect.Proxy;
 41  
 import java.util.Collections;
 42  
 import java.util.HashMap;
 43  
 import java.util.Iterator;
 44  
 import java.util.List;
 45  
 import java.util.Map;
 46  
 
 47  
 import org.apache.commons.logging.Log;
 48  
 import org.apache.commons.logging.LogFactory;
 49  
 
 50  
 /**
 51  
  * <code>DefaultLifecycleAdapter</code> provides lifecycle methods for all Mule
 52  
  * managed components. It's possible to plugin custom lifecycle adapters, this can
 53  
  * provide additional lifecycle methods triggered by an external source.
 54  
  */
 55  
 public class DefaultLifecycleAdapter implements LifecycleAdapter
 56  
 {
 57  
     /** logger used by this class */
 58  2
     protected static final Log logger = LogFactory.getLog(DefaultLifecycleAdapter.class);
 59  
 
 60  
     protected Object componentObject;
 61  
     protected JavaComponent component;
 62  76
     private boolean isStoppable = false;
 63  76
     private boolean isStartable = false;
 64  76
     private boolean isDisposable = false;
 65  
 
 66  76
     private boolean started = false;
 67  76
     private boolean disposed = false;
 68  
 
 69  
     private EntryPointResolverSet entryPointResolver;
 70  
 
 71  
     public DefaultLifecycleAdapter(Object componentObject, JavaComponent component) throws MuleException
 72  
     {
 73  0
         this(componentObject, component, new LegacyEntryPointResolverSet());
 74  0
     }
 75  
 
 76  
     public DefaultLifecycleAdapter(Object componentObject,
 77  
                                    JavaComponent component,
 78  
                                    EntryPointResolverSet entryPointResolver) throws MuleException
 79  76
     {
 80  
 
 81  76
         if (componentObject == null)
 82  
         {
 83  0
             throw new IllegalArgumentException("POJO Service cannot be null");
 84  
         }
 85  76
         if (entryPointResolver == null)
 86  
         {
 87  0
             entryPointResolver = new LegacyEntryPointResolverSet();
 88  
         }
 89  76
         this.componentObject = componentObject;
 90  76
         this.component = component;
 91  76
         this.entryPointResolver = entryPointResolver;
 92  
 
 93  76
         isStartable = Startable.class.isInstance(componentObject);
 94  76
         isStoppable = Stoppable.class.isInstance(componentObject);
 95  76
         isDisposable = Disposable.class.isInstance(componentObject);
 96  
 
 97  76
         if (componentObject instanceof ServiceAware)
 98  
         {
 99  0
             ((ServiceAware) componentObject).setService(component.getService());
 100  
         }
 101  76
         configureNestedRouter();
 102  76
     }
 103  
 
 104  
     /**
 105  
      * Propagates start() life-cycle to component object implementations if they
 106  
      * implement the mule {@link Startable} interface. NOT: It is up to component
 107  
      * implementations to ensure their implementation of start() is thread-safe.
 108  
      */
 109  
     public void start() throws MuleException
 110  
     {
 111  74
         if (isStartable)
 112  
         {
 113  
             try
 114  
             {
 115  4
                 ((Startable) componentObject).start();                
 116  4
                 started = true;
 117  
             }
 118  0
             catch (Exception e)
 119  
             {
 120  0
                 throw new DefaultMuleException(CoreMessages.failedToStart("UMO Service: "
 121  
                                                                           + component.getService().getName()), e);
 122  4
             }
 123  
         }
 124  
         else
 125  
         {
 126  70
             started = true;
 127  
         }
 128  74
     }
 129  
 
 130  
     /**
 131  
      * Propagates stop() life-cycle to component object implementations if they
 132  
      * implement the mule {@link Stoppable} interface. NOT: It is up to component
 133  
      * implementations to ensure their implementation of stop() is thread-safe.
 134  
      */
 135  
     public void stop() throws MuleException
 136  
     {
 137  26
         if (isStoppable)
 138  
         {
 139  
             try
 140  
             {
 141  4
                 ((Stoppable) componentObject).stop();
 142  4
                 started = false;
 143  
             }
 144  0
             catch (Exception e)
 145  
             {
 146  0
                 throw new DefaultMuleException(CoreMessages.failedToStop("UMO Service: "
 147  
                                                                          + component.getService().getName()), e);
 148  4
             }
 149  
         }
 150  
         else
 151  
         {
 152  22
             started = false;
 153  
         }
 154  26
     }
 155  
 
 156  
     /**
 157  
      * Propagates dispose() life-cycle to component object implementations if they
 158  
      * implement the mule {@link Disposable} interface. NOT: It is up to component
 159  
      * implementations to ensure their implementation of dispose() is thread-safe.
 160  
      */
 161  
     public void dispose()
 162  
     {
 163  12
         if (isDisposable)
 164  
         {
 165  
             try
 166  
             {
 167  4
                 ((Disposable) componentObject).dispose();
 168  
             }
 169  0
             catch (Exception e)
 170  
             {
 171  
                 // TODO MULE-863: Handle or fail
 172  0
                 logger.error("failed to dispose: " + component.getService().getName(), e);
 173  4
             }
 174  
         }
 175  12
         disposed = true;
 176  12
     }
 177  
 
 178  
     /** @return true if the service has been started */
 179  
     public boolean isStarted()
 180  
     {
 181  32
         return started;
 182  
     }
 183  
 
 184  
     /** @return whether the service managed by this lifecycle has been disposed */
 185  
     public boolean isDisposed()
 186  
     {
 187  0
         return disposed;
 188  
     }
 189  
 
 190  
     // Note: Invocation argument is not even used!
 191  
     public MuleMessage intercept(Invocation invocation) throws MuleException
 192  
     {
 193  
         // Invoke method
 194  
         Object result;
 195  0
         MuleEvent event = RequestContext.getEvent();
 196  
 
 197  
         try
 198  
         {
 199  
             // Use the overriding entrypoint resolver if one is set
 200  0
             if (component.getEntryPointResolverSet() != null)
 201  
             {
 202  0
                 result = component.getEntryPointResolverSet().invoke(componentObject, RequestContext.getEventContext());
 203  
 
 204  
             }
 205  
             else
 206  
             {
 207  0
                 result = entryPointResolver.invoke(componentObject, RequestContext.getEventContext());
 208  
             }
 209  
         }
 210  0
         catch (Exception e)
 211  
         {
 212  
             // should all Exceptions caught here be a ServiceException?!?
 213  
             // TODO MULE-863: See above
 214  0
             throw new ServiceException(RequestContext.getEventContext().getMessage(), component.getService(), e);
 215  0
         }
 216  
 
 217  0
         MuleMessage resultMessage = null;
 218  0
         if (result instanceof VoidResult)
 219  
         {
 220  
             // This will rewire the current message
 221  0
             event.transformMessage();
 222  0
             resultMessage = event.getMessage();
 223  
         }
 224  0
         else if (result != null)
 225  
         {
 226  0
             if (result instanceof MuleMessage)
 227  
             {
 228  0
                 resultMessage = (MuleMessage) result;
 229  
             }
 230  
             else
 231  
             {
 232  0
                 event.getMessage().applyTransformers(
 233  
                     Collections.singletonList(new TransformerTemplate(new TransformerTemplate.OverwitePayloadCallback(
 234  
                         result))));
 235  0
                 resultMessage = event.getMessage();
 236  
             }
 237  
         }
 238  0
         return resultMessage;
 239  
     }
 240  
 
 241  
     /**
 242  
      * Propagates initialise() life-cycle to component object implementations if they
 243  
      * implement the mule {@link Initialisable} interface.
 244  
      * <p/> 
 245  
      * <b>NOTE:</b> It is up to component implementations to ensure their implementation of 
 246  
      * <code>initialise()</code> is thread-safe.
 247  
      */
 248  
     public void initialise() throws InitialisationException
 249  
     {
 250  76
         if (Initialisable.class.isInstance(componentObject))
 251  
         {
 252  0
             ((Initialisable) componentObject).initialise();
 253  
         }
 254  76
     }
 255  
 
 256  
     protected void configureNestedRouter() throws MuleException
 257  
     {
 258  
         // Initialise the nested router and bind the endpoints to the methods using a
 259  
         // Proxy
 260  76
         if (component.getNestedRouter() != null)
 261  
         {
 262  76
             Map bindings = new HashMap();
 263  76
             for (Iterator it = component.getNestedRouter().getRouters().iterator(); it.hasNext();)
 264  
             {
 265  0
                 NestedRouter nestedRouter = (NestedRouter) it.next();
 266  0
                 Object proxy = bindings.get(nestedRouter.getInterface());
 267  
 
 268  0
                 if (proxy == null)
 269  
                 {
 270  
                     // Create a proxy that implements this interface
 271  
                     // and just routes away using a mule client
 272  
                     // ( using the high level Mule client is probably
 273  
                     // a bit agricultural but this is just POC stuff )
 274  0
                     proxy = nestedRouter.createProxy(componentObject);
 275  0
                     bindings.put(nestedRouter.getInterface(), proxy);
 276  
 
 277  
                     // Now lets set the proxy on the Service object
 278  
                     Method setterMethod;
 279  
 
 280  0
                     List methods = ClassUtils.getSatisfiableMethods(componentObject.getClass(),
 281  
                         new Class[]{nestedRouter.getInterface()}, true, false, null);
 282  0
                     if (methods.size() == 1)
 283  
                     {
 284  0
                         setterMethod = (Method) methods.get(0);
 285  
                     }
 286  0
                     else if (methods.size() > 1)
 287  
                     {
 288  0
                         throw new TooManySatisfiableMethodsException(componentObject.getClass(),
 289  
                             new Class[]{nestedRouter.getInterface()});
 290  
                     }
 291  
                     else
 292  
                     {
 293  0
                         throw new NoSatisfiableMethodsException(componentObject.getClass(),
 294  
                             new Class[]{nestedRouter.getInterface()});
 295  
                     }
 296  
 
 297  
                     try
 298  
                     {
 299  0
                         setterMethod.invoke(componentObject, new Object[]{proxy});
 300  
                     }
 301  0
                     catch (Exception e)
 302  
                     {
 303  0
                         throw new InitialisationException(CoreMessages.failedToSetProxyOnService(nestedRouter,
 304  
                             componentObject.getClass()), e, this);
 305  0
                     }
 306  0
                 }
 307  
                 else
 308  
                 {
 309  0
                     NestedInvocationHandler handler = (NestedInvocationHandler) Proxy.getInvocationHandler(proxy);
 310  0
                     handler.addRouterForInterface(nestedRouter);
 311  
                 }
 312  0
             }
 313  
         }
 314  76
     }
 315  
 
 316  
 }