1 /* 2 * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. 3 * 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * The contents of this file are subject to the terms of either the Universal Permissive License 7 * v 1.0 as shown at http://oss.oracle.com/licenses/upl 8 * 9 * or the following license: 10 * 11 * Redistribution and use in source and binary forms, with or without modification, are permitted 12 * provided that the following conditions are met: 13 * 14 * 1. Redistributions of source code must retain the above copyright notice, this list of conditions 15 * and the following disclaimer. 16 * 17 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of 18 * conditions and the following disclaimer in the documentation and/or other materials provided with 19 * the distribution. 20 * 21 * 3. Neither the name of the copyright holder nor the names of its contributors may be used to 22 * endorse or promote products derived from this software without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 26 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 30 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 31 * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 package org.openjdk.jmc.rjmx.test; 34 35 import java.io.IOException; 36 import java.net.MalformedURLException; 37 import java.util.Map; 38 import java.util.Map.Entry; 39 import java.util.Properties; 40 41 import javax.management.MBeanServerConnection; 42 import javax.management.remote.JMXServiceURL; 43 import javax.security.auth.login.FailedLoginException; 44 45 import org.junit.After; 46 import org.junit.Assert; 47 import org.junit.Assume; 48 import org.junit.Before; 49 import org.openjdk.jmc.common.test.MCTestCase; 50 import org.openjdk.jmc.common.version.JavaVersionSupport; 51 import org.openjdk.jmc.rjmx.ConnectionDescriptorBuilder; 52 import org.openjdk.jmc.rjmx.ConnectionException; 53 import org.openjdk.jmc.rjmx.ConnectionToolkit; 54 import org.openjdk.jmc.rjmx.IConnectionDescriptor; 55 import org.openjdk.jmc.rjmx.IConnectionHandle; 56 import org.openjdk.jmc.rjmx.IServerHandle; 57 import org.openjdk.jmc.rjmx.ServiceNotAvailableException; 58 import org.openjdk.jmc.rjmx.services.IDiagnosticCommandService; 59 import org.openjdk.jmc.rjmx.subscription.IMBeanHelperService; 60 import org.openjdk.jmc.rjmx.subscription.IMRIMetadataService; 61 import org.openjdk.jmc.rjmx.subscription.ISubscriptionService; 62 63 /** 64 */ 65 public class RjmxTestCase extends MCTestCase { 66 /** 67 * The host running the management server. 68 */ 69 public final static String PROPERTY_RJMX_HOST = "jmc.test.rjmx.host"; 70 71 /** 72 * The port of the management server. (Used for both JMX over RMI and RMP.) 73 */ 74 public final static String PROPERTY_RJMX_PORT = "jmc.test.rjmx.port"; 75 76 /** 77 * Boolean option to use RMP to talk to the management server. (False means to use JMX over 78 * RMI.) 79 */ 80 public final static String PROPERTY_RJMX_RMP = "jmc.test.rjmx.rmp"; 81 82 /** 83 * The service URL to the management server. (If set, has precedence over host, port and 84 * protocol.) 85 */ 86 public final static String PROPERTY_JMX_SERVICE_URL = "jmc.test.rjmx.serviceURL"; 87 88 /** 89 * The default host to test against. 90 */ 91 public final static String DEFAULT_HOST = "localhost"; 92 93 protected String m_host; 94 protected IConnectionHandle m_connectionHandle; 95 protected IConnectionDescriptor m_connectionDescriptor; 96 97 protected boolean isLocal14 = false; 98 99 /** 100 * Do not change access. Use {@link #getDefaultConnectionDescriptor()} instead. 101 */ 102 private static volatile IConnectionDescriptor SHARED_DESCRIPTOR; 103 104 /** 105 * Obtain a RJMX ConnectionDescriptor for the server to run tests against. The descriptor is 106 * formed by taking "jmc.test.rjmx.*" properties and the JDK level of the current JVM into 107 * account. If more than one is possible, attempts to probe once. 108 * 109 * @return The ConnectionDescriptor 110 * @throws MalformedURLException 111 */ 112 public static IConnectionDescriptor getDefaultConnectionDescriptor() throws MalformedURLException { 113 if (SHARED_DESCRIPTOR == null) { 114 String serviceURL = System.getProperty(PROPERTY_JMX_SERVICE_URL); 115 if (serviceURL != null) { 116 SHARED_DESCRIPTOR = new ConnectionDescriptorBuilder().url(new JMXServiceURL(serviceURL)).build(); 117 } else { 118 String host = System.getProperty(PROPERTY_RJMX_HOST, DEFAULT_HOST); 119 int jmxPort = Integer.getInteger(PROPERTY_RJMX_PORT, ConnectionDescriptorBuilder.DEFAULT_PORT) 120 .intValue(); 121 IConnectionDescriptor candidate = new ConnectionDescriptorBuilder().hostName(host).port(jmxPort) 122 .build(); 123 SHARED_DESCRIPTOR = candidate; 124 } 125 } 126 return SHARED_DESCRIPTOR; 127 } 128 129 protected static boolean probe(IConnectionDescriptor descriptor) { 130 long start = System.currentTimeMillis(); 131 try { 132 System.out.println("Probing Service URL " + descriptor.createJMXServiceURL() + " ..."); 133 IConnectionHandle handle = createConnectionHandle(descriptor); 134 long up = System.currentTimeMillis(); 135 System.out.println("... connected in " + (up - start) + " ms ..."); 136 // Just in case we fail ... 137 start = up; 138 handle.close(); 139 long down = System.currentTimeMillis(); 140 System.out.println("... closed in " + (down - start) + " ms."); 141 return true; 142 } catch (Exception e) { 143 long fail = System.currentTimeMillis(); 144 System.out.println("... failed in " + (fail - start) + " ms."); 145 return false; 146 } 147 } 148 149 /** 150 * The {@link IConnectionDescriptor} to run the test against. Instance method so it can be 151 * overridden. Mainly intended for tests suites that run against multiple JVMs. 152 * 153 * @return The ConnectionDescriptor 154 * @throws MalformedURLException 155 */ 156 protected IConnectionDescriptor getTestConnectionDescriptor() throws MalformedURLException { 157 return getDefaultConnectionDescriptor(); 158 } 159 160 /** 161 * Adds all system properties from the given connector to props with the given prefix. No 162 * parameters are allowed to be null. 163 * 164 * @param connector 165 * @param props 166 * @param prefix 167 * prefix to use for server properties 168 * @throws Exception 169 */ 170 public static void getServerProperties(IConnectionHandle connector, Properties props, String prefix) 171 throws Exception { 172 System.out.println("Retrieving system properties (prefixed with '" + prefix + "') ..."); 173 MBeanServerConnection server = connector.getServiceOrThrow(MBeanServerConnection.class); 174 Map<String, String> systemProperties = ConnectionToolkit.getRuntimeBean(server).getSystemProperties(); 175 if (systemProperties != null) { 176 for (Entry<String, String> e : systemProperties.entrySet()) { 177 props.setProperty(prefix + e.getKey(), e.getValue()); 178 } 179 } else { 180 System.out.println("Could not retrieve system properties"); 181 } 182 } 183 184 /** 185 * Adds all system properties from the given ConnectionDescriptor to props with the given 186 * prefix. No parameters are allowed to be null. 187 * 188 * @param connDesc 189 * @param props 190 * @param prefix 191 * prefix to use for server properties 192 * @throws Exception 193 */ 194 public static void getServerProperties(IConnectionDescriptor connDesc, Properties props, String prefix) 195 throws Exception { 196 System.out.println("Connecting to " + connDesc.createJMXServiceURL() + " ..."); 197 IConnectionHandle connectionHandle = createConnectionHandle(connDesc); 198 getServerProperties(connectionHandle, props, prefix); 199 System.out.println("Disconnecting ..."); 200 connectionHandle.close(); 201 } 202 203 /** 204 * @see org.junit.Test#Before 205 */ 206 @Before 207 public synchronized void mcTestCaseBefore() throws Exception { 208 m_connectionDescriptor = getTestConnectionDescriptor(); 209 m_host = ConnectionToolkit.getHostName(m_connectionDescriptor.createJMXServiceURL()); 210 m_connectionHandle = createConnectionHandle(m_connectionDescriptor); 211 Assert.assertTrue(m_connectionHandle.isConnected()); 212 } 213 214 /** 215 * Quick'n'Dirty way to create a {@link IConnectionHandle}. 216 * 217 * @return an {@link IConnectionHandle} 218 * @throws FailedLoginException 219 * @throws ConnectionException 220 */ 221 private static IConnectionHandle createConnectionHandle(IConnectionDescriptor descriptor) 222 throws IOException, FailedLoginException, ConnectionException { 223 return IServerHandle.create(descriptor).connect("Test"); 224 } 225 226 /** 227 * @see org.junit.Test#After 228 */ 229 @After 230 public synchronized void mcTestCaseAfter() throws Exception { 231 if (m_connectionHandle != null) { 232 m_connectionHandle.close(); 233 m_connectionHandle = null; 234 } 235 } 236 237 protected MBeanServerConnection getMBeanServerConnection() 238 throws ConnectionException, ServiceNotAvailableException { 239 return m_connectionHandle.getServiceOrThrow(MBeanServerConnection.class); 240 } 241 242 protected IMBeanHelperService getMBeanHelperService() throws ConnectionException, ServiceNotAvailableException { 243 return m_connectionHandle.getServiceOrThrow(IMBeanHelperService.class); 244 } 245 246 protected IMRIMetadataService getMRIMetadataService() throws ConnectionException, ServiceNotAvailableException { 247 return m_connectionHandle.getServiceOrThrow(IMRIMetadataService.class); 248 } 249 250 protected ISubscriptionService getAttributeSubscriptionService() 251 throws ConnectionException, ServiceNotAvailableException { 252 return m_connectionHandle.getServiceOrThrow(ISubscriptionService.class); 253 } 254 255 protected IDiagnosticCommandService getDiagnosticCommandService() 256 throws ConnectionException, ServiceNotAvailableException { 257 assumeHasDiagnosticCommandsService(m_connectionHandle); 258 return m_connectionHandle.getServiceOrThrow(IDiagnosticCommandService.class); 259 } 260 261 protected IConnectionHandle getConnectionHandle() { 262 return m_connectionHandle; 263 } 264 265 protected void assumeHotSpot8OrLater(IConnectionHandle handle) { 266 Assume.assumeTrue("This test assumes JDK 8 (HotSpot 25) or later!", ConnectionToolkit.isHotSpot(handle) 267 && ConnectionToolkit.isJavaVersionAboveOrEqual(handle, JavaVersionSupport.JDK_8)); 268 } 269 270 protected void assumeHotSpot7u4OrLater(IConnectionHandle handle) { 271 Assume.assumeTrue("This test assumes JDK 7u4 (HotSpot 23) or later!", ConnectionToolkit.isHotSpot(handle) 272 && ConnectionToolkit.isJavaVersionAboveOrEqual(handle, JavaVersionSupport.JDK_7_U_4)); 273 } 274 275 protected void assumeHotSpot7u12OrLater(IConnectionHandle handle) { 276 Assume.assumeTrue("This test assumes JDK 7u12 (HotSpot 24) or later!", ConnectionToolkit.isHotSpot(handle) 277 && ConnectionToolkit.isJavaVersionAboveOrEqual(handle, JavaVersionSupport.JDK_7_U_40)); 278 } 279 280 protected void assumeHasDiagnosticCommandsService(IConnectionHandle handle) { 281 Assume.assumeTrue("This test needs a working diagnostic commands service!", 282 handle.hasService(IDiagnosticCommandService.class)); 283 } 284 }