/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.activemq.broker; import java.net.InetAddress; import java.net.URI; import java.net.UnknownHostException; import java.util.HashMap; import java.util.Locale; import java.util.Map; import org.apache.activemq.util.InetAddressUtil; /** * Policy object that controls how a TransportConnector publishes the connector's * address to the outside world. By default the connector will publish itself * using the resolved host name of the bound server socket. * * @org.apache.xbean.XBean */ public class PublishedAddressPolicy { private String clusterClientUriQuery; private PublishedHostStrategy publishedHostStrategy = PublishedHostStrategy.DEFAULT; private Map<Integer, Integer> portMapping = new HashMap<Integer, Integer>(); private Map<String, String> hostMapping = new HashMap<String, String>(); /** * Defines the value of the published host value. */ public enum PublishedHostStrategy { DEFAULT, IPADDRESS, HOSTNAME, FQDN; public static PublishedHostStrategy getValue(String value) { return valueOf(value.toUpperCase(Locale.ENGLISH)); } } /** * Using the supplied TransportConnector this method returns the String that will * be used to update clients with this connector's connect address. * * @param connector * The TransportConnector whose address is to be published. * @return a string URI address that a client can use to connect to this Transport. * @throws Exception */ public URI getPublishableConnectURI(TransportConnector connector) throws Exception { URI connectorURI = connector.getConnectUri(); if (connectorURI == null) { return null; } String scheme = connectorURI.getScheme(); if ("vm".equals(scheme)) { return connectorURI; } String userInfo = getPublishedUserInfoValue(connectorURI.getUserInfo()); String host = getPublishedHostValue(connectorURI.getHost()); if (hostMapping.containsKey(host)) { host = hostMapping.get(host); } int port = connectorURI.getPort(); if (portMapping.containsKey(port)) { port = portMapping.get(port); } String path = getPublishedPathValue(connectorURI.getPath()); String fragment = getPublishedFragmentValue(connectorURI.getFragment()); URI publishedURI = new URI(scheme, userInfo, host, port, path, getClusterClientUriQuery(), fragment); return publishedURI; } public String getPublishableConnectString(TransportConnector connector) throws Exception { return getPublishableConnectURI(connector).toString(); } /** * Subclasses can override what host value is published by implementing alternate * logic for this method. * * @param uriHostEntry * * @return the value published for the given host. * * @throws UnknownHostException */ protected String getPublishedHostValue(String uriHostEntry) throws UnknownHostException { // By default we just republish what was already present. String result = uriHostEntry; if (this.publishedHostStrategy.equals(PublishedHostStrategy.IPADDRESS)) { InetAddress address = InetAddress.getByName(uriHostEntry); result = address.getHostAddress(); } else if (this.publishedHostStrategy.equals(PublishedHostStrategy.HOSTNAME)) { InetAddress address = InetAddress.getByName(uriHostEntry); if (address.isAnyLocalAddress()) { // make it more human readable and useful, an alternative to 0.0.0.0 result = InetAddressUtil.getLocalHostName(); } else { result = address.getHostName(); } } else if (this.publishedHostStrategy.equals(PublishedHostStrategy.FQDN)) { InetAddress address = InetAddress.getByName(uriHostEntry); if (address.isAnyLocalAddress()) { // make it more human readable and useful, an alternative to 0.0.0.0 result = InetAddressUtil.getLocalHostName(); } else { result = address.getCanonicalHostName(); } } return result; } /** * Subclasses can override what path value is published by implementing alternate * logic for this method. By default this method simply returns what was already * set as the Path value in the original URI. * * @param uriPathEntry * The original value of the URI path. * * @return the desired value for the published URI's path. */ protected String getPublishedPathValue(String uriPathEntry) { return uriPathEntry; } /** * Subclasses can override what host value is published by implementing alternate * logic for this method. By default this method simply returns what was already * set as the Fragment value in the original URI. * * @param uriFragmentEntry * The original value of the URI Fragment. * * @return the desired value for the published URI's Fragment. */ protected String getPublishedFragmentValue(String uriFragmentEntry) { return uriFragmentEntry; } /** * Subclasses can override what user info value is published by implementing alternate * logic for this method. By default this method simply returns what was already * set as the UserInfo value in the original URI. * * @param uriUserInfoEntry * The original value of the URI user info. * * @return the desired value for the published URI's user info. */ protected String getPublishedUserInfoValue(String uriUserInfoEntry) { return uriUserInfoEntry; } /** * Gets the URI query that's configured on the published URI that's sent to client's * when the cluster info is updated. * * @return the clusterClientUriQuery */ public String getClusterClientUriQuery() { return clusterClientUriQuery; } /** * Sets the URI query that's configured on the published URI that's sent to client's * when the cluster info is updated. * * @param clusterClientUriQuery the clusterClientUriQuery to set */ public void setClusterClientUriQuery(String clusterClientUriQuery) { this.clusterClientUriQuery = clusterClientUriQuery; } /** * @return the publishedHostStrategy */ public PublishedHostStrategy getPublishedHostStrategy() { return publishedHostStrategy; } /** * @param strategy the publishedHostStrategy to set */ public void setPublishedHostStrategy(PublishedHostStrategy strategy) { this.publishedHostStrategy = strategy; } /** * @param strategy the publishedHostStrategy to set */ public void setPublishedHostStrategy(String strategy) { this.publishedHostStrategy = PublishedHostStrategy.getValue(strategy); } /** * @param portMapping map the ports in restrictive environments */ public void setPortMapping(Map<Integer, Integer> portMapping) { this.portMapping = portMapping; } public Map<Integer, Integer> getPortMapping() { return this.portMapping; } /** * @param hostMapping map the resolved hosts */ public void setHostMapping(Map<String, String> hostMapping) { this.hostMapping = hostMapping; } public Map<String, String> getHostMapping() { return hostMapping; } }