Package org.glassfish.admin.amx.impl.util

Source Code of org.glassfish.admin.amx.impl.util.MBeanInfoSupport

/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2009-2010 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License").  You
* may not use this file except in compliance with the License.  You can
* obtain a copy of the License at
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt.  See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license."  If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above.  However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.glassfish.admin.amx.impl.util;

import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.management.Descriptor;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanConstructorInfo;
import javax.management.MBeanInfo;
import javax.management.MBeanNotificationInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanParameterInfo;
import javax.management.ObjectName;
import javax.management.modelmbean.DescriptorSupport;
import org.glassfish.admin.amx.annotation.ManagedAttribute;
import org.glassfish.admin.amx.annotation.ManagedOperation;
import org.glassfish.admin.amx.annotation.Description;
import org.glassfish.admin.amx.annotation.Param;
import org.glassfish.admin.amx.base.Singleton;
import org.glassfish.admin.amx.core.AMXProxy;
import org.glassfish.admin.amx.core.AMX_SPI;
import org.glassfish.admin.amx.util.jmx.JMXUtil;
import org.glassfish.admin.amx.core.AMXMBeanMetadata;
import static org.glassfish.external.amx.AMX.*;

/**
*
* @author llc
*/
public final class MBeanInfoSupport {

    private MBeanInfoSupport() {
    }

    private static void debug(final Object o) {
        System.out.println(o.toString());
    }
    private static MBeanInfo amxspiMBeanInfo = null;

    public static synchronized MBeanInfo getAMX_SPIMBeanInfo() {
        if (amxspiMBeanInfo == null) {
            amxspiMBeanInfo = MBeanInfoSupport.getMBeanInfo(AMX_SPI.class);
        }
        return amxspiMBeanInfo;
    }

    public static <T extends AMX_SPI> MBeanInfo getMBeanInfo(final Class<T> intf) {
        final Map<String, Method> getters = new HashMap<String, Method>();
        final Map<String, Method> setters = new HashMap<String, Method>();
        final Map<String, Method> getterSetters = new HashMap<String, Method>();
        final Set<Method> operations = new HashSet<Method>();

        findInterfaceMethods(intf, getters, setters, getterSetters, operations);

        if (!AMX_SPI.class.isAssignableFrom(intf)) {
            findInterfaceMethods(AMX_SPI.class, getters, setters, getterSetters, operations);
        }


        final List<MBeanAttributeInfo> attrsList =
                generateMBeanAttributeInfos(getterSetters.values(), getters.values(), setters.values());

        final MBeanOperationInfo[] operationInfos = generateMBeanOperationInfos(operations);

        final MBeanConstructorInfo[] constructorInfos = null;
        final MBeanNotificationInfo[] notificationInfos = null;

        // might or might not have metadata
        final AMXMBeanMetadata meta = intf.getAnnotation(AMXMBeanMetadata.class);

        final boolean globalSingleton = meta != null && meta.globalSingleton();
        final boolean singleton = Singleton.class.isAssignableFrom(intf) || globalSingleton ||
                (meta != null && meta.singleton());
        final String group = GROUP_OTHER;
        final boolean isLeaf = meta != null && meta.leaf();
        final boolean supportsAdoption = !isLeaf;

        if (isLeaf) {
            JMXUtil.remove(attrsList, ATTR_CHILDREN);
        }

        final Descriptor d = mbeanDescriptor(
                true,
                intf,
                singleton,
                globalSingleton,
                group,
                supportsAdoption,
                null);



        final MBeanAttributeInfo[] attrInfos = new MBeanAttributeInfo[attrsList.size()];
        attrsList.toArray(attrInfos);

        final MBeanInfo mbeanInfo = new MBeanInfo(
                intf.getName(),
                intf.getName(),
                attrInfos,
                constructorInfos,
                operationInfos,
                notificationInfos,
                d);
        //debug( "MBeanInfoSupport.getMBeanInfo(): " + mbeanInfo );

        return (mbeanInfo);
    }

