001/**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.activemq.broker.jmx;
018
019import java.io.IOException;
020import java.util.Hashtable;
021
022import javax.management.ObjectName;
023
024import org.apache.activemq.broker.Broker;
025import org.apache.activemq.broker.TransportConnection;
026import org.apache.activemq.broker.TransportConnector;
027import org.apache.activemq.command.ConnectionInfo;
028import org.apache.activemq.command.Response;
029import org.apache.activemq.thread.TaskRunnerFactory;
030import org.apache.activemq.transport.Transport;
031import org.apache.activemq.util.IOExceptionSupport;
032import org.apache.activemq.util.JMXSupport;
033import org.slf4j.Logger;
034import org.slf4j.LoggerFactory;
035
036/**
037 * A managed transport connection
038 */
039public class ManagedTransportConnection extends TransportConnection {
040    private static final Logger LOG = LoggerFactory.getLogger(ManagedTransportConnection.class);
041
042    private final ManagementContext managementContext;
043    private final ObjectName connectorName;
044    private ConnectionViewMBean mbean;
045
046    private ObjectName byClientIdName;
047    private ObjectName byAddressName;
048
049    private final boolean populateUserName;
050
051    public ManagedTransportConnection(TransportConnector connector, Transport transport, Broker broker,
052                                      TaskRunnerFactory factory, ManagementContext context, ObjectName connectorName)
053        throws IOException {
054        super(connector, transport, broker, factory);
055        this.managementContext = context;
056        this.connectorName = connectorName;
057        this.mbean = new ConnectionView(this, managementContext);
058        this.populateUserName = broker.getBrokerService().isPopulateUserNameInMBeans();
059        if (managementContext.isAllowRemoteAddressInMBeanNames()) {
060            byAddressName = createByAddressObjectName("address", transport.getRemoteAddress());
061            registerMBean(byAddressName);
062        }
063    }
064
065    @Override
066    public void stopAsync() {
067        if (!isStopping()) {
068            synchronized (this) {
069                unregisterMBean(byClientIdName);
070                unregisterMBean(byAddressName);
071                byClientIdName = null;
072                byAddressName = null;
073            }
074        }
075        super.stopAsync();
076    }
077
078    public Response processAddConnection(ConnectionInfo info) throws Exception {
079        Response answer = super.processAddConnection(info);
080        String clientId = info.getClientId();
081        if (populateUserName) {
082            ((ConnectionView) mbean).setUserName(info.getUserName());
083        }
084        if (clientId != null) {
085            if (byClientIdName == null) {
086                byClientIdName = createByClientIdObjectName(clientId);
087                registerMBean(byClientIdName);
088            }
089        }
090        return answer;
091    }
092
093    // Implementation methods
094    // -------------------------------------------------------------------------
095    protected void registerMBean(ObjectName name) {
096        if (name != null) {
097            try {
098                AnnotatedMBean.registerMBean(managementContext, mbean, name);
099            } catch (Throwable e) {
100                LOG.warn("Failed to register MBean: " + name);
101                LOG.debug("Failure reason: " + e, e);
102            }
103        }
104    }
105
106    protected void unregisterMBean(ObjectName name) {
107        if (name != null) {
108            try {
109                managementContext.unregisterMBean(name);
110            } catch (Throwable e) {
111                LOG.warn("Failed to unregister mbean: " + name);
112                LOG.debug("Failure reason: " + e, e);
113            }
114        }
115    }
116
117    protected ObjectName createByAddressObjectName(String type, String value) throws IOException {
118        Hashtable<String, String> map = connectorName.getKeyPropertyList();
119        try {
120            return new ObjectName(connectorName.getDomain() + ":" + "BrokerName="
121                                  + JMXSupport.encodeObjectNamePart((String)map.get("BrokerName")) + ","
122                                  + "Type=Connection," + "ConnectorName="
123                                  + JMXSupport.encodeObjectNamePart((String)map.get("ConnectorName")) + ","
124                                  + "ViewType=" + JMXSupport.encodeObjectNamePart(type) + "," + "Name="
125                                  + JMXSupport.encodeObjectNamePart(value));
126        } catch (Throwable e) {
127            throw IOExceptionSupport.create(e);
128        }
129    }
130
131    protected ObjectName createByClientIdObjectName(String value) throws IOException {
132        Hashtable<String, String> map = connectorName.getKeyPropertyList();
133        try {
134            return new ObjectName(connectorName.getDomain() + ":" + "BrokerName="
135                                  + JMXSupport.encodeObjectNamePart((String)map.get("BrokerName")) + ","
136                                  + "Type=Connection," + "ConnectorName="
137                                  + JMXSupport.encodeObjectNamePart((String)map.get("ConnectorName")) + ","
138                                  + "Connection=" + JMXSupport.encodeObjectNamePart(value));
139        } catch (Throwable e) {
140            throw IOExceptionSupport.create(e);
141        }
142    }
143
144}