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.lang.reflect.Method;
020    import java.util.Iterator;
021    import java.util.Map;
022    import java.util.regex.Pattern;
023    
024    import javax.management.Attribute;
025    import javax.management.AttributeList;
026    import javax.management.ObjectInstance;
027    import javax.management.ObjectName;
028    
029    public class MBeansRegExQueryFilter extends RegExQueryFilter {
030        /**
031         * Creates a regular expression query that is able to match the values of
032         * specific mbeans
033         * 
034         * @param next - next query filter
035         */
036        public MBeansRegExQueryFilter(QueryFilter next) {
037            super(next);
038        }
039    
040        /**
041         * Try to match the object data using the regular expression map. The regex
042         * map contains a key-value mapping of an attribute key to a regular
043         * expression the value of the key should match. The basic rule of matching
044         * is that the data must contain a property key that is included in the
045         * regex map, and that the value of the property key should match the regex
046         * specified.
047         * 
048         * @param data - object data to match
049         * @param regex - regex map
050         * @return true if the data matches the regex map specified
051         * @throws Exception
052         */
053        protected boolean matches(Object data, Map regex) throws Exception {
054            // TODO why not just use instanceof?
055    
056            // Use reflection to determine where the object should go
057            try {
058                Method method = this.getClass().getDeclaredMethod("matches", new Class[] {
059                    data.getClass(), Map.class
060                });
061                return ((Boolean)method.invoke(this, new Object[] {
062                    data, regex
063                })).booleanValue();
064            } catch (NoSuchMethodException e) {
065                return false;
066            }
067        }
068    
069        /**
070         * Try to match the object instance using the regular expression map
071         * 
072         * @param data - object instance to match
073         * @param regex - regex map
074         * @return true if the object instance matches the regex map
075         */
076        protected boolean matches(ObjectInstance data, Map regex) {
077            return matches(data.getObjectName(), regex);
078        }
079    
080        /**
081         * Try to match the object name instance using the regular expression map
082         * 
083         * @param data - object name to match
084         * @param regex - regex map
085         * @return true if the object name matches the regex map
086         */
087        protected boolean matches(ObjectName data, Map regex) {
088            for (Iterator i = regex.keySet().iterator(); i.hasNext();) {
089                String key = (String)i.next();
090                String target = data.getKeyProperty(key);
091    
092                // Try to match the value of the property of the object name
093                if (target != null && !((Pattern)regex.get(key)).matcher(target).matches()) {
094                    return false;
095                }
096            }
097            return true;
098        }
099    
100        /**
101         * Try to match the attribute list using the regular expression map
102         * 
103         * @param data - attribute list to match
104         * @param regex - regex map
105         * @return true if the attribute list matches the regex map
106         */
107        protected boolean matches(AttributeList data, Map regex) {
108            for (Iterator i = regex.keySet().iterator(); i.hasNext();) {
109                String key = (String)i.next();
110    
111                // Try to match each regex to the attributes of the mbean including
112                // its ObjectName
113                for (Iterator j = data.iterator(); j.hasNext();) {
114                    Attribute attrib = (Attribute)j.next();
115    
116                    // Try to match to the properties of the ObjectName
117                    if (attrib.getName().equals(MBeansAttributeQueryFilter.KEY_OBJECT_NAME_ATTRIBUTE)) {
118                        String target = ((ObjectName)attrib.getValue()).getKeyProperty(key);
119    
120                        if (target == null || !((Pattern)regex.get(key)).matcher(target).matches()) {
121                            return false;
122                        } else {
123                            // If match skip to the next regex
124                            break;
125                        }
126    
127                        // Try to match to the mbean attributes
128                    } else if (attrib.getName().equals(key)) {
129                        if (!((Pattern)regex.get(key)).matcher(attrib.getValue().toString()).matches()) {
130                            return false;
131                        } else {
132                            // If match skip to the next regex
133                            break;
134                        }
135    
136                        // If mbean does not contain the specified attribute
137                    } else {
138                        return false;
139                    }
140                }
141            }
142            return true;
143        }
144    }