/* Query.java -- Static methods for query construction. Copyright (C) 2007 Free Software Foundation, Inc. This file is part of GNU Classpath. GNU Classpath is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Classpath is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Classpath; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Linking this library statically or dynamically with other modules is making a combined work based on this library. Thus, the terms and conditions of the GNU General Public License cover the whole combination. As a special exception, the copyright holders of this library give you permission to link this library with independent modules to produce an executable, regardless of the license terms of these independent modules, and to copy and distribute the resulting executable under terms of your choice, provided that you also meet, for each linked independent module, the terms and conditions of the license of that module. An independent module is a module which is not derived from or based on this library. If you modify this library, you may extend this exception to your version of the library, but you are not obligated to do so. If you do not wish to do so, delete this exception statement from your version. */ package javax.management; /** * Provides static methods for constructing queries. Queries * may be used to list and enumerate management beans, via * the {@link MBeanServer}. By using the methods in this class, * complex queries can be created from their more basic * components. * * @author Andrew John Hughes (gnu_andrew@member.fsf.org) * @since 1.5 */ public class Query { /** * A code representing the {@link #plus(ValueExp, ValueExp) * query to be used in serialization. */ public static final int PLUS = 0; /** * A code representing the {@link #minus(ValueExp, ValueExp) * query to be used in serialization. */ public static final int MINUS = 1; /** * A code representing the {@link #times(ValueExp, ValueExp) * query to be used in serialization. */ public static final int TIMES = 2; /** * A code representing the {@link #div(ValueExp, ValueExp) * query to be used in serialization. */ public static final int DIV = 3; /** * A code representing the {@link #gt(ValueExp, ValueExp) * query to be used in serialization. */ public static final int GT = 0; /** * A code representing the {@link #lt(ValueExp, ValueExp) * query to be used in serialization. */ public static final int LT = 1; /** * A code representing the {@link #ge(ValueExp, ValueExp) * query to be used in serialization. */ public static final int GE = 2; /** * A code representing the {@link #le(ValueExp, ValueExp) * query to be used in serialization. */ public static final int LE = 3; /** * A code representing the {@link #eq(ValueExp, ValueExp) * query to be used in serialization. */ public static final int EQ = 4; /** * Returns a query expression formed from the conjunction * of the two supplied query expressions. * * @param q1 the first query expression. * @param q2 the second query expression. * @return a query expression representing q1 && q2. This * will be serialized as the non-public class * {@link AndQueryExp}. */ public static QueryExp and(QueryExp q1, QueryExp q2) { return new AndQueryExp(q1, q2); } /** * Returns a query expression which checks that an * attribute value held by the specified * {@link AttributeValueExp} contains the string * specified by the given {@link StringValueExp}. * * @param attrib the attribute to match. * @param string the substring to find. * @return a query expression representing * <code>attrib.matches("*" + string + "*")</code>. * This will be serialized as the non-public class * {@link MatchQueryExp}. */ public static QueryExp anySubString(AttributeValueExp attrib, StringValueExp string) { return new MatchQueryExp(attrib, "*" + string.getValue() + "*"); } /** * Returns a value expression for the value of the * named attribute. Evaluating this using an * {@link ObjectName} involves an underlying call * to {@link MBeanServer#getAttribute(ObjectName,String)}. * * @param name the name of the attribute. * @return a value expression which returns the value * of the named attribute when applied. */ public static AttributeValueExp attr(String name) { return new AttributeValueExp(name); } /** * Returns a value expression for the value of the * named attribute from the specified class. Evaluating * this using an {@link ObjectName} involves an underlying call * to both {@link MBeanServer#getObjectInstance(ObjectName)} and * {@link MBeanServer#getAttribute(ObjectName,String)}. * * @param className the class containing the attribute. * @param name the name of the attribute. * @return a value expression which returns the value * of the named attribute when applied. * This will be serialized as the non-public class * {@link QualifiedAttributeValueExp}. */ public static AttributeValueExp attr(String className, String name) { return new QualifiedAttributeValueExp(className, name); } /** * Returns a query expression representing the constraint * that the value, <code>v1</code>, lies between <code>v2</code> * and <code>v3</code>. * * @param v1 the value to compare against the boundaries. * @param v2 the lower boundary. * @param v3 the upper boundary. * @return a query expression representing a comparison * of <code>v1</code> against <code>v2</code> * and <code>v3</code>. It returns true if * <code>v2 <= v1 <= v3</code>. This * will be serialized as the non-public class * {@link BetweenQueryExp}. */ public static QueryExp between(ValueExp v1, ValueExp v2, ValueExp v3) { return new BetweenQueryExp(v1, v2, v3); } /** * Returns a value expression which evaluates to the name of * the class of the bean when applied. Associating the expression * with an {@link ObjectName} involves an underlying call * to both {@link MBeanServer#getObjectInstance(ObjectName)} * to obtain this information. * * @return a value expression which returns the class name * of the bean to which it is applied. * This will be serialized as the non-public class * {@link ClassAttributeValueExp}. */ public static AttributeValueExp classattr() { return new ClassAttributeValueExp(); } /** * Returns a value expression which evaluates to the result of * dividing <code>v1</code> by <code>v2</code>. * * @param v1 the left-hand operand. * @param v2 the right-hand operand. * @return a value expression which returns the result of * the division when applied. This will be serialized * as the non-public class {@link BinaryOpValueExp} * with an operation of {@link #DIV}. */ public static ValueExp div(ValueExp v1, ValueExp v2) { return new BinaryOpValueExp(DIV, v1, v2); } /** * Returns a query expression which evaluates to the result of * comparing <code>v1</code> to <code>v2</code> for equality. * * @param v1 the left-hand operand. * @param v2 the right-hand operand. * @return a value expression which returns the result of * the comparison when applied. This will be serialized * as the non-public class {@link BinaryRelQueryExp} * with an operation of {@link #EQ}. */ public static QueryExp eq(ValueExp v1, ValueExp v2) { return new BinaryRelQueryExp(EQ, v1, v2); } /** * Returns a query expression which checks that an * attribute value held by the specified * {@link AttributeValueExp} ends with the string * specified by the given {@link StringValueExp}. * * @param attrib the attribute to match. * @param string the substring to find. * @return a query expression representing * <code>attrib.matches("*" + string)</code>. * This will be serialized as the non-public class * {@link MatchQueryExp}. */ public static QueryExp finalSubString(AttributeValueExp attrib, StringValueExp string) { return new MatchQueryExp(attrib, "*" + string.getValue()); } /** * Returns a query expression which evaluates to the result of * comparing <code>v1</code> to <code>v2</code> to see if * <code>v1</code> is greater than or equal to <code>v2</code>. * * @param v1 the left-hand operand. * @param v2 the right-hand operand. * @return a value expression which returns the result of * the comparison when applied. This will be serialized * as the non-public class {@link BinaryRelQueryExp} * with an operation of {@link #GE}. */ public static QueryExp geq(ValueExp v1, ValueExp v2) { return new BinaryRelQueryExp(GE, v1, v2); } /** * Returns a query expression which evaluates to the result of * comparing <code>v1</code> to <code>v2</code> to see if * <code>v1</code> is greater than <code>v2</code>. * * @param v1 the left-hand operand. * @param v2 the right-hand operand. * @return a value expression which returns the result of * the comparison when applied. This will be serialized * as the non-public class {@link BinaryRelQueryExp} * with an operation of {@link #GT}. */ public static QueryExp gt(ValueExp v1, ValueExp v2) { return new BinaryRelQueryExp(GT, v1, v2); } /** * Returns a query expression representing the constraint * that the value, <code>v</code>, is a member of the * list, <code>vlist</code>. * * @param v the value to look for in the list. * @param vlist the list of allowed values. * @return a query expression representing a membership check * of <code>v</code> against the list, <code>vlist</code>. * This will be serialized as the non-public class * {@link InQueryExp}. */ public static QueryExp in(ValueExp v, ValueExp[] vlist) { return new InQueryExp(v, vlist); } /** * Returns a query expression which checks that an * attribute value held by the specified * {@link AttributeValueExp} starts with the string * specified by the given {@link StringValueExp}. * * @param attrib the attribute to match. * @param string the substring to find. * @return a query expression representing * <code>attrib.matches(string + "*")</code>. * This will be serialized as the non-public class * {@link MatchQueryExp}. */ public static QueryExp initialSubString(AttributeValueExp attrib, StringValueExp string) { return new MatchQueryExp(attrib, string.getValue() + "*"); } /** * Returns a query expression which checks that a * bean is an instance of the class specified * by the given {@link StringValueExp}. Associating the * expression with an {@link ObjectName} involves an underlying * call to {@link MBeanServer#isInstanceOf(ObjectName, String)} * using the value of <code>((StringValueExp) * className.apply(objectName)).getValue()</code> as the * class name. * * @param className the name of the class which the bean * should be an instance of. * @return a query expression representing * the inheritance check. This will be serialized * as the non-public class {@link InstanceOfQueryExp}. * @since 1.6 */ public static QueryExp isInstanceOf(StringValueExp className) { return new InstanceOfQueryExp(className); } /** * Returns a query expression which evaluates to the result of * comparing <code>v1</code> to <code>v2</code> to see if * <code>v1</code> is less than or equal to <code>v2</code>. * * @param v1 the left-hand operand. * @param v2 the right-hand operand. * @return a value expression which returns the result of * the comparison when applied. This will be serialized * as the non-public class {@link BinaryRelQueryExp} * with an operation of {@link #LE}. */ public static QueryExp leq(ValueExp v1, ValueExp v2) { return new BinaryRelQueryExp(LE, v1, v2); } /** * Returns a query expression which evaluates to the result of * comparing <code>v1</code> to <code>v2</code> to see if * <code>v1</code> is less than <code>v2</code>. * * @param v1 the left-hand operand. * @param v2 the right-hand operand. * @return a value expression which returns the result of * the comparison when applied. This will be serialized * as the non-public class {@link BinaryRelQueryExp} * with an operation of {@link #LT}. */ public static QueryExp lt(ValueExp v1, ValueExp v2) { return new BinaryRelQueryExp(LT, v1, v2); } /** * <p> * Returns a query expression which checks that an * attribute value matches the pattern * specified by the given {@link StringValueExp}. * The pattern uses file-globbing syntax: * </p> * <ul> * <li>'*' stands for any number of arbitrary characters.</li> * <li>'?' stands for a single arbitrary characters.</li> * <li>An expression within '[' and ']' specify a character * class.</li> * <ul> * <li>A range of characters can be specified by separating * the start and end character with '-'.</li> * <li>The complement of the class can be obtained by using * '!' as the first character of the class.</li> * <li>'?', '*' and '[' can occur freely within the class. '-' * may occur as the first or last character. '!' may occur * normally in any position other than the first. ']' may occur * as the first element of the class.</li> * </ul> * <li>'?', '*' and '[' may be escaped using a backslash * character, '\'.</li> * </ul> * * @param attrib the attribute to match. * @param string the substring to find. * @return a query expression representing the result of * matching the pattern against the evaluated * value of the attribute. This will be serialized * as the non-public class {@link MatchQueryExp}. */ public static QueryExp match(AttributeValueExp attrib, StringValueExp string) { return new MatchQueryExp(attrib, string.getValue()); } /** * Returns a value expression which evaluates to the result of * subtracting <code>v2</code> from <code>v1</code>. * * @param v1 the left-hand operand. * @param v2 the right-hand operand. * @return a value expression which returns the result of * the subtraction when applied. This will be serialized * as the non-public class {@link BinaryOpValueExp} * with an operation of {@link #MINUS}. */ public static ValueExp minus(ValueExp v1, ValueExp v2) { return new BinaryOpValueExp(MINUS, v1, v2); } /** * Returns a query expression representing the negation * of the specified query expression. * * @param q the query to negate. * @return a query expression representing the negation of * <code>q</code>. This will be serialized as the * non-public class {@link NotQueryExp}. */ public static QueryExp not(QueryExp q) { return new NotQueryExp(q); } /** * Returns a query expression formed from the disjunction * of the two supplied query expressions. * * @param q1 the first query expression. * @param q2 the second query expression. * @return a query expression representing q1 || q2. This * will be serialized as the non-public class * {@link OrQueryExp}. */ public static QueryExp or(QueryExp q1, QueryExp q2) { return new OrQueryExp(q1, q2); } /** * Returns a value expression which evaluates to the result of * adding <code>v1</code> to <code>v2</code>. * * @param v1 the left-hand operand. * @param v2 the right-hand operand. * @return a value expression which returns the result of * the addition when applied. This will be serialized * as the non-public class {@link BinaryOpValueExp} * with an operation of {@link #PLUS}. */ public static ValueExp plus(ValueExp v1, ValueExp v2) { return new BinaryOpValueExp(PLUS, v1, v2); } /** * Returns a value expression which evaluates to the result of * multiplying <code>v1</code> by <code>v2</code>. * * @param v1 the left-hand operand. * @param v2 the right-hand operand. * @return a value expression which returns the result of * the multiplication when applied. This will be serialized * as the non-public class {@link BinaryOpValueExp} * with an operation of {@link #TIMES}. */ public static ValueExp times(ValueExp v1, ValueExp v2) { return new BinaryOpValueExp(TIMES, v1, v2); } /** * Returns a value expression wrapping the specified value. * * @param val the boolean value to wrap. * @return a value expression wrapping <code>val</code>. This * will be serialized as the non-public class * {@link BooleanValueExp}. */ public static ValueExp value(boolean val) { return new BooleanValueExp(val); } /** * Returns a value expression wrapping the specified value. * * @param val the double value to wrap. * @return a value expression wrapping <code>val</code>. This * will be serialized as the non-public class * {@link NumericValueExp}. */ public static ValueExp value(double val) { return new NumericValueExp(val); } /** * Returns a value expression wrapping the specified value. * * @param val the float value to wrap. * @return a value expression wrapping <code>val</code>. This * will be serialized as the non-public class * {@link NumericValueExp}. */ public static ValueExp value(float val) { return new NumericValueExp(val); } /** * Returns a value expression wrapping the specified value. * * @param val the integer value to wrap. * @return a value expression wrapping <code>val</code>. This * will be serialized as the non-public class * {@link NumericValueExp}. */ public static ValueExp value(int val) { return new NumericValueExp(val); } /** * Returns a value expression wrapping the specified value. * * @param val the long value to wrap. * @return a value expression wrapping <code>val</code>. This * will be serialized as the non-public class * {@link NumericValueExp}. */ public static ValueExp value(long val) { return new NumericValueExp(val); } /** * Returns a value expression wrapping the specified value. * * @param val the {@link Number} value to wrap. * @return a value expression wrapping <code>val</code>. This * will be serialized as the non-public class * {@link NumericValueExp}. */ public static ValueExp value(Number val) { return new NumericValueExp(val); } /** * Returns a value expression wrapping the specified string. * * @param val the {@link String} to wrap. * @return a {@link StringValueExp} wrapping <code>val</code>. */ public static StringValueExp value(String val) { return new StringValueExp(val); } /** * Representation of the conjunction formed using * {@link #and(QueryExp, QueryExp). * * @author Andrew John Hughes (gnu_andrew@member.fsf.org) * @since 1.5 */ private static final class AndQueryExp extends QueryEval implements QueryExp { /** * Compatible with JDK 1.6 */ private static final long serialVersionUID = -1081892073854801359L; /** * The first operand. */ private QueryExp exp1; /** * The second operand. */ private QueryExp exp2; /** * Constructs a new {@link AndQueryExp} using * the two specified operands. * * @param exp1 the first query expression. * @param exp2 the second query expression. */ public AndQueryExp(QueryExp exp1, QueryExp exp2) { this.exp1 = exp1; this.exp2 = exp2; } /** * Returns the conjunction of the two query * expressions. * * @param name the {@link ObjectName} to apply * the query to. * @return the conjunction of applying the name * to both operands. * @throws BadStringOperationException if an invalid string * operation is used by * the query. * @throws BadBinaryOpValueExpException if an invalid expression * is used by the query. * @throws BadAttributeValueExpException if an invalid attribute * is used by the query. * @throws InvalidApplicationException if the query is applied * to the wrong type of bean. */ public boolean apply(ObjectName name) throws BadStringOperationException, BadBinaryOpValueExpException, BadAttributeValueExpException, InvalidApplicationException { return exp1.apply(name) && exp2.apply(name); } } /** * Representation of a query that matches an * attribute's value against a given pattern. * * @author Andrew John Hughes (gnu_andrew@member.fsf.org) * @since 1.5 */ private static final class MatchQueryExp extends QueryEval implements QueryExp { /** * Compatible with JDK 1.6 */ private static final long serialVersionUID = -7156603696948215014L; /** * The attribute to match against. */ private AttributeValueExp exp; /** * The pattern to be matched. */ private String pattern; /** * Constructs a new {@link MatchQueryExp} using * the specified attribute value and pattern. * * @param exp the attribute value expression. * @param pattern the pattern. */ public MatchQueryExp(AttributeValueExp exp, String pattern) { this.exp = exp; this.pattern = pattern; } /** * Returns the result of matching the attribute * value against the pattern. * * @param name the {@link ObjectName} to apply * the query to. * @return the result of the match. * @throws BadStringOperationException if an invalid string * operation is used by * the query. * @throws BadBinaryOpValueExpException if an invalid expression * is used by the query. * @throws BadAttributeValueExpException if an invalid attribute * is used by the query. * @throws InvalidApplicationException if the query is applied * to the wrong type of bean. */ public boolean apply(ObjectName name) throws BadStringOperationException, BadBinaryOpValueExpException, BadAttributeValueExpException, InvalidApplicationException { String val = ((StringValueExp) exp.apply(name)).getValue(); int valPos = 0; int fallback = -1; int fallbackP = -1; boolean backslash = false; for (int a = 0; a < pattern.length(); ++a) { boolean matched = false; int next = pattern.codePointAt(a); if (!backslash) { if (next == '?' && valPos < val.length()) { ++valPos; matched = true; } else if (next == '*') { fallback = valPos; fallbackP = a; matched = true; } else if (next == '[' && valPos < val.length()) { boolean negated = false; int b = a + 1; int classChar = pattern.codePointAt(b); do { if (classChar == '!' && b == a + 1) negated = true; else if (pattern.codePointAt(b + 1) == '-' && pattern.codePointAt(b + 2) != ']') { if (classChar > pattern.codePointAt(b + 2)) throw new BadStringOperationException("Invalid range: " + classChar + " to " + pattern.codePointAt(b+2)); for (int c = classChar; c <= pattern.codePointAt(b+2); ++c) if (val.codePointAt(valPos) == c) matched = true; b = b + 2; } else if (val.codePointAt(valPos) == classChar) matched = true; ++b; classChar = pattern.codePointAt(b); } while (classChar != ']'); if (negated) matched = !matched; ++valPos; a = b; } else if (next == '\\') backslash = true; else if (valPos < val.length() && next == val.codePointAt(valPos)) { matched = true; ++valPos; } } else { backslash = false; if (valPos < val.length() && next == val.codePointAt(valPos)) { matched = true; ++valPos; } } if (!matched) if (fallback != -1) { ++fallback; valPos = fallback; a = fallbackP; if (valPos == val.length()) return false; continue; } else return false; } return true; } } /** * Representation of the retrieval of an attribute * value from a certain class for {@link #attr(String,String)}. * * @author Andrew John Hughes (gnu_andrew@member.fsf.org) * @since 1.5 */ private static final class QualifiedAttributeValueExp extends AttributeValueExp { /** * Compatible with JDK 1.6 */ private static final long serialVersionUID = 8832517277410933254L; /** * The name of the class from which the attribute is taken. */ private String className; /** * Constructs a new {@link QualifiedAttributeValueExp} using * the specified class name and attribute name. * * @param className the class name. * @param name the attribute name. */ public QualifiedAttributeValueExp(String className, String name) { super(name); this.className = className; } /** * Applies the {@link AttributeValueExp} to the specified * management bean by checking that the attribute will be * obtained from the correct class (by a class to * {@link MBeanServer#getObjectInstance(ObjectName)} and * then obtaining the attribute value from the * {@link MBeanServer}, using it to create a * {@link StringValueExp}. * * @param name the {@link ObjectName} of the bean to obtain * the value from. * @return a {@link StringValueExp} containing the result. * @throws BadStringOperationException if an invalid string * operation is used by * the value expression. * @throws BadBinaryOpValueExpException if an invalid expression * is used by the value expression. * @throws BadAttributeValueExpException if an invalid attribute * is used by the value expression. * @throws InvalidApplicationException if the value expression is applied * to the wrong type of bean. */ public ValueExp apply(ObjectName name) throws BadStringOperationException, BadBinaryOpValueExpException, BadAttributeValueExpException, InvalidApplicationException { try { if (!(QueryEval.getMBeanServer().getObjectInstance(name).getClassName().equals(className))) throw new BadAttributeValueExpException("The value is not from " + "the correct class."); } catch (InstanceNotFoundException e) { throw (BadAttributeValueExpException) new BadAttributeValueExpException("The named bean is not registered.").initCause(e); } return super.apply(name); } } /** * Representation of the comparison of a value with * a pair of bounds formed using * {@link #between(ValueExp, ValueExp, ValueExp). * * @author Andrew John Hughes (gnu_andrew@member.fsf.org) * @since 1.5 */ private static final class BetweenQueryExp extends QueryEval implements QueryExp { /** * Compatible with JDK 1.6 */ private static final long serialVersionUID = -2933597532866307444L; /** * The value to compare. */ private ValueExp exp1; /** * The lower boundary. */ private ValueExp exp2; /** * The upper boundary. */ private ValueExp exp3; /** * Constructs a new {@link BetweenQueryExp} using * the specified comparison value and the given * bounds. * * @param exp1 the value to compare. * @param exp2 the lower bound. * @param exp3 the upper bound. */ public BetweenQueryExp(ValueExp exp1, ValueExp exp2, ValueExp exp3) { this.exp1 = exp1; this.exp2 = exp2; this.exp3 = exp3; } /** * Returns the result of the comparison between * the value and the two bounds. * * @param name the {@link ObjectName} to apply * the query to. * @return the result of the comparison. * @throws BadStringOperationException if an invalid string * operation is used by * the query. * @throws BadBinaryOpValueExpException if an invalid expression * is used by the query. * @throws BadAttributeValueExpException if an invalid attribute * is used by the query. * @throws InvalidApplicationException if the query is applied * to the wrong type of bean. */ public boolean apply(ObjectName name) throws BadStringOperationException, BadBinaryOpValueExpException, BadAttributeValueExpException, InvalidApplicationException { String v1 = exp1.apply(name).toString(); String v2 = exp2.apply(name).toString(); String v3 = exp3.apply(name).toString(); return v1.compareTo(v2) >= 0 && v1.compareTo(v3) <= 0; } } /** * Representation of the retrieval of the name of * a bean's class for {@link #classattr()}. * * @author Andrew John Hughes (gnu_andrew@member.fsf.org) * @since 1.5 */ private static final class ClassAttributeValueExp extends AttributeValueExp { /** * Compatible with JDK 1.6 */ private static final long serialVersionUID = -1081892073854801359L; /** * Obtains the name of the specified bean's class using a call * to {@link MBeanServer#getObjectInstance(ObjectName)}. * * @param name the {@link ObjectName} of the bean to obtain * the class name from. * @return a {@link StringValueExp} containing the result. * @throws BadStringOperationException if an invalid string * operation is used by * the value expression. * @throws BadBinaryOpValueExpException if an invalid expression * is used by the value expression. * @throws BadAttributeValueExpException if an invalid attribute * is used by the value expression. * @throws InvalidApplicationException if the value expression is applied * to the wrong type of bean. */ public ValueExp apply(ObjectName name) throws BadStringOperationException, BadBinaryOpValueExpException, BadAttributeValueExpException, InvalidApplicationException { try { return new StringValueExp(QueryEval.getMBeanServer().getObjectInstance(name).getClassName()); } catch (InstanceNotFoundException e) { throw (BadAttributeValueExpException) new BadAttributeValueExpException("The named bean is not registered.").initCause(e); } } } /** * Representation of a binary operation formed using * {@link #div(ValueExp, ValueExp), {@link #plus(ValueExp,ValueExp)}, * {@link #minus(ValueExp, ValueExp) or * {@link #times(ValueExp, ValueExp)}. * * @author Andrew John Hughes (gnu_andrew@member.fsf.org) * @since 1.5 */ private static final class BinaryOpValueExp extends QueryEval implements ValueExp { /** * Compatible with JDK 1.6 */ private static final long serialVersionUID = 1216286847881456786L; /** * The operation to perform. */ private int op; /** * The left-hand operand. */ private ValueExp exp1; /** * The right-hand operand. */ private ValueExp exp2; /** * Constructs a new {@link BinaryOpValueExp} using * the specified operation and the two values supplied. * * @param op the operation to perform. * @param exp1 the left-hand operand. * @param exp2 the right-hand operand. */ public BinaryOpValueExp(int op, ValueExp exp1, ValueExp exp2) { this.op = op; this.exp1 = exp1; this.exp2 = exp2; } /** * Returns the result of performing the operation on * <code>exp1</code> and <code>exp2</code>. * * @param name the {@link ObjectName} to apply * the query to. * @return the result of the operation. * @throws BadStringOperationException if an invalid string * operation is used by * the query. * @throws BadBinaryOpValueExpException if an invalid expression * is used by the query. * @throws BadAttributeValueExpException if an invalid attribute * is used by the query. * @throws InvalidApplicationException if the query is applied * to the wrong type of bean. */ public ValueExp apply(ObjectName name) throws BadStringOperationException, BadBinaryOpValueExpException, BadAttributeValueExpException, InvalidApplicationException { NumericValueExp v1 = (NumericValueExp) exp1.apply(name); NumericValueExp v2 = (NumericValueExp) exp2.apply(name); switch (op) { case PLUS: return v1.plus(v2); case MINUS: return v1.minus(v2); case TIMES: return v1.times(v2); case DIV: return v1.div(v2); default: throw new BadBinaryOpValueExpException(this); } } /** * Returns a textual representation of the operation. * * @return a textual version of the operation. */ public String toString() { String opS; switch (op) { case PLUS: opS = "+"; break; case MINUS: opS = "-"; break; case TIMES: opS = "x"; break; case DIV: opS = "/"; break; default: opS = "?"; } return exp1 + " " + opS + " " + exp2; } } /** * Representation of a binary operation formed using * {@link #eq(ValueExp, ValueExp), {@link #geq(ValueExp, ValueExp)}, * {@link #leq(ValueExp, ValueExp), {@link #gt(ValueExp, ValueExp)} * or {@link #lt(ValueExp, ValueExp)}. * * @author Andrew John Hughes (gnu_andrew@member.fsf.org) * @since 1.5 */ private static final class BinaryRelQueryExp extends QueryEval implements QueryExp { /** * Compatible with JDK 1.6 */ private static final long serialVersionUID = -5690656271650491000L; /** * The operation to perform. */ private int relOp; /** * The left-hand operand. */ private ValueExp exp1; /** * The right-hand operand. */ private ValueExp exp2; /** * Constructs a new {@link BinaryRelQueryExp} using * the specified operation and the two values supplied. * * @param relOp the operation to perform. * @param exp1 the left-hand operand. * @param exp2 the right-hand operand. */ public BinaryRelQueryExp(int relOp, ValueExp exp1, ValueExp exp2) { this.relOp = relOp; this.exp1 = exp1; this.exp2 = exp2; } /** * Returns the result of performing the operation on * <code>exp1</code> and <code>exp2</code>. * * @param name the {@link ObjectName} to apply * the query to. * @return the result of the comparison. * @throws BadStringOperationException if an invalid string * operation is used by * the query. * @throws BadBinaryOpValueExpException if an invalid expression * is used by the query. * @throws BadAttributeValueExpException if an invalid attribute * is used by the query. * @throws InvalidApplicationException if the query is applied * to the wrong type of bean. */ public boolean apply(ObjectName name) throws BadStringOperationException, BadBinaryOpValueExpException, BadAttributeValueExpException, InvalidApplicationException { String v1 = exp1.apply(name).toString(); String v2 = exp2.apply(name).toString(); switch (relOp) { case EQ: return v1.equals(v2); case GT: return v1.compareTo(v2) > 0; case GE: return v1.compareTo(v2) >= 0; case LE: return v1.compareTo(v2) <= 0; case LT: return v1.compareTo(v2) < 0; default: throw new BadStringOperationException("Invalid operator: " + relOp); } } /** * Returns a textual representation of the operation. * * @return a textual version of the operation. */ public String toString() { String op; switch (relOp) { case EQ: op = "="; break; case GT: op = ">"; break; case GE: op = ">="; break; case LE: op = "<="; break; case LT: op = "<"; break; default: op = "?"; } return exp1 + " " + op + " " + exp2; } } /** * Representation of the comparison of a value with * the members of a list formed using * {@link #in(ValueExp, ValueExp[]). * * @author Andrew John Hughes (gnu_andrew@member.fsf.org) * @since 1.5 */ private static final class InQueryExp extends QueryEval implements QueryExp { /** * Compatible with JDK 1.6 */ private static final long serialVersionUID = -5801329450358952434L; /** * The value to look for. */ private ValueExp val; /** * The array to search. */ private ValueExp[] valueList; /** * Constructs a new {@link InQueryExp} using * the specified comparison value and the given * list. * * @param val the value to compare. * @param valueList the list of values. */ public InQueryExp(ValueExp val, ValueExp[] valueList) { this.val = val; this.valueList = valueList; } /** * Returns the result of the comparison between * the value and the list of allowed values. * * @param name the {@link ObjectName} to apply * the query to. * @return the result of the comparison. * @throws BadStringOperationException if an invalid string * operation is used by * the query. * @throws BadBinaryOpValueExpException if an invalid expression * is used by the query. * @throws BadAttributeValueExpException if an invalid attribute * is used by the query. * @throws InvalidApplicationException if the query is applied * to the wrong type of bean. */ public boolean apply(ObjectName name) throws BadStringOperationException, BadBinaryOpValueExpException, BadAttributeValueExpException, InvalidApplicationException { String v = val.apply(name).toString(); for (ValueExp vl : valueList) if (v.equals(vl.apply(name).toString())) return true; return false; } } /** * Representation of the inheritance check on a * bean for {@link #isInstanceOf(StringValueExp)}. * * @author Andrew John Hughes (gnu_andrew@member.fsf.org) * @since 1.6 */ private static final class InstanceOfQueryExp extends QueryEval implements QueryExp { /** * Compatible with JDK 1.6 */ private static final long serialVersionUID = -1081892073854801359L; /** * The name of the class from which the attribute is taken. */ private StringValueExp classNameValue; /** * Constructs a new {@link InstanceOfQueryExp} using * the specified class name. * * @param classNameValue the class name. */ public InstanceOfQueryExp(StringValueExp classNameValue) { this.classNameValue = classNameValue; } /** * Checks that the bean specified by the supplied * {@link ObjectName} is of the correct class * using {@link MBeanServer#isInstanceOf(ObjectName,String)}. * where the string is obtained by evaluating * <code>classNameValue</code>. * * @param name the {@link ObjectName} of the bean to obtain * the value from. * @return true if the bean is an instance of the class. * @throws BadStringOperationException if an invalid string * operation is used by * the value expression. * @throws BadBinaryOpValueExpException if an invalid expression * is used by the value expression. * @throws BadAttributeValueExpException if an invalid attribute * is used by the value expression. * @throws InvalidApplicationException if the value expression is applied * to the wrong type of bean. */ public boolean apply(ObjectName name) throws BadStringOperationException, BadBinaryOpValueExpException, BadAttributeValueExpException, InvalidApplicationException { try { String className = ((StringValueExp) classNameValue.apply(name)).getValue(); return QueryEval.getMBeanServer().isInstanceOf(name, className); } catch (InstanceNotFoundException e) { throw (BadAttributeValueExpException) new BadAttributeValueExpException("The named bean is not registered.").initCause(e); } } } /** * Representation of the negation of a query formed using * {@link #not(QueryExp). * * @author Andrew John Hughes (gnu_andrew@member.fsf.org) * @since 1.5 */ private static final class NotQueryExp extends QueryEval implements QueryExp { /** * Compatible with JDK 1.6 */ private static final long serialVersionUID = 5269643775896723397L; /** * The expression to negate. */ private QueryExp exp; /** * Constructs a new {@link NotQueryExp} using * the specified query expression. * * @param exp the expression to negate. */ public NotQueryExp(QueryExp exp) { this.exp = exp; } /** * Returns the result of the negation. * * @param name the {@link ObjectName} to apply * the query to. * @return the result of the negation. * @throws BadStringOperationException if an invalid string * operation is used by * the query. * @throws BadBinaryOpValueExpException if an invalid expression * is used by the query. * @throws BadAttributeValueExpException if an invalid attribute * is used by the query. * @throws InvalidApplicationException if the query is applied * to the wrong type of bean. */ public boolean apply(ObjectName name) throws BadStringOperationException, BadBinaryOpValueExpException, BadAttributeValueExpException, InvalidApplicationException { return !(exp.apply(name)); } } /** * Representation of the disjunction formed using * {@link #or(QueryExp, QueryExp). * * @author Andrew John Hughes (gnu_andrew@member.fsf.org) * @since 1.5 */ private static final class OrQueryExp extends QueryEval implements QueryExp { /** * Compatible with JDK 1.6 */ private static final long serialVersionUID = 2962973084421716523L; /** * The first operand. */ private QueryExp exp1; /** * The second operand. */ private QueryExp exp2; /** * Constructs a new {@link OrQueryExp} using * the two specified operands. * * @param exp1 the first query expression. * @param exp2 the second query expression. */ public OrQueryExp(QueryExp exp1, QueryExp exp2) { this.exp1 = exp1; this.exp2 = exp2; } /** * Returns the disjunction of the two query * expressions. * * @param name the {@link ObjectName} to apply * the query to. * @return the disjunction of applying the name * to both operands. * @throws BadStringOperationException if an invalid string * operation is used by * the query. * @throws BadBinaryOpValueExpException if an invalid expression * is used by the query. * @throws BadAttributeValueExpException if an invalid attribute * is used by the query. * @throws InvalidApplicationException if the query is applied * to the wrong type of bean. */ public boolean apply(ObjectName name) throws BadStringOperationException, BadBinaryOpValueExpException, BadAttributeValueExpException, InvalidApplicationException { return exp1.apply(name) || exp2.apply(name); } } /** * Representation of a boolean being used as an argument * to a relational constraint, formed using * {@link #value(boolean)}. * * @author Andrew John Hughes (gnu_andrew@member.fsf.org) * @since 1.5 */ private static final class BooleanValueExp extends QueryEval implements ValueExp { /** * Compatible with JDK 1.6 */ private static final long serialVersionUID = 7754922052666594581L; /** * The boolean value. */ private boolean val; /** * Constructs a new {@link BooleanValueExp} using the * specified value. * * @param val the boolean value used for this expression. */ public BooleanValueExp(boolean val) { this.val = val; } /** * Applies the {@link BooleanValueExp} to the specified * management bean by simply returning the value. * * @param name the {@link ObjectName} of the bean. * @return the {@link BooleanValueExp} itself. * @throws BadStringOperationException if an invalid string * operation is used by * the value expression. * @throws BadBinaryOpValueExpException if an invalid expression * is used by the value expression. * @throws BadAttributeValueExpException if an invalid attribute * is used by the value expression. * @throws InvalidApplicationException if the value expression is applied * to the wrong type of bean. */ public ValueExp apply(ObjectName name) throws BadStringOperationException, BadBinaryOpValueExpException, BadAttributeValueExpException, InvalidApplicationException { return this; } /** * Returns the value as a string. * * @return the value in textual form. */ public String toString() { return Boolean.toString(val); } } /** * Representation of a number being used as an argument * to a relational constraint, formed using * {@link #value(double)}, {@link #value(float)}, * {@link #value(int)}, {@link #value(long)} or * {@link #value(Number)}. * * @author Andrew John Hughes (gnu_andrew@member.fsf.org) * @since 1.5 */ private static final class NumericValueExp extends QueryEval implements ValueExp { /** * Compatible with JDK 1.6 */ private static final long serialVersionUID = -4679739485102359104L; /** * The numeric value. */ private Number val; /** * Constructs a new {@link NumericValueExp} using the * specified value. * * @param val the numeric value used for this expression. */ public NumericValueExp(Number val) { this.val = val; } /** * Applies the {@link NumericValueExp} to the specified * management bean by simply returning the value. * * @param name the {@link ObjectName} of the bean. * @return the {@link NumericValueExp} itself. * @throws BadStringOperationException if an invalid string * operation is used by * the value expression. * @throws BadBinaryOpValueExpException if an invalid expression * is used by the value expression. * @throws BadAttributeValueExpException if an invalid attribute * is used by the value expression. * @throws InvalidApplicationException if the value expression is applied * to the wrong type of bean. */ public ValueExp apply(ObjectName name) throws BadStringOperationException, BadBinaryOpValueExpException, BadAttributeValueExpException, InvalidApplicationException { return this; } /** * Returns the value. */ public Number getValue() { return val; } /** * Returns the value as a string. * * @return the value in textual form. */ public String toString() { return val.toString(); } /** * Return the result of adding the specified * {@link NumericValueExp} to this one. * * @param o the value to add. * @return the result of the addition. */ public NumericValueExp plus(NumericValueExp o) { Number v = o.getValue(); if (val instanceof Double) { double d = val.doubleValue(); if (v instanceof Double) return new NumericValueExp(d + v.doubleValue()); else if (v instanceof Float) return new NumericValueExp(d + v.floatValue()); else if (v instanceof Long) return new NumericValueExp(d + v.longValue()); else return new NumericValueExp(d + v.intValue()); } else if (val instanceof Float) { float f = val.floatValue(); if (v instanceof Double) return new NumericValueExp(f + v.doubleValue()); else if (v instanceof Float) return new NumericValueExp(f + v.floatValue()); else if (v instanceof Long) return new NumericValueExp(f + v.longValue()); else return new NumericValueExp(f + v.intValue()); } else if (val instanceof Long) { long l = val.longValue(); if (v instanceof Double) return new NumericValueExp(l + v.doubleValue()); else if (v instanceof Float) return new NumericValueExp(l + v.floatValue()); else if (v instanceof Long) return new NumericValueExp(l + v.longValue()); else return new NumericValueExp(l + v.intValue()); } int i = val.intValue(); if (v instanceof Double) return new NumericValueExp(i + v.doubleValue()); else if (v instanceof Float) return new NumericValueExp(i + v.floatValue()); else if (v instanceof Long) return new NumericValueExp(i + v.longValue()); else return new NumericValueExp(i + v.intValue()); } /** * Return New NumericValueExp(the result of subtracting the specified * {@link NumericValueExp} from this one. * * @param o the value to subtract. * @return new NumericValueExp(the result of the subtraction. */ public NumericValueExp minus(NumericValueExp o) { Number v = o.getValue(); if (val instanceof Double) { double d = val.doubleValue(); if (v instanceof Double) return new NumericValueExp(d - v.doubleValue()); else if (v instanceof Float) return new NumericValueExp(d - v.floatValue()); else if (v instanceof Long) return new NumericValueExp(d - v.longValue()); else return new NumericValueExp(d - v.intValue()); } else if (val instanceof Float) { float f = val.floatValue(); if (v instanceof Double) return new NumericValueExp(f - v.doubleValue()); else if (v instanceof Float) return new NumericValueExp(f - v.floatValue()); else if (v instanceof Long) return new NumericValueExp(f - v.longValue()); else return new NumericValueExp(f - v.intValue()); } else if (val instanceof Long) { long l = val.longValue(); if (v instanceof Double) return new NumericValueExp(l - v.doubleValue()); else if (v instanceof Float) return new NumericValueExp(l - v.floatValue()); else if (v instanceof Long) return new NumericValueExp(l - v.longValue()); else return new NumericValueExp(l - v.intValue()); } int i = val.intValue(); if (v instanceof Double) return new NumericValueExp(i - v.doubleValue()); else if (v instanceof Float) return new NumericValueExp(i - v.floatValue()); else if (v instanceof Long) return new NumericValueExp(i - v.longValue()); else return new NumericValueExp(i - v.intValue()); } /** * Return New NumericValueExp(the result of multiplying the specified * {@link NumericValueExp} to this one. * * @param o the value to multiply by. * @return new NumericValueExp(the result of the multiplication. */ public NumericValueExp times(NumericValueExp o) { Number v = o.getValue(); if (val instanceof Double) { double d = val.doubleValue(); if (v instanceof Double) return new NumericValueExp(d * v.doubleValue()); else if (v instanceof Float) return new NumericValueExp(d * v.floatValue()); else if (v instanceof Long) return new NumericValueExp(d * v.longValue()); else return new NumericValueExp(d * v.intValue()); } else if (val instanceof Float) { float f = val.floatValue(); if (v instanceof Double) return new NumericValueExp(f * v.doubleValue()); else if (v instanceof Float) return new NumericValueExp(f * v.floatValue()); else if (v instanceof Long) return new NumericValueExp(f * v.longValue()); else return new NumericValueExp(f * v.intValue()); } else if (val instanceof Long) { long l = val.longValue(); if (v instanceof Double) return new NumericValueExp(l * v.doubleValue()); else if (v instanceof Float) return new NumericValueExp(l * v.floatValue()); else if (v instanceof Long) return new NumericValueExp(l * v.longValue()); else return new NumericValueExp(l * v.intValue()); } int i = val.intValue(); if (v instanceof Double) return new NumericValueExp(i * v.doubleValue()); else if (v instanceof Float) return new NumericValueExp(i * v.floatValue()); else if (v instanceof Long) return new NumericValueExp(i * v.longValue()); else return new NumericValueExp(i * v.intValue()); } /** * Return New NumericValueExp(the result of dividing this * number by value of the specified * {@link NumericValueExp}. * * @param o the value to divide by. * @return new NumericValueExp(the result of the division. */ public NumericValueExp div(NumericValueExp o) { Number v = o.getValue(); if (val instanceof Double) { double d = val.doubleValue(); if (v instanceof Double) return new NumericValueExp(d / v.doubleValue()); else if (v instanceof Float) return new NumericValueExp(d / v.floatValue()); else if (v instanceof Long) return new NumericValueExp(d / v.longValue()); else return new NumericValueExp(d / v.intValue()); } else if (val instanceof Float) { float f = val.floatValue(); if (v instanceof Double) return new NumericValueExp(f / v.doubleValue()); else if (v instanceof Float) return new NumericValueExp(f / v.floatValue()); else if (v instanceof Long) return new NumericValueExp(f / v.longValue()); else return new NumericValueExp(f / v.intValue()); } else if (val instanceof Long) { long l = val.longValue(); if (v instanceof Double) return new NumericValueExp(l / v.doubleValue()); else if (v instanceof Float) return new NumericValueExp(l / v.floatValue()); else if (v instanceof Long) return new NumericValueExp(l / v.longValue()); else return new NumericValueExp(l / v.intValue()); } int i = val.intValue(); if (v instanceof Double) return new NumericValueExp(i / v.doubleValue()); else if (v instanceof Float) return new NumericValueExp(i / v.floatValue()); else if (v instanceof Long) return new NumericValueExp(i / v.longValue()); else return new NumericValueExp(i / v.intValue()); } } }