1 /* 2 * Copyright (c) 2005, 2018, 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 /* 25 * @test 26 * @bug 8058865 27 * @summary Checks that a serialized instance is not transmitted from an MXBean. 28 * All the communication should be done via Open Types 29 * @author Olivier Lagneau 30 * @modules java.management.rmi 31 * @library /test/lib 32 * @compile Basic.java 33 * @run main/othervm/timeout=300 -DDEBUG_STANDARD MXBeanWeirdParamTest 34 */ 35 36 import java.util.Map; 37 import java.util.List; 38 import java.util.ArrayList; 39 import java.util.Arrays; 40 41 import java.lang.Process; 42 import java.lang.management.ManagementFactory; 43 44 import javax.management.MBeanServer; 45 import javax.management.MBeanServerConnection; 46 import javax.management.remote.JMXConnector; 47 import javax.management.remote.JMXConnectorFactory; 48 import javax.management.remote.JMXConnectorServer; 49 import javax.management.remote.JMXConnectorServerFactory; 50 import javax.management.remote.JMXServiceURL; 51 52 import javax.management.ObjectName; 53 import javax.management.openmbean.CompositeType; 54 import javax.management.openmbean.CompositeData; 55 import javax.management.openmbean.CompositeDataSupport; 56 import javax.management.openmbean.OpenType; 57 import javax.management.openmbean.SimpleType; 58 import javax.management.openmbean.TabularDataSupport; 59 import javax.management.openmbean.TabularType; 60 61 import jdk.test.lib.JDKToolFinder; 62 import jdk.test.lib.process.ProcessTools; 63 64 public class MXBeanWeirdParamTest { 65 66 private static String BASIC_MXBEAN_CLASS_NAME = "Basic"; 67 68 private static final String CLIENT_CLASS_MAIN = 69 "MXBeanWeirdParamTest$ClientSide"; 70 71 private JMXConnectorServer cs; 72 73 /* 74 * First Debug properties and arguments are collect in expected 75 * map (argName, value) format, then calls original test's run method. 76 */ main(String args[])77 public static void main(String args[]) throws Exception { 78 79 System.out.println("================================================="); 80 81 // Parses parameters 82 Utils.parseDebugProperties(); 83 Map<String, Object> map = Utils.parseParameters(args) ; 84 85 // Run test 86 MXBeanWeirdParamTest test = new MXBeanWeirdParamTest(); 87 test.run(map); 88 89 } 90 91 /* 92 * Create the MBeansServe side of the test and returns its address 93 */ createServerSide()94 private JMXServiceURL createServerSide() throws Exception { 95 final int NINETY_SECONDS = 90; 96 97 // We will use the platform mbean server 98 MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); 99 100 JMXServiceURL url = new JMXServiceURL("rmi", null, 0); 101 cs = JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs); 102 cs.start(); 103 104 Utils.waitReady(cs, NINETY_SECONDS); 105 106 JMXServiceURL addr = cs.getAddress(); 107 return addr; 108 } 109 110 111 /* 112 * Creating command-line for running subprocess JVM: 113 * 114 * JVM command line is like: 115 * {test_jdk}/bin/java {defaultopts} -cp {test.class.path} {testopts} main 116 * 117 * {defaultopts} are the default java options set by the framework. 118 * 119 */ buildCommandLine()120 private List<String> buildCommandLine() { 121 List<String> opts = new ArrayList<>(); 122 opts.add(JDKToolFinder.getJDKTool("java")); 123 opts.addAll(Arrays.asList(jdk.test.lib.Utils.getTestJavaOpts())); 124 // We need to set WEIRD_PARAM propertty on the client-side 125 opts.add("-DWEIRD_PARAM"); 126 opts.add("-cp"); 127 opts.add(System.getProperty("test.class.path", "test.class.path")); 128 opts.add(CLIENT_CLASS_MAIN); 129 130 return opts; 131 } 132 133 /** 134 * Runs MXBeanWeirdParamTest$ClientSide with the passed options and redirects 135 * subprocess standard I/O to the current (parent) process. This provides a 136 * trace of what happens in the subprocess while it is runnning (and before 137 * it terminates). 138 * 139 * @param serviceUrlStr string representing the JMX service Url to connect to. 140 */ runClientSide(String serviceUrlStr)141 private int runClientSide(String serviceUrlStr) throws Exception { 142 143 // Building command-line 144 List<String> opts = buildCommandLine(); 145 opts.add(serviceUrlStr); 146 147 // Launch separate JVM subprocess 148 int exitCode = 0; 149 String[] optsArray = opts.toArray(new String[0]); 150 ProcessBuilder pb = new ProcessBuilder(optsArray); 151 Process p = ProcessTools.startProcess("MXBeanWeirdParamTest$ClientSide", pb); 152 153 // Handling end of subprocess 154 try { 155 exitCode = p.waitFor(); 156 if (exitCode != 0) { 157 System.out.println( 158 "Subprocess unexpected exit value of [" + exitCode + 159 "]. Expected 0.\n"); 160 } 161 } catch (InterruptedException e) { 162 System.out.println("Parent process interrupted with exception : \n " + e + " :" ); 163 164 // Parent thread unknown state, killing subprocess. 165 p.destroyForcibly(); 166 167 throw new RuntimeException( 168 "Parent process interrupted with exception : \n " + e + " :" ); 169 } finally { 170 return exitCode; 171 } 172 173 } 174 run(Map<String, Object> args)175 public void run(Map<String, Object> args) throws Exception { 176 177 System.out.println("MXBeanWeirdParamTest::run: Start") ; 178 int errorCount = 0; 179 180 try { 181 // Initialise the server side 182 JMXServiceURL urlToUse = createServerSide(); 183 184 // Run client side 185 errorCount = runClientSide(urlToUse.toString()); 186 187 if ( errorCount == 0 ) { 188 System.out.println("MXBeanWeirdParamTest::run: Done without any error") ; 189 } else { 190 System.out.println("MXBeanWeirdParamTest::run: Done with " 191 + errorCount 192 + " error(s)") ; 193 throw new RuntimeException("errorCount = " + errorCount); 194 } 195 196 cs.stop(); 197 198 } catch(Exception e) { 199 throw new RuntimeException(e); 200 } 201 202 } 203 204 private static class ClientSide { main(String args[])205 public static void main(String args[]) throws Exception { 206 207 int errorCount = 0 ; 208 String msgTag = "ClientSide::main: "; 209 210 try { 211 212 // Get a connection to remote mbean server 213 JMXServiceURL addr = new JMXServiceURL(args[0]); 214 JMXConnector cc = JMXConnectorFactory.connect(addr); 215 MBeanServerConnection mbsc = cc.getMBeanServerConnection(); 216 217 // ---- 218 System.out.println(msgTag + "Create and register the MBean"); 219 ObjectName objName = new ObjectName("sqe:type=Basic,protocol=rmi") ; 220 mbsc.createMBean(BASIC_MXBEAN_CLASS_NAME, objName); 221 System.out.println(msgTag +"---- OK\n") ; 222 223 // ---- 224 System.out.println(msgTag +"Get attribute SqeParameterAtt on our MXBean"); 225 Object result = mbsc.getAttribute(objName, "SqeParameterAtt"); 226 System.out.println(msgTag +"(OK) Got result of class " 227 + result.getClass().getName()); 228 System.out.println(msgTag +"Received CompositeData is " + result); 229 System.out.println(msgTag +"---- OK\n") ; 230 231 // ---- 232 // We use the value returned by getAttribute to perform the invoke. 233 System.out.println(msgTag +"Call operation doWeird on our MXBean [1]"); 234 mbsc.invoke(objName, "doWeird", 235 new Object[]{result}, 236 new String[]{"javax.management.openmbean.CompositeData"}); 237 System.out.println(msgTag +"---- OK\n") ; 238 239 // ---- 240 // We build the CompositeData ourselves that time. 241 System.out.println(msgTag +"Call operation doWeird on our MXBean [2]"); 242 String typeName = "SqeParameter"; 243 String[] itemNames = new String[] {"glop"}; 244 OpenType<?>[] openTypes = new OpenType<?>[] {SimpleType.STRING}; 245 CompositeType rowType = new CompositeType(typeName, typeName, 246 itemNames, itemNames, openTypes); 247 Object[] itemValues = {"HECTOR"}; 248 CompositeData data = 249 new CompositeDataSupport(rowType, itemNames, itemValues); 250 TabularType tabType = new TabularType(typeName, typeName, 251 rowType, new String[]{"glop"}); 252 TabularDataSupport tds = new TabularDataSupport(tabType); 253 tds.put(data); 254 System.out.println(msgTag +"Source CompositeData is " + data); 255 mbsc.invoke(objName, "doWeird", 256 new Object[]{data}, 257 new String[]{"javax.management.openmbean.CompositeData"}); 258 System.out.println(msgTag +"---- OK\n") ; 259 260 // ---- 261 System.out.println(msgTag +"Unregister the MBean"); 262 mbsc.unregisterMBean(objName); 263 System.out.println(msgTag +"---- OK\n") ; 264 265 // Terminate the JMX Client 266 cc.close(); 267 268 } catch(Exception e) { 269 Utils.printThrowable(e, true) ; 270 errorCount++; 271 throw new RuntimeException(e); 272 } finally { 273 System.exit(errorCount); 274 } 275 } 276 } 277 } 278