1 /* 2 * Copyright (c) 2016, 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 8159377 27 * @library /lib/testlibrary 28 * @library /test/lib 29 * @summary Tests ObjectFilter on default agent 30 * @author Harsha Wardhana B 31 * @modules java.management 32 * @build jdk.testlibrary.* DefaultAgentFilterTest 33 * @run main/othervm/timeout=600 -XX:+UsePerfData DefaultAgentFilterTest 34 */ 35 import java.io.EOFException; 36 import java.io.File; 37 import java.io.IOException; 38 import java.io.InvalidClassException; 39 import java.io.Serializable; 40 import java.lang.reflect.InvocationTargetException; 41 import java.net.BindException; 42 import java.rmi.UnmarshalException; 43 import java.rmi.registry.LocateRegistry; 44 import java.rmi.registry.Registry; 45 import java.util.ArrayList; 46 import java.util.Arrays; 47 import java.util.HashMap; 48 import java.util.HashSet; 49 import java.util.List; 50 import java.util.Map; 51 import java.util.concurrent.atomic.AtomicBoolean; 52 import javax.management.MBeanServerConnection; 53 import javax.management.ObjectName; 54 import javax.management.remote.JMXConnector; 55 import javax.management.remote.JMXConnectorFactory; 56 import javax.management.remote.JMXServiceURL; 57 58 import jdk.test.lib.process.ProcessTools; 59 import jdk.testlibrary.Utils; 60 61 public class DefaultAgentFilterTest { 62 63 public static class MyTestObject implements Serializable { 64 65 String a; 66 int id; 67 } 68 69 public interface TestMBean { 70 71 public void op1(HashSet<Object> params); 72 73 public void op2(String s, HashSet<String> params); 74 75 public void op3(MyTestObject obj, String s, HashMap<String, String> param); 76 } 77 78 public static class Test implements TestMBean { 79 80 @Override 81 public void op1(HashSet<Object> params) { 82 System.out.println("Invoked op1"); 83 } 84 85 @Override 86 public void op2(String s, HashSet<String> params) { 87 System.out.println("Invoked op2"); 88 } 89 90 @Override 91 public void op3(MyTestObject obj, String s, HashMap<String, String> param) { 92 System.out.println("Invoked op3"); 93 } 94 } 95 96 private static class TestAppRun implements AutoCloseable { 97 98 private Process p; 99 private final ProcessBuilder pb; 100 private final String name; 101 private final AtomicBoolean started = new AtomicBoolean(false); 102 private volatile long pid = -1; 103 104 public TestAppRun(ProcessBuilder pb, String name) { 105 this.pb = pb; 106 this.name = name; 107 } 108 109 public synchronized void start() throws Exception { 110 if (started.compareAndSet(false, true)) { 111 try { 112 AtomicBoolean error = new AtomicBoolean(false); 113 AtomicBoolean bindError = new AtomicBoolean(false); 114 p = ProcessTools.startProcess( 115 TEST_APP_NAME + "{" + name + "}", 116 pb, 117 (line) -> { 118 if (line.toLowerCase().contains("exception") 119 || line.toLowerCase().contains("error")) { 120 error.set(true); 121 } 122 bindError.set(line.toLowerCase().contains("bindexception")); 123 return true; 124 }); 125 if (bindError.get()) { 126 throw new BindException("Process could not be started"); 127 } else if (error.get()) { 128 throw new RuntimeException(); 129 } 130 pid = p.pid(); 131 } catch (Exception ex) { 132 if (p != null) { 133 p.destroy(); 134 p.waitFor(); 135 } 136 throw ex; 137 } 138 } 139 } 140 141 public long getPid() { 142 return pid; 143 } 144 145 public synchronized void stop() 146 throws IOException, InterruptedException { 147 if (started.compareAndSet(true, false)) { 148 p.getOutputStream().write(0); 149 p.getOutputStream().flush(); 150 int ec = p.waitFor(); 151 if (ec != 0) { 152 StringBuilder msg = new StringBuilder(); 153 msg.append("Test application '").append(name); 154 msg.append("' failed with exit code: "); 155 msg.append(ec); 156 System.err.println(msg); 157 } 158 } 159 } 160 161 @Override 162 public void close() throws Exception { 163 stop(); 164 } 165 } 166 167 private static final String TEST_APP_NAME = "TestApp"; 168 169 private static void testDefaultAgent(String propertyFile) throws Exception { 170 int port = Utils.getFreePort(); 171 String propFile = System.getProperty("test.src") + File.separator + propertyFile; 172 List<String> pbArgs = new ArrayList<>(Arrays.asList( 173 "-cp", 174 System.getProperty("test.class.path"), 175 "-XX:+UsePerfData" 176 )); 177 String[] args = new String[]{ 178 "-Dcom.sun.management.jmxremote.port=" + port, 179 "-Dcom.sun.management.jmxremote.authenticate=false", 180 "-Dcom.sun.management.jmxremote.ssl=false", 181 "-Dcom.sun.management.config.file=" + propFile 182 }; 183 pbArgs.addAll(Arrays.asList(args)); 184 pbArgs.add(TEST_APP_NAME); 185 186 ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( 187 pbArgs.toArray(new String[pbArgs.size()]) 188 ); 189 190 try (TestAppRun s = new TestAppRun(pb, DefaultAgentFilterTest.class.getSimpleName())) { 191 s.start(); 192 JMXServiceURL url = testConnect(port); 193 testMBeanOperations(url); 194 } 195 } 196 197 private static JMXServiceURL testConnect(int port) throws Exception { 198 EOFException lastException = null; 199 JMXServiceURL url = null; 200 // factor adjusted timeout (5 seconds) for the RMI to become available 201 long timeout = System.currentTimeMillis() + Utils.adjustTimeout(5000); 202 do { 203 lastException = null; 204 try { 205 Registry registry = LocateRegistry.getRegistry(port); 206 String[] relist = registry.list(); 207 for (int i = 0; i < relist.length; ++i) { 208 System.out.println("Got registry: " + relist[i]); 209 } 210 String jmxUrlStr = String.format( 211 "service:jmx:rmi:///jndi/rmi://localhost:%d/jmxrmi", 212 port); 213 url = new JMXServiceURL(jmxUrlStr); 214 215 try (JMXConnector c = JMXConnectorFactory.connect(url, null)) { 216 MBeanServerConnection conn = c.getMBeanServerConnection(); 217 ObjectName name = new ObjectName("jtreg:type=Test"); 218 conn.createMBean(Test.class.getName(), name); 219 } 220 } catch (Exception ex) { 221 if (ex instanceof EOFException) { 222 lastException = (EOFException) ex; 223 System.out.println("Error establishing RMI connection. Retrying in 500ms."); 224 Thread.sleep(500); 225 } else { 226 throw ex; 227 } 228 } 229 } while (lastException != null && System.currentTimeMillis() < timeout); 230 if (lastException != null) { 231 throw lastException; 232 } 233 return url; 234 } 235 236 public static void main(String[] args) throws Exception { 237 System.out.println("---" + DefaultAgentFilterTest.class.getName() + "-main: starting ..."); 238 239 boolean retry = false; 240 do { 241 try { 242 // blacklist String 243 testDefaultAgent("mgmt1.properties"); 244 System.out.println("----\tTest FAILED !!"); 245 throw new RuntimeException("---" + DefaultAgentFilterTest.class.getName() + " - No exception reported"); 246 } catch (Exception ex) { 247 if (ex instanceof InvocationTargetException) { 248 if (ex.getCause() instanceof BindException 249 || ex.getCause() instanceof java.rmi.ConnectException) { 250 System.out.println("Failed to allocate ports. Retrying ..."); 251 retry = true; 252 } 253 } else if (ex instanceof InvalidClassException) { 254 System.out.println("----\tTest PASSED !!"); 255 } else if (ex instanceof UnmarshalException 256 && ((UnmarshalException) ex).getCause() instanceof InvalidClassException) { 257 System.out.println("----\tTest PASSED !!"); 258 } else { 259 System.out.println(ex); 260 System.out.println("----\tTest FAILED !!"); 261 throw ex; 262 } 263 } 264 } while (retry); 265 retry = false; 266 do { 267 try { 268 // blacklist non-existent class 269 testDefaultAgent("mgmt2.properties"); 270 System.out.println("----\tTest PASSED !!"); 271 } catch (Exception ex) { 272 if (ex instanceof InvocationTargetException) { 273 if (ex.getCause() instanceof BindException 274 || ex.getCause() instanceof java.rmi.ConnectException) { 275 System.out.println("Failed to allocate ports. Retrying ..."); 276 retry = true; 277 } 278 } else { 279 System.out.println(ex); 280 System.out.println("----\tTest FAILED !!"); 281 throw ex; 282 } 283 } 284 } while (retry); 285 286 System.out.println("---" + DefaultAgentFilterTest.class.getName() + "-main: finished ..."); 287 } 288 289 private static void testMBeanOperations(JMXServiceURL serverUrl) throws Exception { 290 Map<String, Object> clientEnv = new HashMap<>(1); 291 ObjectName name = new ObjectName("jtreg:type=Test"); 292 try (JMXConnector client = JMXConnectorFactory.connect(serverUrl, clientEnv)) { 293 MBeanServerConnection conn = client.getMBeanServerConnection(); 294 295 HashSet<String> set = new HashSet<>(); 296 set.add("test1"); 297 set.add("test2"); 298 299 String a = "A"; 300 301 Object[] params1 = {set}; 302 String[] sig1 = {HashSet.class.getName()}; 303 conn.invoke(name, "op1", params1, sig1); 304 305 Object[] params2 = {a, set}; 306 String[] sig2 = {String.class.getName(), HashSet.class.getName()}; 307 conn.invoke(name, "op2", params2, sig2); 308 309 HashMap<String, String> map = new HashMap<>(); 310 map.put("a", "A"); 311 map.put("b", "B"); 312 313 Object[] params3 = {new MyTestObject(), a, map}; 314 String[] sig3 = {MyTestObject.class.getName(), String.class.getName(), 315 HashMap.class.getName()}; 316 conn.invoke(name, "op3", params3, sig3); 317 } 318 } 319 } 320 321 class TestApp { 322 323 private static void doSomething() throws IOException { 324 int r = System.in.read(); 325 System.out.println("read: " + r); 326 } 327 328 public static void main(String args[]) throws Exception { 329 System.out.println("main enter"); 330 System.out.flush(); 331 doSomething(); 332 System.out.println("main exit"); 333 } 334 }