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 */
017package org.apache.activemq.console.filter;
018
019import java.lang.reflect.Method;
020import java.util.Iterator;
021import java.util.Map;
022import java.util.regex.Pattern;
023
024import javax.management.Attribute;
025import javax.management.AttributeList;
026import javax.management.ObjectInstance;
027import javax.management.ObjectName;
028
029public 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}