    public static void findInterfaceMethods(final Class<?> intf,
            final Map<String, Method> getters,
            final Map<String, Method> setters,
            final Map<String, Method> getterSetters,
            final Set<Method> operations) {
        final Method[] methods = intf.getMethods();

        for (final Method method : methods) {
            final String methodName = method.getName();

            final ManagedAttribute managedAttr = method.getAnnotation(ManagedAttribute.class);
            final ManagedOperation managedOp = method.getAnnotation(ManagedOperation.class);

            if (managedAttr != null) {
                String attrName = null;
                final int numArgs = method.getParameterTypes().length;
                if (managedOp != null) {
                    ImplUtil.getLogger().warning("MBeanInfoSupport:  @ManagedAttribute cannot also be @ManagedOperation: " + intf.getName() + "." + method.getName() + "()");
                } else if (numArgs == 0 && JMXUtil.isIsOrGetter(method)) {
                    attrName = JMXUtil.getAttributeName(method);
                    getters.put(attrName, method);
                    //debug( "findInterfaceMethods: getter: " + attrName );
                } else if (numArgs == 1 && JMXUtil.isSetter(method)) {
                    attrName = JMXUtil.getAttributeName(method);
                    setters.put(attrName, method);
                    //debug( "findInterfaceMethods: setter: " + attrName );
                } else {
                    ImplUtil.getLogger().warning("MBeanInfoSupport:  @ManagedAttribute not a getter or setter: " + intf.getName() + "." + method.getName() + "()");
                    // ignore
                }

                if ((attrName != null) &&
                        getters.containsKey(attrName) &&
                        setters.containsKey(attrName)) {
                    final Method getter = getters.get(attrName);
                    final Class<?> getterType = getter.getReturnType();
                    final Class<?> setterType = setters.get(attrName).getParameterTypes()[ 0];

                    if (getterType == setterType) {
                        getters.remove(attrName);
                        setters.remove(attrName);
                        getterSetters.put(attrName, getter);
                        //debug( "findInterfaceMethods: getter/setter: " + attrName );
                    } else {
                        throw new IllegalArgumentException("Attribute " + attrName +
                                "has type " + getterType.getName() + " as getter but type " +
                                setterType.getName() + " as setter");
                    }
                }
            } else if (managedOp != null) {
                operations.add(method);
            }
        }

        /*
        java.util.Iterator  iter  = null;
        trace( "-------------------- getterSetters -------------------" );
        iter  = getterSetters.values().iterator();
        while ( iter.hasNext() )
        {
        trace( ((Method)iter.next()).getNameProp() + ", " );
        }
        trace( "-------------------- getters -------------------" );
        iter  = getters.values().iterator();
        while ( iter.hasNext() )
        {
        trace( ((Method)iter.next()).getNameProp() + ", " );
        }
        trace( "-------------------- setters -------------------" );
        iter  = setters.values().iterator();
        while ( iter.hasNext() )
        {
        trace( ((Method)iter.next()).getNameProp() + ", " );
        }
         */
    }

    /**
     * Return MBeanAttributeInfo for the method.  If it's a getter,
     * it's marked as read-only, if it's a setter, it's marked as read/write.
     * @param m
     * @return
     */
    public static MBeanAttributeInfo attributeInfo(final Method m) {
        final ManagedAttribute managed = m.getAnnotation(ManagedAttribute.class);
        if (managed == null) {
            return null;
        }

        final String methodName = m.getName();

        final Description d = m.getAnnotation(Description.class);
        final String description = d == null ? "" : d.value();

        String attrName = JMXUtil.getAttributeName(m);
        final boolean isGetter = JMXUtil.isGetter(m);
        final boolean isSetter = JMXUtil.isSetter(m);
        final boolean isIs = JMXUtil.isIs(m);

        final MBeanAttributeInfo info =
                new MBeanAttributeInfo(attrName, m.getReturnType().getName(),
                description, isGetter, isSetter, isIs, null);

        return info;
    }

    public static Class<?> translatedType(final Class<?> clazz) {
        Class<?> type = clazz;
        if (AMXProxy.class.isAssignableFrom(clazz)) {
            type = ObjectName.class;
        } else if (clazz.isArray() && AMXProxy.class.isAssignableFrom(clazz.getComponentType())) {
            type = ObjectName[].class;
        }

        return type;
    }

    private static List<MBeanAttributeInfo> generateAttributeInfos(
            final Collection<Method> methods,
            final boolean read,
            final boolean write) {
        final List<MBeanAttributeInfo> infos = new ArrayList<MBeanAttributeInfo>();

        for (final Method m : methods) {
            final String methodName = m.getName();

            final String description = getDescription(m);

            String attrName = JMXUtil.getAttributeName(m);
            final boolean isIs = JMXUtil.isIs(m);

            // methods returning AMXProxy should return ObjectName
            Class<?> returnType = m.getReturnType();
            if (AMXProxy.class.isAssignableFrom(returnType)) {
                returnType = ObjectName.class;
            }

            final MBeanAttributeInfo info = new MBeanAttributeInfo(
                    attrName,
                    translatedType(m.getReturnType()).getName(),
                    description,
                    read,
                    write,
                    JMXUtil.isIs(m));
            infos.add(info);
            //debug( "Added MBeanAttributeInfo for: " + attrName );
        }

        return (infos);
    }

