Coverage Report - org.mule.component.DefaultComponentLifecycleAdapter
 
Classes in this File Line Coverage Branch Coverage Complexity
DefaultComponentLifecycleAdapter
0%
0/103
0%
0/36
0
 
 1  
 /*
 2  
  * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
 3  
  * The software in this package is published under the terms of the CPAL v1.0
 4  
  * license, a copy of which has been included with this distribution in the
 5  
  * LICENSE.txt file.
 6  
  */
 7  
 package org.mule.component;
 8  
 
 9  
 import org.mule.DefaultMuleEventContext;
 10  
 import org.mule.RequestContext;
 11  
 import org.mule.api.DefaultMuleException;
 12  
 import org.mule.api.MuleContext;
 13  
 import org.mule.api.MuleEvent;
 14  
 import org.mule.api.MuleEventContext;
 15  
 import org.mule.api.MuleException;
 16  
 import org.mule.api.component.JavaComponent;
 17  
 import org.mule.api.component.LifecycleAdapter;
 18  
 import org.mule.api.construct.FlowConstruct;
 19  
 import org.mule.api.lifecycle.Disposable;
 20  
 import org.mule.api.lifecycle.Initialisable;
 21  
 import org.mule.api.lifecycle.InitialisationException;
 22  
 import org.mule.api.lifecycle.Startable;
 23  
 import org.mule.api.lifecycle.Stoppable;
 24  
 import org.mule.api.model.EntryPointResolverSet;
 25  
 import org.mule.config.i18n.CoreMessages;
 26  
 import org.mule.config.i18n.MessageFactory;
 27  
 import org.mule.model.resolvers.LegacyEntryPointResolverSet;
 28  
 import org.mule.registry.JSR250ValidatorProcessor;
 29  
 import org.mule.util.annotation.AnnotationMetaData;
 30  
 import org.mule.util.annotation.AnnotationUtils;
 31  
 
 32  
 import java.lang.reflect.InvocationTargetException;
 33  
 import java.lang.reflect.Method;
 34  
 import java.util.List;
 35  
 
 36  
 import javax.annotation.PostConstruct;
 37  
 import javax.annotation.PreDestroy;
 38  
 
 39  
 import org.apache.commons.logging.Log;
 40  
 import org.apache.commons.logging.LogFactory;
 41  
 
 42  
 /**
 43  
  * <code>DefaultComponentLifecycleAdapter</code> is a default implementation of
 44  
  * {@link LifecycleAdapter} for use with {@link JavaComponent} that expects component
 45  
  * instances to implement Mule lifecycle interfaces in order to receive lifecycle. Lifecycle interfaces supported are -
 46  
  * <ul>
 47  
  * <li>{@link org.mule.api.lifecycle.Initialisable}</li>
 48  
  * <li>{@link org.mule.api.lifecycle.Startable}</li>
 49  
  * <li>{@link org.mule.api.lifecycle.Stoppable}</li>
 50  
  * <li>{@link org.mule.api.lifecycle.Disposable}</li>
 51  
  * </ul>
 52  
  *  This implementation also supports JSR-250 lifecycle annotations
 53  
  *  {@link javax.annotation.PostConstruct} (for initialisation) and/or {@link javax.annotation.PreDestroy}
 54  
  * (for disposal of the object). Only one of each annotation can be used per component object.
 55  
  *
 56  
  * @see org.mule.registry.JSR250ValidatorProcessor for details about the rules for using JSR-250 lifecycle annotations
 57  
  */
 58  
 public class DefaultComponentLifecycleAdapter implements LifecycleAdapter
 59  
 {
 60  
     /**
 61  
      * logger used by this class
 62  
      */
 63  0
     protected static final Log logger = LogFactory.getLog(DefaultComponentLifecycleAdapter.class);
 64  
 
 65  
     protected Object componentObject;
 66  
 
 67  
     protected JavaComponent component;
 68  
     protected EntryPointResolverSet entryPointResolver;
 69  
     protected FlowConstruct flowConstruct;
 70  
 
 71  0
     protected boolean isInitialisable = false;
 72  0
     protected boolean isStartable = false;
 73  0
     protected boolean isStoppable = false;
 74  0
     protected boolean isDisposable = false;
 75  
 
 76  
     protected Method initMethod;
 77  
     protected Method disposeMethod;
 78  
 
 79  0
     private boolean started = false;
 80  0
     private boolean disposed = false;
 81  
 
 82  
     protected MuleContext muleContext;
 83  
 
 84  
     public DefaultComponentLifecycleAdapter(Object componentObject,
 85  
                                             JavaComponent component,
 86  
                                             FlowConstruct flowConstruct,
 87  
                                             MuleContext muleContext) throws MuleException
 88  0
     {
 89  0
         if (muleContext == null)
 90  
         {
 91  0
             throw new IllegalStateException("No muleContext provided");
 92  
         }
 93  0
         if (componentObject == null)
 94  
         {
 95  0
             throw new IllegalArgumentException("POJO Service cannot be null");
 96  
         }
 97  
 
 98  0
         if (entryPointResolver == null)
 99  
         {
 100  0
             entryPointResolver = new LegacyEntryPointResolverSet();
 101  
         }
 102  0
         this.componentObject = componentObject;
 103  0
         this.component = component;
 104  0
         this.flowConstruct = flowConstruct;
 105  
 
 106  
         // save a ref for later disposal call
 107  0
         this.muleContext = muleContext;
 108  0
         setLifecycleFlags();
 109  0
         BindingUtils.configureBinding(component, componentObject);
 110  0
     }
 111  
 
 112  
     public DefaultComponentLifecycleAdapter(Object componentObject,
 113  
                                             JavaComponent component,
 114  
                                             FlowConstruct flowConstruct,
 115  
                                             EntryPointResolverSet entryPointResolver, MuleContext muleContext) throws MuleException
 116  
     {
 117  
 
 118  0
         this(componentObject, component, flowConstruct, muleContext);
 119  0
         this.entryPointResolver = entryPointResolver;
 120  0
     }
 121  
 
 122  
     protected void setLifecycleFlags()
 123  
     {
 124  0
         Object object = componentObject;
 125  0
         initMethod = findInitMethod(object);
 126  0
         disposeMethod = findDisposeMethod(object);
 127  0
         isInitialisable = initMethod!=null;
 128  0
         isDisposable = disposeMethod!=null;
 129  0
         isStartable = Startable.class.isInstance(object);
 130  0
         isStoppable = Stoppable.class.isInstance(object);
 131  0
     }
 132  
 
 133  
     protected Method findInitMethod(Object object)
 134  
     {
 135  0
         if(object instanceof Initialisable)
 136  
         {
 137  
             try
 138  
             {
 139  0
                 return object.getClass().getMethod(Initialisable.PHASE_NAME);
 140  
             }
 141  0
             catch (NoSuchMethodException e)
 142  
             {
 143  
                 //ignore
 144  
             }
 145  
         }
 146  
 
 147  0
         List<AnnotationMetaData> metaData = AnnotationUtils.getMethodAnnotations(object.getClass(), PostConstruct.class);
 148  0
         if (metaData.size() == 0)
 149  
         {
 150  0
             return null;
 151  
         }
 152  0
         else if(metaData.size() > 1)
 153  
         {
 154  0
             throw new IllegalArgumentException(CoreMessages.objectHasMoreThanOnePostConstructAnnotation(object.getClass()).getMessage());
 155  
         }
 156  
         else
 157  
         {
 158  0
             Method m = (Method) metaData.get(0).getMember();
 159  0
             new JSR250ValidatorProcessor().validateLifecycleMethod(m);
 160  0
             return m;
 161  
         }
 162  
     }
 163  
 
 164  
     protected Method findDisposeMethod(Object object)
 165  
     {
 166  0
         if (object instanceof Disposable)
 167  
         {
 168  
             try
 169  
             {
 170  0
                 return object.getClass().getMethod(Disposable.PHASE_NAME);
 171  
             }
 172  0
             catch (NoSuchMethodException e)
 173  
             {
 174  
                 //ignore
 175  
             }
 176  
         }
 177  
 
 178  0
         List<AnnotationMetaData> metaData = AnnotationUtils.getMethodAnnotations(object.getClass(), PreDestroy.class);
 179  0
         if (metaData.size() == 0)
 180  
         {
 181  0
             return null;
 182  
         }
 183  0
         else if (metaData.size() > 1)
 184  
         {
 185  0
             throw new IllegalArgumentException(CoreMessages.objectHasMoreThanOnePreDestroyAnnotation(object.getClass()).getMessage());
 186  
         }
 187  
         else
 188  
         {
 189  0
             Method m = (Method) metaData.get(0).getMember();
 190  0
             new JSR250ValidatorProcessor().validateLifecycleMethod(m);
 191  0
             return m;
 192  
         }
 193  
     }
 194  
 
 195  
     /**
 196  
      * Propagates initialise() life-cycle to component object implementations if they
 197  
      * implement the mule {@link Initialisable} interface.
 198  
      * <p/>
 199  
      * <b>NOTE:</b> It is up to component implementations to ensure their implementation of
 200  
      * <code>initialise()</code> is thread-safe.
 201  
      */
 202  
     public void initialise() throws InitialisationException
 203  
     {
 204  0
         if (isInitialisable)
 205  
         {
 206  
             try
 207  
             {
 208  0
                 initMethod.invoke(componentObject);
 209  
             }
 210  0
             catch (IllegalAccessException e)
 211  
             {
 212  0
                 throw new InitialisationException(e, this);
 213  
             }
 214  0
             catch (InvocationTargetException e)
 215  
             {
 216  0
                 throw new InitialisationException(e.getTargetException(), this);
 217  0
             }
 218  
         }
 219  0
     }
 220  
 
 221  
     /**
 222  
      * Propagates start() life-cycle to component object implementations if they
 223  
      * implement the mule {@link Startable} interface. NOT: It is up to component
 224  
      * implementations to ensure their implementation of start() is thread-safe.
 225  
      */
 226  
     public void start() throws MuleException
 227  
     {
 228  0
         if (isStartable)
 229  
         {
 230  
             try
 231  
             {
 232  0
                 ((Startable) componentObject).start();
 233  0
                 started = true;
 234  
             }
 235  0
             catch (Exception e)
 236  
             {
 237  0
                 throw new DefaultMuleException(CoreMessages.failedToStart("Service: "
 238  
                                                                           + flowConstruct.getName()), e);
 239  0
             }
 240  
         }
 241  
         else
 242  
         {
 243  0
             started = true;
 244  
         }
 245  0
     }
 246  
 
 247  
     /**
 248  
      * Propagates stop() life-cycle to component object implementations if they
 249  
      * implement the mule {@link Stoppable} interface. NOT: It is up to component
 250  
      * implementations to ensure their implementation of stop() is thread-safe.
 251  
      */
 252  
     public void stop() throws MuleException
 253  
     {
 254  0
         if (isStoppable)
 255  
         {
 256  
             try
 257  
             {
 258  0
                 ((Stoppable) componentObject).stop();
 259  0
                 started = false;
 260  
             }
 261  0
             catch (Exception e)
 262  
             {
 263  0
                 throw new DefaultMuleException(CoreMessages.failedToStop("Service: "
 264  
                                                                          + flowConstruct.getName()), e);
 265  0
             }
 266  
         }
 267  
         else
 268  
         {
 269  0
             started = false;
 270  
         }
 271  0
     }
 272  
 
 273  
     /**
 274  
      * Propagates dispose() life-cycle to component object implementations if they
 275  
      * implement the mule {@link Disposable} interface. NOT: It is up to component
 276  
      * implementations to ensure their implementation of dispose() is thread-safe.
 277  
      */
 278  
     public void dispose()
 279  
     {
 280  
         try
 281  
         {
 282  0
             if (isDisposable)
 283  
             {
 284  
                 // make sure we haven't lost the reference to the object
 285  0
                 Object o = componentObject;
 286  0
                 if (o != null)
 287  
                 {
 288  
                     try
 289  
                     {
 290  0
                         disposeMethod.invoke(o);
 291  
                     }
 292  0
                     catch (InvocationTargetException e)
 293  
                     {
 294  
                         //unwrap
 295  0
                         throw e.getTargetException();
 296  0
                     }
 297  
                 }
 298  
             }
 299  0
             componentObject = null;
 300  
 
 301  
         }
 302  0
         catch (Throwable e)
 303  
         {
 304  0
             logger.error("failed to dispose: " + flowConstruct.getName(), e);
 305  0
         }
 306  0
         disposed = true;
 307  0
     }
 308  
 
 309  
     /**
 310  
      * @return true if the service has been started
 311  
      */
 312  
     public boolean isStarted()
 313  
     {
 314  0
         return started;
 315  
     }
 316  
 
 317  
     /**
 318  
      * @return whether the service managed by this lifecycle has been disposed
 319  
      */
 320  
     public boolean isDisposed()
 321  
     {
 322  0
         return disposed;
 323  
     }
 324  
 
 325  
     public Object invoke(MuleEvent event) throws MuleException
 326  
     {
 327  
         // Invoke method
 328  0
         MuleEventContext eventContext = new DefaultMuleEventContext(event);
 329  
         Object result;
 330  
         try
 331  
         {
 332  0
             if (componentObject == null)
 333  
             {
 334  0
                 throw new ComponentException(MessageFactory.createStaticMessage("componentObject is null"), RequestContext.getEvent(), component);
 335  
             }
 336  
             // Use the overriding entrypoint resolver if one is set
 337  0
             if (component.getEntryPointResolverSet() != null)
 338  
             {
 339  0
                 result = component.getEntryPointResolverSet().invoke(componentObject, eventContext);
 340  
             }
 341  
             else
 342  
             {
 343  0
                 result = entryPointResolver.invoke(componentObject, eventContext);
 344  
             }
 345  
         }
 346  0
         catch (Exception e)
 347  
         {
 348  0
             throw new ComponentException(RequestContext.getEvent(), component, e);
 349  0
         }
 350  
 
 351  0
         return result;
 352  
     }
 353  
 }