/*
* JBoss, Home of Professional Open Source.
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership. Some portions may be licensed
* to Red Hat, Inc. under one or more contributor license agreements.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*/
package org.teiid.net;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;
import org.teiid.core.util.StringUtil;
import org.teiid.jdbc.JDBCPlugin;
/**
* Class defines the URL in the Teiid.
*
* @since 4.2
*/
public class TeiidURL {
public static interface JDBC {
// constant indicating Virtual database name
public static final String VDB_NAME = "VirtualDatabaseName"; //$NON-NLS-1$
// constant indicating Virtual database version
public static final String VDB_VERSION = "VirtualDatabaseVersion"; //$NON-NLS-1$
// constant for vdb version part of serverURL
public static final String VERSION = "version"; //$NON-NLS-1$
}
public static interface CONNECTION {
public static final String CLIENT_IP_ADDRESS = "clientIpAddress"; //$NON-NLS-1$
public static final String CLIENT_HOSTNAME = "clientHostName"; //$NON-NLS-1$
public static final String CLIENT_MAC = "clientMAC"; //$NON-NLS-1$
/**
* If true, will automatically select a new server instance after a communication exception.
* @since 5.6
*/
public static final String AUTO_FAILOVER = "autoFailover"; //$NON-NLS-1$
/**
* A plugable discovery strategy for the client. Defaults to using the AdminApi.
*/
public static final String DISCOVERY_STRATEGY = "discoveryStategy"; //$NON-NLS-1$
public static final String SERVER_URL = "serverURL"; //$NON-NLS-1$
/**
* Non-secure Protocol.
*/
public static final String NON_SECURE_PROTOCOL = "mm"; //$NON-NLS-1$
/**
* Secure Protocol.
*/
public static final String SECURE_PROTOCOL = "mms"; //$NON-NLS-1$
// name of the application which is obtaining connection
public static final String APP_NAME = "ApplicationName"; //$NON-NLS-1$
// constant for username part of url
public static final String USER_NAME = "user"; //$NON-NLS-1$
// constant for password part of url
public static final String PASSWORD = "password"; //$NON-NLS-1$
public static final String PASSTHROUGH_AUTHENTICATION = "PassthroughAuthentication"; //$NON-NLS-1$
public static final String JAAS_NAME = "jaasName"; //$NON-NLS-1$
public static final String KERBEROS_SERVICE_PRINCIPLE_NAME = "kerberosServicePrincipleName"; //$NON-NLS-1$;
public static final String ENCRYPT_REQUESTS = "encryptRequests"; //$NON-NLS-1$;
public static final String LOGIN_TIMEOUT = "loginTimeout"; //$NON-NLS-1$
}
public static final String DOT_DELIMITER = "."; //$NON-NLS-1$
public static final String DOUBLE_SLASH_DELIMITER = "//"; //$NON-NLS-1$
public static final String COMMA_DELIMITER = ","; //$NON-NLS-1$
public static final String COLON_DELIMITER = ":"; //$NON-NLS-1$
public static final String BACKSLASH_DELIMITER = "\\"; //$NON-NLS-1$
public static final String DEFAULT_PROTOCOL= TeiidURL.CONNECTION.NON_SECURE_PROTOCOL + "://"; //$NON-NLS-1$
public static final String SECURE_PROTOCOL= TeiidURL.CONNECTION.SECURE_PROTOCOL + "://"; //$NON-NLS-1$
public static final String INVALID_FORMAT_SERVER = JDBCPlugin.Util.getString("MMURL.INVALID_FORMAT"); //$NON-NLS-1$
/*
* appserver URL
*/
private String appServerURL;
/*
* List of <code> HostData </code> in a cluster
*/
private List<HostInfo> hosts = new ArrayList<HostInfo>();
private boolean usingSSL = false;
/**
* Create an MMURL from the server URL. For use by the server-side.
* @param serverURL Expected format: mm[s]://server1:port1[,server2:port2]
* @throws MalformedURLException
* @since 4.2
*/
public TeiidURL(String serverURL) throws MalformedURLException {
if (serverURL == null) {
throw new MalformedURLException(INVALID_FORMAT_SERVER);
}
if (StringUtil.startsWithIgnoreCase(serverURL, SECURE_PROTOCOL)) {
usingSSL = true;
} else if (!StringUtil.startsWithIgnoreCase(serverURL, DEFAULT_PROTOCOL)) {
throw new MalformedURLException(INVALID_FORMAT_SERVER);
}
appServerURL = serverURL;
parseServerURL(serverURL.substring(usingSSL?SECURE_PROTOCOL.length():DEFAULT_PROTOCOL.length()), INVALID_FORMAT_SERVER);
}
public TeiidURL(String host, int port, boolean secure) {
usingSSL = secure;
if(host.startsWith("[")) { //$NON-NLS-1$
host = host.substring(1, host.indexOf(']'));
}
hosts.add(new HostInfo(host, port));
}
/**
* Validates that a server URL is in the correct format.
* @param serverURL Expected format: mm[s]://server1:port1[,server2:port2]
* @since 4.2
*/
public static boolean isValidServerURL(String serverURL) {
boolean valid = true;
try {
new TeiidURL(serverURL);
} catch (Exception e) {
valid = false;
}
return valid;
}
public List<HostInfo> getHostInfo() {
return hosts;
}
/**
* Get a list of hosts
*
* @return string of host separated by commas
* @since 4.2
*/
public String getHosts() {
StringBuffer hostList = new StringBuffer(""); //$NON-NLS-1$
if( hosts != null) {
Iterator<HostInfo> iterator = hosts.iterator();
while (iterator.hasNext()) {
HostInfo element = iterator.next();
hostList.append(element.getHostName());
if( iterator.hasNext()) {
hostList.append(COMMA_DELIMITER);
}
}
}
return hostList.toString();
}
/**
* Get a list of ports
*
* @return string of ports seperated by commas
* @since 4.2
*/
public String getPorts() {
StringBuffer portList = new StringBuffer(""); //$NON-NLS-1$
if( hosts != null) {
Iterator<HostInfo> iterator = hosts.iterator();
while (iterator.hasNext()) {
HostInfo element = iterator.next();
portList.append(element.getPortNumber());
if( iterator.hasNext()) {
portList.append(COMMA_DELIMITER);
}
}
}
return portList.toString();
}
/**
* @param url
* @throws MalformedURLException
* @since 4.2
*/
private void parseServerURL(String serverURL, String exceptionMessage) throws MalformedURLException {
StringTokenizer st = new StringTokenizer(serverURL, COMMA_DELIMITER);
if (!st.hasMoreTokens()) {
throw new MalformedURLException(exceptionMessage);
}
while (st.hasMoreTokens()) {
String nextToken = st.nextToken();
nextToken = nextToken.trim();
String host = ""; //$NON-NLS-1$
String port = ""; //$NON-NLS-1$
if (nextToken.startsWith("[")) { //$NON-NLS-1$
int hostEnd = nextToken.indexOf("]:"); //$NON-NLS-1$
if (hostEnd == -1) {
throw new MalformedURLException(JDBCPlugin.Util.getString("TeiidURL.invalid_ipv6_hostport", nextToken, exceptionMessage)); //$NON-NLS-1$
}
host = nextToken.substring(1, hostEnd);
port = nextToken.substring(hostEnd+2);
}
else {
int hostEnd = nextToken.indexOf(":"); //$NON-NLS-1$
if (hostEnd == -1) {
throw new MalformedURLException(JDBCPlugin.Util.getString("TeiidURL.invalid_hostport", nextToken, exceptionMessage)); //$NON-NLS-1$
}
host = nextToken.substring(0, hostEnd);
port = nextToken.substring(hostEnd+1);
}
host = host.trim();
port = port.trim();
if (host.equals("") || port.equals("")) { //$NON-NLS-1$ //$NON-NLS-2$
throw new MalformedURLException(JDBCPlugin.Util.getString("TeiidURL.invalid_hostport", nextToken, exceptionMessage)); //$NON-NLS-1$
}
int portNumber = validatePort(port);
HostInfo hostInfo = new HostInfo(host, portNumber);
hosts.add(hostInfo);
}
}
public static int validatePort(String port) throws MalformedURLException {
int portNumber;
try {
portNumber = Integer.parseInt(port);
} catch (NumberFormatException nfe) {
throw new MalformedURLException(JDBCPlugin.Util.getString("TeiidURL.non_numeric_port", port)); //$NON-NLS-1$
}
String msg = validatePort(portNumber);
if (msg != null) {
throw new MalformedURLException(msg);
}
return portNumber;
}
public static String validatePort(int portNumber) {
if (portNumber < 0 || portNumber > 0xFFFF) {
return JDBCPlugin.Util.getString("TeiidURL.port_out_of_range", portNumber); //$NON-NLS-1$
}
return null;
}
/**
* Get the Application Server URL
*
* @return String for connection to the Server
* @since 4.2
*/
public String getAppServerURL() {
if (appServerURL == null) {
StringBuffer sb = new StringBuffer();
if (usingSSL) {
sb.append(SECURE_PROTOCOL);
} else {
sb.append(DEFAULT_PROTOCOL);
}
Iterator<HostInfo> iter = hosts.iterator();
while (iter.hasNext()) {
HostInfo host = iter.next();
boolean ipv6HostName = host.getHostName().indexOf(':') != -1;
if (ipv6HostName) {
sb.append('[');
}
sb.append(host.getHostName());
if (ipv6HostName) {
sb.append(']');
}
sb.append(COLON_DELIMITER);
sb.append(host.getPortNumber());
if (iter.hasNext()) {
sb.append(COMMA_DELIMITER);
}
}
appServerURL = sb.toString();
}
return appServerURL;
}
/**
* @see java.lang.Object#toString()
* @since 4.2
*/
public String toString() {
return getAppServerURL();
}
/**
* @see java.lang.Object#equals(java.lang.Object)
* @since 4.2
*/
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof TeiidURL)) {
return false;
}
TeiidURL url = (TeiidURL)obj;
return (appServerURL.equals(url.getAppServerURL()));
}
/**
* @see java.lang.Object#hashCode()
* @since 4.2
*/
public int hashCode() {
return appServerURL.hashCode();
}
public boolean isUsingSSL() {
return usingSSL;
}
}