Coverage Report - org.mule.lifecycle.DefaultLifecyclePhase
 
Classes in this File Line Coverage Branch Coverage Complexity
DefaultLifecyclePhase
75%
65/87
72%
26/36
2.381
 
 1  
 /*
 2  
  * $Id: DefaultLifecyclePhase.java 11530 2008-04-08 12:49:14Z 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  
 package org.mule.lifecycle;
 11  
 
 12  
 import org.mule.RegistryContext;
 13  
 import org.mule.api.MuleContext;
 14  
 import org.mule.api.MuleException;
 15  
 import org.mule.api.lifecycle.LifecycleException;
 16  
 import org.mule.api.lifecycle.LifecyclePhase;
 17  
 import org.mule.api.registry.Registry;
 18  
 import org.mule.config.i18n.CoreMessages;
 19  
 import org.mule.util.ClassUtils;
 20  
 import org.mule.util.StringMessageUtils;
 21  
 
 22  
 import java.lang.reflect.Method;
 23  
 import java.util.ArrayList;
 24  
 import java.util.Collection;
 25  
 import java.util.HashSet;
 26  
 import java.util.Iterator;
 27  
 import java.util.LinkedHashSet;
 28  
 import java.util.List;
 29  
 import java.util.Set;
 30  
 
 31  
 import org.apache.commons.logging.Log;
 32  
 import org.apache.commons.logging.LogFactory;
 33  
 
 34  
 /**
 35  
  * Represents a configurable lifecycle phase. This is a default implementation of a 'generic phase' in that is
 36  
  * can be configured to represnt any phase. Instances of this phase can then be registered with a
 37  
  * {@link org.mule.api.lifecycle.LifecycleManager} and by used to enforce a lifecycle phase on an object.
 38  
  * Usually, Lifecycle phases have a fixed configuration in which case a specialisation of this class should be
 39  
  * created that initialises its configuration internally.
 40  
  *
 41  
  * <p>Note that this class and {@link org.mule.api.lifecycle.LifecycleTransitionResult} both make assumptions about
 42  
  * the interfaces used - the return values and exceptions.  These are, currently, that the return value is either
 43  
  * void or {@link org.mule.api.lifecycle.LifecycleTransitionResult} and either 0 or 1 exceptions can be
 44  
  * thrown which are either {@link InstantiationException} or {@link org.mule.api.lifecycle.LifecycleException}.
 45  
  *
 46  
  * @see org.mule.api.lifecycle.LifecyclePhase
 47  
  */
 48  
 public class DefaultLifecyclePhase implements LifecyclePhase
 49  
 {
 50  6970
     protected transient final Log logger = LogFactory.getLog(DefaultLifecyclePhase.class);
 51  
     private Class lifecycleClass;
 52  
     private Method lifecycleMethod;
 53  6970
     private Set orderedLifecycleObjects = new LinkedHashSet(6);
 54  
     private Class[] ignorredObjectTypes;
 55  
     private String name;
 56  
     private String oppositeLifecyclePhase;
 57  
     private Set supportedPhases;
 58  6970
     private int registryScope = Registry.SCOPE_REMOTE;
 59  
 
 60  
     public DefaultLifecyclePhase(String name, Class lifecycleClass, String oppositeLifecyclePhase)
 61  6970
     {
 62  6970
         this.name = name;
 63  6970
         this.lifecycleClass = lifecycleClass;
 64  
         //DefaultLifecyclePhase interface only has one method
 65  6970
         lifecycleMethod = lifecycleClass.getMethods()[0];
 66  6970
         this.oppositeLifecyclePhase = oppositeLifecyclePhase;
 67  6970
     }
 68  
 
 69  
     public void fireLifecycle(MuleContext muleContext, String currentPhase) throws MuleException
 70  
     {
 71  2356
         if (logger.isDebugEnabled())
 72  
         {
 73  0
             logger.debug("Attempting to fire lifecycle phase: " + getName());
 74  
         }
 75  2356
         if (currentPhase.equals(name))
 76  
         {
 77  0
             if (logger.isDebugEnabled())
 78  
             {
 79  0
                 logger.debug("Not firing, already in lifecycle phase: " + getName());
 80  
             }
 81  0
             return;
 82  
         }
 83  2356
         if (!isPhaseSupported(currentPhase))
 84  
         {
 85  0
             throw new IllegalStateException("Lifecycle phase: " + name + " does not support current phase: "
 86  
                                             + currentPhase + ". Phases supported are: " + StringMessageUtils.toString(supportedPhases));
 87  
         }
 88  
 
 89  
         // overlapping interfaces can cause duplicates
 90  2356
         Set duplicates = new HashSet();
 91  
 
 92  2356
         for (Iterator iterator = orderedLifecycleObjects.iterator(); iterator.hasNext();)
 93  
         {
 94  15260
             LifecycleObject lo = (LifecycleObject) iterator.next();
 95  
 
 96  15260
             Collection lifecycleInstances = RegistryContext.getRegistry().lookupObjects(lo.getType(), getRegistryScope());
 97  15260
             if (lifecycleInstances.size() == 0)
 98  
             {
 99  14004
                 continue;
 100  
             }
 101  1256
             List targets = this.sortLifecycleInstances(lifecycleInstances, lo);
 102  
                         
 103  1256
             lo.firePreNotification(muleContext);
 104  
 
 105  1256
             for (Iterator target = targets.iterator(); target.hasNext();)
 106  
             {
 107  1264
                 Object o = target.next();
 108  
                 
 109  1264
                 if (duplicates.contains(o))
 110  
                 {
 111  0
                     target.remove();
 112  
                 }
 113  
                 else
 114  
                 {
 115  1264
                     if (logger.isDebugEnabled())
 116  
                     {
 117  0
                         logger.debug("lifecycle phase: " + getName() + " for object: " + o);
 118  
                     }
 119  1264
                     this.applyLifecycle(o);
 120  1264
                     target.remove();
 121  1264
                     duplicates.add(o);
 122  
                 }
 123  1264
             }
 124  
 
 125  1256
             lo.firePostNotification(muleContext);
 126  1256
         }
 127  2356
     }
 128  
 
 129  
     /**
 130  
      * Subclasses can override this method to order <code>objects</code> before
 131  
      * the lifecycle method is applied to them.
 132  
      * 
 133  
      * This method does not apply any special ordering to <code>objects</code>.
 134  
      * 
 135  
      * @param objects
 136  
      * @param lo
 137  
      * @return List with ordered objects
 138  
      */
 139  
     protected List sortLifecycleInstances(Collection objects, LifecycleObject lo)
 140  
     {
 141  1256
         return new ArrayList(objects);
 142  
     }
 143  
 
 144  
     public void addOrderedLifecycleObject(LifecycleObject lco)
 145  
     {
 146  0
         orderedLifecycleObjects.add(lco);
 147  0
     }
 148  
 
 149  
     public void removeOrderedLifecycleObject(LifecycleObject lco)
 150  
     {
 151  0
         orderedLifecycleObjects.remove(lco);
 152  0
     }
 153  
 
 154  
     protected boolean ignoreType(Class type)
 155  
     {
 156  35534
         if (ignorredObjectTypes == null)
 157  
         {
 158  34250
             return false;
 159  
         }
 160  
         else
 161  
         {
 162  2666
             for (int i = 0; i < ignorredObjectTypes.length; i++)
 163  
             {
 164  1382
                 Class ignorredObjectType = ignorredObjectTypes[i];
 165  1382
                 if (ignorredObjectType.isAssignableFrom(type))
 166  
                 {
 167  0
                     return true;
 168  
                 }
 169  
             }
 170  
         }
 171  1284
         return false;
 172  
     }
 173  
 
 174  
     public Set getOrderedLifecycleObjects()
 175  
     {
 176  0
         return orderedLifecycleObjects;
 177  
     }
 178  
 
 179  
     public void setOrderedLifecycleObjects(Set orderedLifecycleObjects)
 180  
     {
 181  4644
         this.orderedLifecycleObjects = orderedLifecycleObjects;
 182  4644
     }
 183  
 
 184  
     public Class[] getIgnoredObjectTypes()
 185  
     {
 186  0
         return ignorredObjectTypes;
 187  
     }
 188  
 
 189  
     public void setIgnoredObjectTypes(Class[] ignorredObjectTypes)
 190  
     {
 191  4644
         this.ignorredObjectTypes = ignorredObjectTypes;
 192  4644
     }
 193  
 
 194  
     public Class getLifecycleClass()
 195  
     {
 196  35534
         return lifecycleClass;
 197  
     }
 198  
 
 199  
     public void setLifecycleClass(Class lifecycleClass)
 200  
     {
 201  0
         this.lifecycleClass = lifecycleClass;
 202  0
     }
 203  
 
 204  
     public String getName()
 205  
     {
 206  18612
         return name;
 207  
     }
 208  
 
 209  
     public Set getSupportedPhases()
 210  
     {
 211  7224
         return supportedPhases;
 212  
     }
 213  
 
 214  
     public void setSupportedPhases(Set supportedPhases)
 215  
     {
 216  0
         this.supportedPhases = supportedPhases;
 217  0
     }
 218  
 
 219  
     public void registerSupportedPhase(String phase)
 220  
     {
 221  6970
         if (supportedPhases == null)
 222  
         {
 223  4646
             supportedPhases = new HashSet();
 224  
         }
 225  6970
         supportedPhases.add(phase);
 226  6970
     }
 227  
 
 228  
     public boolean isPhaseSupported(String phase)
 229  
     {
 230  3552
         if (getSupportedPhases() == null)
 231  
         {
 232  1144
             return true;
 233  
         }
 234  
         else
 235  
         {
 236  2408
             if (getSupportedPhases().contains(ALL_PHASES))
 237  
             {
 238  1144
                 return true;
 239  
             }
 240  
             else
 241  
             {
 242  1264
                 return getSupportedPhases().contains(phase);
 243  
             }
 244  
         }
 245  
     }
 246  
 
 247  
     public void applyLifecycle(Object o) throws LifecycleException
 248  
     {
 249  35534
         if (o == null)
 250  
         {
 251  0
             return;
 252  
         }
 253  35534
         if (ignoreType(o.getClass()))
 254  
         {
 255  0
             return;
 256  
         }
 257  35534
         if (!getLifecycleClass().isAssignableFrom(o.getClass()))
 258  
         {
 259  24972
             return;
 260  
         }
 261  
         try
 262  
         {
 263  10562
             lifecycleMethod.invoke(o, ClassUtils.NO_ARGS);
 264  
         }
 265  0
         catch (Exception e)
 266  
         {
 267  0
             throw new LifecycleException(CoreMessages.failedToInvokeLifecycle(lifecycleMethod.getName(), o), e, this);
 268  10562
         }
 269  10562
     }
 270  
 
 271  
     public int getRegistryScope()
 272  
     {
 273  15260
         return registryScope;
 274  
     }
 275  
 
 276  
     public void setRegistryScope(int registryScope)
 277  
     {
 278  2320
         this.registryScope = registryScope;
 279  2320
     }
 280  
 
 281  
     public String getOppositeLifecyclePhase()
 282  
     {
 283  4660
         return oppositeLifecyclePhase;
 284  
     }
 285  
 }
 286  
 
 287  
 
 288  
 
 289