    public static List<MBeanAttributeInfo> generateMBeanAttributeInfos(
            final Collection<Method> getterSetters,
            final Collection<Method> getters,
            final Collection<Method> setters) {
        final List<MBeanAttributeInfo> attrsList = new ArrayList<MBeanAttributeInfo>();

        attrsList.addAll(generateAttributeInfos(getterSetters, true, true));
        attrsList.addAll(generateAttributeInfos(getters, true, false));
        attrsList.addAll(generateAttributeInfos(setters, false, true));

        return (attrsList);
    }

    public static <T extends Annotation> T getAnnotation(final Annotation[] annotations, final Class<T> clazz) {
        T result = null;

        for (final Annotation a : annotations) {
            if (a.annotationType() == clazz) {
                result = (T) a;
                break;
            }
        }
        return result;
    }

    private static String getDescription(final AnnotatedElement o) {
        final Description d = o.getAnnotation(Description.class);
        return d == null ? "" : d.value();
    }

    public static MBeanParameterInfo[] parameterInfos(final Method method) {
        final Class<?>[] sig = method.getParameterTypes();
        final Annotation[][] paramAnnotations = method.getParameterAnnotations();

        final MBeanParameterInfo[] infos = new MBeanParameterInfo[sig.length];

        for (int i = 0; i < sig.length; ++i) {
            final Class<?> paramClass = translatedType(sig[i]);
            final Annotation[] annotations = paramAnnotations[i];

            final Param p = getAnnotation(annotations, Param.class);
            final String paramName = (p == null || p.name().length() == 0) ? ("p" + i) : p.name();

            final Description d = getAnnotation(annotations, Description.class);
            String description = "";
            if (d != null && d.value().length() != 0) {
                description = d.value();
            }

            final String type = paramClass.getName();

            final MBeanParameterInfo info = new MBeanParameterInfo(paramName, type, description);
            infos[i] = info;
        }

        return (infos);
    }

    public static MBeanOperationInfo[] generateMBeanOperationInfos(final Collection<Method> methods) {
        final MBeanOperationInfo[] infos = new MBeanOperationInfo[methods.size()];

        int i = 0;
        for (final Method m : methods) {
            final ManagedOperation managed = m.getAnnotation(ManagedOperation.class);

            final String methodName = m.getName();
            final MBeanParameterInfo[] parameterInfos = parameterInfos(m);
            final int impact = managed == null ? MBeanOperationInfo.UNKNOWN : managed.impact();
            final String description = getDescription(m);
            final Descriptor descriptor = null;

            final MBeanOperationInfo info = new MBeanOperationInfo(
                    methodName,
                    description,
                    parameterInfos,
                    translatedType(m.getReturnType()).getName(),
                    impact,
                    descriptor);

            infos[i] = info;
            ++i;

        }

        return (infos);
    }

    public static DescriptorSupport mbeanDescriptor(
            final boolean immutable,
            final Class<?> intf,
            final boolean singleton,
            final boolean globalSingleton,
            final String group,
            final boolean supportsAdoption,
            final String[] subTypes) {
        final DescriptorSupport desc = new DescriptorSupport();

        if (intf == null || !intf.isInterface()) {
            throw new IllegalArgumentException("interface class must be an interface");
        }

        desc.setField(DESC_STD_IMMUTABLE_INFO, immutable);
        desc.setField(DESC_STD_INTERFACE_NAME, intf.getName());
        desc.setField(DESC_IS_SINGLETON, singleton);
        desc.setField(DESC_IS_GLOBAL_SINGLETON, globalSingleton);
        desc.setField(DESC_GROUP, group);
        desc.setField(DESC_SUPPORTS_ADOPTION, supportsAdoption);

        if (subTypes != null) {
            desc.setField(DESC_SUB_TYPES, subTypes);
        }

        return desc;
    }
}

TOP

Related Classes of org.glassfish.admin.amx.impl.util.MBeanInfoSupport

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.