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