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