Author: dain Date: Tue Nov 23 12:37:03 2004 New Revision: 106345 Added: geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/AbstractGBeanReference.java geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/GBeanCollectionProxy.java geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/GBeanCollectionReference.java geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/GBeanReference.java geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/GBeanSingleProxy.java geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/GBeanSingleReference.java geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/LifecycleAdapter.java geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/LifecycleListener.java geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/LifecycleMonitor.java Removed: geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/CollectionProxy.java geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/GBeanMBeanReference.java geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/Proxy.java geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/SingleProxy.java Modified: geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/AbstractManagedObject.java geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/CGLibMethodInterceptor.java geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/CGLibProxyFactory.java geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/GBeanMBean.java geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/ProxyMethodInterceptor.java geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/VMMethodInterceptor.java geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/DependencyManager.java geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/Kernel.java Log: Fixed lifecycle notification bugs. Moved notification monitor code from GBeanReference to a LifecycleMonitor kernel service. The LifecycleMoniter serverice should NOT be used until we are happy with it.
Added: geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/AbstractGBeanReference.java Url: http://svn.apache.org/viewcvs/geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/AbstractGBeanReference.java?view=auto&rev=106345 ============================================================================== --- (empty file) +++ geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/AbstractGBeanReference.java Tue Nov 23 12:37:03 2004 @@ -0,0 +1,260 @@ +/** + * + * Copyright 2004 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.geronimo.gbean.jmx; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; +import javax.management.AttributeNotFoundException; +import javax.management.InstanceNotFoundException; +import javax.management.ObjectName; + +import org.apache.geronimo.kernel.LifecycleAdapter; +import org.apache.geronimo.kernel.LifecycleListener; +import org.apache.geronimo.gbean.GReferenceInfo; +import org.apache.geronimo.gbean.InvalidConfigurationException; +import org.apache.geronimo.kernel.ClassLoading; +import org.apache.geronimo.kernel.Kernel; +import org.apache.geronimo.kernel.LifecycleListener; +import org.apache.geronimo.kernel.LifecycleAdapter; +import org.apache.geronimo.kernel.management.State; + +/** + * @version $Rev$ $Date$ + */ +public abstract class AbstractGBeanReference implements GBeanReference { + /** + * Name of this reference. + */ + private final String name; + + /** + * Interface this GBeanMBean uses to refer to the other. + */ + private final Class type; + + /** + * The GBeanMBean to which this reference belongs. + */ + private final GBeanMBean gmbean; + + /** + * The method that will be called to set the attribute value. If null, the value will be set with + * a constructor argument + */ + private final MethodInvoker setInvoker; + + /** + * The target objectName patterns to watch for a connection. + */ + private Set patterns = Collections.EMPTY_SET; + + /** + * Our listener for lifecycle events + */ + private final LifecycleListener listener; + + /** + * Current set of targets + */ + private final Set targets = new HashSet(); + + /** + * The kernel to which the reference is bound. + */ + private Kernel kernel; + + public AbstractGBeanReference(GBeanMBean gmbean, GReferenceInfo referenceInfo, Class constructorType) throws InvalidConfigurationException { + this.gmbean = gmbean; + this.name = referenceInfo.getName(); + try { + this.type = ClassLoading.loadClass(referenceInfo.getType(), gmbean.getClassLoader()); + } catch (ClassNotFoundException e) { + throw new InvalidConfigurationException("Could not load reference proxy interface class:" + + " name=" + name + + " class=" + referenceInfo.getType()); + } + if (Modifier.isFinal(type.getModifiers())) { + throw new IllegalArgumentException("Proxy interface cannot be a final class: " + type.getName()); + } + + if (constructorType != null) { + setInvoker = null; + } else { + Method setterMethod = searchForSetter(gmbean, referenceInfo); + setInvoker = new FastMethodInvoker(setterMethod); + } + + listener = new LifecycleAdapter() { + public void running(ObjectName objectName) { + if (!targets.contains(objectName)) { + targets.add(objectName); + targetAdded(objectName); + } + } + + public void stoping(ObjectName objectName) { + boolean wasTarget = targets.remove(objectName); + if (wasTarget) { + targetRemoved(objectName); + } + } + }; + } + + protected final Kernel getKernel() { + return kernel; + } + + protected final GBeanMBean getGBeanMBean() { + return gmbean; + } + + public final String getName() { + return name; + } + + public final Class getType() { + return type; + } + + public final Set getPatterns() { + return patterns; + } + + public final void setPatterns(Set patterns) { + if (kernel != null) { + throw new IllegalStateException("Pattern set can not be modified while online"); + } + + if (patterns == null || patterns.isEmpty() || (patterns.size() == 1 && patterns.iterator().next() == null)) { + this.patterns = Collections.EMPTY_SET; + } else { + patterns = new HashSet(patterns); + for (Iterator iterator = this.patterns.iterator(); iterator.hasNext();) { + if (iterator.next() == null) { + iterator.remove(); + //there can be at most one null value in a set. + break; + } + } + this.patterns = Collections.unmodifiableSet(patterns); + } + } + + public final synchronized void online(Kernel kernel) { + this.kernel = kernel; + + Set gbeans = kernel.listGBeans(patterns); + for (Iterator objectNameIterator = gbeans.iterator(); objectNameIterator.hasNext();) { + ObjectName target = (ObjectName) objectNameIterator.next(); + if (!targets.contains(target)) { + + // if the bean is running add it to the runningTargets list + if (isRunning(kernel, target)) { + targets.add(target); + } + } + } + + kernel.getLifecycleMonitor().addLifecycleListener(listener, patterns); + } + + public final synchronized void offline() { + // make sure we are stoped + stop(); + + kernel.getLifecycleMonitor().removeLifecycleListener(listener); + + targets.clear(); + kernel = null; + } + + protected abstract void targetAdded(ObjectName target); + + protected abstract void targetRemoved(ObjectName target); + + protected final Set getTargets() { + return targets; + } + + public final synchronized void inject() throws Exception { + // set the proxy into the instance + if (setInvoker != null && patterns.size() > 0) { + setInvoker.invoke(gmbean.getTarget(), new Object[]{getProxy()}); + } + } + + /** + * Is the component in the Running state + * + * @param objectName name of the component to check + * @return true if the component is running; false otherwise + */ + private boolean isRunning(Kernel kernel, ObjectName objectName) { + try { + final int state = ((Integer) kernel.getAttribute(objectName, "state")).intValue(); + return state == State.RUNNING_INDEX; + } catch (AttributeNotFoundException e) { + // ok -- mbean is not a startable + return true; + } catch (InstanceNotFoundException e) { + // mbean is no longer registerd + return false; + } catch (Exception e) { + // problem getting the attribute, mbean has most likely failed + return false; + } + } + + protected static Method searchForSetter(GBeanMBean gMBean, GReferenceInfo referenceInfo) throws InvalidConfigurationException { + if (referenceInfo.getSetterName() == null) { + // no explicit name give so we must search for a name + String setterName = "set" + referenceInfo.getName(); + Method[] methods = gMBean.getType().getMethods(); + for (int i = 0; i < methods.length; i++) { + Method method = methods[i]; + if (method.getParameterTypes().length == 1 && + method.getReturnType() == Void.TYPE && + setterName.equalsIgnoreCase(method.getName())) { + + return method; + } + } + } else { + // even though we have an exact name we need to search the methods because + // we don't know the parameter type + Method[] methods = gMBean.getType().getMethods(); + String setterName = referenceInfo.getSetterName(); + for (int i = 0; i < methods.length; i++) { + Method method = methods[i]; + if (method.getParameterTypes().length == 1 && + method.getReturnType() == Void.TYPE && + setterName.equals(method.getName())) { + + return method; + } + } + } + throw new InvalidConfigurationException("Target does not have specified method:" + + " name=" + referenceInfo.getName() + + " targetClass=" + gMBean.getType().getName()); + } +} Modified: geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/AbstractManagedObject.java Url: http://svn.apache.org/viewcvs/geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/AbstractManagedObject.java?view=diff&rev=106345&p1=geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/AbstractManagedObject.java&r1=106344&p2=geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/AbstractManagedObject.java&r2=106345 ============================================================================== --- geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/AbstractManagedObject.java (original) +++ geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/AbstractManagedObject.java Tue Nov 23 12:37:03 2004 @@ -166,10 +166,10 @@ } public void preDeregister() throws Exception { + sendNotification(NotificationType.OBJECT_DELETED); } public void postDeregister() { - sendNotification(NotificationType.OBJECT_DELETED); synchronized (this) { server = null; objectName = null; Modified: geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/CGLibMethodInterceptor.java Url: http://svn.apache.org/viewcvs/geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/CGLibMethodInterceptor.java?view=diff&rev=106345&p1=geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/CGLibMethodInterceptor.java&r1=106344&p2=geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/CGLibMethodInterceptor.java&r2=106345 ============================================================================== --- geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/CGLibMethodInterceptor.java (original) +++ geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/CGLibMethodInterceptor.java Tue Nov 23 12:37:03 2004 @@ -67,13 +67,9 @@ } public synchronized void connect(MBeanServerConnection server, ObjectName objectName) { - this.connect(server, objectName, false); - } - - public synchronized void connect(MBeanServerConnection server, ObjectName objectName, boolean stopped) { assert server != null && objectName != null; this.objectName = objectName; - this.stopped = stopped; + stopped = false; gbeanInvokers = createGBeanInvokers(server, objectName); } @@ -81,17 +77,6 @@ stopped = true; objectName = null; gbeanInvokers = null; - } - - public synchronized void start() { - if (gbeanInvokers == null) { - throw new IllegalStateException("Proxy is not connected"); - } - this.stopped = false; - } - - public synchronized void stop() { - this.stopped = true; } public final Object intercept(final Object object, final Method method, final Object[] args, final MethodProxy proxy) throws Throwable { Modified: geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/CGLibProxyFactory.java Url: http://svn.apache.org/viewcvs/geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/CGLibProxyFactory.java?view=diff&rev=106345&p1=geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/CGLibProxyFactory.java&r1=106344&p2=geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/CGLibProxyFactory.java&r2=106345 ============================================================================== --- geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/CGLibProxyFactory.java (original) +++ geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/CGLibProxyFactory.java Tue Nov 23 12:37:03 2004 @@ -16,8 +16,6 @@ */ package org.apache.geronimo.gbean.jmx; -import java.lang.reflect.InvocationTargetException; - import net.sf.cglib.proxy.Callback; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; Deleted: /geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/CollectionProxy.java Url: http://svn.apache.org/viewcvs/geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/CollectionProxy.java?view=auto&rev=106344 ============================================================================== Added: geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/GBeanCollectionProxy.java Url: http://svn.apache.org/viewcvs/geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/GBeanCollectionProxy.java?view=auto&rev=106345 ============================================================================== --- (empty file) +++ geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/GBeanCollectionProxy.java Tue Nov 23 12:37:03 2004 @@ -0,0 +1,293 @@ +/** + * + * Copyright 2003-2004 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.geronimo.gbean.jmx; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Set; +import javax.management.ObjectName; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.geronimo.gbean.ReferenceCollection; +import org.apache.geronimo.gbean.ReferenceCollectionEvent; +import org.apache.geronimo.gbean.ReferenceCollectionListener; +import org.apache.geronimo.kernel.Kernel; + +/** + * @version $Rev: 46019 $ $Date: 2004-09-14 02:56:06 -0700 (Tue, 14 Sep 2004) $ + */ +public class GBeanCollectionProxy { + private static final Log log = LogFactory.getLog(GBeanCollectionProxy.class); + + /** + * Name of the reference + */ + public String name; + + /** + * A map from object names to the proxy + */ + private Map proxies = new HashMap(); + + /** + * A map from object names to the proxy interceptor + */ + private Map interceptors = new HashMap(); + + /** + * Proxy collection implementation held by the component + */ + private ClientCollection proxy = new ClientCollection(); + + /** + * Facotry for proxy instances. + */ + private ProxyFactory factory; + private Kernel kernel; + + public GBeanCollectionProxy(Kernel kernel, String name, Class type, Set targets) { + this.kernel = kernel; + this.name = name; + factory = ProxyFactory.newProxyFactory(type); + + for (Iterator iterator = targets.iterator(); iterator.hasNext();) { + addTarget((ObjectName) iterator.next()); + } + } + + public synchronized void destroy() { + for (Iterator iterator = interceptors.values().iterator(); iterator.hasNext();) { + ProxyMethodInterceptor interceptor = (ProxyMethodInterceptor) iterator.next(); + interceptor.disconnect(); + } + proxy.listeners = null; + kernel = null; + name = null; + proxies = null; + interceptors = null; + proxy = null; + factory = null; + } + + public synchronized Object getProxy() { + return proxy; + } + + public synchronized void addTarget(ObjectName target) { + // if this is a new target... + if (!proxies.containsKey(target)) { + // create the interceptor + ProxyMethodInterceptor interceptor = factory.getMethodInterceptor(); + interceptor.connect(kernel.getMBeanServer(), target); + interceptors.put(target, interceptor); + + // create the proxy + Object targetProxy = factory.create(interceptor); + proxies.put(target, targetProxy); + proxy.fireMemberAdddedEvent(targetProxy); + } + } + + public synchronized void removeTarget(ObjectName target) { + Object targetProxy = proxies.remove(target); + if (targetProxy != null) { + proxy.fireMemberRemovedEvent(targetProxy); + ProxyMethodInterceptor interceptor = (ProxyMethodInterceptor) interceptors.remove(target); + if (interceptor != null) { + interceptor.disconnect(); + } + } + } + + private class ClientCollection implements ReferenceCollection { + private Set listeners = new HashSet(); + + public boolean isStopped() { + synchronized (GBeanCollectionProxy.this) { + return proxy == null; + } + } + + public void addReferenceCollectionListener(ReferenceCollectionListener listener) { + synchronized (GBeanCollectionProxy.this) { + listeners.add(listener); + } + } + + public void removeReferenceCollectionListener(ReferenceCollectionListener listener) { + synchronized (GBeanCollectionProxy.this) { + listeners.remove(listener); + } + } + + private void fireMemberAdddedEvent(Object member) { + ArrayList listenerCopy; + synchronized (GBeanCollectionProxy.this) { + listenerCopy = new ArrayList(listeners); + } + for (Iterator iterator = listenerCopy.iterator(); iterator.hasNext();) { + ReferenceCollectionListener listener = (ReferenceCollectionListener) iterator.next(); + try { + listener.memberAdded(new ReferenceCollectionEvent(name, member)); + } catch (Throwable t) { + log.error("Listener threw exception", t); + } + } + } + + private void fireMemberRemovedEvent(Object member) { + ArrayList listenerCopy; + synchronized (GBeanCollectionProxy.this) { + listenerCopy = new ArrayList(listeners); + } + for (Iterator iterator = listenerCopy.iterator(); iterator.hasNext();) { + ReferenceCollectionListener listener = (ReferenceCollectionListener) iterator.next(); + try { + listener.memberRemoved(new ReferenceCollectionEvent(name, member)); + } catch (Throwable t) { + log.error("Listener threw exception", t); + } + } + } + + public int size() { + synchronized (GBeanCollectionProxy.this) { + if (proxy == null) { + return 0; + } + return proxies.size(); + } + } + + public boolean isEmpty() { + synchronized (GBeanCollectionProxy.this) { + if (proxy == null) { + return true; + } + return proxies.isEmpty(); + } + } + + public boolean contains(Object o) { + synchronized (GBeanCollectionProxy.this) { + if (proxy == null) { + return false; + } + return proxies.containsValue(o); + } + } + + public Iterator iterator() { + synchronized (GBeanCollectionProxy.this) { + if (proxy == null) { + return new Iterator() { + public boolean hasNext() { + return false; + } + + public Object next() { + throw new NoSuchElementException(); + } + + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + + return new Iterator() { + // copy the proxies, so the client can iterate without concurrent modification + // this is necssary since the client has nothing to synchronize on + private final Iterator iterator = new ArrayList(proxies.values()).iterator(); + + public boolean hasNext() { + return iterator.hasNext(); + } + + public Object next() { + return iterator.next(); + } + + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + } + + public Object[] toArray() { + synchronized (GBeanCollectionProxy.this) { + if (proxy == null) { + return new Object[0]; + } + return proxies.values().toArray(); + } + } + + public Object[] toArray(Object a[]) { + synchronized (GBeanCollectionProxy.this) { + if (proxy == null) { + if (a.length > 0) { + a[0] = null; + } + return a; + } + return proxies.values().toArray(a); + } + } + + public boolean containsAll(Collection c) { + synchronized (GBeanCollectionProxy.this) { + if (proxy == null) { + return c.isEmpty(); + } + return proxies.values().containsAll(c); + } + } + + public boolean add(Object o) { + throw new UnsupportedOperationException(); + } + + public boolean remove(Object o) { + throw new UnsupportedOperationException(); + } + + public boolean addAll(Collection c) { + throw new UnsupportedOperationException(); + } + + public boolean removeAll(Collection c) { + throw new UnsupportedOperationException(); + } + + public boolean retainAll(Collection c) { + throw new UnsupportedOperationException(); + } + + public void clear() { + throw new UnsupportedOperationException(); + } + } +} Added: geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/GBeanCollectionReference.java Url: http://svn.apache.org/viewcvs/geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/GBeanCollectionReference.java?view=auto&rev=106345 ============================================================================== --- (empty file) +++ geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/GBeanCollectionReference.java Tue Nov 23 12:37:03 2004 @@ -0,0 +1,79 @@ +/** + * + * Copyright 2003-2004 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.geronimo.gbean.jmx; + +import javax.management.ObjectName; + +import org.apache.geronimo.gbean.GReferenceInfo; +import org.apache.geronimo.gbean.InvalidConfigurationException; + +/** + * @version $Rev: 71492 $ $Date: 2004-11-14 21:31:50 -0800 (Sun, 14 Nov 2004) $ + */ +public class GBeanCollectionReference extends AbstractGBeanReference { + /** + * Proxy to the to this connection. + */ + private GBeanCollectionProxy proxy; + + public GBeanCollectionReference(GBeanMBean gmbean, GReferenceInfo referenceInfo, Class constructorType) throws InvalidConfigurationException { + super(gmbean, referenceInfo, constructorType); + } + + public synchronized void start() throws Exception { + // if there are no patterns then there is nothing to start + if (getPatterns().isEmpty()) { + return; + } + + // if we already have a proxy then we have already been started + if (proxy != null) { + return; + } + + // add a dependency on our target and create the proxy + proxy = new GBeanCollectionProxy(getKernel(), getName(), getType(), getTargets()); + } + + public synchronized void stop() { + if (proxy != null) { + proxy.destroy(); + proxy = null; + } + } + + public Object getProxy() { + if (proxy == null) { + return null; + } else { + return proxy.getProxy(); + } + } + + public synchronized void targetAdded(ObjectName target) { + if (proxy != null) { + proxy.addTarget(target); + } + } + + public synchronized void targetRemoved(ObjectName target) { + if (proxy != null) { + proxy.removeTarget(target); + } + } +} Modified: geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/GBeanMBean.java Url: http://svn.apache.org/viewcvs/geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/GBeanMBean.java?view=diff&rev=106345&p1=geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/GBeanMBean.java&r1=106344&p2=geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/GBeanMBean.java&r2=106345 ============================================================================== --- geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/GBeanMBean.java (original) +++ geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/GBeanMBean.java Tue Nov 23 12:37:03 2004 @@ -19,6 +19,7 @@ import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -45,6 +46,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.geronimo.gbean.GAttributeInfo; +import org.apache.geronimo.gbean.GBeanData; import org.apache.geronimo.gbean.GBeanInfo; import org.apache.geronimo.gbean.GBeanLifecycle; import org.apache.geronimo.gbean.GBeanLifecycleController; @@ -53,7 +55,7 @@ import org.apache.geronimo.gbean.GOperationSignature; import org.apache.geronimo.gbean.GReferenceInfo; import org.apache.geronimo.gbean.InvalidConfigurationException; -import org.apache.geronimo.gbean.GBeanData; +import org.apache.geronimo.gbean.WaitingException; import org.apache.geronimo.kernel.Kernel; import org.apache.geronimo.kernel.management.NotificationType; @@ -106,7 +108,7 @@ /** * References lookup table */ - private final GBeanMBeanReference[] references; + private final GBeanReference[] references; /** * References supported by this GBeanMBean by (String) name. @@ -173,6 +175,8 @@ */ private final RawInvoker rawInvoker; + private Kernel kernel; + /** * Constructa a GBeanMBean using the supplied GBeanData and class loader * @@ -238,9 +242,14 @@ Set referencesSet = new HashSet(); for (Iterator iterator = gbeanInfo.getReferences().iterator(); iterator.hasNext();) { GReferenceInfo referenceInfo = (GReferenceInfo) iterator.next(); - referencesSet.add(new GBeanMBeanReference(this, referenceInfo, (Class) constructorTypes.get(referenceInfo.getName()))); + Class constructorType = (Class) constructorTypes.get(referenceInfo.getName()); + if (isCollectionValuedReference(this, referenceInfo, constructorType)) { + referencesSet.add(new GBeanCollectionReference(this, referenceInfo, constructorType)); + } else { + referencesSet.add(new GBeanSingleReference(this, referenceInfo, constructorType)); + } } - references = (GBeanMBeanReference[]) referencesSet.toArray(new GBeanMBeanReference[gbeanInfo.getReferences().size()]); + references = (GBeanReference[]) referencesSet.toArray(new GBeanReference[gbeanInfo.getReferences().size()]); for (int i = 0; i < references.length; i++) { referenceIndex.put(references[i].getName(), new Integer(i)); } @@ -297,6 +306,15 @@ gbeanLifecycleController = new GBeanMBeanLifecycleController(this); } + private static boolean isCollectionValuedReference(GBeanMBean gbeanMBean, GReferenceInfo referenceInfo, Class constructorType) { + if (constructorType != null) { + return Collection.class == constructorType; + } else { + Method setterMethod = AbstractGBeanReference.searchForSetter(gbeanMBean, referenceInfo); + return Collection.class == setterMethod.getParameterTypes()[0]; + } + } + /** * Search for a single valid constructor in the class. A valid constructor is determined by the * attributes and references declared in the GBeanInfo. For each, constructor gbean attribute @@ -523,17 +541,12 @@ setAttribute("classLoader", classLoader); try { String kernelName = (String) server.getAttribute(Kernel.KERNEL, "KernelName"); - Kernel kernel = Kernel.getKernel(kernelName); + kernel = Kernel.getKernel(kernelName); setAttribute("kernel", kernel); } catch (Exception e) { setAttribute("kernel", null); } - // bring any reference not used in the constructor online - for (int i = 0; i < references.length; i++) { - references[i].online(); - } - return returnValue; } @@ -542,39 +555,50 @@ if (registrationDone.booleanValue()) { // we're now offically on line - offline = false; - } else { - // we need to bring the reference back off line for (int i = 0; i < references.length; i++) { - references[i].offline(); + references[i].online(kernel); } + offline = false; + } else { + kernel = null; target = null; } } public void postDeregister() { - // take all of the reference offline + // just to be sure, stop all the references again for (int i = 0; i < references.length; i++) { references[i].offline(); } offline = true; + kernel = null; target = null; super.postDeregister(); } protected void doStart() throws Exception { - // start all of the proxies + // start each of the references... if they need to wait remember the + // waiting exception so we can throw it later. this way we the dependecies + // are held until we can start + WaitingException waitingException = null; for (int i = 0; i < references.length; i++) { - references[i].start(); + try { + references[i].start(); + } catch (WaitingException e) { + waitingException = e; + } + } + if (waitingException != null) { + throw waitingException; } GConstructorInfo constructorInfo = gbeanInfo.getConstructor(); Class[] parameterTypes = constructor.getParameterTypes(); - // create parameter array + // create constructor parameter array Object[] parameters = new Object[parameterTypes.length]; Iterator names = constructorInfo.getAttributeNames().iterator(); for (int i = 0; i < parameters.length; i++) { @@ -614,7 +638,7 @@ attributes[i].inject(); } - // inject the proxy into the new instance + // inject the proxies into the new instance for (int i = 0; i < references.length; i++) { references[i].inject(); } @@ -641,6 +665,7 @@ for (int i = 0; i < attributes.length; i++) { GBeanMBeanAttribute attribute = attributes[i]; if (attribute.isPersistent() && attribute.isReadable()) { + // copy the current attribute value to the persistent value Object value = attribute.getValue(); attribute.setPersistentValue(value); } @@ -748,7 +773,7 @@ // add the references for (int i = 0; i < references.length; i++) { - GBeanMBeanReference reference = references[i]; + GBeanReference reference = references[i]; String name = reference.getName(); Set patterns = reference.getPatterns(); gbeanData.setReferencePatterns(name, patterns); @@ -943,12 +968,12 @@ getReferenceByName(name).setPatterns(patterns); } - private GBeanMBeanReference getReferenceByName(String name) { + private GBeanReference getReferenceByName(String name) { Integer index = (Integer) referenceIndex.get(name); if (index == null) { throw new IllegalArgumentException("Unknown reference " + name); } - GBeanMBeanReference reference = references[index.intValue()]; + GBeanReference reference = references[index.intValue()]; return reference; } Deleted: /geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/GBeanMBeanReference.java Url: http://svn.apache.org/viewcvs/geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/GBeanMBeanReference.java?view=auto&rev=106344 ============================================================================== Added: geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/GBeanReference.java Url: http://svn.apache.org/viewcvs/geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/GBeanReference.java?view=auto&rev=106345 ============================================================================== --- (empty file) +++ geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/GBeanReference.java Tue Nov 23 12:37:03 2004 @@ -0,0 +1,46 @@ +/** + * + * Copyright 2004 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.geronimo.gbean.jmx; + +import java.util.Set; + +import org.apache.geronimo.kernel.Kernel; + +/** + * @version $Rev$ $Date$ + */ +public interface GBeanReference { + String getName(); + + Class getType(); + + Set getPatterns(); + + void setPatterns(Set patterns); + + void online(Kernel kernel); + + void offline(); + + void start() throws Exception; + + void stop(); + + Object getProxy(); + + void inject() throws Exception; +} Added: geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/GBeanSingleProxy.java Url: http://svn.apache.org/viewcvs/geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/GBeanSingleProxy.java?view=auto&rev=106345 ============================================================================== --- (empty file) +++ geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/GBeanSingleProxy.java Tue Nov 23 12:37:03 2004 @@ -0,0 +1,70 @@ +/** + * + * Copyright 2003-2004 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.geronimo.gbean.jmx; + +import javax.management.ObjectName; + +import org.apache.geronimo.kernel.Kernel; + +/** + * @version $Rev: 46019 $ $Date: 2004-09-14 02:56:06 -0700 (Tue, 14 Sep 2004) $ + */ +public class GBeanSingleProxy { + /** + * The GBean we are proxying. + */ + private ObjectName target; + + /** + * Proxy implementation held by the component + */ + private Object proxy; + + /** + * The interceptor for the proxy instance + */ + private ProxyMethodInterceptor methodInterceptor; + + public GBeanSingleProxy(Kernel kernel, Class type, ObjectName target) throws Exception { + assert kernel != null: "kernel is null"; + assert type != null: "type is null"; + assert target != null: "target is null"; + + this.target = target; + ProxyFactory factory = ProxyFactory.newProxyFactory(type); + methodInterceptor = factory.getMethodInterceptor(); + proxy = factory.create(methodInterceptor); + + methodInterceptor.connect(kernel.getMBeanServer(), target); + } + + public synchronized void destroy() { + methodInterceptor.disconnect(); + + proxy = null; + methodInterceptor = null; + } + + public synchronized Object getProxy() { + return proxy; + } + + public ObjectName getTarget() { + return target; + } +} Added: geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/GBeanSingleReference.java Url: http://svn.apache.org/viewcvs/geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/GBeanSingleReference.java?view=auto&rev=106345 ============================================================================== --- (empty file) +++ geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/GBeanSingleReference.java Tue Nov 23 12:37:03 2004 @@ -0,0 +1,150 @@ +/** + * + * Copyright 2003-2004 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.geronimo.gbean.jmx; + +import java.util.Set; +import javax.management.ObjectName; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.geronimo.gbean.GReferenceInfo; +import org.apache.geronimo.gbean.InvalidConfigurationException; +import org.apache.geronimo.gbean.WaitingException; +import org.apache.geronimo.kernel.Kernel; +import org.apache.geronimo.kernel.management.State; + +/** + * @version $Rev: 71492 $ $Date: 2004-11-14 21:31:50 -0800 (Sun, 14 Nov 2004) $ + */ +public class GBeanSingleReference extends AbstractGBeanReference { + private static final Log log = LogFactory.getLog(GBeanSingleReference.class); + + /** + * Is the GBeanMBean waitng for me to start? + */ + private boolean waitingForMe = false; + + /** + * Proxy to the to this connection. + */ + private GBeanSingleProxy proxy; + + public GBeanSingleReference(GBeanMBean gmbean, GReferenceInfo referenceInfo, Class constructorType) throws InvalidConfigurationException { + super(gmbean, referenceInfo, constructorType); + } + + public synchronized void start() throws Exception { + // if there are no patterns then there is nothing to start + if (getPatterns().isEmpty()) { + return; + } + + // if we already have a proxy then we have already been started + if (proxy != null) { + return; + } + + // + // We must have exactally one running target + // + Set targets = getTargets(); + if (targets.size() == 0) { + waitingForMe = true; + throw new WaitingException("No targets are running for " + getName() + " reference"); + } else if (targets.size() > 1) { + waitingForMe = true; + throw new WaitingException("More then one targets are running for " + getName() + " reference"); + } + waitingForMe = false; + + // stop all gbeans that would match our patterns from starting + Kernel kernel = getKernel(); + ObjectName objectName = getGBeanMBean().getObjectNameObject(); + kernel.getDependencyManager().addStartHolds(objectName, getPatterns()); + + // add a dependency on our target and create the proxy + ObjectName target = (ObjectName) targets.iterator().next(); + kernel.getDependencyManager().addDependency(objectName, target); + proxy = new GBeanSingleProxy(kernel, getType(), target); + } + + public synchronized void stop() { + waitingForMe = false; + Kernel kernel = getKernel(); + ObjectName objectName = getGBeanMBean().getObjectNameObject(); + Set patterns = getPatterns(); + if (!patterns.isEmpty()) { + kernel.getDependencyManager().removeStartHolds(objectName, patterns); + } + + if (proxy != null) { + kernel.getDependencyManager().removeDependency(objectName, proxy.getTarget()); + proxy.destroy(); + proxy = null; + } + } + + public Object getProxy() { + if (proxy == null) { + return null; + } else { + return proxy.getProxy(); + } + } + + public synchronized void targetAdded(ObjectName target) { + // if we are running, and we now have two valid targets, which is an illegal state so we need to fail + GBeanMBean gbeanMBean = getGBeanMBean(); + if (gbeanMBean.getStateInstance() == State.RUNNING) { + gbeanMBean.fail(); + } else if (waitingForMe) { + Set targets = getTargets(); + if (targets.size() == 1) { + // the gbean was waiting for me and not there is now just one target + attemptFullStart(); + } + } + } + + public synchronized void targetRemoved(ObjectName target) { + GBeanMBean gbeanMBean = getGBeanMBean(); + if (gbeanMBean.getStateInstance() == State.RUNNING) { + // we no longer have a valid target, which is an illegal state so we need to fail + gbeanMBean.fail(); + } else if (waitingForMe) { + Set targets = getTargets(); + if (targets.size() == 1) { + // the gbean was waiting for me and not there is now just one target + attemptFullStart(); + } + } + } + + private synchronized void attemptFullStart() { + try { + // there could be an issue with really badly written components holding up a stop when the + // component never reached the starting phase... then a target registers and we automatically + // attempt to restart + waitingForMe = false; + getGBeanMBean().attemptFullStart(); + } catch (Exception e) { + log.warn("Exception occured while attempting to fully start: objectName=" + getGBeanMBean().getObjectName(), e); + } + } + +} Deleted: /geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/Proxy.java Url: http://svn.apache.org/viewcvs/geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/Proxy.java?view=auto&rev=106344 ============================================================================== Modified: geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/ProxyMethodInterceptor.java Url: http://svn.apache.org/viewcvs/geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/ProxyMethodInterceptor.java?view=diff&rev=106345&p1=geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/ProxyMethodInterceptor.java&r1=106344&p2=geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/ProxyMethodInterceptor.java&r2=106345 ============================================================================== --- geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/ProxyMethodInterceptor.java (original) +++ geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/ProxyMethodInterceptor.java Tue Nov 23 12:37:03 2004 @@ -27,13 +27,7 @@ void connect(MBeanServerConnection server, ObjectName objectName); - void connect(MBeanServerConnection server, ObjectName objectName, boolean stopped); - void disconnect(); - - void start(); - - void stop(); static final class HashCodeInvoke implements GBeanInvoker { public Object invoke(ObjectName objectName, Object[] arguments) throws Throwable { Deleted: /geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/SingleProxy.java Url: http://svn.apache.org/viewcvs/geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/SingleProxy.java?view=auto&rev=106344 ============================================================================== Modified: geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/VMMethodInterceptor.java Url: http://svn.apache.org/viewcvs/geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/VMMethodInterceptor.java?view=diff&rev=106345&p1=geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/VMMethodInterceptor.java&r1=106344&p2=geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/VMMethodInterceptor.java&r2=106345 ============================================================================== --- geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/VMMethodInterceptor.java (original) +++ geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/gbean/jmx/VMMethodInterceptor.java Tue Nov 23 12:37:03 2004 @@ -45,13 +45,9 @@ } public void connect(MBeanServerConnection server, ObjectName objectName) { - connect(server, objectName, false); - } - - public void connect(MBeanServerConnection server, ObjectName objectName, boolean stopped) { assert server != null && objectName != null; this.objectName = objectName; - this.stopped = stopped; + stopped = false; gbeanInvokers = createGBeanInvokers(server, objectName); } @@ -59,17 +55,6 @@ stopped = true; objectName = null; gbeanInvokers = null; - } - - public void start() { - if (gbeanInvokers == null) { - throw new DeadProxyException("Proxy is no longer valid"); - } - this.stopped = false; - } - - public void stop() { - this.stopped = true; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Modified: geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/DependencyManager.java Url: http://svn.apache.org/viewcvs/geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/DependencyManager.java?view=diff&rev=106345&p1=geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/DependencyManager.java&r1=106344&p2=geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/DependencyManager.java&r2=106345 ============================================================================== --- geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/DependencyManager.java (original) +++ geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/DependencyManager.java Tue Nov 23 12:37:03 2004 @@ -193,7 +193,7 @@ if (parents == null) { return Collections.EMPTY_SET; } - return parents; + return new HashSet(parents); } /** @@ -208,7 +208,7 @@ if (children == null) { return Collections.EMPTY_SET; } - return children; + return new HashSet(children); } /** Modified: geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/Kernel.java Url: http://svn.apache.org/viewcvs/geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/Kernel.java?view=diff&rev=106345&p1=geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/Kernel.java&r1=106344&p2=geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/Kernel.java&r2=106345 ============================================================================== --- geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/Kernel.java (original) +++ geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/Kernel.java Tue Nov 23 12:37:03 2004 @@ -28,6 +28,8 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.Iterator; +import java.util.HashSet; import javax.management.Attribute; import javax.management.InstanceAlreadyExistsException; import javax.management.InstanceNotFoundException; @@ -44,12 +46,12 @@ import org.apache.geronimo.gbean.GBeanData; import org.apache.geronimo.gbean.GBeanInfo; import org.apache.geronimo.gbean.jmx.GBeanMBean; +import org.apache.geronimo.kernel.config.Configuration; import org.apache.geronimo.kernel.config.ConfigurationManager; import org.apache.geronimo.kernel.config.ConfigurationManagerImpl; import org.apache.geronimo.kernel.config.InvalidConfigException; import org.apache.geronimo.kernel.config.NoSuchConfigException; import org.apache.geronimo.kernel.config.NoSuchStoreException; -import org.apache.geronimo.kernel.config.Configuration; import org.apache.geronimo.kernel.jmx.JMXUtil; @@ -158,6 +160,12 @@ private GBeanMBean configurationManagerGBean; /** + * Monitors the lifecycle of all gbeans. + * @deprecated don't use this yet... it may go away + */ + private LifecycleMonitor lifecycleMonitor; + + /** * No-arg constructor allowing this class to be used as a GBean reference. */ public Kernel() { @@ -249,6 +257,14 @@ return configurationManager; } + /** + * Gets the lifecycle monitor. + * @deprecated don't use this yet... it may change or go away + */ + public LifecycleMonitor getLifecycleMonitor() { + return lifecycleMonitor; + } + public Object getAttribute(ObjectName objectName, String attributeName) throws Exception { try { return mbServer.getAttribute(objectName, attributeName); @@ -404,6 +420,15 @@ return mbServer.queryNames(query, null); } + public Set listGBeans(Set patterns) { + Set gbeans = new HashSet(); + for (Iterator iterator = patterns.iterator(); iterator.hasNext();) { + ObjectName pattern = (ObjectName) iterator.next(); + gbeans.addAll(listGBeans(pattern)); + } + return gbeans; + } + public List listConfigurationStores() { return getConfigurationManager().listStores(); } @@ -479,12 +504,13 @@ mbServer.registerMBean(this, KERNEL); dependencyManager = new DependencyManager(mbServer); + lifecycleMonitor = new LifecycleMonitor(mbServer); + configurationManagerGBean = new GBeanMBean(ConfigurationManagerImpl.GBEAN_INFO); configurationManagerGBean.setReferencePatterns("Stores", Collections.singleton(CONFIGURATION_STORE_PATTERN)); mbServer.registerMBean(configurationManagerGBean, CONFIGURATION_MANAGER_NAME); configurationManagerGBean.start(); configurationManager = (ConfigurationManager) configurationManagerGBean.getTarget(); - running = true; log.info("Booted"); } Added: geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/LifecycleAdapter.java Url: http://svn.apache.org/viewcvs/geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/LifecycleAdapter.java?view=auto&rev=106345 ============================================================================== --- (empty file) +++ geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/LifecycleAdapter.java Tue Nov 23 12:37:03 2004 @@ -0,0 +1,42 @@ +/** + * + * Copyright 2004 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.geronimo.kernel; + +import javax.management.ObjectName; + +/** + * @version $Rev$ $Date$ + */ +public class LifecycleAdapter implements LifecycleListener { + public void created(ObjectName objectName) { + } + + public void starting(ObjectName objectName) { + } + + public void running(ObjectName objectName) { + } + + public void stopping(ObjectName objectName) { + } + + public void stopped(ObjectName objectName) { + } + + public void deleted(ObjectName objectName) { + } +} Added: geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/LifecycleListener.java Url: http://svn.apache.org/viewcvs/geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/LifecycleListener.java?view=auto&rev=106345 ============================================================================== --- (empty file) +++ geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/LifecycleListener.java Tue Nov 23 12:37:03 2004 @@ -0,0 +1,32 @@ +/** + * + * Copyright 2004 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.geronimo.kernel; + +import java.util.EventListener; +import javax.management.ObjectName; + +/** + * @version $Rev$ $Date$ + */ +public interface LifecycleListener extends EventListener { + public void created(ObjectName objectName); + public void starting(ObjectName objectName); + public void running(ObjectName objectName); + public void stopping(ObjectName objectName); + public void stopped(ObjectName objectName); + public void deleted(ObjectName objectName); +} Added: geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/LifecycleMonitor.java Url: http://svn.apache.org/viewcvs/geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/LifecycleMonitor.java?view=auto&rev=106345 ============================================================================== --- (empty file) +++ geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/LifecycleMonitor.java Tue Nov 23 12:37:03 2004 @@ -0,0 +1,276 @@ +/** + * + * Copyright 2003-2004 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.geronimo.kernel; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; +import java.util.Map; +import java.util.Collections; +import java.util.HashMap; +import javax.management.InstanceNotFoundException; +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 javax.management.NotificationBroadcaster; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.geronimo.kernel.jmx.JMXUtil; +import org.apache.geronimo.kernel.management.NotificationType; + +/** + * @version $Rev: 71492 $ $Date: 2004-11-14 21:31:50 -0800 (Sun, 14 Nov 2004) $ + */ +public class LifecycleMonitor implements NotificationListener { + private static final Log log = LogFactory.getLog(LifecycleMonitor.class); + + private final MBeanServer server; + + // todo we should only hold weak references to the listeners + private final Map boundListeners = new HashMap(); + private final Map listenerPatterns = new HashMap(); + + /** + * @deprecated don't use this yet... it may change or go away + */ + public LifecycleMonitor(MBeanServer server) { + this.server = server; + + // listen for all mbean registration events + try { + NotificationFilterSupport mbeanServerFilter = new NotificationFilterSupport(); + mbeanServerFilter.enableType(MBeanServerNotification.REGISTRATION_NOTIFICATION); + mbeanServerFilter.enableType(MBeanServerNotification.UNREGISTRATION_NOTIFICATION); + server.addNotificationListener(JMXUtil.DELEGATE_NAME, this, mbeanServerFilter, null); + } catch (Exception e) { + // this will never happen... all of the above is well formed + throw new AssertionError(e); + } + + // register for state change notifications with all mbeans that match the target patterns + Set names = server.queryNames(null, null); + for (Iterator objectNameIterator = names.iterator(); objectNameIterator.hasNext();) { + addSource((ObjectName) objectNameIterator.next()); + } + + for (Iterator iterator = boundListeners.keySet().iterator(); iterator.hasNext();) { + ObjectName source = (ObjectName) iterator.next(); + try { + if (server.isInstanceOf(source, NotificationBroadcaster.class.getName())) { + server.addNotificationListener(source, this, NotificationType.STATE_CHANGE_FILTER, null); + } + } catch (InstanceNotFoundException e) { + // the instance died before we could get going... not a big deal + break; + } catch (Throwable e) { + log.warn("Could not add state change listener to: " + source + " on behalf of objectName", e); + } + } + } + + public synchronized void destroy() { + try { + server.removeNotificationListener(JMXUtil.DELEGATE_NAME, this); + } catch (Exception ignore) { + // don't care... we tried + } + + // unregister for all notifications + for (Iterator iterator = boundListeners.keySet().iterator(); iterator.hasNext();) { + ObjectName target = (ObjectName) iterator.next(); + try { + server.removeNotificationListener(target, this, NotificationType.STATE_CHANGE_FILTER, null); + } catch (Exception ignore) { + // don't care... we tried + } + } + + boundListeners.clear(); + listenerPatterns.clear(); + } + + private synchronized void addSource(ObjectName source) { + if (boundListeners.containsKey(source)) { + // alreayd registered + return; + } + + // find all listeners interested in events from this source + HashSet listeners = new HashSet(); + for (Iterator listenerIterator = listenerPatterns.entrySet().iterator(); listenerIterator.hasNext();) { + Map.Entry entry = (Map.Entry) listenerIterator.next(); + Set patterns = (Set) entry.getValue(); + for (Iterator patternIterator = patterns.iterator(); patternIterator.hasNext();) { + ObjectName pattern = (ObjectName) patternIterator.next(); + if (pattern.apply(source)) { + LifecycleListener listener = (LifecycleListener) entry.getKey(); + listeners.add(listener); + } + } + } + + boundListeners.put(source, listeners); + } + + private synchronized void removeSource(ObjectName source) { + boundListeners.remove(source); + } + + public synchronized void addLifecycleListener(LifecycleListener listener, Set patterns) { + for (Iterator patternIterator = patterns.iterator(); patternIterator.hasNext();) { + ObjectName pattern = (ObjectName) patternIterator.next(); + for (Iterator iterator = boundListeners.entrySet().iterator(); iterator.hasNext();) { + Map.Entry entry = (Map.Entry) iterator.next(); + ObjectName source = (ObjectName) entry.getKey(); + if (pattern.apply(source)) { + Set listeners = (Set) entry.getValue(); + listeners.add(listener); + } + } + } + listenerPatterns.put(listener, patterns); + } + + public synchronized void removeLifecycleListener(LifecycleListener listener) { + for (Iterator iterator = boundListeners.values().iterator(); iterator.hasNext();) { + Set set = (Set) iterator.next(); + set.remove(listener); + } + listenerPatterns.remove(listener); + } + + private synchronized Set getTargets(ObjectName source) { + Set targets = (Set) boundListeners.get(source); + if (targets == null) { + // no one is interested in this event + return Collections.EMPTY_SET; + } else { + return new HashSet(targets); + } + } + + private void fireCreatedEvent(ObjectName objectName) { + Set targets = getTargets(objectName); + for (Iterator iterator = targets.iterator(); iterator.hasNext();) { + LifecycleListener listener = (LifecycleListener) iterator.next(); + try { + listener.created(objectName); + } catch (Throwable e) { + log.warn("Exception occured while notifying listener", e); + } + } + } + + private void fireStartingEvent(ObjectName source) { + Set targets = getTargets(source); + for (Iterator iterator = targets.iterator(); iterator.hasNext();) { + LifecycleListener listener = (LifecycleListener) iterator.next(); + try { + listener.starting(source); + } catch (Throwable e) { + log.warn("Exception occured while notifying listener", e); + } + } + } + + private void fireRunningEvent(ObjectName source) { + Set targets = getTargets(source); + for (Iterator iterator = targets.iterator(); iterator.hasNext();) { + LifecycleListener listener = (LifecycleListener) iterator.next(); + try { + listener.running(source); + } catch (Throwable e) { + log.warn("Exception occured while notifying listener", e); + } + } + } + + private void fireStoppingEvent(ObjectName source) { + Set targets = getTargets(source); + for (Iterator iterator = targets.iterator(); iterator.hasNext();) { + LifecycleListener listener = (LifecycleListener) iterator.next(); + try { + listener.stopping(source); + } catch (Throwable e) { + log.warn("Exception occured while notifying listener", e); + } + } + } + + private void fireStoppedEvent(ObjectName source) { + Set targets = getTargets(source); + for (Iterator iterator = targets.iterator(); iterator.hasNext();) { + LifecycleListener listener = (LifecycleListener) iterator.next(); + try { + listener.stopped(source); + } catch (Throwable e) { + log.warn("Exception occured while notifying listener", e); + } + } + } + + private void fireDeleteEvent(ObjectName source) { + Set targets = getTargets(source); + for (Iterator iterator = targets.iterator(); iterator.hasNext();) { + LifecycleListener listener = (LifecycleListener) iterator.next(); + try { + listener.deleted(source); + } catch (Throwable e) { + log.warn("Exception occured while notifying listener", e); + } + } + } + + public void handleNotification(Notification notification, Object o) { + String type = notification.getType(); + + if (MBeanServerNotification.REGISTRATION_NOTIFICATION.equals(type)) { + ObjectName source = ((MBeanServerNotification) notification).getMBeanName(); + addSource(source); + + // register for state change notifications + try { + server.addNotificationListener(source, this, NotificationType.STATE_CHANGE_FILTER, null); + } catch (InstanceNotFoundException e) { + // the instance died before we could get going... not a big deal + return; + } + } else if (MBeanServerNotification.UNREGISTRATION_NOTIFICATION.equals(type)) { + removeSource(((MBeanServerNotification) notification).getMBeanName()); + } else { + final ObjectName source = (ObjectName) notification.getSource(); + if (NotificationType.OBJECT_CREATED.equals(type)) { + fireCreatedEvent(source); + } else if (NotificationType.STATE_STARTING.equals(type)) { + fireStartingEvent(source); + } else if (NotificationType.STATE_RUNNING.equals(type)) { + fireRunningEvent(source); + } else if (NotificationType.STATE_STOPPING.equals(type)) { + fireStoppingEvent(source); + } else if (NotificationType.STATE_STOPPED.equals(type)) { + fireStoppedEvent(source); + } else if (NotificationType.OBJECT_DELETED.equals(type)) { + fireDeleteEvent(source); + } + } + } +}