/* * * Licensed to the Apache Software Foundation (ASF) under one or more contributor license * agreements. See the NOTICE file distributed with this work for additional information regarding * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the License. You may obtain a * copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. * */ package org.apache.geode.tools.pulse.internal.data; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketAddress; import org.apache.geode.tools.pulse.internal.log.PulseLogWriter; import org.apache.geode.tools.pulse.internal.util.ConnectionUtil; /** * This class can be used to connect to a locator and ask it to find a jmx manager. If the locator * can find a jmx manager that is already running it returns it. Otherwise the locator will attempt * to start a jmx manager and then return it. * * This code does not depend on gemfire.jar but in order to do this some of GemFire's internal * serialization codes and byte sequences have been hard coded into this code. * * @since GemFire version 7.0.Beta 2012-09-23 * */ public class JmxManagerFinder { private final static PulseLogWriter LOGGER = PulseLogWriter.getLogger(); /* * public static void main(String[] args) throws IOException { if (args.length != 2) { * System.err.println( * "Usage: JmxManagerFinder locatorHost locatorPort. Expected two arguments but found " + * args.length); return; } String locatorHost = args[0]; int locatorPort = * Integer.parseInt(args[1]); * * InetAddress addr = InetAddress.getByName(locatorHost); JmxManagerInfo locRes = * askLocatorForJmxManager(addr, locatorPort, 15000); * * if (locRes.port == 0) { System.out.println("Locator could not find a jmx manager"); } else { * System.out.println("Locator on host " + locRes.host + " port " + locRes.port + (locRes.ssl ? * " ssl" : "")); } } */ private static final short JMX_MANAGER_LOCATOR_REQUEST = 2150; private static final short JMX_MANAGER_LOCATOR_RESPONSE = 2151; private static final byte DS_FIXED_ID_SHORT = 2; private static final int GOSSIPVERSION = 1001; private static final byte STRING_BYTES = 87; private static final byte NULL_STRING = 69; /** * Describes the location of a jmx manager. If a jmx manager does not exist then port will be 0. * * */ public static class JmxManagerInfo { JmxManagerInfo(String host, int port, boolean ssl) { this.host = host; this.port = port; this.ssl = ssl; } /** * The host/address the jmx manager is listening on. */ public final String host; /** * The port the jmx manager is listening on. */ public final int port; /** * True if the jmx manager is using SSL. */ public final boolean ssl; } /** * Ask a locator to find a jmx manager. The locator will start one if one is not already running. * * @param addr the host address the locator is listening on * @param port the port the locator is listening on * @param timeout the number of milliseconds to wait for a response; 15000 is a reasonable default * @return describes the location of the jmx manager. The port will be zero if no jmx manager was * found. * @throws IOException if a problem occurs trying to connect to the locator or communicate with * it. */ public static JmxManagerInfo askLocatorForJmxManager(InetAddress addr, int port, int timeout, boolean usessl) throws IOException { SocketAddress sockaddr = new InetSocketAddress(addr, port); Socket sock = ConnectionUtil.getSocketFactory(usessl).createSocket(); try { sock.connect(sockaddr, timeout); sock.setSoTimeout(timeout); DataOutputStream out = new DataOutputStream(sock.getOutputStream()); out.writeInt(GOSSIPVERSION); out.writeByte(DS_FIXED_ID_SHORT); out.writeShort(JMX_MANAGER_LOCATOR_REQUEST); out.flush(); DataInputStream in = new DataInputStream(sock.getInputStream()); byte header = in.readByte(); if (header != DS_FIXED_ID_SHORT) { throw new IllegalStateException("Expected " + DS_FIXED_ID_SHORT + " but found " + header); } int msgType = in.readShort(); if (msgType != JMX_MANAGER_LOCATOR_RESPONSE) { throw new IllegalStateException( "Expected " + JMX_MANAGER_LOCATOR_RESPONSE + " but found " + msgType); } byte hostHeader = in.readByte(); String host; if (hostHeader == NULL_STRING) { host = ""; } else if (hostHeader == STRING_BYTES) { int len = in.readUnsignedShort(); byte[] buf = new byte[len]; in.readFully(buf, 0, len); @SuppressWarnings("deprecation") String str = new String(buf, 0); host = str; } else { throw new IllegalStateException( "Expected " + STRING_BYTES + " or " + NULL_STRING + " but found " + hostHeader); } int jmport = in.readInt(); boolean ssl = in.readBoolean(); if (host.equals("")) { jmport = 0; } return new JmxManagerInfo(host, jmport, ssl); } finally { try { sock.close(); } catch (Exception e) { } } } }