class ZTSClient implements Closeable {

    String generateAccessTokenRequestBody(String domainName, List<String> roleNames,
            String idTokenServiceName, String proxyForPrincipal, long expiryTime)
            throws UnsupportedEncodingException {

        StringBuilder body = new StringBuilder(256);
        body.append("grant_type=client_credentials");
        if (expiryTime > 0) {
            body.append("&expires_in=").append(expiryTime);
        }

        StringBuilder scope = new StringBuilder(256);
        if (roleNames == null || roleNames.isEmpty()) {
            scope.append(domainName).append(":domain");
        } else {
            for (String role : roleNames) {
                if (scope.length() != 0) {
                    scope.append(' ');
                }
                scope.append(domainName).append(AuthorityConsts.ROLE_SEP).append(role);
            }
        }
        if (idTokenServiceName != null && !idTokenServiceName.isEmpty()) {
            scope.append(" openid ").append(domainName).append(":service.").append(idTokenServiceName);
        }
        final String scopeStr = scope.toString();
        body.append("&scope=").append(URLEncoder.encode(scopeStr, "UTF-8"));

        if (proxyForPrincipal != null && !proxyForPrincipal.isEmpty()) {
            body.append("&proxy_for_principal=").append(URLEncoder.encode(proxyForPrincipal, "UTF-8"));
        }

        return body.toString();
    }

    public  ZTSClient();
    public  ZTSClient(String ztsUrl);
    public  ZTSClient(Principal identity);
    public  ZTSClient(String ztsUrl, Principal identity);
    public  ZTSClient(String ztsUrl, SSLContext sslContext);
    public  ZTSClient(String ztsUrl, String proxyUrl, SSLContext sslContext);
    public  ZTSClient(String domainName, String serviceName, ServiceIdentityProvider siaProvider);
    public  ZTSClient(String ztsUrl, String domainName, String serviceName,
                     ServiceIdentityProvider siaProvider);

}