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; 024 025import org.apache.activemq.util.InetAddressUtil; 026 027/** 028 * Policy object that controls how a TransportConnector publishes the connector's 029 * address to the outside world. By default the connector will publish itself 030 * using the resolved host name of the bound server socket. 031 * 032 * @org.apache.xbean.XBean 033 */ 034public class PublishedAddressPolicy { 035 036 private String clusterClientUriQuery; 037 private PublishedHostStrategy publishedHostStrategy = PublishedHostStrategy.DEFAULT; 038 private HashMap<Integer, Integer> portMapping = new HashMap<Integer, Integer>(); 039 040 /** 041 * Defines the value of the published host value. 042 */ 043 public enum PublishedHostStrategy { 044 DEFAULT, 045 IPADDRESS, 046 HOSTNAME, 047 FQDN; 048 049 public static PublishedHostStrategy getValue(String value) { 050 return valueOf(value.toUpperCase(Locale.ENGLISH)); 051 } 052 } 053 054 /** 055 * Using the supplied TransportConnector this method returns the String that will 056 * be used to update clients with this connector's connect address. 057 * 058 * @param connector 059 * The TransportConnector whose address is to be published. 060 * @return a string URI address that a client can use to connect to this Transport. 061 * @throws Exception 062 */ 063 public URI getPublishableConnectURI(TransportConnector connector) throws Exception { 064 065 URI connectorURI = connector.getConnectUri(); 066 067 if (connectorURI == null) { 068 return null; 069 } 070 071 String scheme = connectorURI.getScheme(); 072 if ("vm".equals(scheme)) { 073 return connectorURI; 074 } 075 076 String userInfo = getPublishedUserInfoValue(connectorURI.getUserInfo()); 077 String host = getPublishedHostValue(connectorURI.getHost()); 078 int port = connectorURI.getPort(); 079 if (portMapping.containsKey(port)) { 080 port = portMapping.get(port); 081 } 082 String path = getPublishedPathValue(connectorURI.getPath()); 083 String fragment = getPublishedFragmentValue(connectorURI.getFragment()); 084 085 URI publishedURI = new URI(scheme, userInfo, host, port, path, getClusterClientUriQuery(), fragment); 086 return publishedURI; 087 } 088 089 public String getPublishableConnectString(TransportConnector connector) throws Exception { 090 return getPublishableConnectURI(connector).toString(); 091 } 092 093 /** 094 * Subclasses can override what host value is published by implementing alternate 095 * logic for this method. 096 * 097 * @param uriHostEntry 098 * 099 * @return the value published for the given host. 100 * 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 strategy the publishedHostStrategy to set 203 */ 204 public void setPublishedHostStrategy(PublishedHostStrategy strategy) { 205 this.publishedHostStrategy = strategy; 206 } 207 208 /** 209 * @param strategy 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(HashMap<Integer, Integer> portMapping) { 219 this.portMapping = portMapping; 220 } 221}