View Javadoc

1   /**
2    *
3    * Copyright 2003-2004 The Apache Software Foundation
4    *
5    *  Licensed under the Apache License, Version 2.0 (the "License");
6    *  you may not use this file except in compliance with the License.
7    *  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   *  Unless required by applicable law or agreed to in writing, software
12   *  distributed under the License is distributed on an "AS IS" BASIS,
13   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   *  See the License for the specific language governing permissions and
15   *  limitations under the License.
16   */
17  
18  package org.apache.geronimo.kernel.basic;
19  
20  import org.apache.geronimo.gbean.AbstractName;
21  import org.apache.geronimo.gbean.AbstractNameQuery;
22  import org.apache.geronimo.kernel.DependencyManager;
23  import org.apache.geronimo.kernel.lifecycle.LifecycleAdapter;
24  import org.apache.geronimo.kernel.lifecycle.LifecycleListener;
25  import org.apache.geronimo.kernel.lifecycle.LifecycleMonitor;
26  
27  import javax.management.ObjectName;
28  import java.util.Collections;
29  import java.util.HashMap;
30  import java.util.HashSet;
31  import java.util.Iterator;
32  import java.util.Map;
33  import java.util.Set;
34  
35  /**
36   * DependencyManager is the record keeper of the dependencies in Geronimo.  The DependencyManager
37   * does not enforce any dependencies, it is simply a place where components can register their intent
38   * to be dependent on another component.  Since a JMX Component can pretty much do whatever it wants
39   * a component must watch the components it depends on to assure that they are following the
40   * J2EE-Management state machine.
41   * <p/>
42   * The DependencyManager uses the nomenclature of parent-child where a child is dependent on a parent.
43   * The names parent and child have no other meaning are just a convience to make the code readable.
44   *
45   * @version $Rev: 384351 $ $Date: 2006-03-08 14:28:35 -0800 (Wed, 08 Mar 2006) $
46   */
47  public class BasicDependencyManager implements DependencyManager {
48      /**
49       * The lifecycleMonitor informs us when gbeans go off line,
50       * so we can clean up the lingering dependencies.
51       */
52      private final LifecycleMonitor lifecycleMonitor;
53  
54      /**
55       * Listenes for GBeans to unregister and removes all dependencies associated with the dependency
56       */
57      private final LifecycleListener lifecycleListener = new DependencyManagerLifecycleListener();
58  
59      /**
60       * A map from child names to a list of parents.
61       */
62      private final Map childToParentMap = new HashMap();
63  
64      /**
65       * A map from parent back to a list of its children.
66       */
67      private final Map parentToChildMap = new HashMap();
68  
69      public BasicDependencyManager(LifecycleMonitor lifecycleMonitor) throws Exception {
70          assert lifecycleMonitor != null;
71          this.lifecycleMonitor = lifecycleMonitor;
72          lifecycleMonitor.addLifecycleListener(lifecycleListener, new AbstractNameQuery(null, Collections.EMPTY_MAP, Collections.EMPTY_SET));
73      }
74  
75      public synchronized void close() {
76          lifecycleMonitor.removeLifecycleListener(lifecycleListener);
77          childToParentMap.clear();
78          parentToChildMap.clear();
79      }
80  
81      /**
82       * Declares a dependency from a child to a parent.
83       *
84       * @param child the dependent component
85       * @param parent the component the child is depending on
86       */
87      public synchronized void addDependency(AbstractName child, AbstractName parent) {
88          Set parents = (Set) childToParentMap.get(child);
89          if (parents == null) {
90              parents = new HashSet();
91              childToParentMap.put(child, parents);
92          }
93          parents.add(parent);
94  
95          Set children = (Set) parentToChildMap.get(parent);
96          if (children == null) {
97              children = new HashSet();
98              parentToChildMap.put(parent, children);
99          }
100         children.add(child);
101     }
102 
103     /**
104      * Removes a dependency from a child to a parent
105      *
106      * @param child the dependnet component
107      * @param parent the component that the child wil no longer depend on
108      */
109     public synchronized void removeDependency(AbstractName child, AbstractName parent) {
110         Set parents = (Set) childToParentMap.get(child);
111         if (parents != null) {
112             parents.remove(parent);
113         }
114 
115         Set children = (Set) parentToChildMap.get(parent);
116         if (children != null) {
117             children.remove(child);
118         }
119     }
120 
121     /**
122      * Removes all dependencies for a child
123      *
124      * @param child the component that will no longer depend on anything
125      */
126     public synchronized void removeAllDependencies(AbstractName child) {
127         Set parents = (Set) childToParentMap.remove(child);
128         if (parents == null) {
129             return;
130         }
131         for (Iterator iterator = parents.iterator(); iterator.hasNext();) {
132             ObjectName parent = (ObjectName) iterator.next();
133             Set children = (Set) parentToChildMap.get(parent);
134             if (children != null) {
135                 children.remove(child);
136             }
137 
138         }
139     }
140 
141     /**
142      * Adds dependencies from the child to every parent in the parents set
143      *
144      * @param child the dependent component
145      * @param parents the set of components the child is depending on
146      */
147     public synchronized void addDependencies(AbstractName child, Set parents) {
148         Set existingParents = (Set) childToParentMap.get(child);
149         if (existingParents == null) {
150             existingParents = new HashSet(parents);
151             childToParentMap.put(child, existingParents);
152         } else {
153             existingParents.addAll(parents);
154         }
155 
156         for (Iterator i = parents.iterator(); i.hasNext();) {
157             Object startParent = i.next();
158             Set children = (Set) parentToChildMap.get(startParent);
159             if (children == null) {
160                 children = new HashSet();
161                 parentToChildMap.put(startParent, children);
162             }
163             children.add(child);
164         }
165     }
166 
167     /**
168      * Gets the set of parents that the child is depending on
169      *
170      * @param child the dependent component
171      * @return a collection containing all of the components the child depends on; will never be null
172      */
173     public synchronized Set getParents(AbstractName child) {
174         Set parents = (Set) childToParentMap.get(child);
175         if (parents == null) {
176             return Collections.EMPTY_SET;
177         }
178         return new HashSet(parents);
179     }
180 
181     /**
182      * Gets all of the MBeans that have a dependency on the specified startParent.
183      *
184      * @param parent the component the returned childen set depend on
185      * @return a collection containing all of the components that depend on the parent; will never be null
186      */
187     public synchronized Set getChildren(AbstractName parent) {
188         Set children = (Set) parentToChildMap.get(parent);
189         if (children == null) {
190             return Collections.EMPTY_SET;
191         }
192         return new HashSet(children);
193     }
194 
195 
196     private class DependencyManagerLifecycleListener extends LifecycleAdapter {
197         public void unloaded(AbstractName abstractName) {
198             synchronized (BasicDependencyManager.this) {
199                 removeAllDependencies(abstractName);
200             }
201 
202         }
203     }
204 }