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