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 
24 import java.util.ArrayList;
25 
26 import javax.management.Query;
27 import javax.management.QueryExp;
28 import 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  */
37 public 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      */
QueryFactory(String name)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      */
getSize()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      */
buildQueries()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      */
getQuery(int index)325     public QueryExp getQuery(int index) {
326         return queries.get(index - 1);
327     }
328 }
329