1/*
2 * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24import java.util.ArrayList;
25
26import javax.management.Query;
27import javax.management.QueryExp;
28import javax.management.ValueExp;
29
30/**
31 * Class used for building QueryExp instances of all every possible type
32 * in terms of JMX API members; note that several JMX classes are private
33 * and appears in the JDK API only by their serial form.
34 * Comments in each case of the big switch in method getQuery() details which
35 * API member we cover with a given query.
36 */
37public class QueryFactory extends QueryData {
38
39    private String mbeanClassName = "";
40    private String primitiveIntAttName = "IntAtt";
41    private String primitiveLongAttName = "LongAtt";
42    private String integerAttName = "IntegerAtt";
43    private String primitiveBooleanAttName = "BooleanAtt";
44    private String primitiveDoubleAttName = "DoubleAtt";
45    private String primitiveFloatAttName = "FloatAtt";
46    private String stringAttName = "StringAtt";
47    private ArrayList<QueryExp> queries = new ArrayList<QueryExp>();
48
49    /**
50     * Creates a new instance of QueryFactory.
51     * The name is the fully qualified class name of an MBean.
52     * There is severe constraints on that MBean that must:
53     * <ul>
54     * <li>extend QueryData in order to inherit attribute values.
55     * <li>define a RW attribute IntAtt of type int
56     * initialized to QueryData.longValue
57     * <li>define a RW attribute LongAtt of type long
58     * initialized to QueryData.intValue
59     * <li>define a RW attribute IntegerAtt of type Integer
60     * initialized to QueryData.integerValue
61     * <li>define a RW attribute BooleanAtt of type boolean
62     * initialized to QueryData.booleanValue
63     * <li>define a RW attribute DoubleAtt of type double
64     * initialized to QueryData.doubleValue
65     * <li>define a RW attribute FloatAtt of type float
66     * initialized to QueryData.floatValue
67     * <li>define a RW attribute StringAtt of type String
68     * initialized to QueryData.stringValue
69     * </ul>
70     */
71    public QueryFactory(String name) {
72        this.mbeanClassName = name;
73    }
74
75    /**
76     * Returns the highest index value the method getQuery supports.
77     * WARNING : returns 0 if buildQueries haven't been called first !
78     */
79    public int getSize() {
80        return queries.size();
81    }
82
83    /**
84     * Populates an ArrayList of QueryExp.
85     * Lowest index is 1.
86     * Highest index is returned by getSize().
87     * <br>The queries numbered 1 to 23 allow to cover all the underlying
88     * Java classes of the JMX API used to build queries.
89     */
90    public void buildQueries() {
91        if ( queries.size() == 0 ) {
92            int smallerIntValue = intValue - 1;
93            int biggerIntValue = intValue + 1;
94
95            // case 1:
96            // True if the MBean is of class mbeanClassName
97            // We cover javax.management.InstanceOfQueryExp
98            queries.add(Query.isInstanceOf(Query.value(mbeanClassName)));
99
100            // case 2:
101            // True if the MBean is of class mbeanClassName
102            // We cover javax.management.MatchQueryExp and
103            // javax.management.ClassAttributeValueExp
104            queries.add(Query.match(Query.classattr(),
105                    Query.value(mbeanClassName)));
106
107            // case 3:
108            // True if an attribute named primitiveIntAttName of type int has
109            // the value intValue
110            // We cover javax.management.BinaryRelQueryExp with
111            // a relOp equal to EQ and javax.management.NumericValueExp
112            queries.add(Query.eq(Query.attr(primitiveIntAttName),
113                    Query.value(intValue)));
114
115            // case 4:
116            // True if an attribute named primitiveLongAttName of type long has
117            // the value longValue
118            // We cover javax.management.BinaryRelQueryExp with
119            // a relOp equal to EQ and javax.management.NumericValueExp
120            queries.add(Query.eq(Query.attr(primitiveLongAttName),
121                    Query.value(longValue)));
122
123            // case 5:
124            // True if an attribute named primitiveDoubleAttName of type double
125            // has the value doubleValue
126            // We cover javax.management.BinaryRelQueryExp with
127            // a relOp equal to EQ and javax.management.NumericValueExp
128            queries.add(Query.eq(Query.attr(primitiveDoubleAttName),
129                    Query.value(doubleValue)));
130
131            // case 6:
132            // True if an attribute named primitiveFloatAttName of type float
133            // has the value floatValue
134            // We cover javax.management.BinaryRelQueryExp with
135            // a relOp equal to EQ and javax.management.NumericValueExp
136            queries.add(Query.eq(Query.attr(primitiveFloatAttName),
137                    Query.value(floatValue)));
138
139            // case 7:
140            // True if an attribute named primitiveIntAttName of type int is
141            // hold by an MBean of class mbeanClassName and has
142            // the value intValue
143            // We cover javax.management.QualifiedAttributeValueExp
144            queries.add(Query.eq(Query.attr(mbeanClassName, primitiveIntAttName),
145                    Query.value(intValue)));
146
147            // case 8:
148            // True if an attribute named stringAttName of type String has
149            // the value stringValue
150            // We cover javax.management.BinaryRelQueryExp with
151            // a relOp equal to EQ and javax.management.StringValueExp
152            queries.add(Query.eq(Query.attr(stringAttName),
153                    Query.value(stringValue)));
154
155            // case 9:
156            // True if an attribute named integerAttName of type Integer has
157            // the value integerValue
158            // We cover javax.management.BinaryRelQueryExp with
159            // a relOp equal to EQ and javax.management.NumericValueExp
160            queries.add(Query.eq(Query.attr(integerAttName),
161                    Query.value(integerValue)));
162
163            // case 10:
164            // True if an attribute named primitiveBooleanAttName of type boolean
165            // has the value booleanValue
166            // We cover javax.management.BinaryRelQueryExp with
167            // a relOp equal to EQ and javax.management.BooleanValueExp
168            queries.add(Query.eq(Query.attr(primitiveBooleanAttName),
169                    Query.value(booleanValue)));
170
171            // case 11:
172            // True if an attribute named primitiveIntAttName of type int has
173            // not the value smallerIntValue
174            // We cover javax.management.NotQueryExp
175            queries.add(Query.not(Query.eq(Query.attr(primitiveIntAttName),
176                    Query.value(smallerIntValue))));
177
178            // case 12:
179            // True if either
180            // an attribute named primitiveIntAttName of type int has
181            // the value intValue
182            // or
183            // an attribute named primitiveLongAttName of type long has
184            // the value longValue
185            // We cover javax.management.OrQueryExp
186            queries.add(Query.or(
187                    Query.eq(Query.attr(primitiveIntAttName),
188                    Query.value(intValue)),
189                    Query.eq(Query.attr(primitiveLongAttName),
190                    Query.value(longValue))));
191
192            // case 13:
193            // True if
194            // an attribute named primitiveIntAttName of type int has
195            // the value intValue
196            // and
197            // an attribute named primitiveLongAttName of type long has
198            // the value longValue
199            // We cover javax.management.AndQueryExp
200            queries.add(Query.and(
201                    Query.eq(Query.attr(primitiveIntAttName),
202                    Query.value(intValue)),
203                    Query.eq(Query.attr(primitiveLongAttName),
204                    Query.value(longValue))));
205
206            // case 14:
207            // True if an attribute named primitiveIntAttName of type int has
208            // the value intValue
209            // We cover javax.management.InQueryExp
210            ValueExp[] inArray = {Query.value(intValue)};
211            queries.add(Query.in(Query.attr(primitiveIntAttName), inArray));
212
213            // case 15:
214            // True if an attribute named primitiveIntAttName of type int has
215            // its value in between smallerIntValue and biggerIntValue
216            // We cover javax.management.BetweenRelQueryExp
217            queries.add(Query.between(Query.attr(primitiveIntAttName),
218                    Query.value(smallerIntValue),
219                    Query.value(biggerIntValue)));
220
221            // case 16:
222            // True if an attribute named primitiveIntAttName of type int has
223            // a value greater than smallerIntValue
224            // We cover javax.management.BinaryRelQueryExp with
225            // a relOp equal to GT
226            queries.add(Query.gt(Query.attr(primitiveIntAttName),
227                    Query.value(smallerIntValue)));
228
229            // case 17:
230            // True if an attribute named primitiveIntAttName of type int has
231            // a value greater or equal to smallerIntValue
232            // We cover javax.management.BinaryRelQueryExp with
233            // a relOp equal to GE
234            queries.add(Query.geq(Query.attr(primitiveIntAttName),
235                    Query.value(smallerIntValue)));
236
237            // case 18:
238            // True if an attribute named primitiveIntAttName of type int has
239            // a value smaller than biggerIntValue
240            // We cover javax.management.BinaryRelQueryExp with
241            // a relOp equal to LT
242            queries.add(Query.lt(Query.attr(primitiveIntAttName),
243                    Query.value(biggerIntValue)));
244
245            // case 19:
246            // True if an attribute named primitiveIntAttName of type int has
247            // a value smaller or equal to biggerIntValue
248            // We cover javax.management.BinaryRelQueryExp with
249            // a relOp equal to LE
250            queries.add(Query.leq(Query.attr(primitiveIntAttName),
251                    Query.value(biggerIntValue)));
252
253            // case 20:
254            // True if an attribute named primitiveIntAttName of type int has
255            // a value equal to intValue minus zero
256            // We cover javax.management.BinaryRelQueryExp with
257            // a relOp equal to MINUS
258            queries.add(Query.eq(Query.attr(primitiveIntAttName),
259                    Query.minus(Query.value(intValue), Query.value(0))));
260
261            // case 21:
262            // True if an attribute named primitiveIntAttName of type int has
263            // a value equal to intValue plus zero
264            // We cover javax.management.BinaryRelQueryExp with
265            // a relOp equal to PLUS
266            queries.add(Query.eq(Query.attr(primitiveIntAttName),
267                    Query.plus(Query.value(intValue), Query.value(0))));
268
269            // case 22:
270            // True if an attribute named primitiveIntAttName of type int has
271            // a value equal to intValue divided by one
272            // We cover javax.management.BinaryRelQueryExp with
273            // a relOp equal to DIV
274            queries.add(Query.eq(Query.attr(primitiveIntAttName),
275                    Query.div(Query.value(intValue), Query.value(1))));
276
277            // case 23:
278            // True if an attribute named primitiveIntAttName of type int has
279            // a value equal to intValue multiplicated by one
280            // We cover javax.management.BinaryRelQueryExp with
281            // a relOp equal to TIMES
282            queries.add(Query.eq(Query.attr(primitiveIntAttName),
283                    Query.times(Query.value(intValue), Query.value(1))));
284
285            // case 24:
286            // That query is a complex one that combines within a big AND
287            // queries with index 2 to 23 inclusive. But because a List is
288            // zero based, we must decrement all indexes by 1 when retrieving
289            // any previously stored query.
290            QueryExp q2_3 = Query.and(queries.get(2-1), queries.get(3-1));
291            QueryExp q4_5 = Query.and(queries.get(4-1), queries.get(5-1));
292            QueryExp q6_7 = Query.and(queries.get(6-1), queries.get(7-1));
293            QueryExp q8_9 = Query.and(queries.get(8-1), queries.get(9-1));
294            QueryExp q10_11 = Query.and(queries.get(10-1), queries.get(11-1));
295            QueryExp q12_13 = Query.and(queries.get(12-1), queries.get(13-1));
296            QueryExp q14_15 = Query.and(queries.get(14-1), queries.get(15-1));
297            QueryExp q16_17 = Query.and(queries.get(16-1), queries.get(17-1));
298            QueryExp q18_19 = Query.and(queries.get(18-1), queries.get(19-1));
299            QueryExp q20_21 = Query.and(queries.get(20-1), queries.get(21-1));
300            QueryExp q22_23 = Query.and(queries.get(22-1), queries.get(23-1));
301            QueryExp q2_5 = Query.and(q2_3, q4_5);
302            QueryExp q6_9 = Query.and(q6_7, q8_9);
303            QueryExp q10_13 = Query.and(q10_11, q12_13);
304            QueryExp q14_17 = Query.and(q14_15, q16_17);
305            QueryExp q18_21 = Query.and(q18_19, q20_21);
306            QueryExp q2_9 = Query.and(q2_5, q6_9);
307            QueryExp q10_17 = Query.and(q10_13, q14_17);
308            QueryExp q18_23 = Query.and(q18_21, q22_23);
309            QueryExp q2_17 = Query.and(q2_9, q10_17);
310            queries.add(Query.and(q2_17, q18_23));
311
312            // case 25:
313            // Complex query mixing AND and OR.
314            queries.add(Query.or(q6_9, q18_23));
315        }
316    }
317
318    /**
319     * Returns a QueryExp taken is the ArrayList populated by buildQueries().
320     * Lowest index is 1.
321     * Highest index is returned by getSize().
322     * <br>The queries numbered 1 to 23 allow to cover all the underlying
323     * Java classes of the JMX API used to build queries.
324     */
325    public QueryExp getQuery(int index) {
326        return queries.get(index - 1);
327    }
328}
329