You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by da...@apache.org on 2003/11/06 20:50:08 UTC
cvs commit: incubator-geronimo/modules/kernel/src/java/org/apache/geronimo/kernel/service DependencyService2.java
dain 2003/11/06 11:50:08
Added: modules/kernel/src/java/org/apache/geronimo/kernel/service
DependencyService2.java
Log:
New simplified dependency service. This should be moved to
DependencyService.java when the rest of the mbeans are updated.
Revision Changes Path
1.1 incubator-geronimo/modules/kernel/src/java/org/apache/geronimo/kernel/service/DependencyService2.java
Index: DependencyService2.java
===================================================================
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" and
* "Apache Geronimo" must not be used to endorse or promote products
* derived from this software without prior written permission. For
* written permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* "Apache Geronimo", nor may "Apache" appear in their name, without
* prior written permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
* ====================================================================
*/
package org.apache.geronimo.kernel.service;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.management.JMException;
import javax.management.MBeanRegistration;
import javax.management.MBeanServer;
import javax.management.MBeanServerNotification;
import javax.management.Notification;
import javax.management.NotificationFilterSupport;
import javax.management.NotificationListener;
import javax.management.ObjectName;
import org.apache.geronimo.kernel.jmx.JMXUtil;
/**
* DependencyService is the record keeper of the dependencies in Geronimo. The DependencyService
* does not enforce any dependencies, it is simply a place where components can register thier intent
* to be dependent on another component. Since a JMX Component can pretty much do whatever it wants
* a component must watch the components it depends on to assure that they are following the
* J2EE-Management state machine.
*
* The DependencyService uses the nomenclature of parent-child where a child is dependent on a parent.
* The names parent and child have no other meaning are just a convience to make the code readable.
*
* @jmx:mbean
*
* @version $Revision: 1.1 $ $Date: 2003/11/06 19:50:08 $
*/
public class DependencyService2 implements MBeanRegistration, NotificationListener, DependencyService2MBean {
/**
* The mbean server we are registered with.
*/
private MBeanServer server;
/**
* A map from child names to a list of parents.
*/
private final Map childToParentMap = new HashMap();
/**
* A map from parent back to a list of its children.
*/
private final Map parentToChildMap = new HashMap();
/**
* A map from a component's ObjectName to the list of ObjectPatterns that the component is blocking
* from starting.
*/
private final Map startHoldsMap = new HashMap();
public ObjectName preRegister(MBeanServer server, ObjectName objectName) throws Exception {
if (objectName == null) {
objectName = JMXUtil.DEPENDENCY_SERVICE_NAME;
}
this.server = server;
NotificationFilterSupport mbeanServerFilter = new NotificationFilterSupport();
mbeanServerFilter.enableType(MBeanServerNotification.UNREGISTRATION_NOTIFICATION);
server.addNotificationListener(JMXUtil.DELEGATE_NAME, this, mbeanServerFilter, null);
return objectName;
}
public void postRegister(Boolean aBoolean) {
}
public void preDeregister() throws Exception {
}
public void postDeregister() {
try {
server.removeNotificationListener(JMXUtil.DELEGATE_NAME, this);
} catch (JMException ignored) {
// no big deal... just good citizen clean up code
}
synchronized(this) {
server = null;
childToParentMap.clear();
parentToChildMap.clear();
startHoldsMap.clear();
}
}
/**
* Declares a dependency from a child to a parent.
* @param child the dependent component
* @param parent the component the child is depending on
*
* @jmx:managed-operation
*/
public synchronized void addDependency(ObjectName child, ObjectName parent) {
Set parents = (Set) childToParentMap.get(child);
if (parents == null) {
parents = new HashSet();
childToParentMap.put(child, parents);
}
parents.add(parent);
Set children = (Set) parentToChildMap.get(parent);
if (children == null) {
children = new HashSet();
parentToChildMap.put(parent, children);
}
children.add(child);
}
/**
* Removes a dependency from a child to a parent
* @param child the dependnet component
* @param parent the component that the child wil no longer depend on
*
* @jmx:managed-operation
*/
public synchronized void removeDependency(ObjectName child, ObjectName parent) {
Set parents = (Set) childToParentMap.get(child);
if (parents != null) {
parents.remove(parent);
}
Set children = (Set) parentToChildMap.get(parent);
if (children != null) {
children.remove(child);
}
}
/**
* Removes all dependencies for a child
* @param child the component that will no longer depend on anything
*
* @jmx:managed-operation
*/
public synchronized void removeAllDependencies(ObjectName child) {
Set parents = (Set) childToParentMap.remove(child);
if(parents == null) {
return;
}
for (Iterator iterator = parents.iterator(); iterator.hasNext();) {
ObjectName parent = (ObjectName) iterator.next();
Set children = (Set) parentToChildMap.get(parent);
if (children != null) {
children.remove(child);
}
}
}
/**
* Adds dependcies from the child to every parent in the parents set
* @param child the dependent component
* @param parents the set of components the child is depending on
*
* @jmx:managed-operation
*/
public synchronized void addDependencies(ObjectName child, Set parents) {
Set existingParents = (Set) childToParentMap.get(child);
if (existingParents == null) {
existingParents = new HashSet(parents);
childToParentMap.put(child, existingParents);
} else {
existingParents.addAll(parents);
}
for (Iterator i = parents.iterator(); i.hasNext();) {
Object startParent = i.next();
Set children = (Set) parentToChildMap.get(startParent);
if (children == null) {
children = new HashSet();
parentToChildMap.put(startParent, children);
}
children.add(child);
}
}
/**
* Gets the set of parents that the child is depending on
* @param child the depend component
* @return a collection containing all of the components the child depends on; will never be null
*
* @jmx:managed-operation
*/
public synchronized Set getParents(ObjectName child) {
Set parents = (Set) childToParentMap.get(child);
if (parents == null) {
return Collections.EMPTY_SET;
}
return parents;
}
/**
* Gets all of the MBeans that have a dependency on the specificed startParent.
* @param parent the component the returned childen set depend on
* @return a collection containing all of the components that depend on the parent; will never be null
*
* @jmx:managed-operation
*/
public synchronized Set getChildren(ObjectName parent) {
Set children = (Set) parentToChildMap.get(parent);
if (children == null) {
return Collections.EMPTY_SET;
}
return children;
}
/**
* Adds a hold on a collection of object name patterns. If the name of a component matches an object name
* pattern in the collection, the component should not start.
* @param objectName the name of the component placing the holds
* @param holds a collection of object name patterns which should not start
*
* @jmx:managed-operation
*/
public synchronized void addStartHolds(ObjectName objectName, Collection holds) {
Collection currentHolds = (Collection)startHoldsMap.get(objectName);
if(currentHolds == null) {
currentHolds = new LinkedList(holds);
startHoldsMap.put(objectName, currentHolds);
} else {
currentHolds.addAll(holds);
}
}
/**
* Removes a collection of holds.
* @param objectName the object name of the components owning the holds
* @param holds a collection of the holds to remove
*
* @jmx:managed-operation
*/
public synchronized void removeStartHolds(ObjectName objectName, Collection holds) {
Collection currentHolds = (Collection)startHoldsMap.get(objectName);
if(currentHolds != null) {
currentHolds.removeAll(holds);
}
}
/**
* Removes all of the holds owned by a component.
* @param objectName the object name of the component that will no longer have any holds
*
* @jmx:managed-operation
*/
public synchronized void removeAllStartHolds(ObjectName objectName) {
startHoldsMap.remove(objectName);
}
/**
* Gets the object name of the mbean blocking the start specified mbean.
* @param objectName the mbean to check for blockers
* @return the mbean blocking the specified mbean, or null if there are no blockers
*
* @jmx:managed-operation
*/
public synchronized ObjectName checkBlocker(ObjectName objectName) {
// check if objectName name is on one of the hold lists
for (Iterator iterator = startHoldsMap.keySet().iterator(); iterator.hasNext();) {
ObjectName blocker = (ObjectName) iterator.next();
List holds = (List) startHoldsMap.get(blocker);
for (Iterator holdsIterator = holds.iterator(); holdsIterator.hasNext();) {
ObjectName pattern = (ObjectName) holdsIterator.next();
if(pattern.apply(objectName)) {
return blocker;
}
}
}
return null;
}
public void handleNotification(Notification n, Object handback) {
String type = n.getType();
if (MBeanServerNotification.UNREGISTRATION_NOTIFICATION.equals(type)) {
MBeanServerNotification notification = (MBeanServerNotification) n;
ObjectName source = notification.getMBeanName();
synchronized(this) {
removeAllDependencies(source);
removeAllStartHolds(source);
}
}
}
}