/******************************************************************************* * Copyright (c) 2017 Pivotal, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Pivotal, Inc. - initial API and implementation *******************************************************************************/ package org.springframework.ide.eclipse.boot.dash.model.requestmappings; import java.util.Set; import javax.inject.Provider; import org.springframework.ide.eclipse.boot.launch.util.JMXClient; import org.springsource.ide.eclipse.commons.frameworks.core.ExceptionUtil; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.collect.ImmutableSet; /** * Concretization of abstract {@link ActuatorClient} which uses JMX to connect * to actuator endpoint(s). * * @author Kris De Volder */ public class JMXActuatorClient extends ActuatorClient { private static final String OBJECT_NAME = "org.springframework.boot:type=Endpoint,name=requestMappingEndpoint"; private static final String ATTRIBUTE_NAME = "Data"; private final Provider<Integer> portProvider; private JMXClient client = null; private Integer port = null; public JMXActuatorClient(TypeLookup typeLookup, Provider<Integer> jmxPort) { super(typeLookup); this.portProvider = jmxPort; } @Override protected String getRequestMappingData() throws Exception { try { JMXClient client = getClient(); if (client!=null) { Object obj = client.getAttribute(ATTRIBUTE_NAME); if (obj!=null) { //TODO: Can we avoid conversion to string only to parse it again later? return new ObjectMapper().writeValueAsString(obj); } } } catch (Exception e) { disposeClient(); if (!isExpectedException(e)) { throw e; } } return null; } private static final Set<String> EXPECTED_EXCEPTIONS = ImmutableSet.of( "ConnectException", "InstanceNotFoundException" ); private boolean isExpectedException(Exception _e) { Throwable e = ExceptionUtil.getDeepestCause(_e); String className = e.getClass().getSimpleName(); return EXPECTED_EXCEPTIONS.contains(className); } private synchronized JMXClient getClient() throws Exception { Integer currentPort = portProvider.get(); if (currentPort==null) return null; if (!currentPort.equals(port) || client==null) { disposeClient(); port = currentPort; client = new JMXClient(currentPort, OBJECT_NAME); } return client; } private void disposeClient() { JMXClient client = this.client; if (client!=null) { this.client = null; client.dispose(); } } }