You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by jd...@apache.org on 2003/08/30 22:12:23 UTC
cvs commit: incubator-geronimo/modules/common/src/java/org/apache/geronimo/common/jmx MBeanProxyHandler.java MBeanProxyFactory.java ObjectNameFactory.java
jdillon 2003/08/30 13:12:23
Modified: modules/common/src/java/org/apache/geronimo/common/jmx
MBeanProxyFactory.java ObjectNameFactory.java
Added: modules/common/src/java/org/apache/geronimo/common/jmx
MBeanProxyHandler.java
Log:
o Replaced MPF impl with a version that checks more details before
determining what to do
o What to be done is encapsulated into a Task, which can be cached
for future use
* Tests need to be expanded
Revision Changes Path
1.3 +43 -36 incubator-geronimo/modules/common/src/java/org/apache/geronimo/common/jmx/MBeanProxyFactory.java
Index: MBeanProxyFactory.java
===================================================================
RCS file: /home/cvs/incubator-geronimo/modules/common/src/java/org/apache/geronimo/common/jmx/MBeanProxyFactory.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- MBeanProxyFactory.java 30 Aug 2003 17:49:17 -0000 1.2
+++ MBeanProxyFactory.java 30 Aug 2003 20:12:23 -0000 1.3
@@ -61,47 +61,73 @@
import javax.management.MBeanServer;
import javax.management.ObjectName;
+import org.apache.geronimo.common.NullArgumentException;
+
/**
* Creates a dynamic proxy to an MBean by ObjectName.
*
* The interface type and object existance is not enforced during construction.
* Instead, if a method is invoked on the proxy and there is no object registered
* with the assigned name, an InvocationTargetException is thrown, which contains
- * an InstanceNotFoundException. If an interface method that is not implemented by
+ * an InstanceNotFoundException.
+ *
+ * If an interface method that is not implemented by
* the MBean is invoked, an InvocationTargetException is thrown, which contains an
* NoSuchMethodException.
*
* @version $Revision$ $Date$
*/
-public final class MBeanProxyFactory
+public class MBeanProxyFactory
{
- /** Disallow instantation. */
- private MBeanProxyFactory() {}
-
/**
* Creates an MBean proxy using the specified interface to the objectName.
*
- * @param iface The interface to implement for this proxy
+ * @param type The interface to implement for this proxy
* @param server The MBeanServer in which the object is registered
* @param objectName The objectName of the MBean to proxy
* @return The new MBean proxy, which implemnts the specified interface.
*/
- public static Object getProxy(final Class iface,
- final MBeanServer server,
- final ObjectName objectName)
+ public static Object create(final Class type,
+ final MBeanServer server,
+ final ObjectName objectName)
{
- assert iface != null;
- assert iface.isInterface();
- assert server != null;
+ if (type == null) {
+ throw new NullArgumentException("type");
+ }
+ if (!type.isInterface()) {
+ throw new IllegalArgumentException("Type is not an interface: " + type);
+ }
+ if (server == null) {
+ throw new NullArgumentException("server");
+ }
- ClassLoader cl = iface.getClassLoader();
- LocalHandler handler = new LocalHandler(iface, server, objectName);
+ ClassLoader cl = type.getClassLoader();
+ Class[] types = { type, MBeanProxy.class };
+
+ MBeanProxyHandler handler = new MBeanProxyHandler(server, objectName);
+
+ return Proxy.newProxyInstance(cl, types, handler);
+ }
+
+ /**
+ * Creates an MBean proxy using the specified interface to the objectName.
+ *
+ * @param tyep The interface to implement for this proxy
+ * @param objectName The objectName of the MBean to proxy
+ * @return The new MBean proxy, which implemnts the specified interface.
+ */
+ public static Object create(final Class type, final ObjectName objectName)
+ {
+ MBeanServer server = MBeanServerLocator.locate();
+ assert server != null;
- return Proxy.newProxyInstance(
- cl, new Class[] { iface, MBeanProxy.class }, handler
- );
+ return create(type, server, objectName);
}
+ /**
+ * An interface which all proxies created by {@link MBeanProxyFactory}
+ * will implement in addition to the requested interface.
+ */
public static interface MBeanProxy
{
/**
@@ -117,24 +143,5 @@
* @return The ObjectName for this proxy.
*/
MBeanServer getMBeanProxyMBeanServer();
- }
-
- private static class LocalHandler
- extends AbstractMBeanProxyHandler
- {
- private ObjectName objectName;
-
- public LocalHandler(final Class iface,
- final MBeanServer server,
- final ObjectName objectName)
- {
- super(iface, server);
-
- this.objectName = objectName;
- }
-
- public ObjectName getObjectName() {
- return objectName;
- }
}
}
1.2 +4 -0 incubator-geronimo/modules/common/src/java/org/apache/geronimo/common/jmx/ObjectNameFactory.java
Index: ObjectNameFactory.java
===================================================================
RCS file: /home/cvs/incubator-geronimo/modules/common/src/java/org/apache/geronimo/common/jmx/ObjectNameFactory.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- ObjectNameFactory.java 30 Aug 2003 16:32:38 -0000 1.1
+++ ObjectNameFactory.java 30 Aug 2003 20:12:23 -0000 1.2
@@ -75,6 +75,10 @@
*/
public class ObjectNameFactory
{
+ //
+ // TODO: Replace Error with InvalidArgumentException
+ //
+
public static ObjectName create(String name) {
try {
return new ObjectName(name);
1.1 incubator-geronimo/modules/common/src/java/org/apache/geronimo/common/jmx/MBeanProxyHandler.java
Index: MBeanProxyHandler.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.common.jmx;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.HashMap;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.management.Attribute;
import javax.management.MBeanInfo;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanException;
import javax.management.ReflectionException;
import javax.management.RuntimeOperationsException;
import javax.management.RuntimeMBeanException;
import javax.management.RuntimeErrorException;
import org.apache.geronimo.common.NullArgumentException;
/**
* This class handles invocations for MBean proxies.
*
* @version $Revision: 1.1 $ $Date: 2003/08/30 20:12:23 $
*/
public class MBeanProxyHandler
implements InvocationHandler, MBeanProxyFactory.MBeanProxy
{
protected final MBeanServer server;
protected ObjectName target;
protected Map attributeMap;
protected Map taskCache;
public MBeanProxyHandler(final MBeanServer server,
final ObjectName target)
{
if (server == null) {
throw new NullArgumentException("server");
}
// target can be null
this.server = server;
this.target = target;
}
public Object invoke(final Object proxy, final Method method, final Object[] args)
throws Throwable
{
assert proxy != null;
assert method != null;
Class declaringClass = method.getDeclaringClass();
// if the method belongs to MBeanProxy, then invoke locally
if (declaringClass == MBeanProxyFactory.MBeanProxy.class) {
return method.invoke(this, args);
}
//
// TODO: Handle DynamicMBean.class
//
try {
return getTask(method, args).execute(proxy, method, args);
}
catch (Throwable t) {
Throwable decoded = JMXExceptionDecoder.decode(t);
// If it is a RuntimeException or Error just toss is
if (decoded instanceof RuntimeException) {
throw (RuntimeException)decoded;
}
if (decoded instanceof Error) {
throw (Error)decoded;
}
// Attempt to throw a declared exception
Class[] declared = method.getExceptionTypes();
for (int i=0; i < declared.length; i++) {
Class type = declared[i];
if (type.isInstance(decoded)) {
throw decoded;
}
}
// Else we don't have much choice, so just toss the original
throw t;
}
}
/////////////////////////////////////////////////////////////////////////
// Tasks //
/////////////////////////////////////////////////////////////////////////
protected interface Task
{
Object execute(Object proxy, Method method, Object[] args) throws Throwable;
}
protected class GetAttributeTask
implements Task
{
private MBeanAttributeInfo info;
public GetAttributeTask(MBeanAttributeInfo info)
{
this.info = info;
}
public Object execute(final Object proxy, final Method method, final Object[] args)
throws Throwable
{
return server.getAttribute(
getMBeanProxyObjectName(),
info.getName()
);
}
}
protected class SetAttributeTask
implements Task
{
private MBeanAttributeInfo info;
public SetAttributeTask(MBeanAttributeInfo info)
{
this.info = info;
}
public Object execute(final Object proxy, final Method method, final Object[] args)
throws Throwable
{
server.setAttribute(
getMBeanProxyObjectName(),
new Attribute(info.getName(), args[0])
);
return null;
}
}
protected class InvokeOperationTask
implements Task
{
public Object execute(final Object proxy, final Method method, final Object[] args)
throws Throwable
{
String[] signature = null;
if (args != null) {
signature = new String[args.length];
Class[] types = method.getParameterTypes();
for (int i=0; i<types.length; i++) {
signature[i] = types[i].getName();
}
}
return server.invoke(
getMBeanProxyObjectName(),
method.getName(),
args,
signature
);
}
}
protected Task createTask(final Method method, final Object[] args)
throws Exception
{
assert method != null;
if (taskCache == null) {
// Allow sub-class overrides
ObjectName objectName = getMBeanProxyObjectName();
// Get information about the target
MBeanInfo info = server.getMBeanInfo(objectName);
// Initialize the task cache
taskCache = new HashMap();
// Load up the attribute mapping
attributeMap = new HashMap();
MBeanAttributeInfo[] attributes = info.getAttributes();
for (int i=0; i<attributes.length; i++) {
attributeMap.put(attributes[i].getName(), attributes[i]);
}
}
String methodName = method.getName();
// Check for getters
if (args == null) {
if (methodName.startsWith("get")) {
String attrName = methodName.substring(3, methodName.length());
MBeanAttributeInfo info = (MBeanAttributeInfo)attributeMap.get(attrName);
if (info != null) {
//
// TODO: Check that return value is what is expected
//
return new GetAttributeTask(info);
}
}
else if (methodName.startsWith("is")) {
String attrName = methodName.substring(2, methodName.length());
MBeanAttributeInfo info = (MBeanAttributeInfo)attributeMap.get(attrName);
if (info != null && info.isIs()) {
// is getters must return booleans
Class rtype = method.getReturnType();
if (rtype == Boolean.class || rtype == boolean.class) {
return new GetAttributeTask(info);
}
}
}
}
// Check for setters
else if (args.length == 1 && methodName.startsWith("set")) {
String attrName = methodName.substring(3, methodName.length());
MBeanAttributeInfo info = (MBeanAttributeInfo)attributeMap.get(attrName);
if (info != null) {
// setters must return void
Class rtype = method.getReturnType();
if (rtype == void.class) {
return new SetAttributeTask(info);
}
}
}
// Else it will pass through as an attempted operation
return new InvokeOperationTask();
}
protected Task getTask(final Method method, final Object[] args)
throws Exception
{
// Key off of method name & arg count
Object key = method.getName() + (args == null ? 0 : args.length);
// Check if there is a cached task
Task task = null;
if (taskCache != null) {
task = (Task)taskCache.get(key);
}
// If not create one and cache it
if (task == null) {
task = createTask(method, args);
taskCache.put(key, task);
}
return task;
}
/////////////////////////////////////////////////////////////////////////
// MBeanProxy //
/////////////////////////////////////////////////////////////////////////
//
// TODO: Replace with a MBeanProxyContext interface
//
public ObjectName getMBeanProxyObjectName()
{
return target;
}
public MBeanServer getMBeanProxyMBeanServer()
{
return server;
}
}