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 org.apache.activemq.broker.Broker;
020import org.apache.activemq.broker.TransportConnection;
021import org.apache.activemq.broker.TransportConnector;
022import org.apache.activemq.command.ConnectionInfo;
023import org.apache.activemq.command.Response;
024import org.apache.activemq.thread.TaskRunnerFactory;
025import org.apache.activemq.transport.Transport;
026import org.apache.activemq.util.IOExceptionSupport;
027import org.apache.activemq.util.JMXSupport;
028import org.slf4j.Logger;
029import org.slf4j.LoggerFactory;
030import java.io.IOException;
031import java.util.Hashtable;
032import javax.management.ObjectName;
033
034/**
035 * A managed transport connection
036 * 
037 * 
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    public ManagedTransportConnection(TransportConnector connector, Transport transport, Broker broker,
050                                      TaskRunnerFactory factory, ManagementContext context, ObjectName connectorName)
051        throws IOException {
052        super(connector, transport, broker, factory);
053        this.managementContext = context;
054        this.connectorName = connectorName;
055        this.mbean = new ConnectionView(this);
056        byAddressName = createByAddressObjectName("address", transport.getRemoteAddress());
057        registerMBean(byAddressName);
058    }
059
060    public void doStop() throws Exception {
061        if (isStarting()) {
062            setPendingStop(true);
063            return;
064        }
065        synchronized (this) {
066            unregisterMBean(byClientIdName);
067            unregisterMBean(byAddressName);
068            byClientIdName = null;
069            byAddressName = null;
070        }
071        super.doStop();
072    }
073
074    /**
075     * Sets the connection ID of this connection. On startup this connection ID
076     * is set to an incrementing counter; once the client registers it is set to
077     * the clientID of the JMS client.
078     */
079    public void setConnectionId(String connectionId) throws IOException {
080    }
081
082    public Response processAddConnection(ConnectionInfo info) throws Exception {
083        Response answer = super.processAddConnection(info);
084        String clientId = info.getClientId();
085        if (clientId != null) {
086            if (byClientIdName == null) {
087                byClientIdName = createByClientIdObjectName(clientId);
088                registerMBean(byClientIdName);
089            }
090        }
091        return answer;
092    }
093
094    // Implementation methods
095    // -------------------------------------------------------------------------
096    protected void registerMBean(ObjectName name) {
097        if (name != null) {
098            try {
099                AnnotatedMBean.registerMBean(managementContext, mbean, name);
100            } catch (Throwable e) {
101                LOG.warn("Failed to register MBean: " + name);
102                LOG.debug("Failure reason: " + e, e);
103            }
104        }
105    }
106
107    protected void unregisterMBean(ObjectName name) {
108        if (name != null) {
109            try {
110                managementContext.unregisterMBean(name);
111            } catch (Throwable e) {
112                LOG.warn("Failed to unregister mbean: " + name);
113                LOG.debug("Failure reason: " + e, e);
114            }
115        }
116    }
117
118    protected ObjectName createByAddressObjectName(String type, String value) throws IOException {
119        // Build the object name for the destination
120        Hashtable map = connectorName.getKeyPropertyList();
121        try {
122            return new ObjectName(connectorName.getDomain() + ":" + "BrokerName="
123                                  + JMXSupport.encodeObjectNamePart((String)map.get("BrokerName")) + ","
124                                  + "Type=Connection," + "ConnectorName="
125                                  + JMXSupport.encodeObjectNamePart((String)map.get("ConnectorName")) + ","
126                                  + "ViewType=" + JMXSupport.encodeObjectNamePart(type) + "," + "Name="
127                                  + JMXSupport.encodeObjectNamePart(value));
128        } catch (Throwable e) {
129            throw IOExceptionSupport.create(e);
130        }
131    }
132
133    protected ObjectName createByClientIdObjectName(String value) throws IOException {
134        // Build the object name for the destination
135        Hashtable map = connectorName.getKeyPropertyList();
136        try {
137            return new ObjectName(connectorName.getDomain() + ":" + "BrokerName="
138                                  + JMXSupport.encodeObjectNamePart((String)map.get("BrokerName")) + ","
139                                  + "Type=Connection," + "ConnectorName="
140                                  + JMXSupport.encodeObjectNamePart((String)map.get("ConnectorName")) + ","
141                                  + "Connection=" + JMXSupport.encodeObjectNamePart(value));
142        } catch (Throwable e) {
143            throw IOExceptionSupport.create(e);
144        }
145    }
146
147}