Package org.apache.geronimo.gbean.jmx

Source Code of org.apache.geronimo.gbean.jmx.ProxyMethodInterceptor$ToStringInvoke

/**
*
* 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.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanServer;
import javax.management.ObjectName;

import org.apache.geronimo.kernel.jmx.InvokeMBean;
import org.apache.geronimo.kernel.jmx.MBeanOperationSignature;

import net.sf.cglib.core.Signature;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import net.sf.cglib.reflect.FastClass;
import org.objectweb.asm.Type;

/**
*
*
* @version $Revision: 1.9 $ $Date: 2004/03/10 09:59:01 $
*/
public final class ProxyMethodInterceptor implements MethodInterceptor {
    /**
     * Type of the proxy interface
     */
    private final Class proxyType;

    /**
     * The MBeanServer we are using.
     */
    private MBeanServer server;

    /**
     * The object name to which we are connected.
     */
    private ObjectName objectName;

    /**
     * Map from interface method ids to InvokeMBean objects.
     */
    private InvokeMBean[] methodTable;

    /**
     * Is this proxy currently stoped.  If it is invocations will not be allowed.
     */
    private boolean stopped;

    public ProxyMethodInterceptor(Class proxyType) {
        assert proxyType != null;
        this.proxyType = proxyType;
        stopped = true;
    }

    public synchronized void connect(MBeanServer server, ObjectName objectName) {
        this.connect(server, objectName, false);
    }

    public synchronized void connect(MBeanServer server, ObjectName objectName, boolean stopped) {
        assert server != null && objectName != null;
        this.server = server;
        this.objectName = objectName;
        this.stopped = stopped;
        this.methodTable = ProxyMethodInterceptor.createMethodTable(server, objectName, proxyType);
    }

    public synchronized void disconnect() {
        stopped = true;
        this.server = null;
        this.objectName = null;
        this.methodTable = null;
    }

    public synchronized void start() {
        if (server == null || objectName == null) {
            throw new IllegalStateException("Server or objectName is null");
        }
        this.stopped = false;
    }

    public synchronized void stop() {
        this.stopped = true;
    }

    /**
     * Handles an invocation on a proxy
     * @param object the proxy instance
     * @param method java method that was invoked
     * @param args arguments to the mentod
     * @param proxy a CGLib method proxy of the method invoked
     * @return the result of the invocation
     * @throws java.lang.Throwable if any exceptions are thrown by the implementation method
     */
    public Object intercept(Object object, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        synchronized (this) {
            if (stopped) {
                throw new IllegalStateException("Proxy is stopped");
            }
        }
        InvokeMBean invoker = methodTable[proxy.getSuperIndex()];
        if (invoker == null) {
            throw new NoSuchOperationError("No implementation method:" +
                    " objectName=" + objectName + ", method=" + method);
        }
        return invoker.invoke(server, objectName, args);
    }

    public static InvokeMBean[] createMethodTable(MBeanServer server, ObjectName objectName, Class proxyType) {
        MBeanInfo info = null;
        try {
            info = server.getMBeanInfo(objectName);
        } catch (Exception e) {
            throw new IllegalArgumentException("Could not get MBeanInfo for target object: " + objectName);
        }

        // build attributeName->attributeInfo map
        MBeanAttributeInfo[] attributeInfos = info.getAttributes();
        Map attributes = new HashMap(attributeInfos.length);
        for (int i = 0; i < attributeInfos.length; i++) {
            MBeanAttributeInfo attributeInfo = attributeInfos[i];
            attributes.put(attributeInfo.getName(), attributeInfo);
        }

        // build operationName->operationInfo map
        MBeanOperationInfo[] operationInfos = info.getOperations();
        Map operations = new HashMap(operationInfos.length);
        for (int i = 0; i < operationInfos.length; i++) {
            MBeanOperationInfo operationInfo = operationInfos[i];
            operations.put(new MBeanOperationSignature(operationInfo), operationInfo);
        }

        // build the method lookup table
        FastClass fastClass = FastClass.create(proxyType);
        InvokeMBean[] methodTable = new InvokeMBean[fastClass.getMaxIndex() + 1];
        Method[] methods = proxyType.getMethods();
        for (int i = 0; i < methods.length; i++) {
            Method method = methods[i];
            int index = getSuperIndex(proxyType, method);
            if (index >= 0) {
                if (operations.containsKey(new MBeanOperationSignature(method))) {
                    methodTable[index] = new InvokeMBean(method, false, false);
                } else if (method.getName().startsWith("get") && attributes.containsKey(method.getName().substring(3))) {
                    methodTable[index] = new InvokeMBean(method, true, true);
                } else if (method.getName().startsWith("is") && attributes.containsKey(method.getName().substring(2))) {
                    methodTable[index] = new InvokeMBean(method, true, true);
                } else if (method.getName().startsWith("set") && attributes.containsKey(method.getName().substring(3))) {
                    methodTable[index] = new InvokeMBean(method, true, false);
                }
            }
        }

        // handle equals, hashCode and toString directly here
        try {
            methodTable[getSuperIndex(proxyType, proxyType.getMethod("equals", new Class[]{Object.class}))] = new EqualsInvoke();
            methodTable[getSuperIndex(proxyType, proxyType.getMethod("hashCode", null))] = new HashCodeInvoke();
            methodTable[getSuperIndex(proxyType, proxyType.getMethod("toString", null))] = new ToStringInvoke(proxyType.getName());
        } catch (Exception e) {
            // this can not happen... all classes must implement equals, hashCode and toString
            throw new AssertionError(e);
        }

        return methodTable;
    }

    private static int getSuperIndex(Class proxyType, Method method) {
        Signature signature = new Signature(method.getName(), Type.getReturnType(method), Type.getArgumentTypes(method));
        MethodProxy methodProxy = MethodProxy.find(proxyType, signature);
        if (methodProxy != null) {
            return methodProxy.getSuperIndex();
        }
        return -1;
    }

    private static final class HashCodeInvoke extends InvokeMBean {
        public HashCodeInvoke() {
            super("hashCode", new String[0], new Class[0], false, false, 0);
        }

        public Object invoke(MBeanServer server, ObjectName objectName, Object[] arguments) throws Throwable {
            return new Integer(objectName.hashCode());
        }
    }

    private static final class EqualsInvoke extends InvokeMBean {
        public EqualsInvoke() {
            super("hashCode", new String[]{"java.lang.Object"}, new Class[]{Object.class}, false, false, 1);
        }

        public Object invoke(MBeanServer server, ObjectName objectName, Object[] arguments) throws Throwable {
            return new Boolean(objectName.equals(arguments[0]));
        }
    }

    private static final class ToStringInvoke extends InvokeMBean {
        private final String interfaceName;

        public ToStringInvoke(String interfaceName) {
            super("toString", new String[0], new Class[0], false, false, 0);
            this.interfaceName = "[" + interfaceName + ": ";
        }

        public Object invoke(MBeanServer server, ObjectName objectName, Object[] arguments) throws Throwable {
            return interfaceName + objectName + "]";
        }
    }
}
TOP

Related Classes of org.apache.geronimo.gbean.jmx.ProxyMethodInterceptor$ToStringInvoke

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.