001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.activemq.console.filter;
018    
019    import java.io.IOException;
020    import java.util.ArrayList;
021    import java.util.Collection;
022    import java.util.Iterator;
023    import java.util.List;
024    import java.util.Set;
025    
026    import javax.management.Attribute;
027    import javax.management.AttributeList;
028    import javax.management.InstanceNotFoundException;
029    import javax.management.IntrospectionException;
030    import javax.management.MBeanAttributeInfo;
031    import javax.management.MBeanServerConnection;
032    import javax.management.ObjectInstance;
033    import javax.management.ObjectName;
034    import javax.management.ReflectionException;
035    import javax.management.remote.JMXConnector;
036    import javax.management.remote.JMXConnectorFactory;
037    import javax.management.remote.JMXServiceURL;
038    
039    public class MBeansAttributeQueryFilter extends AbstractQueryFilter {
040        public static final String KEY_OBJECT_NAME_ATTRIBUTE = "Attribute:ObjectName:";
041    
042        private JMXServiceURL jmxServiceUrl;
043        private Set attribView;
044    
045        /**
046         * Create an mbean attributes query filter that is able to select specific
047         * mbean attributes based on the object name to get.
048         * 
049         * @param jmxServiceUrl - JMX service url to connect to.
050         * @param attribView - the attributes to extract
051         * @param next - the next query filter
052         */
053        public MBeansAttributeQueryFilter(JMXServiceURL jmxServiceUrl, Set attribView, MBeansObjectNameQueryFilter next) {
054            super(next);
055            this.jmxServiceUrl = jmxServiceUrl;
056            this.attribView = attribView;
057        }
058    
059        /**
060         * Filter the query by retrieving the attributes specified, this will modify
061         * the collection to a list of AttributeList
062         * 
063         * @param queries - query list
064         * @return List of AttributeList, which includes the ObjectName, which has a
065         *         key of MBeansAttributeQueryFilter.KEY_OBJECT_NAME_ATTRIBUTE
066         * @throws Exception
067         */
068        public List query(List queries) throws Exception {
069            return getMBeanAttributesCollection(next.query(queries));
070        }
071    
072        /**
073         * Retrieve the specified attributes of the mbean
074         * 
075         * @param result - collection of ObjectInstances and/or ObjectNames
076         * @return List of AttributeList
077         * @throws IOException
078         * @throws ReflectionException
079         * @throws InstanceNotFoundException
080         * @throws NoSuchMethodException
081         */
082        protected List getMBeanAttributesCollection(Collection result) throws IOException, ReflectionException, InstanceNotFoundException, NoSuchMethodException, IntrospectionException {
083            List mbeansCollection = new ArrayList();
084    
085            for (Iterator i = result.iterator(); i.hasNext();) {
086                Object mbean = i.next();
087                if (mbean instanceof ObjectInstance) {
088                    mbeansCollection.add(getMBeanAttributes(((ObjectInstance)mbean).getObjectName(), attribView));
089                } else if (mbean instanceof ObjectName) {
090                    mbeansCollection.add(getMBeanAttributes((ObjectName)mbean, attribView));
091                } else {
092                    throw new NoSuchMethodException("Cannot get the mbean attributes for class: " + mbean.getClass().getName());
093                }
094            }
095    
096            return mbeansCollection;
097        }
098    
099        /**
100         * Retrieve the specified attributes of the mbean
101         * 
102         * @param obj - mbean ObjectInstance
103         * @param attrView - list of attributes to retrieve
104         * @return AttributeList for the mbean
105         * @throws ReflectionException
106         * @throws InstanceNotFoundException
107         * @throws IOException
108         */
109        protected AttributeList getMBeanAttributes(ObjectInstance obj, Set attrView) throws ReflectionException, InstanceNotFoundException, IOException, IntrospectionException {
110            return getMBeanAttributes(obj.getObjectName(), attrView);
111        }
112    
113        /**
114         * Retrieve the specified attributes of the mbean
115         * 
116         * @param objName - mbean ObjectName
117         * @param attrView - list of attributes to retrieve
118         * @return AttributeList for the mbean
119         * @throws IOException
120         * @throws ReflectionException
121         * @throws InstanceNotFoundException
122         */
123        protected AttributeList getMBeanAttributes(ObjectName objName, Set attrView) throws IOException, ReflectionException, InstanceNotFoundException, IntrospectionException {
124            JMXConnector jmxConnector = JMXConnectorFactory.connect(jmxServiceUrl);
125            MBeanServerConnection server = jmxConnector.getMBeanServerConnection();
126    
127            // If no attribute view specified, get all attributes
128            String[] attribs;
129            if (attrView == null || attrView.isEmpty()) {
130                MBeanAttributeInfo[] infos = server.getMBeanInfo(objName).getAttributes();
131                attribs = new String[infos.length];
132    
133                for (int i = 0; i < infos.length; i++) {
134                    if (infos[i].isReadable()) {
135                        attribs[i] = infos[i].getName();
136                    }
137                }
138    
139                // Get selected attributes
140            } else {
141    
142                attribs = new String[attrView.size()];
143                int count = 0;
144                for (Iterator i = attrView.iterator(); i.hasNext();) {
145                    attribs[count++] = (String)i.next();
146                }
147            }
148    
149            AttributeList attribList = server.getAttributes(objName, attribs);
150    
151            jmxConnector.close();
152    
153            attribList.add(0, new Attribute(KEY_OBJECT_NAME_ATTRIBUTE, objName));
154    
155            return attribList;
156        }
157    }