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; 018 019import java.net.InetAddress; 020import java.net.URI; 021import java.net.UnknownHostException; 022import java.util.HashMap; 023import java.util.Locale; 024import java.util.Map; 025 026import org.apache.activemq.transport.vm.VMTransport; 027import org.apache.activemq.util.InetAddressUtil; 028 029/** 030 * Policy object that controls how a TransportConnector publishes the connector's 031 * address to the outside world. By default the connector will publish itself 032 * using the resolved host name of the bound server socket. 033 * 034 * @org.apache.xbean.XBean 035 */ 036public class PublishedAddressPolicy { 037 038 private String clusterClientUriQuery; 039 private PublishedHostStrategy publishedHostStrategy = PublishedHostStrategy.DEFAULT; 040 private Map<Integer, Integer> portMapping = new HashMap<Integer, Integer>(); 041 private Map<String, String> hostMapping = new HashMap<String, String>(); 042 043 /** 044 * Defines the value of the published host value. 045 */ 046 public enum PublishedHostStrategy { 047 DEFAULT, 048 IPADDRESS, 049 HOSTNAME, 050 FQDN; 051 052 public static PublishedHostStrategy getValue(String value) { 053 return valueOf(value.toUpperCase(Locale.ENGLISH)); 054 } 055 } 056 057 /** 058 * Using the supplied TransportConnector this method returns the String that will 059 * be used to update clients with this connector's connect address. 060 * 061 * @param connector 062 * The TransportConnector whose address is to be published. 063 * @return a string URI address that a client can use to connect to this Transport. 064 * @throws Exception 065 */ 066 public URI getPublishableConnectURI(TransportConnector connector) throws Exception { 067 068 URI connectorURI = connector.getConnectUri(); 069 070 if (connectorURI == null) { 071 return null; 072 } 073 074 String scheme = connectorURI.getScheme(); 075 if ("vm".equals(scheme)) { 076 return connectorURI; 077 } 078 079 String userInfo = getPublishedUserInfoValue(connectorURI.getUserInfo()); 080 String host = getPublishedHostValue(connectorURI.getHost()); 081 if (hostMapping.containsKey(host)) { 082 host = hostMapping.get(host); 083 } 084 085 int port = connectorURI.getPort(); 086 if (portMapping.containsKey(port)) { 087 port = portMapping.get(port); 088 } 089 String path = getPublishedPathValue(connectorURI.getPath()); 090 String fragment = getPublishedFragmentValue(connectorURI.getFragment()); 091 092 URI publishedURI = new URI(scheme, userInfo, host, port, path, getClusterClientUriQuery(), fragment); 093 return publishedURI; 094 } 095 096 public String getPublishableConnectString(TransportConnector connector) throws Exception { 097 return getPublishableConnectURI(connector).toString(); 098 } 099 100 /** 101 * Subclasses can override what host value is published by implementing alternate 102 * logic for this method. 103 * 104 * @param uriHostEntry 105 * @return 106 * @throws UnknownHostException 107 */ 108 protected String getPublishedHostValue(String uriHostEntry) throws UnknownHostException { 109 110 // By default we just republish what was already present. 111 String result = uriHostEntry; 112 113 if (this.publishedHostStrategy.equals(PublishedHostStrategy.IPADDRESS)) { 114 InetAddress address = InetAddress.getByName(uriHostEntry); 115 result = address.getHostAddress(); 116 } else if (this.publishedHostStrategy.equals(PublishedHostStrategy.HOSTNAME)) { 117 InetAddress address = InetAddress.getByName(uriHostEntry); 118 if (address.isAnyLocalAddress()) { 119 // make it more human readable and useful, an alternative to 0.0.0.0 120 result = InetAddressUtil.getLocalHostName(); 121 } else { 122 result = address.getHostName(); 123 } 124 } else if (this.publishedHostStrategy.equals(PublishedHostStrategy.FQDN)) { 125 InetAddress address = InetAddress.getByName(uriHostEntry); 126 if (address.isAnyLocalAddress()) { 127 // make it more human readable and useful, an alternative to 0.0.0.0 128 result = InetAddressUtil.getLocalHostName(); 129 } else { 130 result = address.getCanonicalHostName(); 131 } 132 } 133 134 return result; 135 } 136 137 /** 138 * Subclasses can override what path value is published by implementing alternate 139 * logic for this method. By default this method simply returns what was already 140 * set as the Path value in the original URI. 141 * 142 * @param uriPathEntry 143 * The original value of the URI path. 144 * 145 * @return the desired value for the published URI's path. 146 */ 147 protected String getPublishedPathValue(String uriPathEntry) { 148 return uriPathEntry; 149 } 150 151 /** 152 * Subclasses can override what host value is published by implementing alternate 153 * logic for this method. By default this method simply returns what was already 154 * set as the Fragment value in the original URI. 155 * 156 * @param uriFragmentEntry 157 * The original value of the URI Fragment. 158 * 159 * @return the desired value for the published URI's Fragment. 160 */ 161 protected String getPublishedFragmentValue(String uriFragmentEntry) { 162 return uriFragmentEntry; 163 } 164 165 /** 166 * Subclasses can override what user info value is published by implementing alternate 167 * logic for this method. By default this method simply returns what was already 168 * set as the UserInfo value in the original URI. 169 * 170 * @param uriUserInfoEntry 171 * The original value of the URI user info. 172 * 173 * @return the desired value for the published URI's user info. 174 */ 175 protected String getPublishedUserInfoValue(String uriUserInfoEntry) { 176 return uriUserInfoEntry; 177 } 178 179 /** 180 * Gets the URI query that's configured on the published URI that's sent to client's 181 * when the cluster info is updated. 182 * 183 * @return the clusterClientUriQuery 184 */ 185 public String getClusterClientUriQuery() { 186 return clusterClientUriQuery; 187 } 188 189 /** 190 * Sets the URI query that's configured on the published URI that's sent to client's 191 * when the cluster info is updated. 192 * 193 * @param clusterClientUriQuery the clusterClientUriQuery to set 194 */ 195 public void setClusterClientUriQuery(String clusterClientUriQuery) { 196 this.clusterClientUriQuery = clusterClientUriQuery; 197 } 198 199 /** 200 * @return the publishedHostStrategy 201 */ 202 public PublishedHostStrategy getPublishedHostStrategy() { 203 return publishedHostStrategy; 204 } 205 206 /** 207 * @param strategy the publishedHostStrategy to set 208 */ 209 public void setPublishedHostStrategy(PublishedHostStrategy strategy) { 210 this.publishedHostStrategy = strategy; 211 } 212 213 /** 214 * @param strategy the publishedHostStrategy to set 215 */ 216 public void setPublishedHostStrategy(String strategy) { 217 this.publishedHostStrategy = PublishedHostStrategy.getValue(strategy); 218 } 219 220 /** 221 * @param portMapping map the ports in restrictive environments 222 */ 223 public void setPortMapping(Map<Integer, Integer> portMapping) { 224 this.portMapping = portMapping; 225 } 226 227 public Map<Integer, Integer> getPortMapping() { 228 return this.portMapping; 229 } 230 231 /** 232 * @param hostMapping map the resolved hosts 233 */ 234 public void setHostMapping(Map<String, String> hostMapping) { 235 this.hostMapping = hostMapping; 236 } 237 238 public Map<String, String> getHostMapping() { 239 return hostMapping; 240 } 241}