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.network; 018 019import java.net.URI; 020import java.net.URISyntaxException; 021import java.util.Collection; 022import java.util.HashSet; 023import java.util.List; 024import java.util.Set; 025import java.util.concurrent.ConcurrentHashMap; 026 027import javax.management.MalformedObjectNameException; 028import javax.management.ObjectName; 029 030import org.apache.activemq.Service; 031import org.apache.activemq.broker.BrokerService; 032import org.apache.activemq.broker.jmx.AnnotatedMBean; 033import org.apache.activemq.broker.jmx.BrokerMBeanSupport; 034import org.apache.activemq.broker.jmx.NetworkBridgeView; 035import org.apache.activemq.broker.jmx.NetworkBridgeViewMBean; 036import org.apache.activemq.command.ActiveMQDestination; 037import org.apache.activemq.command.ConsumerId; 038import org.apache.activemq.transport.Transport; 039import org.apache.activemq.transport.TransportFactory; 040import org.apache.activemq.util.ServiceStopper; 041import org.apache.activemq.util.ServiceSupport; 042import org.slf4j.Logger; 043import org.slf4j.LoggerFactory; 044 045/** 046 * Connector class for bridging broker networks. 047 */ 048public abstract class NetworkConnector extends NetworkBridgeConfiguration implements Service { 049 050 private static final Logger LOG = LoggerFactory.getLogger(NetworkConnector.class); 051 protected URI localURI; 052 protected ConnectionFilter connectionFilter; 053 protected ConcurrentHashMap<URI, NetworkBridge> bridges = new ConcurrentHashMap<URI, NetworkBridge>(); 054 055 protected ServiceSupport serviceSupport = new ServiceSupport() { 056 057 @Override 058 protected void doStart() throws Exception { 059 handleStart(); 060 } 061 062 @Override 063 protected void doStop(ServiceStopper stopper) throws Exception { 064 handleStop(stopper); 065 } 066 }; 067 068 private Set<ActiveMQDestination> durableDestinations; 069 070 private BrokerService brokerService; 071 private ObjectName objectName; 072 073 public NetworkConnector() { 074 } 075 076 public NetworkConnector(URI localURI) { 077 this.localURI = localURI; 078 } 079 080 public URI getLocalUri() throws URISyntaxException { 081 return localURI; 082 } 083 084 public void setLocalUri(URI localURI) { 085 this.localURI = localURI; 086 } 087 088 /** 089 * @return Returns the durableDestinations. 090 */ 091 public Set<ActiveMQDestination> getDurableDestinations() { 092 return durableDestinations; 093 } 094 095 /** 096 * @param durableDestinations The durableDestinations to set. 097 */ 098 public void setDurableDestinations(Set<ActiveMQDestination> durableDestinations) { 099 this.durableDestinations = durableDestinations; 100 } 101 102 103 public void addExcludedDestination(ActiveMQDestination destiantion) { 104 this.excludedDestinations.add(destiantion); 105 } 106 107 108 public void addStaticallyIncludedDestination(ActiveMQDestination destiantion) { 109 this.staticallyIncludedDestinations.add(destiantion); 110 } 111 112 113 public void addDynamicallyIncludedDestination(ActiveMQDestination destiantion) { 114 this.dynamicallyIncludedDestinations.add(destiantion); 115 } 116 117 public ConnectionFilter getConnectionFilter() { 118 return connectionFilter; 119 } 120 121 public void setConnectionFilter(ConnectionFilter connectionFilter) { 122 this.connectionFilter = connectionFilter; 123 } 124 125 // Implementation methods 126 // ------------------------------------------------------------------------- 127 protected NetworkBridge configureBridge(DemandForwardingBridgeSupport result) { 128 List<ActiveMQDestination> destsList = getDynamicallyIncludedDestinations(); 129 ActiveMQDestination dests[] = destsList.toArray(new ActiveMQDestination[destsList.size()]); 130 result.setDynamicallyIncludedDestinations(dests); 131 destsList = getExcludedDestinations(); 132 dests = destsList.toArray(new ActiveMQDestination[destsList.size()]); 133 result.setExcludedDestinations(dests); 134 destsList = getStaticallyIncludedDestinations(); 135 dests = destsList.toArray(new ActiveMQDestination[destsList.size()]); 136 result.setStaticallyIncludedDestinations(dests); 137 if (durableDestinations != null) { 138 139 HashSet<ActiveMQDestination> topics = new HashSet<ActiveMQDestination>(); 140 for (ActiveMQDestination d : durableDestinations) { 141 if( d.isTopic() ) { 142 topics.add(d); 143 } 144 } 145 146 ActiveMQDestination[] dest = new ActiveMQDestination[topics.size()]; 147 dest = topics.toArray(dest); 148 result.setDurableDestinations(dest); 149 } 150 return result; 151 } 152 153 protected Transport createLocalTransport() throws Exception { 154 return TransportFactory.connect(localURI); 155 } 156 157 @Override 158 public void start() throws Exception { 159 serviceSupport.start(); 160 } 161 162 @Override 163 public void stop() throws Exception { 164 serviceSupport.stop(); 165 } 166 167 protected void handleStart() throws Exception { 168 if (localURI == null) { 169 throw new IllegalStateException("You must configure the 'localURI' property"); 170 } 171 LOG.info("Network Connector {} started", this); 172 } 173 174 protected void handleStop(ServiceStopper stopper) throws Exception { 175 LOG.info("Network Connector {} stopped", this); 176 } 177 178 public boolean isStarted() { 179 return serviceSupport.isStarted(); 180 } 181 182 public boolean isStopped() { 183 return serviceSupport.isStopped(); 184 } 185 186 public boolean isStopping() { 187 return serviceSupport.isStopping(); 188 } 189 190 public ObjectName getObjectName() { 191 return objectName; 192 } 193 194 public void setObjectName(ObjectName objectName) { 195 this.objectName = objectName; 196 } 197 198 public BrokerService getBrokerService() { 199 return brokerService; 200 } 201 202 public void setBrokerService(BrokerService brokerService) { 203 this.brokerService = brokerService; 204 } 205 206 protected void registerNetworkBridgeMBean(NetworkBridge bridge) { 207 if (!getBrokerService().isUseJmx()) { 208 return; 209 } 210 NetworkBridgeViewMBean view = new NetworkBridgeView(bridge); 211 try { 212 ObjectName objectName = createNetworkBridgeObjectName(bridge); 213 AnnotatedMBean.registerMBean(getBrokerService().getManagementContext(), view, objectName); 214 } catch (Throwable e) { 215 LOG.debug("Network bridge could not be registered in JMX: {}", e.getMessage(), e); 216 } 217 } 218 219 protected void unregisterNetworkBridgeMBean(NetworkBridge bridge) { 220 if (!getBrokerService().isUseJmx()) { 221 return; 222 } 223 try { 224 ObjectName objectName = createNetworkBridgeObjectName(bridge); 225 getBrokerService().getManagementContext().unregisterMBean(objectName); 226 } catch (Throwable e) { 227 LOG.debug("Network bridge could not be unregistered in JMX: {}", e.getMessage(), e); 228 } 229 } 230 231 protected ObjectName createNetworkBridgeObjectName(NetworkBridge bridge) throws MalformedObjectNameException { 232 return BrokerMBeanSupport.createNetworkBridgeObjectName(getObjectName(), bridge.getRemoteAddress()); 233 } 234 235 // ask all the bridges as we can't know to which this consumer is tied 236 public boolean removeDemandSubscription(ConsumerId consumerId) { 237 boolean removeSucceeded = false; 238 for (NetworkBridge bridge : bridges.values()) { 239 if (bridge instanceof DemandForwardingBridgeSupport) { 240 DemandForwardingBridgeSupport demandBridge = (DemandForwardingBridgeSupport) bridge; 241 if (demandBridge.removeDemandSubscriptionByLocalId(consumerId)) { 242 removeSucceeded = true; 243 break; 244 } 245 } 246 } 247 return removeSucceeded; 248 } 249 250 public Collection<NetworkBridge> activeBridges() { 251 return bridges.values(); 252 } 253}