/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.intel.mtwilson.datatypes;
import com.intel.mtwilson.model.Hostname;
import com.intel.mtwilson.model.InternetAddress;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Properties;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.MapConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The general connection string format is vendor:url;options
* The vendor-specific URL can be anything that does not include a semicolon, but is expected to be an https URL.
* If it must include semicolons they should be percent-encoded as %3B (see https://en.wikipedia.org/wiki/Percent-encoding)
*
* @author ssbangal
*/
public class ConnectionString {
private static Logger log = LoggerFactory.getLogger(ConnectionString.class);
private static final String httpDelimiter = "//";
private static final String parameterDelimiter = ":";
private static final String urlOptionsDelimiter = ";";
private static final String intelVendorRegEx = "^(https?://)?([a-zA-Z0-9\\._-])+(:)*([0-9])*$";
private String addOnConnectionString;
private Vendor vendor;
private InternetAddress hostname;
private String managementServerName;
private Integer port;
private String userName;
private String password;
public static final String OPT_USERNAME = "u";
public static final String OPT_PASSWORD = "p";
public static final String OPT_HOSTNAME = "h";
// public static final String LONGOPT_USERNAME = "username";
// public static final String LONGOPT_PASSWORD = "password";
// public static final String LONGOPT_HOSTNAME = "hostname";
public static class VendorConnection {
public Vendor vendor;
public URL url;
public Configuration options;
}
public static VendorConnection parseConnectionString(String connectionString) throws MalformedURLException {
// log.debug("Connection string: {}", connectionString); // do not log this regularly because it may contain a password
VendorConnection vc = new VendorConnection();
vc.vendor = vendorFromURL(connectionString);
String vendorURL;
if( vc.vendor == null ) {
vc.vendor = guessVendorFromURL(connectionString);
vendorURL = connectionString;
}
else {
vendorURL = connectionString.substring(vc.vendor.name().length()+1);
}
if( vc.vendor != null ) {
// log.debug("Vendor URL: {}", vendorURL); // do not log this regularly because it may contain a password
int optionStartIndex = vendorURL.indexOf(urlOptionsDelimiter);
if( optionStartIndex > -1 ) {
String urlPart = vendorURL.substring(0, optionStartIndex);
String optionsPart = vendorURL.substring(optionStartIndex+1); // skip the delimiter
log.debug("URL part: {}", urlPart);
// log.debug("Options part: {}", optionsPart); // do not log this regularly because it may contain a password
vc.url = new URL(urlPart); // vendorURL without the options
vc.options = parseOptions(optionsPart);
}
else {
vc.url = new URL(vendorURL);
vc.options = null;
}
}
return vc;
}
private static Configuration parseOptions(String options) {
while(options.startsWith(urlOptionsDelimiter)) {
options = options.substring(urlOptionsDelimiter.length());
}
Properties p = new Properties();
String[] keyValuePairs = options.split(urlOptionsDelimiter);
for(String keyValuePair : keyValuePairs) {
String[] keyValue = keyValuePair.trim().split("=");
if( keyValue.length == 2 && !keyValue[0].isEmpty() ) {
p.setProperty(keyValue[0], keyValue[1]);
}
// ignore any options that are not in key=value format
}
// backwards compatible options: username;password or username;password;hostname
if( !p.containsKey(OPT_USERNAME) ) {
String username = usernameFromURL(urlOptionsDelimiter+options);
if( username != null ) {
p.setProperty(OPT_USERNAME, username);
}
}
if( !p.containsKey(OPT_PASSWORD) ) {
String password = passwordFromURL(urlOptionsDelimiter+options);
if( password != null ) {
p.setProperty(OPT_PASSWORD, password);
}
}
if( !p.containsKey(OPT_HOSTNAME) ) {
String hostname = hostnameFromURL(urlOptionsDelimiter+options);
if( hostname != null ) {
p.setProperty(OPT_HOSTNAME, hostname);
}
}
return new MapConfiguration(p);
}
public ConnectionString() {
this.addOnConnectionString = "";
this.hostname = null;
this.port = 0;
this.managementServerName = "";
this.userName = "";
this.password = "";
}
/**
* This constructor can be used if the user has already formated the connection string for the vendor. This option
* can be used if the user is using http instead of default https.
*
* @param vendor
* @param addOnConnectionString
*/
public ConnectionString(Vendor vendor, String addOnConnectionString) throws MalformedURLException {
this(vendor.name()+":"+addOnConnectionString);
}
/**
* URL must be something like https://intelhost.com:9999 or https://citrixhost.com:443 or https://vcenter.com:443/sdk
* @param url
* @return
*/
private static Vendor guessVendorFromURL(String url) {
Vendor v;
// In this case we do not have the prefix
if (url.matches(intelVendorRegEx)) {
v = Vendor.INTEL;
} else {
if (url.contains("/sdk")) {
v = Vendor.VMWARE;
} else {
v = Vendor.CITRIX;
}
}
return v;
}
/**
* This constructor has to be used to extract individual information from the connection string.
*
* For cases where the input connection string may be provided without a prefix, SEE ALSO ConnectionString.from(TxtHostRecord)
* where you can provide additional information to help guess the right connection string.
*
* @param connectionString
*/
public ConnectionString(String connectionString) throws MalformedURLException {
this();
vendor = vendorFromURL(connectionString);
// Let us first check if the connection string has the prefix of the vendor or not.
if( vendor == null ) {
vendor = guessVendorFromURL(connectionString);
}
else { // if( vendor != null )
connectionString = vendorConnectionFromURL(connectionString);
if( connectionString == null ) { throw new IllegalArgumentException("Invalid or missing connection string"); }
}
addOnConnectionString = connectionString;
switch(vendor) {
case INTEL:
IntelConnectionString intelConnection = IntelConnectionString.forURL(connectionString);
hostname = intelConnection.getHost();
port = intelConnection.getPort();
managementServerName = hostname.toString();
break;
case CITRIX:
CitrixConnectionString citrixConnection = CitrixConnectionString.forURL(connectionString);
hostname = citrixConnection.getHost();
port = citrixConnection.getPort();
managementServerName = hostname.toString();
userName = citrixConnection.getUsername();
password = citrixConnection.getPassword();
break;
case VMWARE:
VmwareConnectionString vmwareConnection = VmwareConnectionString.forURL(connectionString);
hostname = vmwareConnection.getHost();
port = vmwareConnection.getPort();
managementServerName = vmwareConnection.getVCenter().toString();
userName = vmwareConnection.getUsername();
password = vmwareConnection.getPassword();
break;
default:
throw new UnsupportedOperationException("Vendor not supported yet: "+vendor.toString());
}
}
/**
* Returns the formated connection string based on the parameters specified by the user. Example of Citrix:
* citrix:https://xenserver:port;username;password Example of VMware:
* vmware:https://vcenterserver:port/sdk;username;password
* Example of Xen/KVM: intel:https://hostname:9999
*
* @return
*/
public String getConnectionStringWithPrefix() {
if( this.vendor == null ) { return ""; }
String connStr = getConnectionString();
if( connStr.toLowerCase().startsWith(this.vendor.name().toLowerCase())) {
return connStr;
}
return String.format("%s:%s", this.vendor.name().toLowerCase(), connStr);
}
/**
* This method returns the formated connection string based on the parameters specified without the prefix of the
* vendor. Example of Citrix: https://xenserver:port;username;password Example of VMware:
* https://vcenterserver:port/sdk;username;password Example of Xen/KVM: https://hostname:9999
*
* @return
*/
public String getConnectionString() {
String connectionString;
if (this.vendor == Vendor.INTEL) {
connectionString = String.format("https://%s:%d", this.managementServerName, this.port);
} else if (this.vendor == Vendor.VMWARE) {
connectionString = (this.addOnConnectionString.isEmpty()) ?
String.format("https://%s:%d/sdk;%s;%s;h=%s", this.managementServerName, this.port, this.userName, this.password, this.hostname.toString()) :
String.format("%s", this.addOnConnectionString);
} else if (this.vendor == Vendor.CITRIX) {
connectionString = (this.addOnConnectionString.isEmpty()) ?
String.format("https://%s:%d/;%s;%s", this.managementServerName, this.port, this.userName, this.password) :
String.format("%s", this.addOnConnectionString);
} else {
connectionString = "";
}
return connectionString;
}
/**
* Returns just the URL portion of the connection string without any options.
* This is important because for citrix, the format %s:%d;%s;%s isn't a valid URL. there must be a slash
* after the port number.
*
* But this is the method that should be used when you want to display a connection string in the UI or logs - since
* this method will not leak any secrets.
*
* @return
*/
public URL getURL() {
try {
if (this.vendor == Vendor.INTEL) {
return new URL(String.format("https://%s:%d", this.managementServerName, this.port));
}
else if (this.vendor == Vendor.VMWARE) {
if( this.addOnConnectionString.isEmpty() ) {
return new URL(String.format("https://%s:%d/sdk", this.managementServerName, this.port));
}
else {
return new URL(this.addOnConnectionString);
}
}
else if (this.vendor == Vendor.CITRIX) {
if( this.addOnConnectionString.isEmpty() ) {
return new URL(String.format("https://%s:%d", this.managementServerName, this.port));
}
else {
return new URL(this.addOnConnectionString);
}
} else {
return null;
}
}
catch(MalformedURLException e) {
log.error("ConnectionString.getURL: "+e.toString(), e);
// log.debug("Connection string: ", this.addOnConnectionString);
throw new IllegalArgumentException("Invalid connection string");
}
}
/**
* This retrieves the addOnConnectionString component of the connection string. Before calling this method
* ConnectionString(String connectionString) constructor has to be called by passing in the completed connection
* string.
*
* @return
*/
public String getAddOnConnectionString() {
return addOnConnectionString;
}
/**
* Returns the hostname of the host represented by this connection string.
* @return
*/
public Hostname getHostname() {
return new Hostname(hostname.toString());
}
/**
* This retrieves the hostName component of the connection string. Before calling this method
* ConnectionString(String connectionString) constructor has to be called by passing in the completed connection
* string.
*
* @return
*/
public String getManagementServerName() {
return managementServerName;
}
/**
* This retrieves the port number component of the connection string. Before calling this method
* ConnectionString(String connectionString) constructor has to be called by passing in the completed connection
* string.
*
* @return
*/
public Integer getPort() {
return port;
}
/**
* This would return the host type of the host, which can be either INTEL, VMWARE or CITRIX.
* @return
*/
public Vendor getVendor() {
return vendor;
}
public static class IntelConnectionString {
private InternetAddress hostAddress;
private int port;
public InternetAddress getHost() { return hostAddress; }
public int getPort() { return port; }
public URL toURL() {
try {
return new URL(String.format("https://%s:%d", hostAddress.toString(), port));
}
catch(MalformedURLException e) {
log.error("Cannot create Intel Host URL: {}", e.toString());
return null;
}
}
@Override
public String toString() {
return String.format("https://%s:%d", hostAddress.toString(), port);
}
public static IntelConnectionString forURL(String url) throws MalformedURLException {
log.debug("IntelConnectionString forURL {}", url);
IntelConnectionString cs = new IntelConnectionString();
VendorConnection info = parseConnectionString(url);
if( info.url == null ) { throw new IllegalArgumentException("Missing host address in URL"); }
if( info.vendor != Vendor.INTEL ) {
throw new IllegalArgumentException("Not an Intel Host URL: "+info.url.toExternalForm());
}
cs.hostAddress = new InternetAddress(info.url.getHost());
cs.port = portFromURL(info.url);
return cs;
}
}
public static class CitrixConnectionString {
private InternetAddress hostAddress;
private int port;
private String username;
private String password;
public InternetAddress getHost() { return hostAddress; }
public int getPort() { return port; }
public String getUsername() { return username; }
public String getPassword() { return password; }
public URL toURL() {
try {
return new URL(String.format("https://%s:%d", hostAddress.toString(), port));
}
catch(MalformedURLException e) {
log.error("Cannot create Citrix Host URL: {}", e.toString());
return null;
}
}
@Override
public String toString() {
return String.format("https://%s:%d/;u=%s;p=%s", hostAddress.toString(), port, username, password);
}
public static CitrixConnectionString forURL(String url) throws MalformedURLException {
// log.debug("CitrixConnectionString forURL {}", url); //REMOVED debug log statement as it has the password in the connection string
CitrixConnectionString cs = new CitrixConnectionString();
VendorConnection info = parseConnectionString(url);
if( info.url == null ) { throw new IllegalArgumentException("Missing host address in URL"); }
if( info.vendor != Vendor.CITRIX ) {
throw new IllegalArgumentException("Not a Citrix Host URL: "+info.url.toExternalForm());
}
cs.hostAddress = new InternetAddress(info.url.getHost());
cs.port = portFromURL(info.url);
if( info.options != null ) {
cs.username = info.options.getString(OPT_USERNAME); // usernameFromURL(url);
cs.password = info.options.getString(OPT_PASSWORD); // passwordFromURL(url);
}
return cs;
}
}
public static class VmwareConnectionString {
private InternetAddress hostAddress;
private InternetAddress vcenterAddress;
private int port;
private String username;
private String password;
public InternetAddress getVCenter() { return vcenterAddress; }
public InternetAddress getHost() { return hostAddress; }
public int getPort() { return port; }
public String getUsername() { return username; }
public String getPassword() { return password; }
public void setVCenter(InternetAddress vcenterAddress) { this.vcenterAddress = vcenterAddress; }
public void setHost(InternetAddress hostAddress) { this.hostAddress = hostAddress; }
public void setPort(int port) { this.port = port; }
public void setUsername(String username) { this.username = username; }
public void setPassword(String password) { this.password = password; }
public URL toURL() {
try {
return new URL(String.format("https://%s:%d/sdk", vcenterAddress.toString(), port));
}
catch(MalformedURLException e) {
log.error("Cannot create VMware Host URL: {}", e.toString());
return null;
}
}
@Override
public String toString() {
return String.format("https://%s:%d/sdk;u=%s;p=%s;h=%s", vcenterAddress.toString(), port, username, password, hostAddress.toString());
}
public static VmwareConnectionString forURL(String url) throws MalformedURLException {
// log.debug("VmwareConnectionString forURL {}", url);
VmwareConnectionString cs = new VmwareConnectionString();
VendorConnection info = parseConnectionString(url);
if( info.url == null ) { throw new IllegalArgumentException("Missing host address in URL"); }
if( info.vendor != Vendor.VMWARE ) {
throw new IllegalArgumentException("Not a VMware Host URL: "+info.url.toExternalForm());
}
cs.vcenterAddress = new InternetAddress(info.url.getHost());
cs.port = portFromURL(info.url);
if( info.options != null ) {
cs.hostAddress = new InternetAddress(info.options.getString(OPT_HOSTNAME)); // new InternetAddress(hostnameFromURL(url));
cs.username = info.options.getString(OPT_USERNAME); // usernameFromURL(url);
cs.password = info.options.getString(OPT_PASSWORD); // passwordFromURL(url);
}
return cs;
}
}
/**
* Creates a connection string for an Intel host with default port 9999
* @param hostname DNS name or IP address
* @return
*/
public static ConnectionString forIntel(String hostname) {
return forIntel(new Hostname(hostname));
}
/**
* Creates a connection string for an Intel host with default port 9999
* @param hostname DNS name or IP address
* @return
*/
public static ConnectionString forIntel(Hostname hostname) {
ConnectionString conn = new ConnectionString();
conn.vendor = Vendor.INTEL;
conn.hostname = new InternetAddress(hostname.toString());
conn.managementServerName = hostname.toString();
conn.port = 9999; // default Intel Trust Agent port
return conn;
}
/**
* Creates a connection string for an Intel host with specified port
* @param hostname DNS name or IP address
* @param port to connect to Trust Agent
* @return
*/
public static ConnectionString forIntel(Hostname hostname, Integer port) {
ConnectionString conn = new ConnectionString();
conn.vendor = Vendor.INTEL;
conn.hostname = new InternetAddress(hostname.toString());
conn.managementServerName = hostname.toString();
conn.port = port;
return conn;
}
/**
* Creates a connection string for an Intel host with specified port
* @param hostname DNS name or IP address
* @param port to connect to Trust Agent
* @return
*/
public static ConnectionString forIntel(String hostname, Integer port) {
return forIntel(new Hostname(hostname), port);
}
/**
* Creates a connection string for an Intel host with specified port
* @param url like https://hostname:9999
* @return
*/
/*
public static ConnectionString forIntel(URL url) {
return forIntel(new Hostname(url.getHost()), portFromURL(url));
}
*/
/**
* Creates a connection string for a Citrix host with default port 443
* @param hostname DNS name or IP address
* @param username for Citrix host management
* @param password for Citrix host management
* @return
*/
public static ConnectionString forCitrix(Hostname hostname, String username, String password) {
ConnectionString conn = new ConnectionString();
conn.vendor = Vendor.CITRIX;
conn.hostname = new InternetAddress(hostname.toString());
conn.managementServerName = hostname.toString();
conn.port = 443;
conn.userName = username;
conn.password = password;
return conn;
}
/**
* Creates a connection string for a Citrix host with specified default port
* @param hostname DNS name or IP address
* @param port to connect to Citrix host management API
* @param username for Citrix host management
* @param password for Citrix host management
* @return
*/
public static ConnectionString forCitrix(Hostname hostname, Integer port, String username, String password) {
ConnectionString conn = new ConnectionString();
conn.vendor = Vendor.CITRIX;
conn.hostname = new InternetAddress(hostname.toString());
conn.managementServerName = hostname.toString();
conn.port = port;
conn.userName = username;
conn.password = password;
return conn;
}
/**
* Creates a connection string for a Citrix host with specified port
* @param url like https://hostname:443;username;password or https://hostname:443;u=username;p=password
* @return
*/
/*
public static ConnectionString forCitrix(URL url) {
return forCitrix(new Hostname(url.getHost()), portFromURL(url), usernameFromURL(url), passwordFromURL(url));
}
*/
/**
* Creates a connection string for a VMware host with default port 443
* @param hostname DNS name or IP address of the host
* @param vcenter DNS name or IP address of the vcenter appliance
* @param username for Vcenter host management
* @param password for Vcenter host management
* @return
*/
public static ConnectionString forVmware(Hostname hostname, Hostname vcenter, String username, String password) {
ConnectionString conn = new ConnectionString();
conn.vendor = Vendor.VMWARE;
conn.hostname = new InternetAddress(hostname.toString());
conn.managementServerName = vcenter.toString();
conn.port = 443;
conn.userName = username;
conn.password = password;
return conn;
}
/**
* Creates a connection string for a VMware host with specified port
* @param hostname DNS name or IP address of the host
* @param vcenter DNS name or IP address of the vcenter appliance
* @param port to connect to the vcenter API
* @param username for Vcenter host management
* @param password for Vcenter host management
* @return
*/
public static ConnectionString forVmware(Hostname hostname, Hostname vcenter, Integer port, String username, String password) {
ConnectionString conn = new ConnectionString();
conn.vendor = Vendor.VMWARE;
conn.hostname = new InternetAddress(hostname.toString());
conn.managementServerName = vcenter.toString();
conn.port = port;
conn.userName = username;
conn.password = password;
return conn;
}
/**
* Creates a connection string for a VMware host with specified Vcenter URL
* @param hostname DNS name or IP address of the host
* @param vcenter URL for the Vcenter API
* @param username for Vcenter host management
* @param password for Vcenter host management
* @return
*/
public static ConnectionString forVmware(Hostname hostname, URL vcenter, String username, String password) {
ConnectionString conn = new ConnectionString();
conn.vendor = Vendor.VMWARE;
conn.hostname = new InternetAddress(hostname.toString());
conn.managementServerName = vcenter.toString();
conn.port = portFromURL(vcenter);
conn.userName = username;
conn.password = password;
return conn;
}
/**
* Creates a connection string for a VMware host with specified port
* @param url like https://vcenter:443/sdk;username;password;hostname or https://hostname:443;u=username;p=password;h=hostname
* @return
*/
/*
public static ConnectionString forVmware(URL url) {
return forVmware(new Hostname(url.getHost()), new Hostname(hostnameFromURL(url)), portFromURL(url), usernameFromURL(url), passwordFromURL(url));
}
*/
/**
* Creates a connection string with the given vendor and vendor-specific URL
* @param vendor like INTEL, CITRIX, VMWARE
* @param url vendor-specific URL like https://citrix:443;username;password or https://vcenter:443/sdk;u=username;p=password;h=hostname or https://hostname:9999
* @return
*/
/*
public static ConnectionString forVendor(Vendor vendor, String url) {
if( vendor == null ) { return null; }
switch(vendor) {
case INTEL:
return forIntel(url);
case CITRIX:
return forCitrix(url);
case VMWARE:
return forVmware(url);
default:
log.error("Unknown vendor: "+vendor.name());
return null;
}
}
*/
/**
* The URL object returns -1 for the port number if it was not explicitly defined in the URL.
* So this method checks for -1 and returns default https or default http port depending on
* the protocol of the URL. If the port is not defined in the URL and the scheme is neither
* https nor http then the -1 is returned.
* @param url
* @return
*/
private static int portFromURL(URL url) {
if( url.getPort() == -1 && url.getProtocol().equals("https") ) {
return 443;
}
else if( url.getPort() == -1 && url.getProtocol().equals("http") ) {
return 80;
}
else {
return url.getPort();
}
}
/**
* For supported URLs that include a username and password, the username is either
* the first parameter after the first semicolon, or a parameter that starts with u=
*
* For example:
* https://citrix:443;username;password
* https://citrix:443;u=username;p=password
* https://citrix:443;p=password;u=username
* https://vcenter:443/sdk;username;password;hostname
* https://vcenter:443/sdk;u=username;p=password;u=hostname
* https://vcenter:443/sdk;u=hostname;u=username;p=password
*
* @param url
* @return
*/
private static String usernameFromURL(String url) {
String str = url;
if( str.indexOf(';') == -1 ) {
return null;
}
String params = str.substring(str.indexOf(';')+1); // get everything after the first semicolon
String[] parts = params.split(";");
if( parts.length == 1 ) {
if( parts[0].toLowerCase().startsWith("u=") ) {
return parts[0].substring(2); // value after the "u=" for URL like https://citrix:443;u=username
}
return parts[0]; // the only value after semicolon for URL like https://citrix:443;username
}
if( parts.length == 2 ) {
if( parts[0].startsWith("u=") ) {
return parts[0].substring(2); // value after the "u=" for URL like https://citrix:443;u=username;p=password
}
if( parts[1].startsWith("u=") ) {
return parts[1].substring(2); // value after the "u=" for URL like https://citrix:443;p=password;u=username
}
return parts[0]; // the first value after semicolon for URL like https://citrix:443;username;password
}
if( parts.length == 3 ) {
if( parts[0].startsWith("u=") ) {
return parts[0].substring(2); // value after the "u=" for URL like https://vcenter:443/sdk;u=username;p=password;h=hostname
}
if( parts[1].startsWith("u=") ) {
return parts[1].substring(2); // value after the "u=" for URL like https://vcenter:443/sdk;h=hostname;u=username;p=password or https://vcenter:443/sdk;p=password;u=username;h=hostname
}
if( parts[2].startsWith("u=") ) {
return parts[2].substring(2); // value after the "u=" for URL like https://vcenter:443/sdk;h=hostname;p=password;u=username
}
return parts[0]; // the first value after semicolon for URL like https://vcenter:443/sdk;username;password;hostname
}
return null;
}
/**
* For supported URLs that include a username and password, the password is either
* the second parameter after the first semicolon, or a parameter that starts with p=
*
* For example:
* https://citrix:443;username;password
* https://citrix:443;u=username;p=password
* https://citrix:443;p=password;u=username
* https://vcenter:443/sdk;username;password;hostname
* https://vcenter:443/sdk;u=username;p=password;u=hostname
* https://vcenter:443/sdk;u=hostname;u=username;p=password
*
* @param url
* @return
*/
private static String passwordFromURL(String url) {
String str = url;
if( str.indexOf(';') == -1 ) {
return null;
}
String params = str.substring(str.indexOf(';')+1); // get everything after the first semicolon
String[] parts = params.split(";");
if( parts.length == 1 ) {
return null; // no password in URL like https://citrix:443;username or https://vcenter:443/sdk;username
}
if( parts.length == 2 ) {
if( parts[0].startsWith("p=") ) {
return parts[0].substring(2); // value after the "p=" for URL like https://citrix:443;u=username;p=password
}
if( parts[1].startsWith("p=") ) {
return parts[1].substring(2); // value after the "p=" for URL like https://citrix:443;p=password;u=username
}
return parts[1]; // the second value after semicolon for URL like https://citrix:443;username;password
}
if( parts.length == 3 ) {
if( parts[0].startsWith("p=") ) {
return parts[0].substring(2); // value after the "p=" for URL like https://vcenter:443/sdk;p=password;u=username;h=hostname
}
if( parts[1].startsWith("p=") ) {
return parts[1].substring(2); // value after the "p=" for URL like https://vcenter:443/sdk;h=hostname;p=password;u=username or https://vcenter:443/sdk;u=username;p=password;h=hostname
}
if( parts[2].startsWith("p=") ) {
return parts[2].substring(2); // value after the "p=" for URL like https://vcenter:443/sdk;h=hostname;u=username;p=password
}
return parts[1]; // the second value after semicolon for URL like https://vcenter:443/sdk;username;password;hostname
}
return null;
}
/**
* For vmware URLs, the hostname in the URL is the vcenter hostname, and the "real" hostname
* is passed as a parameter next to username and password. So this function searches for that
* parameter and returns it if it was found.
*
* For example:
* https://vcenter:443/sdk;username;password;hostname
* https://vcenter:443/sdk;u=username;p=password;u=hostname
* https://vcenter:443/sdk;u=hostname;u=username;p=password
*
* @param url
* @return
*/
private static String hostnameFromURL(String url) {
String str = url;
if( str.indexOf(';') == -1 ) {
return null;
}
String params = str.substring(str.indexOf(';')+1); // get everything after the first semicolon
String[] parts = params.split(";");
if( parts.length == 1 ) {
return null; // no hostname in URL like https://vcenter:443/sdk;username
}
if( parts.length == 2 ) {
if( parts[0].startsWith("h=") ) {
return parts[0].substring(2); // value after the "p=" for URL like https://vcenter:443/sdk;h=hostname;u=username
}
if( parts[1].startsWith("h=") ) {
return parts[1].substring(2); // value after the "p=" for URL like https://vcenter:443/sdk;u=username;h=hostname
}
return null; // no hostname URL like https://vcenter:443/sdk;username;password
}
if( parts.length == 3 ) {
if( parts[0].startsWith("h=") ) {
return parts[0].substring(2); // value after the "h=" for URL like https://vcenter:443/sdk;h=hostname;u=username;p=password
}
if( parts[1].startsWith("h=") ) {
return parts[1].substring(2); // value after the "h=" for URL like https://vcenter:443/sdk;p=password;h=hostname;u=username or https://vcenter:443/sdk;u=username;h=hostname;p=password
}
if( parts[2].startsWith("h=") ) {
return parts[2].substring(2); // value after the "h=" for URL like https://vcenter:443/sdk;p=password;u=username;h=hostname
}
return parts[2]; // the third value after semicolon for URL like https://vcenter:443/sdk;username;password;hostname
}
return null;
}
/*
private static Vendor vendorFromURL(URL url) {
return vendorFromURL(url.toExternalForm());
}
*/
private static Vendor vendorFromURL(String url) {
for( Vendor v : Vendor.values() ) {
if( url.toLowerCase().startsWith(v.name().toLowerCase()+":") ) {
return v;
}
}
return null;
}
// private static String vendorConnectionFromURL(URL url) throws MalformedURLException {
// return vendorConnectionFromURL(url.toExternalForm());
// }
private static String vendorConnectionFromURL(String url) throws MalformedURLException {
// log.debug("url: {}", url); // do not log this regularly because it may contain a password
Vendor v = vendorFromURL(url);
if( v == null ) {
return null;
}
// log.debug("vendor name: {}", v.name());
// log.debug("vendor name length: {}", v.name().length());
String str = url.substring(v.name().length()+1); // start one character after the vendor prefix (vendor name followed by the colon)
// log.debug("vendor connection: {}", str);
return str;
}
public static ConnectionString from(TxtHostRecord host) throws MalformedURLException {
String connectionString = host.AddOn_Connection_String;
if( connectionString == null || connectionString.isEmpty() ) {
if( host.HostName != null && !host.HostName.isEmpty() && host.Port != null ) {
connectionString = String.format("intel:https://%s:%d", host.HostName, host.Port);
log.debug("Assuming Intel connection string " + connectionString + " for host: " + host.HostName + " with IP address: "+host.HostName +" and port: "+host.Port);
return new ConnectionString(connectionString);
}
else if(host.IPAddress != null && !host.IPAddress.isEmpty() && host.Port != null ) {
connectionString = String.format("intel:https://%s:%d", host.IPAddress, host.Port);
log.debug("Assuming Intel connection string " + connectionString + " for host: " + host.HostName +" with IP address: "+host.IPAddress);
return new ConnectionString(connectionString);
}
else if(host.IPAddress != null && !host.IPAddress.isEmpty() ) {
connectionString = String.format("intel:https://%s:%d", host.IPAddress, 9999); // NOTE: empty port is assumed to be a mtwilson 1.x trust agent for backward compatibility;
log.debug("Assuming Intel connection string " + connectionString + " for host: " + host.HostName +" with IP address: "+host.IPAddress);
return new ConnectionString(connectionString);
}
throw new IllegalArgumentException("Host does not have a connection string or hostname set");
}
else if (connectionString.startsWith("intel") ) {
return new ConnectionString(connectionString);
}
else if ( connectionString.startsWith("vmware") || connectionString.startsWith("citrix") ) {
// ensure the hostname itself is present as a parameter on the connection string, since we have that information in the TxtHostRecord object
ConnectionString cs = new ConnectionString(connectionString);
cs.hostname = new InternetAddress(host.HostName);
return cs;
}
else {
// use a combination of connection string and other information in the record (port number, vmm name, ...)
// to make a better guess than is possible with just the connection string.
// for example:
//if( host.Port != null && host.Port == 9999 ) {
// ConnectionString.forIntel(host.HostName);
//}
return new ConnectionString(connectionString);
}
}
}