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 String userInfo = getPublishedUserInfoValue(connectorURI.getUserInfo()); 075 String host = getPublishedHostValue(connectorURI.getHost()); 076 if (hostMapping.containsKey(host)) { 077 host = hostMapping.get(host); 078 } 079 080 int port = connectorURI.getPort(); 081 if (portMapping.containsKey(port)) { 082 port = portMapping.get(port); 083 } 084 String path = getPublishedPathValue(connectorURI.getPath()); 085 String fragment = getPublishedFragmentValue(connectorURI.getFragment()); 086 087 URI publishedURI = new URI(scheme, userInfo, host, port, path, getClusterClientUriQuery(), fragment); 088 return publishedURI; 089 } 090 091 public String getPublishableConnectString(TransportConnector connector) throws Exception { 092 return getPublishableConnectURI(connector).toString(); 093 } 094 095 /** 096 * Subclasses can override what host value is published by implementing alternate 097 * logic for this method. 098 * 099 * @param uriHostEntry 100 * @return 101 * @throws UnknownHostException 102 */ 103 protected String getPublishedHostValue(String uriHostEntry) throws UnknownHostException { 104 105 // By default we just republish what was already present. 106 String result = uriHostEntry; 107 108 if (this.publishedHostStrategy.equals(PublishedHostStrategy.IPADDRESS)) { 109 InetAddress address = InetAddress.getByName(uriHostEntry); 110 result = address.getHostAddress(); 111 } else if (this.publishedHostStrategy.equals(PublishedHostStrategy.HOSTNAME)) { 112 InetAddress address = InetAddress.getByName(uriHostEntry); 113 if (address.isAnyLocalAddress()) { 114 // make it more human readable and useful, an alternative to 0.0.0.0 115 result = InetAddressUtil.getLocalHostName(); 116 } else { 117 result = address.getHostName(); 118 } 119 } else if (this.publishedHostStrategy.equals(PublishedHostStrategy.FQDN)) { 120 InetAddress address = InetAddress.getByName(uriHostEntry); 121 if (address.isAnyLocalAddress()) { 122 // make it more human readable and useful, an alternative to 0.0.0.0 123 result = InetAddressUtil.getLocalHostName(); 124 } else { 125 result = address.getCanonicalHostName(); 126 } 127 } 128 129 return result; 130 } 131 132 /** 133 * Subclasses can override what path value is published by implementing alternate 134 * logic for this method. By default this method simply returns what was already 135 * set as the Path value in the original URI. 136 * 137 * @param uriPathEntry 138 * The original value of the URI path. 139 * 140 * @return the desired value for the published URI's path. 141 */ 142 protected String getPublishedPathValue(String uriPathEntry) { 143 return uriPathEntry; 144 } 145 146 /** 147 * Subclasses can override what host value is published by implementing alternate 148 * logic for this method. By default this method simply returns what was already 149 * set as the Fragment value in the original URI. 150 * 151 * @param uriFragmentEntry 152 * The original value of the URI Fragment. 153 * 154 * @return the desired value for the published URI's Fragment. 155 */ 156 protected String getPublishedFragmentValue(String uriFragmentEntry) { 157 return uriFragmentEntry; 158 } 159 160 /** 161 * Subclasses can override what user info value is published by implementing alternate 162 * logic for this method. By default this method simply returns what was already 163 * set as the UserInfo value in the original URI. 164 * 165 * @param uriUserInfoEntry 166 * The original value of the URI user info. 167 * 168 * @return the desired value for the published URI's user info. 169 */ 170 protected String getPublishedUserInfoValue(String uriUserInfoEntry) { 171 return uriUserInfoEntry; 172 } 173 174 /** 175 * Gets the URI query that's configured on the published URI that's sent to client's 176 * when the cluster info is updated. 177 * 178 * @return the clusterClientUriQuery 179 */ 180 public String getClusterClientUriQuery() { 181 return clusterClientUriQuery; 182 } 183 184 /** 185 * Sets the URI query that's configured on the published URI that's sent to client's 186 * when the cluster info is updated. 187 * 188 * @param clusterClientUriQuery the clusterClientUriQuery to set 189 */ 190 public void setClusterClientUriQuery(String clusterClientUriQuery) { 191 this.clusterClientUriQuery = clusterClientUriQuery; 192 } 193 194 /** 195 * @return the publishedHostStrategy 196 */ 197 public PublishedHostStrategy getPublishedHostStrategy() { 198 return publishedHostStrategy; 199 } 200 201 /** 202 * @param publishedHostStrategy the publishedHostStrategy to set 203 */ 204 public void setPublishedHostStrategy(PublishedHostStrategy strategy) { 205 this.publishedHostStrategy = strategy; 206 } 207 208 /** 209 * @param publishedHostStrategy the publishedHostStrategy to set 210 */ 211 public void setPublishedHostStrategy(String strategy) { 212 this.publishedHostStrategy = PublishedHostStrategy.getValue(strategy); 213 } 214 215 /** 216 * @param portMapping map the ports in restrictive environments 217 */ 218 public void setPortMapping(Map<Integer, Integer> portMapping) { 219 this.portMapping = portMapping; 220 } 221 222 public Map<Integer, Integer> getPortMapping() { 223 return this.portMapping; 224 } 225 226 /** 227 * @param hostMapping map the resolved hosts 228 */ 229 public void setHostMapping(Map<String, String> hostMapping) { 230 this.hostMapping = hostMapping; 231 } 232 233 public Map<String, String> getHostMapping() { 234 return hostMapping; 235 } 236}