/* * (C) 2007-2012 Alibaba Group Holding Limited. * * Licensed 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. * Authors: * wuhua <wq163@163.com> , boyan <killme2008@gmail.com> */ package com.taobao.metamorphosis.tools.utils; import java.io.IOException; import java.net.MalformedURLException; import java.rmi.NotBoundException; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import javax.management.MBeanServerConnection; import javax.management.ObjectInstance; import javax.management.ObjectName; import javax.management.QueryExp; import javax.management.remote.JMXConnector; import javax.management.remote.JMXServiceURL; import javax.management.remote.rmi.RMIConnector; import javax.management.remote.rmi.RMIServer; import javax.rmi.ssl.SslRMIClientSocketFactory; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * * @author �޻� * @since 2011-8-23 ����1:44:37 */ public class JMXClient { private static Log log = LogFactory.getLog(JMXClient.class); private final String hostName; private final int port; private final String userName; private final String password; private final JMXServiceURL address; private JMXConnector jmxConnector; private MBeanServerConnection mbs; private RMIServer stub = null; private final AtomicBoolean closed = new AtomicBoolean(false); private final AtomicInteger referenceCount = new AtomicInteger(0); private static Map<String, JMXClient> cache = Collections.synchronizedMap(new HashMap<String, JMXClient>()); public static JMXClient getJMXClient(String hostName, int port) throws JMXClientException { return getJMXClient(hostName, port, null, null); } public static JMXClient getJMXClient(String hostName, int port, String userName, String password) throws JMXClientException { final String key = getKey(hostName, port, userName, password); JMXClient jmxClient = cache.get(key); if (jmxClient == null) { jmxClient = new JMXClient(hostName, port, userName, password); cache.put(key, jmxClient); } jmxClient.increaseReferece(); log.debug("=============referenceCount:" + jmxClient.referenceCount.get()); return jmxClient; } private JMXClient(String hostName, int port) throws JMXClientException { this(hostName, port, null, null); } private int increaseReferece(){ return this.referenceCount.incrementAndGet(); } private int decreaseReferece(){ int count = this.referenceCount.decrementAndGet(); if(count<0){ this.referenceCount.set(0); } log.debug("=============referenceCount:" + this.referenceCount.get()); return this.referenceCount.get(); } private JMXClient(String hostName, int port, String userName, String password) throws JMXClientException { this.hostName = hostName; this.port = port; this.userName = userName; this.password = password; try { this.address = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + this.hostName + ":" + this.port + "/jmxrmi"); } catch (MalformedURLException e) { throw new JMXClientException(e); } this.connect(); } public Object invoke(ObjectName name, String operationName, Object[] params, String[] signature) throws JMXClientException { this.tryReconnect(); try { return this.mbs.invoke(name, operationName, params, signature); } catch (Exception e) { throw new JMXClientException("error occurred when invoke " + name.getClass() + "#" + operationName, e); } } public ObjectInstance queryMBeanForOne(String name) { try { return this.queryMBeanForOne(new ObjectName(name)); } catch (Exception e) { log.error(e); } return null; } public ObjectInstance queryMBeanForOne(ObjectName name) { Set<ObjectInstance> mBeans = null; try { this.tryReconnect(); mBeans = this.mbs.queryMBeans(name, null); } catch (Exception e) { log.error(e); } if (mBeans == null || mBeans.isEmpty()) { return null; } return mBeans.iterator().next(); } public Set<ObjectInstance> queryMBeans(ObjectName name, QueryExp query) throws JMXClientException { this.tryReconnect(); try { return this.mbs.queryMBeans(name, query); } catch (IOException e) { throw new JMXClientException(e); } } public Object getAttribute(ObjectName name, String attribute) throws JMXClientException { this.tryReconnect(); try { return this.mbs.getAttribute(name, attribute); } catch (Exception e) { // ��ʹ��ͨ���ObjectNameʱ,������һ�� if (log.isDebugEnabled()) { log.debug("û�о�ȷ���ҵ�ObjectName = " + name + ",��ʼ����.."); } try { return this.mbs.getAttribute(this.queryMBeanForOne(name).getObjectName(), attribute); } catch (Exception e1) { throw new JMXClientException(e); } } } public void close() { if (this.decreaseReferece()!=0) { return; } if (this.closed.compareAndSet(false, true)) { this.stub = null; if (this.jmxConnector != null) { try { this.jmxConnector.close(); } catch (IOException e) { // ignore } } cache.remove(getKey(this.hostName, this.port, this.userName, this.password)); log.debug("=================jmx closed!"); } } public String getAddressAsString() { return this.address.toString(); } synchronized private void tryReconnect() throws JMXClientException{ if(this.closed.compareAndSet(true, false)){ this.connect(); } } private void connect() throws JMXClientException { try { if (this.stub == null) { this.checkSslConfig(); } this.jmxConnector = new RMIConnector(this.stub, null); if (this.userName == null && this.password == null) { // this.jmxConnector = // JMXConnectorFactory.connect(this.address); this.jmxConnector.connect(); } else { Map<String, String[]> env = new HashMap<String, String[]>(); env.put(JMXConnector.CREDENTIALS, new String[] { this.userName, this.password }); // this.jmxConnector = JMXConnectorFactory.connect(this.address, // env); this.jmxConnector.connect(env); } this.mbs = this.jmxConnector.getMBeanServerConnection(); } catch (Exception e) { throw new JMXClientException(e); } } private static final SslRMIClientSocketFactory sslRMIClientSocketFactory = new SslRMIClientSocketFactory(); private void checkSslConfig() throws IOException { // Get the reference to the RMI Registry and lookup RMIServer stub Registry registry; try { registry = LocateRegistry.getRegistry(this.hostName, this.port, sslRMIClientSocketFactory); try { this.stub = (RMIServer) registry.lookup("jmxrmi"); } catch (NotBoundException nbe) { throw (IOException) new IOException(nbe.getMessage()).initCause(nbe); } } catch (IOException e) { registry = LocateRegistry.getRegistry(this.hostName, this.port); try { this.stub = (RMIServer) registry.lookup("jmxrmi"); } catch (NotBoundException nbe) { throw (IOException) new IOException(nbe.getMessage()).initCause(nbe); } } } private static String getKey(String hostName, int port, String userName, String password) { return (hostName == null ? "" : hostName) + ":" + port + ":" + (userName == null ? "" : userName) + ":" + (password == null ? "" : password); } }