blob: 5edc4e00a1277f7e4b7ad533e84bd8c51ee058d5 [file] [log] [blame]
/*
* 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 flex.messaging.util;
import flex.messaging.MessageException;
import flex.messaging.FlexContext;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
/**
* Methods for replacing tokens in config files
* {context.root}, {context-root}, {server.name}, {server-name}, {server.port}, {server-port}.
*
*
*/
public class SettingsReplaceUtil
{
private static final int TOKEN_NOT_SUPPORTED = 10129;
private static final int TOKEN_NOT_SUPPORTED_ANY = 10130;
private static final int PARSE_ERROR_DYNAMIC_URL = 10131;
public static final String SLASH_CONTEXT_PATH_TOKEN = "/{context.root}";
public static final String CONTEXT_PATH_TOKEN = "{context.root}";
public static final String CONTEXT_PATH_ALT_TOKEN = "{context-root}";
public static final String SERVER_NAME_TOKEN = "{server.name}";
public static final String SERVER_NAME_ALT_TOKEN = "{server-name}";
public static final String SERVER_PORT_TOKEN = "{server.port}";
public static final String SERVER_PORT_ALT_TOKEN = "{server-port}";
/**
* Replace {context.root} in the url string.
* @param url the url string
* @param contextPath the context path
* @return String the url string after replacement
*/
public static String replaceContextPath(String url, String contextPath)
{
String token = CONTEXT_PATH_TOKEN;
int contextIndex = url.indexOf(CONTEXT_PATH_ALT_TOKEN);
if (contextIndex != -1)
{
token = CONTEXT_PATH_ALT_TOKEN;
url = StringUtils.substitute(url, CONTEXT_PATH_ALT_TOKEN, CONTEXT_PATH_TOKEN);
}
contextIndex = url.indexOf(CONTEXT_PATH_TOKEN);
if ((contextPath == null) && (contextIndex != -1))
{
MessageException me = new MessageException();
if (FlexContext.getHttpRequest() == null)
me.setMessage(TOKEN_NOT_SUPPORTED, "0", new Object[] {token});
else
me.setMessage(TOKEN_NOT_SUPPORTED, new Object[] {token});
throw me;
}
else if (contextPath != null)
{
if (contextIndex == 0)
{
url = contextPath + url.substring(CONTEXT_PATH_TOKEN.length());
}
else if (contextIndex > 0)
{
// Avoid adding //contextPath to URLs that have a /{context.root} pattern
if (url.indexOf(SLASH_CONTEXT_PATH_TOKEN) != -1)
{
url = StringUtils.substitute(url, SLASH_CONTEXT_PATH_TOKEN, contextPath);
}
else
{
url = StringUtils.substitute(url, CONTEXT_PATH_TOKEN, contextPath);
}
}
}
return url;
}
public static String replaceAllTokensGivenServerName(String url, String contextPath, String serverName,
String serverPort, String serverProtocol)
{
if (url.startsWith("/"))
{
url = serverProtocol + "://{server.name}:{server.port}" + url;
}
url = SettingsReplaceUtil.replaceContextPath(url, contextPath);
String token = SERVER_NAME_TOKEN;
int serverNameIndex = url.indexOf(SERVER_NAME_ALT_TOKEN);
if (serverNameIndex != -1)
{
token = SERVER_NAME_ALT_TOKEN;
url = StringUtils.substitute(url, SERVER_NAME_ALT_TOKEN, SERVER_NAME_TOKEN);
}
serverNameIndex = url.indexOf(SERVER_NAME_TOKEN);
if ((serverName == null) && (serverNameIndex != -1))
{
MessageException me = new MessageException();
me.setMessage(TOKEN_NOT_SUPPORTED, new Object[] {token});
throw me;
}
else if ((serverName != null) && (serverNameIndex != -1))
{
url = StringUtils.substitute(url, SERVER_NAME_TOKEN, serverName);
}
token = SERVER_PORT_TOKEN;
int serverPortIndex = url.indexOf(SERVER_PORT_ALT_TOKEN);
if (serverPortIndex != -1)
{
token = SERVER_PORT_ALT_TOKEN;
url = StringUtils.substitute(url, SERVER_PORT_ALT_TOKEN, SERVER_PORT_TOKEN);
}
serverPortIndex = url.indexOf(SERVER_PORT_TOKEN);
if ((serverPort == null) && (serverPortIndex != -1))
{
MessageException me = new MessageException();
me.setMessage(TOKEN_NOT_SUPPORTED, new Object[] {token});
throw me;
}
else if ((serverPort != null) && (serverPortIndex != -1))
{
url = StringUtils.substitute(url, SERVER_PORT_TOKEN, serverPort);
}
return updateIPv6(url);
}
/**
* Replace all tokens in the urls.
* @param urls a list of urls
* @param contextPath the context path
* @return Set a set of urls after replacement
*/
public static Set replaceAllTokensCalculateServerName(List urls, String contextPath)
{
List contextParsedUrls = new ArrayList(urls.size());
Set newURLs = new HashSet(urls.size());
// first replace context path
for (int i = 0; i < urls.size(); i++)
{
String url = (String)urls.get(i);
url = url.toLowerCase().trim();
url = SettingsReplaceUtil.replaceContextPath(url, contextPath);
contextParsedUrls.add(url);
}
// then replace {server.name}
replaceServerNameWithLocalHost(contextParsedUrls, newURLs);
return newURLs;
}
/**
* Replace {server.name} a horribly complicated way. This is needed to support relative
* URLs. I would like for us to rethink this someday and find a better way to do this
*
* @param urls the list of urls to replace
* @param newURLs the set of new urls
*/
public static void replaceServerNameWithLocalHost(List urls, Set newURLs)
{
for (Iterator iterator = urls.iterator(); iterator.hasNext();)
{
String url = (String) iterator.next();
url = url.toLowerCase().trim();
String token = SERVER_PORT_TOKEN;
int serverPortIndex = url.indexOf(SERVER_PORT_ALT_TOKEN);
if (serverPortIndex != -1)
{
token = SERVER_PORT_ALT_TOKEN;
url = StringUtils.substitute(url, SERVER_PORT_ALT_TOKEN, SERVER_PORT_TOKEN);
}
serverPortIndex = url.indexOf(SERVER_PORT_TOKEN);
if (serverPortIndex != -1)
{
MessageException me = new MessageException();
me.setMessage(TOKEN_NOT_SUPPORTED_ANY, new Object[] {token});
throw me;
}
if (url.indexOf(SERVER_NAME_ALT_TOKEN) != 0)
{
StringUtils.substitute(url, SERVER_NAME_ALT_TOKEN, SERVER_NAME_TOKEN);
}
if (url.indexOf(SERVER_NAME_TOKEN) != 0)
{
try
{
addLocalServerURL(url, "localhost", newURLs);
addLocalServerURL(url, "127.0.0.1", newURLs);
addLocalServerURL(url, "[::1]", newURLs); // for IPv6
InetAddress local = InetAddress.getLocalHost();
addInetAddress(local, url, newURLs);
// if we're using JDK 1.4 or higher, we use NetworkInterface to get the list of hostnames
// and IP addresses.
Enumeration e = NetworkInterface.getNetworkInterfaces();
while (e.hasMoreElements())
{
NetworkInterface address = (NetworkInterface)e.nextElement();
Enumeration e2 = (Enumeration)address.getInetAddresses();
while (e2.hasMoreElements())
{
local = (InetAddress) e2.nextElement();
addInetAddress(local, url, newURLs);
}
}
}
catch(Exception e)
{
MessageException me = new MessageException();
me.setMessage(PARSE_ERROR_DYNAMIC_URL);
throw me;
}
}
else {
addParsedURL(url, newURLs);
}
}
}
private static void addInetAddress(InetAddress local, String url, Set newURLs) throws Exception
{
String localHostAddress = local.getHostAddress();
if (localHostAddress != null)
{
addLocalServerURL(url, localHostAddress, newURLs);
}
String localHostName = local.getHostName();
if (localHostName != null)
{
addLocalServerURL(url, localHostName, newURLs);
InetAddress[] addrs = InetAddress.getAllByName(localHostName);
for (int i = 0; i < addrs.length; i++)
{
InetAddress addr = addrs[i];
String hostName = addr.getHostName();
if (! hostName.equals(localHostName))
{
addLocalServerURL(url, hostName, newURLs);
}
String hostAddress = addr.getHostAddress();
if (! hostAddress.equals(localHostAddress))
{
addLocalServerURL(url, hostAddress, newURLs);
}
}
}
}
private static void addLocalServerURL(String url, String sub, Set newURLs)
{
String toSub = null;
// if ipv6, then add square brackets
if (sub.indexOf(":") != -1)
{
StringBuffer ipv6Sub = new StringBuffer("[");
ipv6Sub.append(sub);
ipv6Sub.append("]");
toSub = ipv6Sub.toString();
}
else
{
toSub = sub;
}
String newUrl = StringUtils.substitute(url, SERVER_NAME_TOKEN, toSub);
addParsedURL(newUrl, newURLs);
}
private static void addParsedURL(String url, Set newURLs)
{
if (! newURLs.contains(url))
{
newURLs.add(updateIPv6(url));
}
}
/**
* Update IPv6 IP address.
* @param src the source IP address string
* @return String the updated IP address string
*/
public static String updateIPv6(String src)
{
// if the ip address has "[" and "]" then it's IPv6, check that it's long form as well
if ((src != null) && (src.indexOf('[') != -1) && (src.indexOf(']') != -1))
{
// then, it's IPv6 and remove the square brackets and update to long form if required
int start = src.indexOf('[');
int end = src.indexOf(']');
StringBuffer updated = new StringBuffer(src.substring(0, start + 1));
updated.append(updateToLongForm(src.substring(start + 1, end)));
updated.append(src.substring(end));
return updated.toString();
}
else
{
return src;
}
}
protected static String updateToLongForm(String src)
{
// Let's see if the short form is in use.
int numberOfTokens = 0;
int doubleColonIndex = src.indexOf("::", 0);
if (doubleColonIndex != -1)
{
String[] hexTokens = src.split("\\:");
for (int i = 0; i < hexTokens.length; i++)
{
if (!hexTokens[i].equals(""))
numberOfTokens++;
}
// Replace missing zeros
int numberOfMissingZeros = 8 - numberOfTokens;
if (numberOfMissingZeros > 0)
{
String replacement = "";
if (!src.startsWith("::"))
replacement = ":";
while (numberOfMissingZeros-- > 0)
replacement += "0:";
src = src.replaceFirst("\\::", replacement);
}
}
return src;
}
}