View Javadoc

1   /*
2    * $Id: AgentSorter.java 12269 2008-07-10 04:19:03Z dfeist $
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.agent;
12  
13  import org.mule.api.agent.Agent;
14  
15  import java.util.ArrayList;
16  import java.util.Collection;
17  import java.util.Iterator;
18  import java.util.List;
19  import java.util.ListIterator;
20  
21  import org.apache.commons.collections.CollectionUtils;
22  import org.apache.commons.collections.Predicate;
23  
24  /**
25   * Sort {@link Agent} instances so that dependencies of each agent are started before the 
26   * actual {@link Agent} is started itself.
27   */
28  public class AgentSorter extends Object
29  {
30      
31      public static List sortAgents(Collection/*<Agent>*/ agents)
32      {
33          List sortedAgents = new ArrayList();
34          
35          // step 1: add all agents with no dependencies
36          Collection agentsWithoutDependencies = CollectionUtils.select(agents, new Predicate()
37          {
38              public boolean evaluate(Object object)
39              {
40                  return ((Agent) object).getDependentAgents().size() == 0;
41              }
42          });
43          sortedAgents.addAll(agentsWithoutDependencies);
44          
45          // step 2: process the remaining agents
46          List remainingAgents = new ArrayList(agents);
47          remainingAgents.removeAll(agentsWithoutDependencies);
48          while (!remainingAgents.isEmpty())
49          {
50              int processedAgents = 0;
51              ListIterator iter = remainingAgents.listIterator();
52              while (iter.hasNext())
53              {
54                  Agent agent = (Agent) iter.next();
55                  if (dependentAgentsPresent(agent.getDependentAgents(), agents, sortedAgents))
56                  {
57                      sortedAgents.add(agent);
58                      iter.remove();
59                      processedAgents++;
60                  }
61              }
62              
63              // if we did not process any agents this iteration, the remaining agents 
64              // likely form a dependency cycle
65              if (processedAgents == 0)
66              {
67                  throw new IllegalArgumentException("Dependency cycle: " + remainingAgents);
68              }
69          }
70  
71          return sortedAgents;
72      }
73      
74      private static boolean dependentAgentsPresent(List dependentClasses, Collection allRegisteredAgents, 
75          List sortedAgents)
76      {
77          Iterator dependencyIterator = dependentClasses.iterator();
78          while (dependencyIterator.hasNext())
79          {
80              Class dependentClass = (Class) dependencyIterator.next();
81              
82              if (!classExistsInCollection(dependentClass, allRegisteredAgents))
83              {
84                  // this agent is currently not registed, ignore this dependency
85                  continue;
86              }
87  
88              if (!classExistsInCollection(dependentClass, sortedAgents))
89              {
90                  return false;
91              }
92          }
93          return true;
94      }
95      
96      private static boolean classExistsInCollection(Class clazz, Collection collection)
97      {
98          return CollectionUtils.exists(collection, new ClassEqualityPredicate(clazz));
99      }
100     
101     private static class ClassEqualityPredicate extends Object implements Predicate
102     {
103         private Class requiredClass;
104 
105         public ClassEqualityPredicate(Class requiredClass)
106         {
107             super();
108             this.requiredClass = requiredClass;
109         }
110         
111         public boolean evaluate(Object object)
112         {
113             return object.getClass().equals(requiredClass);
114         }
115     }
116     
117 }
118 
119