1 /*
2  * Copyright (c) 2005, 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.Map;
25 import java.util.HashMap;
26 import java.util.Properties;
27 import java.lang.reflect.Method;
28 import javax.management.remote.JMXConnectorServerMBean;
29 
30 // utility class for MXBean* tests coming from JMX Tonga test suite
31 class Utils {
32 
33     // DEBUG is printed depending on the DEBUG and DEBUG_LEVEL JAVA property
34     private static final String DEBUG_HEADER = "[debug] ";
35 
36     // DEBUG levels
37     private static int selectedDebugLevel = 0;
38     static final int DEBUG_STANDARD = 1;
39     static final int DEBUG_VERBOSE = 2;  // Mainly used for stress tests
40     static final int DEBUG_ALL = DEBUG_STANDARD | DEBUG_VERBOSE;
41 
parseDebugProperties()42     static void parseDebugProperties() {
43         int level = 0;
44         Properties p = System.getProperties();
45 
46         // get selected levels
47         if (p.getProperty("DEBUG_STANDARD") != null) {
48             level |= DEBUG_STANDARD;
49         }
50 
51         if (p.getProperty("DEBUG_VERBOSE") != null) {
52             level |= DEBUG_VERBOSE;
53         }
54 
55         if (p.getProperty("DEBUG_ALL") != null) {
56             level |= DEBUG_ALL;
57         }
58 
59         selectedDebugLevel = level;
60     }
61 
62     /**
63      * Reproduces the original parsing and collection of test parameters
64      * from the DTonga JMX test suite.
65      *
66      * Collects passed args and returns them in a map(argname, value) structure,
67      * which will be then propagated as necessary to various called methods.
68      */
parseParameters(String args[])69     static Map<String, Object> parseParameters(String args[])
70     throws Exception {
71         Utils.debug(DEBUG_STANDARD, "TestRoot::parseParameters: Start");
72         HashMap<String, Object> map = new HashMap<>();
73 
74         for ( int i = 0; i < args.length; i++ ) {
75             if ( args[i].trim().startsWith("-") ) {
76                 if ((i+1) < args.length && !args[i+1].startsWith("-") ) {
77                     Utils.debug(DEBUG_STANDARD,
78                         "TestRoot::parseParameters: added in map = " +
79                         args[i] +
80                         " with value " +
81                         args[i+1]) ;
82                     map.put(args[i].trim(), args[i+1].trim()) ;
83                 } else if ((i+1) < args.length && args[i+1].startsWith("-") ||
84                            (i+1) == args.length ) {
85                     Utils.debug(DEBUG_STANDARD,
86                             "TestRoot::parseParameters: added in map = " +
87                             args[i] +
88                             " with null value") ;
89                     map.put(args[i].trim(), null) ;
90                 } else {
91                     System.out.println(
92                         "TestRoot::parseParameters: (WARNING) not added in map = " +
93                         args[i]) ;
94                 }
95             }
96         }
97 
98         Utils.debug(DEBUG_STANDARD, "TestRoot::parseParameters: Done") ;
99         return map ;
100     }
101 
102     /**
103      * This method is to be used in all tests to print anything
104      * that is temporary.
105      * Printing is done only when debug is activated by the property DEBUG.
106      * Printing depends also on the DEBUG_LEVEL property.
107      * Here it encapsulates a System.out.println.
108      */
debug(int level, String line)109     public static void debug(int level, String line) {
110         if ((selectedDebugLevel & level) != 0) {
111             System.out.println(DEBUG_HEADER + line);
112         }
113     }
114 
115     /**
116      * Do print stack trace when withStack is true.
117      * Does try to call getTargetException() and getTargetError() then
118      * print embedded stacks in the case of an Exception wrapping
119      * another Exception or an Error. Recurse until no more wrapping
120      * is found.
121      */
printThrowable(Throwable theThro, boolean withStack)122     public static void printThrowable(Throwable theThro, boolean withStack) {
123         try {
124             if (withStack) {
125                 theThro.printStackTrace(System.out);
126             }
127             if (theThro instanceof Exception) {
128                 Exception t = (Exception) theThro;
129                 Method target = null;
130                 String blank = " ";
131                 try {
132                     target = t.getClass().getMethod("getTargetException",
133                             (java.lang.Class<?>[]) null);
134                 } catch (Exception ee) {
135                 // OK: getTargetException method could be there or not
136                 }
137                 System.out.println(blank + t.getClass() + "==>" + t.getMessage());
138                 while (target != null) {
139                     try {
140                         t = (Exception) target.invoke(t,
141                                 (java.lang.Object[]) null);
142                     } catch (Exception ee) {
143                         t = null;
144                     }
145                     try {
146                         if (t != null) {
147                             blank = blank + "  ";
148                             System.out.println(blank + t.getClass() + "==>" +
149                                     t.getMessage());
150                             try {
151                                 target =
152                                         t.getClass().getMethod("getTargetException",
153                                         (java.lang.Class<?>[]) null);
154                             } catch (Exception ee) {
155                             // OK: getTargetException method could be there or not                            }
156                             }
157                         } else {
158                             target = null;
159                         }
160                     } catch (Exception ee) {
161                         target = null;
162                     }
163                 }
164 
165                 // We may have exceptions wrapping an Error then it is
166                 // getTargetError that is likely to be called
167                 try {
168                     target = ((Exception) theThro).getClass().getMethod("getTargetError",
169                             (java.lang.Class<?>[]) null);
170                 } catch (Exception ee) {
171                 // OK: getTargetError method could be there or not
172                 }
173                 Throwable err = theThro;
174                 while (target != null) {
175                     try {
176                         err = (Error) target.invoke(err,
177                                 (java.lang.Object[]) null);
178                     } catch (Exception ee) {
179                         err = null;
180                     }
181                     try {
182                         if (err != null) {
183                             blank = blank + "  ";
184                             System.out.println(blank + err.getClass() + "==>" +
185                                     err.getMessage());
186                             if (withStack) {
187                                 err.printStackTrace(System.out);
188                             }
189                             try {
190                                 target = err.getClass().getMethod("getTargetError",
191                                         (java.lang.Class<?>[]) null);
192                             } catch (Exception ee) {
193                             // OK: getTargetError method could be there or not
194                             }
195                         } else {
196                             target = null;
197                         }
198                     } catch (Exception ee) {
199                         target = null;
200                     }
201                 }
202             } else {
203                 System.out.println("Throwable is : " + theThro);
204             }
205         } catch (Throwable x) {
206             System.out.println("Exception : raised in printException : " + x);
207         }
208     }
209 
210     /**
211      * Wait up to maxTimeInSeconds second(s) the given JMX connector server
212      * comes up (which means isActive returns true).
213      * If it fails to do so we throw a RunTime exception.
214      */
waitReady(JMXConnectorServerMBean server, int maxTimeInSeconds)215     public static void waitReady(JMXConnectorServerMBean server,
216                                  int maxTimeInSeconds) throws Exception {
217         int elapsed = 0;
218 
219         while (!server.isActive() && elapsed < maxTimeInSeconds) {
220             Thread.sleep(1000);
221             elapsed++;
222         }
223 
224         if (server.isActive()) {
225             String message = "Utils::waitReady: JMX connector server came up";
226             if ( elapsed == 0) {
227                 message += " immediately";
228             } else {
229                 message += " after " + elapsed + " seconds";
230             }
231             message += " [" + server.getAddress() + "]";
232             Utils.debug(DEBUG_STANDARD, message);
233         } else {
234             String message = "Utils::waitReady: (ERROR) JMX connector" +
235                     " server didn't come up after " + elapsed + " seconds [" +
236                     server.getAddress() + "]";
237             System.out.println(message);
238             throw new RuntimeException(message);
239         }
240     }
241 }
242