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